WPBDC 2013.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,292 @@
1
+ #include "stdafx.h"
2
+ #include "internal.h"
3
+
4
+ void randomly_permute_unsigned(unsigned *v, unsigned n)
5
+ {
6
+ unsigned i, r, t;
7
+
8
+ if (n == 0)
9
+ return;
10
+ for (i = n - 1; i > 0; i--) {
11
+ r = rand() % (i + 1);
12
+ t = v[r];
13
+ v[r] = v[i];
14
+ v[i] = t;
15
+ }
16
+ }
17
+
18
+ void randomly_permute_members(TMember *v, unsigned n)
19
+ {
20
+ unsigned i, r;
21
+ TMember t;
22
+
23
+ if (n == 0)
24
+ return;
25
+ for (i = n - 1; i > 0; i--) {
26
+ r = rand() % (i + 1);
27
+ t = v[r];
28
+ v[r] = v[i];
29
+ v[i] = t;
30
+ }
31
+ }
32
+
33
+ // Select sn values at random from the range [m,n]
34
+ // and place them (ascending sorted) into s.
35
+ void sample(unsigned *s, unsigned sn,
36
+ unsigned m, unsigned n)
37
+ {
38
+ unsigned i, j, t, sz;
39
+
40
+ sz = n - m + 1;
41
+ assert(sn <= sz);
42
+ for (i = 0; i < sn; i++) {
43
+ t = (m + i) + rand() % (sz - i);
44
+ for (j = i; j > 0; j--)
45
+ if (s[j-1] < t)
46
+ break;
47
+ else {
48
+ t--;
49
+ s[j] = s[j-1];
50
+ }
51
+ s[j] = t;
52
+ }
53
+ }
54
+
55
+ void perturb(TBridge *dst, TBridge *src, unsigned seed,
56
+ unsigned n_joints, unsigned n_members)
57
+ {
58
+ unsigned i, j, dir;
59
+ unsigned n_perturbable_joints;
60
+ TCoordinate x, y, x_min, x_max, y_min, y_max;
61
+ TXSection *xs;
62
+
63
+ // Define offsets in ccw order.
64
+ static int dx[] = { 1, 1, 0, -1, -1, -1, 0, 1};
65
+ static int dy[] = { 0, 1, 1, 1, 0, -1, -1, -1};
66
+
67
+ if (src->error != BridgeNoError)
68
+ return;
69
+
70
+ if (seed)
71
+ srand(seed);
72
+
73
+ copy_bridge(dst, src);
74
+
75
+ if (n_joints > 0) {
76
+
77
+ unsigned pj_indices[MAX_JOINTS];
78
+
79
+ // Check parameter.
80
+ n_perturbable_joints = dst->n_joints - dst->load_scenario.n_prescribed_joints;
81
+ if (n_joints > n_perturbable_joints)
82
+ n_joints = n_perturbable_joints;
83
+
84
+ sample(pj_indices, n_joints, dst->load_scenario.n_prescribed_joints + 1, dst->n_joints);
85
+
86
+ // Establish bounding box for perturbed coordinates.
87
+ x_min = 0;
88
+ x_max = dst->load_scenario.num_length_grids;
89
+ y_min = -(int)dst->load_scenario.under_grids;
90
+ y_max = dst->load_scenario.over_grids;
91
+
92
+ // Perturb the joints.
93
+ for (i = 0; i < n_joints; i++) {
94
+ j = dir = rand() / (RAND_MAX / 8 + 1);
95
+ assert(dir < 8);
96
+ // Search around the clock in case we have a joint right
97
+ // at the edge and would otherwise push it out of bounds.
98
+ do {
99
+ x = dst->joints[pj_indices[i]].x + dx[j];
100
+ y = dst->joints[pj_indices[i]].y + dy[j];
101
+ j = (j + 1) % 8;
102
+ } while (j != dir && (x < x_min || x > x_max || y < y_min || y > y_max));
103
+ if (j != dir) {
104
+ dst->joints[pj_indices[i]].x = x;
105
+ dst->joints[pj_indices[i]].y = y;
106
+ }
107
+ else {
108
+ assert(0); // Should never happen.
109
+ }
110
+ }
111
+ }
112
+ if (n_members > 0) {
113
+
114
+ unsigned pm_indices[MAX_MEMBERS];
115
+
116
+ if (n_members > dst->n_members)
117
+ n_members = dst->n_members;
118
+
119
+ sample(pm_indices, n_members, 1, dst->n_members);
120
+
121
+ for (i = 0; i < n_members; i++) {
122
+ xs = &dst->members[pm_indices[i]].x_section;
123
+
124
+ // If we're not already at largest size, bump up one, else bump down one.
125
+ if (xs->size < n_sizes(xs->section) - 1)
126
+ xs->size++;
127
+ else
128
+ xs->size--;
129
+ }
130
+ }
131
+ }
132
+
133
+ int fix_failure(TBridge *dst, TBridge *src, TParams *params)
134
+ {
135
+ unsigned member_index;
136
+ TAnalysis analysis[1];
137
+ int n_fixups;
138
+
139
+ if (src->error != BridgeNoError)
140
+ return -1;
141
+
142
+ init_analysis(analysis);
143
+
144
+ copy_bridge(dst, src);
145
+
146
+ n_fixups = 0;
147
+ for (;;) {
148
+ setup_analysis(analysis, dst, 0, 0, 0);
149
+
150
+ // Check for analysis problems.
151
+ if (analysis->error != NoAnalError)
152
+ return -2;
153
+
154
+ if (analysis->n_compressive_failures == 0 &&
155
+ analysis->n_tensile_failures == 0)
156
+ return n_fixups;
157
+
158
+ // Find a failed member.
159
+ for (member_index = 1; member_index <= dst->n_members; member_index++) {
160
+ if (analysis->member_strength[member_index].tensile_fail_mode != FailModeNone ||
161
+ analysis->member_strength[member_index].compressive_fail_mode != FailModeNone)
162
+ break;
163
+ }
164
+ if (member_index > dst->n_members) // search failed; should never happen
165
+ return -3;
166
+ // Have located a failed member. Increase its size if possible.
167
+ if (dst->members[member_index].x_section.size >= params->n_sizes[dst->members[member_index].x_section.section])
168
+ return -4; // already at top of scale
169
+ ++dst->members[member_index].x_section.size;
170
+ ++n_fixups;
171
+ }
172
+ }
173
+
174
+ int induce_failure(TBridge *dst, TBridge *src, unsigned seed)
175
+ {
176
+ unsigned start_member_index, member_index;
177
+ unsigned new_size, saved_size;
178
+ TAnalysis analysis[1];
179
+
180
+ if (src->error != BridgeNoError)
181
+ return -1;
182
+
183
+ init_analysis(analysis);
184
+
185
+ if (seed)
186
+ srand(seed);
187
+
188
+ copy_bridge(dst, src);
189
+
190
+ start_member_index = (rand() % dst->n_members) + 1;
191
+
192
+ #define NEXT(I) ((((I) - 1 + 1) % dst->n_members) + 1)
193
+
194
+ for (member_index = NEXT(start_member_index);
195
+ member_index != start_member_index;
196
+ member_index = NEXT(member_index)) {
197
+
198
+ // Get the size of the randomly selected member.
199
+ saved_size = dst->members[member_index].x_section.size;
200
+ if (saved_size > 0) {
201
+ // Reduce size one at a time until failure.
202
+ do {
203
+ new_size = --dst->members[member_index].x_section.size;
204
+ setup_analysis(analysis, dst, 0, 0, 0);
205
+
206
+ // Check for analysis problems.
207
+ if (analysis->error != NoAnalError)
208
+ return -2;
209
+
210
+ // Check for failure and return if we've done it!
211
+ if (analysis->n_compressive_failures > 0 ||
212
+ analysis->n_tensile_failures > 0)
213
+ return 0;
214
+ } while (new_size > 0);
215
+ // Couldn't do it with this member.
216
+ // Restore and loop to try the next member.
217
+ dst->members[member_index].x_section.size = saved_size;
218
+ }
219
+ }
220
+ #undef NEXT
221
+ // Very very unlikely, but who knows?
222
+ return -3;
223
+ }
224
+
225
+ // Make a randomized variant of the source bridge. This is just
226
+ // permuting joints and members into a pseudo-random order. But we have
227
+ // to keep joint references in members correct.
228
+ void vary(TBridge *dst, TBridge *src, unsigned seed)
229
+ {
230
+ unsigned *new_joint_to_old, *old_joint_to_new;
231
+ unsigned joint_index, member_index;
232
+
233
+ if (src->error != BridgeNoError)
234
+ return;
235
+
236
+ if (seed)
237
+ srand(seed);
238
+
239
+ copy_bridge(dst, src);
240
+
241
+ Newz(170, new_joint_to_old, dst->n_joints + 1, unsigned);
242
+ for (joint_index = 1; joint_index <= dst->n_joints; joint_index++)
243
+ new_joint_to_old[joint_index] = joint_index;
244
+
245
+ {
246
+ // Indirect random reordering of joint map so that, when done,
247
+ // joints[new_joint_to_old[i]] for permute_base + 1 <= i <= n_joints are randomized.
248
+ // Sort_base is first joint after those fixed by the scenario. We can't permute
249
+ // prescribed joints, or the bridge won't be usable by the Designer.
250
+ unsigned permute_base = dst->load_scenario.n_prescribed_joints + 1;
251
+ randomly_permute_unsigned(&new_joint_to_old[permute_base], dst->n_joints - permute_base + 1);
252
+ }
253
+
254
+ // Compute inverse map.
255
+ Newz(180, old_joint_to_new, dst->n_joints + 1, unsigned);
256
+ for (joint_index = 1; joint_index <= dst->n_joints; joint_index++)
257
+ old_joint_to_new[new_joint_to_old[joint_index]] = joint_index;
258
+
259
+ // Translate joint numbers in members.
260
+ for (member_index = 1; member_index <= dst->n_members; member_index++) {
261
+ dst->members[member_index].start_joint = old_joint_to_new[dst->members[member_index].start_joint];
262
+ dst->members[member_index].end_joint = old_joint_to_new[dst->members[member_index].end_joint];
263
+ }
264
+
265
+ // Now actually move the joints.
266
+ // Copy from source joints to avoid overlapping moves. Renumber while copying.
267
+ for (joint_index = 1; joint_index <= dst->n_joints; joint_index++) {
268
+ dst->joints[joint_index] = src->joints[new_joint_to_old[joint_index]];
269
+ dst->joints[joint_index].number = joint_index;
270
+ }
271
+
272
+ Safefree(new_joint_to_old);
273
+ Safefree(old_joint_to_new);
274
+
275
+ // Randomly swap joint references.
276
+ for (member_index = 1; member_index <= dst->n_members; member_index++) {
277
+ if (rand() < RAND_MAX/2) {
278
+ TElementNumber j1 = dst->members[member_index].start_joint;
279
+ TElementNumber j2 = dst->members[member_index].end_joint;
280
+ dst->members[member_index].start_joint = j2;
281
+ dst->members[member_index].end_joint = j1;
282
+ }
283
+ }
284
+
285
+ // Now randomize order of members.
286
+ randomly_permute_members(&dst->members[1], dst->n_members);
287
+
288
+ // And renumber members, too.
289
+ for (member_index = 1; member_index <= dst->n_members; member_index++)
290
+ dst->members[member_index].number = member_index;
291
+ }
292
+
@@ -0,0 +1,125 @@
1
+ #include "stdafx.h"
2
+ #include "internal.h"
3
+
4
+ static INLINE FLOAT float_min(FLOAT x, FLOAT y)
5
+ {
6
+ return x < y ? x : y;
7
+ }
8
+
9
+ static INLINE long round_to_long(FLOAT x)
10
+ {
11
+ return ((long)(x + (FLOAT)0.5));
12
+ }
13
+
14
+ // Number of bridge designer grids to use as a margin around the image edge.
15
+ #define SKETCH_MARGIN 3
16
+
17
+ // Number of pixels in a single bridge designer grid.
18
+ #define SKETCH_GRID_SIZE 8
19
+
20
+ #define MAX_NOFORCE_R 192
21
+ #define MAX_NOFORCE_G 192
22
+ #define MAX_NOFORCE_B 192
23
+
24
+ #define MAX_TENSION_R 0
25
+ #define MAX_TENSION_G 0
26
+ #define MAX_TENSION_B 255
27
+
28
+ static void set_tension_color(FLOAT intensity, RGB_TRIPLE *color)
29
+ {
30
+ if (intensity < 0) intensity = 0;
31
+ else if (intensity > 1) intensity = 1;
32
+ color->r = (BYTE)(MAX_TENSION_R * intensity + MAX_NOFORCE_R * (1 - intensity));
33
+ color->g = (BYTE)(MAX_TENSION_G * intensity + MAX_NOFORCE_G * (1 - intensity));
34
+ color->b = (BYTE)(MAX_TENSION_B * intensity + MAX_NOFORCE_B * (1 - intensity));
35
+ }
36
+
37
+ #define MAX_COMPRESSION_R 255
38
+ #define MAX_COMPRESSION_G 0
39
+ #define MAX_COMPRESSION_B 0
40
+
41
+ static void set_compression_color(FLOAT intensity, RGB_TRIPLE *color)
42
+ {
43
+ if (intensity < 0) intensity = 0;
44
+ else if (intensity > 1) intensity = 1;
45
+ color->r = (BYTE)(MAX_COMPRESSION_R * intensity + MAX_NOFORCE_R * (1 - intensity));
46
+ color->g = (BYTE)(MAX_COMPRESSION_G * intensity + MAX_NOFORCE_G * (1 - intensity));
47
+ color->b = (BYTE)(MAX_COMPRESSION_B * intensity + MAX_NOFORCE_B * (1 - intensity));
48
+ }
49
+
50
+ void do_sketch(TBridge *bridge,
51
+ TAnalysis *analysis,
52
+ int width, int height,
53
+ COMPRESSED_IMAGE *compressed_image)
54
+ {
55
+ IMAGE image[1];
56
+ static RGB_TRIPLE white[1] = {{255, 255, 255}};
57
+ static RGB_TRIPLE black[1] = {{0, 0, 0}};
58
+ static RGB_TRIPLE gray[1] = {{192, 192, 192}};
59
+ RGB_TRIPLE color[1];
60
+ UNSIGNED bridge_width_grids;
61
+ UNSIGNED bridge_height_grids;
62
+ UNSIGNED bridge_left_anchorage_margin;
63
+ UNSIGNED bridge_right_anchorage_margin;
64
+ UNSIGNED x_org_pixel;
65
+ UNSIGNED y_org_pixel;
66
+ FLOAT grid_pixels;
67
+ UNSIGNED member_index;
68
+
69
+ init_image(image);
70
+
71
+ // Clear any old image stored in the compressed image data structure.
72
+ clear_compressed_image(compressed_image);
73
+
74
+ // Build a blank white image.
75
+ setup_image(image, width, height, white);
76
+
77
+ // Draw the bridge into the image.
78
+ bridge_width_grids = bridge->load_scenario.num_length_grids;
79
+ bridge_height_grids = bridge->load_scenario.over_grids + bridge->load_scenario.under_grids;
80
+ bridge_left_anchorage_margin = (bridge->load_scenario.support_type & CABLE_SUPPORT_LEFT) ? CABLE_ANCHORAGE_X_OFFSET : 0;
81
+ bridge_right_anchorage_margin = (bridge->load_scenario.support_type & CABLE_SUPPORT_RIGHT) ? CABLE_ANCHORAGE_X_OFFSET : 0;
82
+
83
+ grid_pixels = float_min(width / (float)(bridge_width_grids + bridge_left_anchorage_margin + bridge_right_anchorage_margin + 2 * SKETCH_MARGIN),
84
+ height / (float)(bridge_height_grids + 2 * SKETCH_MARGIN));
85
+
86
+ x_org_pixel = round_to_long( (width - (bridge_width_grids - bridge_left_anchorage_margin + bridge_right_anchorage_margin) * grid_pixels) / 2.0f );
87
+ y_org_pixel = round_to_long( (height - bridge_height_grids * grid_pixels) / 2.0f );
88
+
89
+ #define SKETCH_X(Grid) (x_org_pixel + round_to_long((Grid) * grid_pixels))
90
+ #define SKETCH_Y(Grid) (y_org_pixel + round_to_long(((Grid) + bridge->load_scenario.under_grids) * grid_pixels))
91
+
92
+ draw_rect_raw(image,
93
+ SKETCH_X(0), SKETCH_Y(-(int)bridge->load_scenario.under_grids),
94
+ SKETCH_X(bridge->load_scenario.num_length_grids), SKETCH_Y(bridge->load_scenario.over_grids),
95
+ gray);
96
+
97
+ for (member_index = 1; member_index <= bridge->n_members; member_index++) {
98
+
99
+ TMember *m = &bridge->members[member_index];
100
+ TJoint *j1 = &bridge->joints[m->start_joint];
101
+ TJoint *j2 = &bridge->joints[m->end_joint];
102
+
103
+ if (analysis->member_strength[member_index].compressive_fail_mode == FailModeSlenderness) {
104
+ color->r = color->b = 255;
105
+ color->g = 0;
106
+ }
107
+ else {
108
+ TFloat compressive = analysis->member_strength[member_index].compressive;
109
+ TFloat compression_intensity = compressive > 0 ? analysis->max_forces[member_index].compression / compressive : 0;
110
+
111
+ TFloat tensile = analysis->member_strength[member_index].tensile;
112
+ TFloat tension_intensity = tensile > 0 ? analysis->max_forces[member_index].tension / tensile : 0;
113
+
114
+ if (compression_intensity > tension_intensity)
115
+ set_compression_color((FLOAT)compression_intensity, color);
116
+ else
117
+ set_tension_color((FLOAT)tension_intensity, color);
118
+ }
119
+ draw_line_raw(image, SKETCH_X(j1->x), SKETCH_Y(j1->y), SKETCH_X(j2->x), SKETCH_Y(j2->y), color);
120
+ }
121
+ // Compress the image.
122
+ compress_image(image, compressed_image);
123
+ clear_image(image);
124
+ }
125
+
@@ -0,0 +1,5 @@
1
+ require 'mkmf'
2
+
3
+ have_library("png", "png_create_write_struct_2")
4
+ have_library("z", "zlibVersion")
5
+ create_makefile('WPBDC/WPBDC')
@@ -0,0 +1,46 @@
1
+ #include "stdafx.h"
2
+ #include "internal.h"
3
+
4
+ // Bridge geometry -------------------------------------------------------------
5
+
6
+ // Initialize a geometry.
7
+ void init_geometry(TGeometry *geometry)
8
+ {
9
+ memset(geometry, 0, sizeof(*geometry));
10
+ }
11
+
12
+ // Free storage of a geometry and re-initialize it.
13
+ void clear_geometry(TGeometry *geometry)
14
+ {
15
+ Safefree(geometry->cos_x);
16
+ Safefree(geometry->cos_y);
17
+ Safefree(geometry->length);
18
+ init_geometry(geometry);
19
+ }
20
+
21
+ // Fill in a geometry by calculation from given bridge.
22
+ void setup_geometry(TGeometry *geometry, TBridge *bridge)
23
+ {
24
+ unsigned member_index;
25
+
26
+ clear_geometry(geometry);
27
+
28
+ Newz(210, geometry->length, bridge->n_members + 1, TFloat);
29
+ Newz(220, geometry->cos_x, bridge->n_members + 1, TFloat);
30
+ Newz(230, geometry->cos_y, bridge->n_members + 1, TFloat);
31
+
32
+ // Convert grid coords to physical world coords.
33
+ #define World(Grid) ((Grid) * bridge->load_scenario.grid_size)
34
+
35
+ for (member_index = 1; member_index <= bridge->n_members; member_index++) {
36
+ TJoint *start = &bridge->joints[bridge->members[member_index].start_joint];
37
+ TJoint *end = &bridge->joints[bridge->members[member_index].end_joint];
38
+ TFloat dx = World(end->x - start->x);
39
+ TFloat dy = World(end->y - start->y);
40
+ TFloat len = sqrt(dx * dx + dy * dy);
41
+ geometry->length[member_index] = len;
42
+ geometry->cos_x[member_index] = dx / len;
43
+ geometry->cos_y[member_index] = dy / len;
44
+ }
45
+ }
46
+