1
/* ADMesh -- process triangulated solid meshes
2
* Copyright (C) 1995, 1996 Anthony D. Martin
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; either version 2, or (at your option)
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
* Questions, comments, suggestions, etc to <amartin@engr.csulb.edu>
28
static void stl_rotate(float *x, float *y, float angle);
29
static float get_area(stl_facet *facet);
30
static float get_volume(stl_file *stl);
34
stl_verify_neighbors(stl_file *stl)
43
stl->stats.backwards_edges = 0;
45
for(i = 0; i < stl->stats.number_of_facets; i++)
47
for(j = 0; j < 3; j++)
49
edge_a.p1 = stl->facet_start[i].vertex[j];
50
edge_a.p2 = stl->facet_start[i].vertex[(j + 1) % 3];
51
neighbor = stl->neighbors_start[i].neighbor[j];
52
vnot = stl->neighbors_start[i].which_vertex_not[j];
55
continue; /* this edge has no neighbor... Continue. */
58
edge_b.p1 = stl->facet_start[neighbor].vertex[(vnot + 2) % 3];
59
edge_b.p2 = stl->facet_start[neighbor].vertex[(vnot + 1) % 3];
63
stl->stats.backwards_edges += 1;
64
edge_b.p1 = stl->facet_start[neighbor].vertex[(vnot + 1) % 3];
65
edge_b.p2 = stl->facet_start[neighbor].vertex[(vnot + 2) % 3];
67
if(memcmp(&edge_a, &edge_b, SIZEOF_EDGE_SORT) != 0)
69
/* These edges should match but they don't. Print results. */
70
printf("edge %d of facet %d doesn't match edge %d of facet %d\n",
71
j, i, vnot + 1, neighbor);
72
stl_write_facet(stl, (char*)"first facet", i);
73
stl_write_facet(stl, (char*)"second facet", neighbor);
80
stl_translate_relative(stl_file *stl, float x, float y, float z)
85
for(i = 0; i < stl->stats.number_of_facets; i++)
87
for(j = 0; j < 3; j++)
89
stl->facet_start[i].vertex[j].x += x;
90
stl->facet_start[i].vertex[j].y += y;
91
stl->facet_start[i].vertex[j].z += z;
94
stl->stats.min.x += x;
95
stl->stats.min.y += y;
96
stl->stats.min.z += z;
97
stl->stats.max.x += x;
98
stl->stats.max.y += y;
99
stl->stats.max.z += z;
101
stl_invalidate_shared_vertices(stl);
105
stl_scale_versor(stl_file *stl, float versor[3])
111
stl->stats.min.x *= versor[0];
112
stl->stats.min.y *= versor[1];
113
stl->stats.min.z *= versor[2];
114
stl->stats.max.x *= versor[0];
115
stl->stats.max.y *= versor[1];
116
stl->stats.max.z *= versor[2];
119
stl->stats.size.x *= versor[0];
120
stl->stats.size.y *= versor[1];
121
stl->stats.size.z *= versor[2];
124
if (stl->stats.volume > 0.0) {
125
stl->stats.volume *= (versor[0] * versor[1] * versor[2]);
128
for(i = 0; i < stl->stats.number_of_facets; i++)
130
for(j = 0; j < 3; j++)
132
stl->facet_start[i].vertex[j].x *= versor[0];
133
stl->facet_start[i].vertex[j].y *= versor[1];
134
stl->facet_start[i].vertex[j].z *= versor[2];
138
stl_invalidate_shared_vertices(stl);
142
stl_scale(stl_file *stl, float factor)
148
stl_scale_versor(stl, versor);
151
static void calculate_normals(stl_file *stl)
156
for(i = 0; i < stl->stats.number_of_facets; i++){
157
stl_calculate_normal(normal, &stl->facet_start[i]);
158
stl_normalize_vector(normal);
159
stl->facet_start[i].normal.x = normal[0];
160
stl->facet_start[i].normal.y = normal[1];
161
stl->facet_start[i].normal.z = normal[2];
166
stl_rotate_x(stl_file *stl, float angle)
171
for(i = 0; i < stl->stats.number_of_facets; i++)
173
for(j = 0; j < 3; j++)
175
stl_rotate(&stl->facet_start[i].vertex[j].y,
176
&stl->facet_start[i].vertex[j].z, angle);
180
calculate_normals(stl);
184
stl_rotate_y(stl_file *stl, float angle)
189
for(i = 0; i < stl->stats.number_of_facets; i++)
191
for(j = 0; j < 3; j++)
193
stl_rotate(&stl->facet_start[i].vertex[j].z,
194
&stl->facet_start[i].vertex[j].x, angle);
198
calculate_normals(stl);
202
stl_rotate_z(stl_file *stl, float angle)
207
for(i = 0; i < stl->stats.number_of_facets; i++)
209
for(j = 0; j < 3; j++)
211
stl_rotate(&stl->facet_start[i].vertex[j].x,
212
&stl->facet_start[i].vertex[j].y, angle);
216
calculate_normals(stl);
222
stl_rotate(float *x, float *y, float angle)
228
radian_angle = (angle / 180.0) * M_PI;
230
r = sqrt((*x * *x) + (*y * *y));
231
theta = atan2(*y, *x);
232
*x = r * cos(theta + radian_angle);
233
*y = r * sin(theta + radian_angle);
237
stl_get_size(stl_file *stl)
239
if (stl->stats.number_of_facets == 0) return;
244
stl->stats.min.x = stl->facet_start[0].vertex[0].x;
245
stl->stats.min.y = stl->facet_start[0].vertex[0].y;
246
stl->stats.min.z = stl->facet_start[0].vertex[0].z;
247
stl->stats.max.x = stl->facet_start[0].vertex[0].x;
248
stl->stats.max.y = stl->facet_start[0].vertex[0].y;
249
stl->stats.max.z = stl->facet_start[0].vertex[0].z;
251
for(i = 0; i < stl->stats.number_of_facets; i++)
253
for(j = 0; j < 3; j++)
255
stl->stats.min.x = STL_MIN(stl->stats.min.x,
256
stl->facet_start[i].vertex[j].x);
257
stl->stats.min.y = STL_MIN(stl->stats.min.y,
258
stl->facet_start[i].vertex[j].y);
259
stl->stats.min.z = STL_MIN(stl->stats.min.z,
260
stl->facet_start[i].vertex[j].z);
261
stl->stats.max.x = STL_MAX(stl->stats.max.x,
262
stl->facet_start[i].vertex[j].x);
263
stl->stats.max.y = STL_MAX(stl->stats.max.y,
264
stl->facet_start[i].vertex[j].y);
265
stl->stats.max.z = STL_MAX(stl->stats.max.z,
266
stl->facet_start[i].vertex[j].z);
269
stl->stats.size.x = stl->stats.max.x - stl->stats.min.x;
270
stl->stats.size.y = stl->stats.max.y - stl->stats.min.y;
271
stl->stats.size.z = stl->stats.max.z - stl->stats.min.z;
272
stl->stats.bounding_diameter = sqrt(
273
stl->stats.size.x * stl->stats.size.x +
274
stl->stats.size.y * stl->stats.size.y +
275
stl->stats.size.z * stl->stats.size.z
280
stl_mirror_xy(stl_file *stl)
286
for(i = 0; i < stl->stats.number_of_facets; i++)
288
for(j = 0; j < 3; j++)
290
stl->facet_start[i].vertex[j].z *= -1.0;
293
temp_size = stl->stats.min.z;
294
stl->stats.min.z = stl->stats.max.z;
295
stl->stats.max.z = temp_size;
296
stl->stats.min.z *= -1.0;
297
stl->stats.max.z *= -1.0;
301
stl_mirror_yz(stl_file *stl)
307
for(i = 0; i < stl->stats.number_of_facets; i++)
309
for(j = 0; j < 3; j++)
311
stl->facet_start[i].vertex[j].x *= -1.0;
314
temp_size = stl->stats.min.x;
315
stl->stats.min.x = stl->stats.max.x;
316
stl->stats.max.x = temp_size;
317
stl->stats.min.x *= -1.0;
318
stl->stats.max.x *= -1.0;
322
stl_mirror_xz(stl_file *stl)
328
for(i = 0; i < stl->stats.number_of_facets; i++)
330
for(j = 0; j < 3; j++)
332
stl->facet_start[i].vertex[j].y *= -1.0;
335
temp_size = stl->stats.min.y;
336
stl->stats.min.y = stl->stats.max.y;
337
stl->stats.max.y = temp_size;
338
stl->stats.min.y *= -1.0;
339
stl->stats.max.y *= -1.0;
342
static float get_volume(stl_file *stl)
352
/* Choose a point, any point as the reference */
353
p0.x = stl->facet_start[0].vertex[0].x;
354
p0.y = stl->facet_start[0].vertex[0].y;
355
p0.z = stl->facet_start[0].vertex[0].z;
357
for(i = 0; i < stl->stats.number_of_facets; i++){
358
p.x = stl->facet_start[i].vertex[0].x - p0.x;
359
p.y = stl->facet_start[i].vertex[0].y - p0.y;
360
p.z = stl->facet_start[i].vertex[0].z - p0.z;
361
/* Do dot product to get distance from point to plane */
362
n = stl->facet_start[i].normal;
363
height = (n.x * p.x) + (n.y * p.y) + (n.z * p.z);
364
area = get_area(&stl->facet_start[i]);
365
volume += (area * height) / 3.0;
370
void stl_calculate_volume(stl_file *stl)
372
stl->stats.volume = get_volume(stl);
373
if(stl->stats.volume < 0.0){
374
stl_reverse_all_facets(stl);
375
stl->stats.volume = -stl->stats.volume;
379
static float get_area(stl_facet *facet)
387
// cast to double before calculating cross product because large coordinates
388
// can result in overflowing product
389
// (bad area is responsible for bad volume and bad facets reversal)
390
for(i = 0; i < 3; i++){
391
cross[i][0]=(((double)facet->vertex[i].y * (double)facet->vertex[(i + 1) % 3].z) -
392
((double)facet->vertex[i].z * (double)facet->vertex[(i + 1) % 3].y));
393
cross[i][1]=(((double)facet->vertex[i].z * (double)facet->vertex[(i + 1) % 3].x) -
394
((double)facet->vertex[i].x * (double)facet->vertex[(i + 1) % 3].z));
395
cross[i][2]=(((double)facet->vertex[i].x * (double)facet->vertex[(i + 1) % 3].y) -
396
((double)facet->vertex[i].y * (double)facet->vertex[(i + 1) % 3].x));
399
sum[0] = cross[0][0] + cross[1][0] + cross[2][0];
400
sum[1] = cross[0][1] + cross[1][1] + cross[2][1];
401
sum[2] = cross[0][2] + cross[1][2] + cross[2][2];
403
/* This should already be done. But just in case, let's do it again */
404
stl_calculate_normal(n, facet);
405
stl_normalize_vector(n);
407
area = 0.5 * (n[0] * sum[0] + n[1] * sum[1] + n[2] * sum[2]);