-
Notifications
You must be signed in to change notification settings - Fork 0
/
meshmaker.c
193 lines (171 loc) · 5.54 KB
/
meshmaker.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
//-------------------------------------------------------------------------
// This program checks the rigidity of various structures by building them
// as mass-spring systems and seeing if they stay rigid under various
// forces and gravity.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
// Visual Studio doesn't have random() defined in stdlib.h, so we use rand() instead.
#ifndef random
#define random(x) rand(x)
#endif
// Global variables describing default values.
double g_mass_damping = 1.0;
double g_mass_radius = 2.0;
double g_mass = 1.0;
double g_edge_mass_radius = 5.0;
double g_edge_mass = 1.0e6;
double g_spring_constant_over_length = 100.0;
double g_rest_length_fraction = 0.9;
// Number of potential cross-link locations in X and Y
// Location to store an array of NX x NY crosslink values.
unsigned g_NX = 20;
unsigned g_NY = 16;
int *g_crosslinks = NULL;
double g_fraction = 1.0;
// Functions to specify the X and Y coordinates given a mesh
// index.
double X(int i)
{
return (i-10)*15;
}
double Y(int j)
{
return (j-8)*15;
}
void Usage(const char *s)
{
fprintf(stderr,"Usage: %s [-frac F] [outfile_name]\n", s);
fprintf(stderr," outfile_name: (default stdout)\n");
fprintf(stderr," -frac: Fraction of potential links made (default 1.0)\n");
exit(-1);
}
int main(int argc, const char *argv[])
{
// File name to write, defaults to empty
const char *outfile_name = "";
//-------------------------------------------------------------
// Command-line parsing
unsigned i;
unsigned real_params = 0; //< Number of non-flag parameters
for (i = 1; i < argc; i++) {
if (!strcmp(argv[i],"-help")) {
Usage(argv[0]);
} else if (!strcmp(argv[i],"-frac")) {
if (++i >= argc) { Usage(argv[0]); }
g_fraction = atof(argv[i]);
} else if (argv[i][0] == '-') {
Usage(argv[0]);
} else {
switch (real_params) {
case 0:
outfile_name = argv[i];
break;
default:
Usage(argv[0]);
}
}
}
//-------------------------------------------------------------
// Configure the output file. Use stdout if the name is blank, or open
// the file if it is not.
FILE *f = stdout;
if (strlen(outfile_name) > 0) {
f = fopen(outfile_name, "w");
}
if (f == NULL) {
char s[1024];
sprintf(s, "Could not open output file '%s' for writing", outfile_name);
perror(s);
return(-3);
}
//-------------------------------------------------------------
// Generate an NxM array to keep track of which entries have crosslinks.
// Fill in its entries with 0 or 1 for whether it has a link or not.
// The border entries always have crosslinks.
g_crosslinks = (int*)malloc(g_NX * g_NY * sizeof(int));
if (g_crosslinks == NULL) {
fprintf(stderr,"Out of memory\n");
return -4;
}
unsigned j;
for (i = 0; i < g_NX; i++) {
for (j = 0; j < g_NY; j++) {
if ( (i == 0) || (j == 0) || (i == g_NX-1) || (j == g_NY-1) ) {
g_crosslinks[i + j*g_NX] = 1;
} else {
if ( (random() % 1000) <= (g_fraction * 1000) ) {
g_crosslinks[i + j*g_NX] = 1;
} else {
g_crosslinks[i + j*g_NX] = 0;
}
}
}
}
//-------------------------------------------------------------
// Generate the output describing the mesh structure.
// Open the structure and set default parameters.
fprintf(f, "structure {\n");
fprintf(f, " mass_damping %lg\n", g_mass_damping);
fprintf(f, " spring_constant_over_length %lg\n", g_spring_constant_over_length);
fprintf(f, " rest_length_fraction %lg\n", g_rest_length_fraction);
fprintf(f, "\n");
// Put in the masses. All masses are named by their coordinates,
// format XxY, where X and Y are the coordinates.
// We only put in a crosslinked mass if it has a nonzero value in
// its entry. All of the edge masses are present and have large
// masses.
for (i = 0; i < g_NX; i++) {
for (j = 0; j < g_NY; j++) {
if ( (i == 0) || (j == 0) || (i == g_NX-1) || (j == g_NY-1) ) {
fprintf(f, " mass_radius %lg\n", g_edge_mass_radius);
fprintf(f, " mass\t%dx%d\t%lg\t%lg\t%lg\t%lg\n", i, j, g_edge_mass,
X(i), Y(j), 0.0);
} else if (g_crosslinks[i + j*g_NX] == 1) {
fprintf(f, " mass_radius %lg\n", g_mass_radius);
fprintf(f, " mass\t%dx%d\t%lg\t%lg\t%lg\t%lg\n", i, j, g_mass,
X(i), Y(j), 0.0);
}
}
}
fprintf(f, "\n");
// Put in the springs. We add springs from the left to the right and from
// top to bottom. If we're at a node that has no entry, we don't add a spring.
// If we're at a node that has an entry, we look to the right (or down) until
// we find another node that does have an entry. When we find it, we attach
// a spring between the nodes. We don't need to worry about whether we are
// an edge node for this.
unsigned k;
for (i = 0; i < g_NX; i++) {
for (j = 0; j < g_NY; j++) {
// Only add links for nodes that exist.
if (g_crosslinks[i + j*g_NX] == 1) {
// Find and add the spring going in X
// There is guaranteed to be one.
for (k = i+1; k < g_NX; k++) {
if (g_crosslinks[k + j*g_NX] == 1) {
fprintf(f, " spring %dx%d %dx%d\n", i,j, k,j);
break;
}
}
// Find and add the spring going in Y
// There is guaranteed to be one.
for (k = j+1; k < g_NY; k++) {
if (g_crosslinks[i + k*g_NX] == 1) {
fprintf(f, " spring %dx%d %dx%d\n", i,j, i,k);
break;
}
}
}
}
}
fprintf(f, "\n");
// End of structure.
fprintf(f, "}\n");
//-------------------------------------------------------------
// Close the output file and return.
free(g_crosslinks);
fclose(f);
return 0;
}