connect.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988
  1. /* ADMesh -- process triangulated solid meshes
  2. * Copyright (C) 1995, 1996 Anthony D. Martin <amartin@engr.csulb.edu>
  3. * Copyright (C) 2013, 2014 several contributors, see AUTHORS
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  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.
  13. * You should have received a copy of the GNU General Public License along
  14. * with this program; if not, write to the Free Software Foundation, Inc.,
  15. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  16. *
  17. * Questions, comments, suggestions, etc to
  18. * https://github.com/admesh/admesh/issues
  19. */
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <math.h>
  24. #include "stl.h"
  25. static void stl_match_neighbors_exact(stl_file *stl,
  26. stl_hash_edge *edge_a, stl_hash_edge *edge_b);
  27. static void stl_match_neighbors_nearby(stl_file *stl,
  28. stl_hash_edge *edge_a, stl_hash_edge *edge_b);
  29. static void stl_record_neighbors(stl_file *stl,
  30. stl_hash_edge *edge_a, stl_hash_edge *edge_b);
  31. static void stl_initialize_facet_check_exact(stl_file *stl);
  32. static void stl_initialize_facet_check_nearby(stl_file *stl);
  33. static void stl_load_edge_exact(stl_file *stl, stl_hash_edge *edge,
  34. stl_vertex *a, stl_vertex *b);
  35. static int stl_load_edge_nearby(stl_file *stl, stl_hash_edge *edge,
  36. stl_vertex *a, stl_vertex *b, float tolerance);
  37. static void insert_hash_edge(stl_file *stl, stl_hash_edge edge,
  38. void (*match_neighbors)(stl_file *stl,
  39. stl_hash_edge *edge_a, stl_hash_edge *edge_b));
  40. static int stl_get_hash_for_edge(int M, stl_hash_edge *edge);
  41. static int stl_compare_function(stl_hash_edge *edge_a, stl_hash_edge *edge_b);
  42. static void stl_free_edges(stl_file *stl);
  43. static void stl_remove_facet(stl_file *stl, int facet_number);
  44. static void stl_change_vertices(stl_file *stl, int facet_num, int vnot,
  45. stl_vertex new_vertex);
  46. static void stl_which_vertices_to_change(stl_file *stl, stl_hash_edge *edge_a,
  47. stl_hash_edge *edge_b, int *facet1, int *vertex1,
  48. int *facet2, int *vertex2,
  49. stl_vertex *new_vertex1, stl_vertex *new_vertex2);
  50. static void stl_remove_degenerate(stl_file *stl, int facet);
  51. extern int stl_check_normal_vector(stl_file *stl,
  52. int facet_num, int normal_fix_flag);
  53. static void stl_update_connects_remove_1(stl_file *stl, int facet_num);
  54. void
  55. stl_check_facets_exact(stl_file *stl) {
  56. /* This function builds the neighbors list. No modifications are made
  57. * to any of the facets. The edges are said to match only if all six
  58. * floats of the first edge matches all six floats of the second edge.
  59. */
  60. stl_hash_edge edge;
  61. stl_facet facet;
  62. int i;
  63. int j;
  64. if (stl->error) return;
  65. stl->stats.connected_edges = 0;
  66. stl->stats.connected_facets_1_edge = 0;
  67. stl->stats.connected_facets_2_edge = 0;
  68. stl->stats.connected_facets_3_edge = 0;
  69. stl_initialize_facet_check_exact(stl);
  70. for(i = 0; i < stl->stats.number_of_facets; i++) {
  71. facet = stl->facet_start[i];
  72. // Positive and negative zeros are possible in the floats, which are considered equal by the FP unit.
  73. // When using a memcmp on raw floats, those numbers report to be different.
  74. // Unify all +0 and -0 to +0 to make the floats equal under memcmp.
  75. {
  76. uint32_t *f = (uint32_t*)&facet;
  77. for (int j = 0; j < 12; ++ j, ++ f) // 3x vertex + normal: 4x3 = 12 floats
  78. if (*f == 0x80000000)
  79. // Negative zero, switch to positive zero.
  80. *f = 0;
  81. }
  82. /* If any two of the three vertices are found to be exactally the same, call them degenerate and remove the facet. */
  83. if( !memcmp(&facet.vertex[0], &facet.vertex[1],
  84. sizeof(stl_vertex))
  85. || !memcmp(&facet.vertex[1], &facet.vertex[2],
  86. sizeof(stl_vertex))
  87. || !memcmp(&facet.vertex[0], &facet.vertex[2],
  88. sizeof(stl_vertex))) {
  89. stl->stats.degenerate_facets += 1;
  90. stl_remove_facet(stl, i);
  91. i--;
  92. continue;
  93. }
  94. for(j = 0; j < 3; j++) {
  95. edge.facet_number = i;
  96. edge.which_edge = j;
  97. stl_load_edge_exact(stl, &edge, &facet.vertex[j],
  98. &facet.vertex[(j + 1) % 3]);
  99. insert_hash_edge(stl, edge, stl_match_neighbors_exact);
  100. }
  101. }
  102. stl_free_edges(stl);
  103. #if 0
  104. printf("Number of faces: %d, number of manifold edges: %d, number of connected edges: %d, number of unconnected edges: %d\r\n",
  105. stl->stats.number_of_facets, stl->stats.number_of_facets * 3,
  106. stl->stats.connected_edges, stl->stats.number_of_facets * 3 - stl->stats.connected_edges);
  107. #endif
  108. }
  109. static void
  110. stl_load_edge_exact(stl_file *stl, stl_hash_edge *edge,
  111. stl_vertex *a, stl_vertex *b) {
  112. if (stl->error) return;
  113. {
  114. float diff_x = ABS(a->x - b->x);
  115. float diff_y = ABS(a->y - b->y);
  116. float diff_z = ABS(a->z - b->z);
  117. float max_diff = STL_MAX(diff_x, diff_y);
  118. max_diff = STL_MAX(diff_z, max_diff);
  119. stl->stats.shortest_edge = STL_MIN(max_diff, stl->stats.shortest_edge);
  120. }
  121. // Ensure identical vertex ordering of equal edges.
  122. // This method is numerically robust.
  123. if ((a->x != b->x) ?
  124. (a->x < b->x) :
  125. ((a->y != b->y) ?
  126. (a->y < b->y) :
  127. (a->z < b->z))) {
  128. memcpy(&edge->key[0], a, sizeof(stl_vertex));
  129. memcpy(&edge->key[3], b, sizeof(stl_vertex));
  130. } else {
  131. memcpy(&edge->key[0], b, sizeof(stl_vertex));
  132. memcpy(&edge->key[3], a, sizeof(stl_vertex));
  133. edge->which_edge += 3; /* this edge is loaded backwards */
  134. }
  135. }
  136. static void
  137. stl_initialize_facet_check_exact(stl_file *stl) {
  138. int i;
  139. if (stl->error) return;
  140. stl->stats.malloced = 0;
  141. stl->stats.freed = 0;
  142. stl->stats.collisions = 0;
  143. stl->M = 81397;
  144. for(i = 0; i < stl->stats.number_of_facets ; i++) {
  145. /* initialize neighbors list to -1 to mark unconnected edges */
  146. stl->neighbors_start[i].neighbor[0] = -1;
  147. stl->neighbors_start[i].neighbor[1] = -1;
  148. stl->neighbors_start[i].neighbor[2] = -1;
  149. }
  150. stl->heads = (stl_hash_edge**)calloc(stl->M, sizeof(*stl->heads));
  151. if(stl->heads == NULL) perror("stl_initialize_facet_check_exact");
  152. stl->tail = (stl_hash_edge*)malloc(sizeof(stl_hash_edge));
  153. if(stl->tail == NULL) perror("stl_initialize_facet_check_exact");
  154. stl->tail->next = stl->tail;
  155. for(i = 0; i < stl->M; i++) {
  156. stl->heads[i] = stl->tail;
  157. }
  158. }
  159. static void
  160. insert_hash_edge(stl_file *stl, stl_hash_edge edge,
  161. void (*match_neighbors)(stl_file *stl,
  162. stl_hash_edge *edge_a, stl_hash_edge *edge_b)) {
  163. stl_hash_edge *link;
  164. stl_hash_edge *new_edge;
  165. stl_hash_edge *temp;
  166. int chain_number;
  167. if (stl->error) return;
  168. chain_number = stl_get_hash_for_edge(stl->M, &edge);
  169. link = stl->heads[chain_number];
  170. if(link == stl->tail) {
  171. /* This list doesn't have any edges currently in it. Add this one. */
  172. new_edge = (stl_hash_edge*)malloc(sizeof(stl_hash_edge));
  173. if(new_edge == NULL) perror("insert_hash_edge");
  174. stl->stats.malloced++;
  175. *new_edge = edge;
  176. new_edge->next = stl->tail;
  177. stl->heads[chain_number] = new_edge;
  178. return;
  179. } else if(!stl_compare_function(&edge, link)) {
  180. /* This is a match. Record result in neighbors list. */
  181. match_neighbors(stl, &edge, link);
  182. /* Delete the matched edge from the list. */
  183. stl->heads[chain_number] = link->next;
  184. free(link);
  185. stl->stats.freed++;
  186. return;
  187. } else {
  188. /* Continue through the rest of the list */
  189. for(;;) {
  190. if(link->next == stl->tail) {
  191. /* This is the last item in the list. Insert a new edge. */
  192. new_edge = (stl_hash_edge*)malloc(sizeof(stl_hash_edge));
  193. if(new_edge == NULL) perror("insert_hash_edge");
  194. stl->stats.malloced++;
  195. *new_edge = edge;
  196. new_edge->next = stl->tail;
  197. link->next = new_edge;
  198. stl->stats.collisions++;
  199. return;
  200. } else if(!stl_compare_function(&edge, link->next)) {
  201. /* This is a match. Record result in neighbors list. */
  202. match_neighbors(stl, &edge, link->next);
  203. /* Delete the matched edge from the list. */
  204. temp = link->next;
  205. link->next = link->next->next;
  206. free(temp);
  207. stl->stats.freed++;
  208. return;
  209. } else {
  210. /* This is not a match. Go to the next link */
  211. link = link->next;
  212. stl->stats.collisions++;
  213. }
  214. }
  215. }
  216. }
  217. static int
  218. stl_get_hash_for_edge(int M, stl_hash_edge *edge) {
  219. return ((edge->key[0] / 23 + edge->key[1] / 19 + edge->key[2] / 17
  220. + edge->key[3] /13 + edge->key[4] / 11 + edge->key[5] / 7 ) % M);
  221. }
  222. static int
  223. stl_compare_function(stl_hash_edge *edge_a, stl_hash_edge *edge_b) {
  224. if(edge_a->facet_number == edge_b->facet_number) {
  225. return 1; /* Don't match edges of the same facet */
  226. } else {
  227. return memcmp(edge_a, edge_b, SIZEOF_EDGE_SORT);
  228. }
  229. }
  230. void
  231. stl_check_facets_nearby(stl_file *stl, float tolerance) {
  232. stl_hash_edge edge[3];
  233. stl_facet facet;
  234. int i;
  235. int j;
  236. if (stl->error) return;
  237. if( (stl->stats.connected_facets_1_edge == stl->stats.number_of_facets)
  238. && (stl->stats.connected_facets_2_edge == stl->stats.number_of_facets)
  239. && (stl->stats.connected_facets_3_edge == stl->stats.number_of_facets)) {
  240. /* No need to check any further. All facets are connected */
  241. return;
  242. }
  243. stl_initialize_facet_check_nearby(stl);
  244. for(i = 0; i < stl->stats.number_of_facets; i++) {
  245. facet = stl->facet_start[i];
  246. // Positive and negative zeros are possible in the floats, which are considered equal by the FP unit.
  247. // When using a memcmp on raw floats, those numbers report to be different.
  248. // Unify all +0 and -0 to +0 to make the floats equal under memcmp.
  249. {
  250. uint32_t *f = (uint32_t*)&facet;
  251. for (int j = 0; j < 12; ++ j, ++ f) // 3x vertex + normal: 4x3 = 12 floats
  252. if (*f == 0x80000000)
  253. // Negative zero, switch to positive zero.
  254. *f = 0;
  255. }
  256. for(j = 0; j < 3; j++) {
  257. if(stl->neighbors_start[i].neighbor[j] == -1) {
  258. edge[j].facet_number = i;
  259. edge[j].which_edge = j;
  260. if(stl_load_edge_nearby(stl, &edge[j], &facet.vertex[j],
  261. &facet.vertex[(j + 1) % 3],
  262. tolerance)) {
  263. /* only insert edges that have different keys */
  264. insert_hash_edge(stl, edge[j], stl_match_neighbors_nearby);
  265. }
  266. }
  267. }
  268. }
  269. stl_free_edges(stl);
  270. }
  271. static int
  272. stl_load_edge_nearby(stl_file *stl, stl_hash_edge *edge,
  273. stl_vertex *a, stl_vertex *b, float tolerance) {
  274. // Index of a grid cell spaced by tolerance.
  275. uint32_t vertex1[3] = {
  276. (uint32_t)((a->x - stl->stats.min.x) / tolerance),
  277. (uint32_t)((a->y - stl->stats.min.y) / tolerance),
  278. (uint32_t)((a->z - stl->stats.min.z) / tolerance)
  279. };
  280. uint32_t vertex2[3] = {
  281. (uint32_t)((b->x - stl->stats.min.x) / tolerance),
  282. (uint32_t)((b->y - stl->stats.min.y) / tolerance),
  283. (uint32_t)((b->z - stl->stats.min.z) / tolerance)
  284. };
  285. if( (vertex1[0] == vertex2[0])
  286. && (vertex1[1] == vertex2[1])
  287. && (vertex1[2] == vertex2[2])) {
  288. /* Both vertices hash to the same value */
  289. return 0;
  290. }
  291. // Ensure identical vertex ordering of edges, which vertices land into equal grid cells.
  292. // This method is numerically robust.
  293. if ((vertex1[0] != vertex2[0]) ?
  294. (vertex1[0] < vertex2[0]) :
  295. ((vertex1[1] != vertex2[1]) ?
  296. (vertex1[1] < vertex2[1]) :
  297. (vertex1[2] < vertex2[2]))) {
  298. memcpy(&edge->key[0], vertex1, sizeof(stl_vertex));
  299. memcpy(&edge->key[3], vertex2, sizeof(stl_vertex));
  300. } else {
  301. memcpy(&edge->key[0], vertex2, sizeof(stl_vertex));
  302. memcpy(&edge->key[3], vertex1, sizeof(stl_vertex));
  303. edge->which_edge += 3; /* this edge is loaded backwards */
  304. }
  305. return 1;
  306. }
  307. static void
  308. stl_free_edges(stl_file *stl) {
  309. int i;
  310. stl_hash_edge *temp;
  311. if (stl->error) return;
  312. if(stl->stats.malloced != stl->stats.freed) {
  313. for(i = 0; i < stl->M; i++) {
  314. for(temp = stl->heads[i]; stl->heads[i] != stl->tail;
  315. temp = stl->heads[i]) {
  316. stl->heads[i] = stl->heads[i]->next;
  317. free(temp);
  318. stl->stats.freed++;
  319. }
  320. }
  321. }
  322. free(stl->heads);
  323. free(stl->tail);
  324. }
  325. static void
  326. stl_initialize_facet_check_nearby(stl_file *stl) {
  327. int i;
  328. if (stl->error) return;
  329. stl->stats.malloced = 0;
  330. stl->stats.freed = 0;
  331. stl->stats.collisions = 0;
  332. /* tolerance = STL_MAX(stl->stats.shortest_edge, tolerance);*/
  333. /* tolerance = STL_MAX((stl->stats.bounding_diameter / 500000.0), tolerance);*/
  334. /* tolerance *= 0.5;*/
  335. stl->M = 81397;
  336. stl->heads = (stl_hash_edge**)calloc(stl->M, sizeof(*stl->heads));
  337. if(stl->heads == NULL) perror("stl_initialize_facet_check_nearby");
  338. stl->tail = (stl_hash_edge*)malloc(sizeof(stl_hash_edge));
  339. if(stl->tail == NULL) perror("stl_initialize_facet_check_nearby");
  340. stl->tail->next = stl->tail;
  341. for(i = 0; i < stl->M; i++) {
  342. stl->heads[i] = stl->tail;
  343. }
  344. }
  345. static void
  346. stl_record_neighbors(stl_file *stl,
  347. stl_hash_edge *edge_a, stl_hash_edge *edge_b) {
  348. int i;
  349. int j;
  350. if (stl->error) return;
  351. /* Facet a's neighbor is facet b */
  352. stl->neighbors_start[edge_a->facet_number].neighbor[edge_a->which_edge % 3] =
  353. edge_b->facet_number; /* sets the .neighbor part */
  354. stl->neighbors_start[edge_a->facet_number].
  355. which_vertex_not[edge_a->which_edge % 3] =
  356. (edge_b->which_edge + 2) % 3; /* sets the .which_vertex_not part */
  357. /* Facet b's neighbor is facet a */
  358. stl->neighbors_start[edge_b->facet_number].neighbor[edge_b->which_edge % 3] =
  359. edge_a->facet_number; /* sets the .neighbor part */
  360. stl->neighbors_start[edge_b->facet_number].
  361. which_vertex_not[edge_b->which_edge % 3] =
  362. (edge_a->which_edge + 2) % 3; /* sets the .which_vertex_not part */
  363. if( ((edge_a->which_edge < 3) && (edge_b->which_edge < 3))
  364. || ((edge_a->which_edge > 2) && (edge_b->which_edge > 2))) {
  365. /* these facets are oriented in opposite directions. */
  366. /* their normals are probably messed up. */
  367. stl->neighbors_start[edge_a->facet_number].
  368. which_vertex_not[edge_a->which_edge % 3] += 3;
  369. stl->neighbors_start[edge_b->facet_number].
  370. which_vertex_not[edge_b->which_edge % 3] += 3;
  371. }
  372. /* Count successful connects */
  373. /* Total connects */
  374. stl->stats.connected_edges += 2;
  375. /* Count individual connects */
  376. i = ((stl->neighbors_start[edge_a->facet_number].neighbor[0] == -1) +
  377. (stl->neighbors_start[edge_a->facet_number].neighbor[1] == -1) +
  378. (stl->neighbors_start[edge_a->facet_number].neighbor[2] == -1));
  379. j = ((stl->neighbors_start[edge_b->facet_number].neighbor[0] == -1) +
  380. (stl->neighbors_start[edge_b->facet_number].neighbor[1] == -1) +
  381. (stl->neighbors_start[edge_b->facet_number].neighbor[2] == -1));
  382. if(i == 2) {
  383. stl->stats.connected_facets_1_edge +=1;
  384. } else if(i == 1) {
  385. stl->stats.connected_facets_2_edge +=1;
  386. } else {
  387. stl->stats.connected_facets_3_edge +=1;
  388. }
  389. if(j == 2) {
  390. stl->stats.connected_facets_1_edge +=1;
  391. } else if(j == 1) {
  392. stl->stats.connected_facets_2_edge +=1;
  393. } else {
  394. stl->stats.connected_facets_3_edge +=1;
  395. }
  396. }
  397. static void
  398. stl_match_neighbors_exact(stl_file *stl,
  399. stl_hash_edge *edge_a, stl_hash_edge *edge_b) {
  400. if (stl->error) return;
  401. stl_record_neighbors(stl, edge_a, edge_b);
  402. }
  403. static void
  404. stl_match_neighbors_nearby(stl_file *stl,
  405. stl_hash_edge *edge_a, stl_hash_edge *edge_b) {
  406. int facet1;
  407. int facet2;
  408. int vertex1;
  409. int vertex2;
  410. int vnot1;
  411. int vnot2;
  412. stl_vertex new_vertex1;
  413. stl_vertex new_vertex2;
  414. if (stl->error) return;
  415. stl_record_neighbors(stl, edge_a, edge_b);
  416. stl_which_vertices_to_change(stl, edge_a, edge_b, &facet1, &vertex1,
  417. &facet2, &vertex2, &new_vertex1, &new_vertex2);
  418. if(facet1 != -1) {
  419. if(facet1 == edge_a->facet_number) {
  420. vnot1 = (edge_a->which_edge + 2) % 3;
  421. } else {
  422. vnot1 = (edge_b->which_edge + 2) % 3;
  423. }
  424. if(((vnot1 + 2) % 3) == vertex1) {
  425. vnot1 += 3;
  426. }
  427. stl_change_vertices(stl, facet1, vnot1, new_vertex1);
  428. }
  429. if(facet2 != -1) {
  430. if(facet2 == edge_a->facet_number) {
  431. vnot2 = (edge_a->which_edge + 2) % 3;
  432. } else {
  433. vnot2 = (edge_b->which_edge + 2) % 3;
  434. }
  435. if(((vnot2 + 2) % 3) == vertex2) {
  436. vnot2 += 3;
  437. }
  438. stl_change_vertices(stl, facet2, vnot2, new_vertex2);
  439. }
  440. stl->stats.edges_fixed += 2;
  441. }
  442. static void
  443. stl_change_vertices(stl_file *stl, int facet_num, int vnot,
  444. stl_vertex new_vertex) {
  445. int first_facet;
  446. int direction;
  447. int next_edge;
  448. int pivot_vertex;
  449. if (stl->error) return;
  450. first_facet = facet_num;
  451. direction = 0;
  452. for(;;) {
  453. if(vnot > 2) {
  454. if(direction == 0) {
  455. pivot_vertex = (vnot + 2) % 3;
  456. next_edge = pivot_vertex;
  457. direction = 1;
  458. } else {
  459. pivot_vertex = (vnot + 1) % 3;
  460. next_edge = vnot % 3;
  461. direction = 0;
  462. }
  463. } else {
  464. if(direction == 0) {
  465. pivot_vertex = (vnot + 1) % 3;
  466. next_edge = vnot;
  467. } else {
  468. pivot_vertex = (vnot + 2) % 3;
  469. next_edge = pivot_vertex;
  470. }
  471. }
  472. #if 0
  473. if (stl->facet_start[facet_num].vertex[pivot_vertex].x == new_vertex.x &&
  474. stl->facet_start[facet_num].vertex[pivot_vertex].y == new_vertex.y &&
  475. stl->facet_start[facet_num].vertex[pivot_vertex].z == new_vertex.z)
  476. printf("Changing vertex %f,%f,%f: Same !!!\r\n",
  477. new_vertex.x, new_vertex.y, new_vertex.z);
  478. else {
  479. if (stl->facet_start[facet_num].vertex[pivot_vertex].x != new_vertex.x)
  480. printf("Changing coordinate x, vertex %e (0x%08x) to %e(0x%08x)\r\n",
  481. stl->facet_start[facet_num].vertex[pivot_vertex].x,
  482. *reinterpret_cast<const int*>(&stl->facet_start[facet_num].vertex[pivot_vertex].x),
  483. new_vertex.x,
  484. *reinterpret_cast<const int*>(&new_vertex.x));
  485. if (stl->facet_start[facet_num].vertex[pivot_vertex].y != new_vertex.y)
  486. printf("Changing coordinate x, vertex %e (0x%08x) to %e(0x%08x)\r\n",
  487. stl->facet_start[facet_num].vertex[pivot_vertex].y,
  488. *reinterpret_cast<const int*>(&stl->facet_start[facet_num].vertex[pivot_vertex].y),
  489. new_vertex.y,
  490. *reinterpret_cast<const int*>(&new_vertex.y));
  491. if (stl->facet_start[facet_num].vertex[pivot_vertex].z != new_vertex.z)
  492. printf("Changing coordinate x, vertex %e (0x%08x) to %e(0x%08x)\r\n",
  493. stl->facet_start[facet_num].vertex[pivot_vertex].z,
  494. *reinterpret_cast<const int*>(&stl->facet_start[facet_num].vertex[pivot_vertex].z),
  495. new_vertex.z,
  496. *reinterpret_cast<const int*>(&new_vertex.z));
  497. }
  498. #endif
  499. stl->facet_start[facet_num].vertex[pivot_vertex] = new_vertex;
  500. vnot = stl->neighbors_start[facet_num].which_vertex_not[next_edge];
  501. facet_num = stl->neighbors_start[facet_num].neighbor[next_edge];
  502. if(facet_num == -1) {
  503. break;
  504. }
  505. if(facet_num == first_facet) {
  506. /* back to the beginning */
  507. printf("\
  508. Back to the first facet changing vertices: probably a mobius part.\n\
  509. Try using a smaller tolerance or don't do a nearby check\n");
  510. return;
  511. }
  512. }
  513. }
  514. static void
  515. stl_which_vertices_to_change(stl_file *stl, stl_hash_edge *edge_a,
  516. stl_hash_edge *edge_b, int *facet1, int *vertex1,
  517. int *facet2, int *vertex2,
  518. stl_vertex *new_vertex1, stl_vertex *new_vertex2) {
  519. int v1a; /* pair 1, facet a */
  520. int v1b; /* pair 1, facet b */
  521. int v2a; /* pair 2, facet a */
  522. int v2b; /* pair 2, facet b */
  523. /* Find first pair */
  524. if(edge_a->which_edge < 3) {
  525. v1a = edge_a->which_edge;
  526. v2a = (edge_a->which_edge + 1) % 3;
  527. } else {
  528. v2a = edge_a->which_edge % 3;
  529. v1a = (edge_a->which_edge + 1) % 3;
  530. }
  531. if(edge_b->which_edge < 3) {
  532. v1b = edge_b->which_edge;
  533. v2b = (edge_b->which_edge + 1) % 3;
  534. } else {
  535. v2b = edge_b->which_edge % 3;
  536. v1b = (edge_b->which_edge + 1) % 3;
  537. }
  538. /* Of the first pair, which vertex, if any, should be changed */
  539. if(!memcmp(&stl->facet_start[edge_a->facet_number].vertex[v1a],
  540. &stl->facet_start[edge_b->facet_number].vertex[v1b],
  541. sizeof(stl_vertex))) {
  542. /* These facets are already equal. No need to change. */
  543. *facet1 = -1;
  544. } else {
  545. if( (stl->neighbors_start[edge_a->facet_number].neighbor[v1a] == -1)
  546. && (stl->neighbors_start[edge_a->facet_number].
  547. neighbor[(v1a + 2) % 3] == -1)) {
  548. /* This vertex has no neighbors. This is a good one to change */
  549. *facet1 = edge_a->facet_number;
  550. *vertex1 = v1a;
  551. *new_vertex1 = stl->facet_start[edge_b->facet_number].vertex[v1b];
  552. } else {
  553. *facet1 = edge_b->facet_number;
  554. *vertex1 = v1b;
  555. *new_vertex1 = stl->facet_start[edge_a->facet_number].vertex[v1a];
  556. }
  557. }
  558. /* Of the second pair, which vertex, if any, should be changed */
  559. if(!memcmp(&stl->facet_start[edge_a->facet_number].vertex[v2a],
  560. &stl->facet_start[edge_b->facet_number].vertex[v2b],
  561. sizeof(stl_vertex))) {
  562. /* These facets are already equal. No need to change. */
  563. *facet2 = -1;
  564. } else {
  565. if( (stl->neighbors_start[edge_a->facet_number].neighbor[v2a] == -1)
  566. && (stl->neighbors_start[edge_a->facet_number].
  567. neighbor[(v2a + 2) % 3] == -1)) {
  568. /* This vertex has no neighbors. This is a good one to change */
  569. *facet2 = edge_a->facet_number;
  570. *vertex2 = v2a;
  571. *new_vertex2 = stl->facet_start[edge_b->facet_number].vertex[v2b];
  572. } else {
  573. *facet2 = edge_b->facet_number;
  574. *vertex2 = v2b;
  575. *new_vertex2 = stl->facet_start[edge_a->facet_number].vertex[v2a];
  576. }
  577. }
  578. }
  579. static void
  580. stl_remove_facet(stl_file *stl, int facet_number) {
  581. int neighbor[3];
  582. int vnot[3];
  583. int i;
  584. int j;
  585. if (stl->error) return;
  586. stl->stats.facets_removed += 1;
  587. /* Update list of connected edges */
  588. j = ((stl->neighbors_start[facet_number].neighbor[0] == -1) +
  589. (stl->neighbors_start[facet_number].neighbor[1] == -1) +
  590. (stl->neighbors_start[facet_number].neighbor[2] == -1));
  591. if(j == 2) {
  592. stl->stats.connected_facets_1_edge -= 1;
  593. } else if(j == 1) {
  594. stl->stats.connected_facets_2_edge -= 1;
  595. stl->stats.connected_facets_1_edge -= 1;
  596. } else if(j == 0) {
  597. stl->stats.connected_facets_3_edge -= 1;
  598. stl->stats.connected_facets_2_edge -= 1;
  599. stl->stats.connected_facets_1_edge -= 1;
  600. }
  601. stl->facet_start[facet_number] =
  602. stl->facet_start[stl->stats.number_of_facets - 1];
  603. /* I could reallocate at this point, but it is not really necessary. */
  604. stl->neighbors_start[facet_number] =
  605. stl->neighbors_start[stl->stats.number_of_facets - 1];
  606. stl->stats.number_of_facets -= 1;
  607. for(i = 0; i < 3; i++) {
  608. neighbor[i] = stl->neighbors_start[facet_number].neighbor[i];
  609. vnot[i] = stl->neighbors_start[facet_number].which_vertex_not[i];
  610. }
  611. for(i = 0; i < 3; i++) {
  612. if(neighbor[i] != -1) {
  613. if(stl->neighbors_start[neighbor[i]].neighbor[(vnot[i] + 1)% 3] !=
  614. stl->stats.number_of_facets) {
  615. printf("\
  616. in stl_remove_facet: neighbor = %d numfacets = %d this is wrong\n",
  617. stl->neighbors_start[neighbor[i]].neighbor[(vnot[i] + 1)% 3],
  618. stl->stats.number_of_facets);
  619. return;
  620. }
  621. stl->neighbors_start[neighbor[i]].neighbor[(vnot[i] + 1)% 3]
  622. = facet_number;
  623. }
  624. }
  625. }
  626. void
  627. stl_remove_unconnected_facets(stl_file *stl) {
  628. /* A couple of things need to be done here. One is to remove any */
  629. /* completely unconnected facets (0 edges connected) since these are */
  630. /* useless and could be completely wrong. The second thing that needs to */
  631. /* be done is to remove any degenerate facets that were created during */
  632. /* stl_check_facets_nearby(). */
  633. int i;
  634. if (stl->error) return;
  635. /* remove degenerate facets */
  636. for(i = 0; i < stl->stats.number_of_facets; i++) {
  637. if( !memcmp(&stl->facet_start[i].vertex[0],
  638. &stl->facet_start[i].vertex[1], sizeof(stl_vertex))
  639. || !memcmp(&stl->facet_start[i].vertex[1],
  640. &stl->facet_start[i].vertex[2], sizeof(stl_vertex))
  641. || !memcmp(&stl->facet_start[i].vertex[0],
  642. &stl->facet_start[i].vertex[2], sizeof(stl_vertex))) {
  643. stl_remove_degenerate(stl, i);
  644. i--;
  645. }
  646. }
  647. if(stl->stats.connected_facets_1_edge < stl->stats.number_of_facets) {
  648. /* remove completely unconnected facets */
  649. for(i = 0; i < stl->stats.number_of_facets; i++) {
  650. if( (stl->neighbors_start[i].neighbor[0] == -1)
  651. && (stl->neighbors_start[i].neighbor[1] == -1)
  652. && (stl->neighbors_start[i].neighbor[2] == -1)) {
  653. /* This facet is completely unconnected. Remove it. */
  654. stl_remove_facet(stl, i);
  655. i--;
  656. }
  657. }
  658. }
  659. }
  660. static void
  661. stl_remove_degenerate(stl_file *stl, int facet) {
  662. int edge1;
  663. int edge2;
  664. int edge3;
  665. int neighbor1;
  666. int neighbor2;
  667. int neighbor3;
  668. int vnot1;
  669. int vnot2;
  670. int vnot3;
  671. if (stl->error) return;
  672. if( !memcmp(&stl->facet_start[facet].vertex[0],
  673. &stl->facet_start[facet].vertex[1], sizeof(stl_vertex))
  674. && !memcmp(&stl->facet_start[facet].vertex[1],
  675. &stl->facet_start[facet].vertex[2], sizeof(stl_vertex))) {
  676. /* all 3 vertices are equal. Just remove the facet. I don't think*/
  677. /* this is really possible, but just in case... */
  678. printf("removing a facet in stl_remove_degenerate\n");
  679. stl_remove_facet(stl, facet);
  680. return;
  681. }
  682. if(!memcmp(&stl->facet_start[facet].vertex[0],
  683. &stl->facet_start[facet].vertex[1], sizeof(stl_vertex))) {
  684. edge1 = 1;
  685. edge2 = 2;
  686. edge3 = 0;
  687. } else if(!memcmp(&stl->facet_start[facet].vertex[1],
  688. &stl->facet_start[facet].vertex[2], sizeof(stl_vertex))) {
  689. edge1 = 0;
  690. edge2 = 2;
  691. edge3 = 1;
  692. } else if(!memcmp(&stl->facet_start[facet].vertex[2],
  693. &stl->facet_start[facet].vertex[0], sizeof(stl_vertex))) {
  694. edge1 = 0;
  695. edge2 = 1;
  696. edge3 = 2;
  697. } else {
  698. /* No degenerate. Function shouldn't have been called. */
  699. return;
  700. }
  701. neighbor1 = stl->neighbors_start[facet].neighbor[edge1];
  702. neighbor2 = stl->neighbors_start[facet].neighbor[edge2];
  703. if(neighbor1 == -1) {
  704. stl_update_connects_remove_1(stl, neighbor2);
  705. }
  706. if(neighbor2 == -1) {
  707. stl_update_connects_remove_1(stl, neighbor1);
  708. }
  709. neighbor3 = stl->neighbors_start[facet].neighbor[edge3];
  710. vnot1 = stl->neighbors_start[facet].which_vertex_not[edge1];
  711. vnot2 = stl->neighbors_start[facet].which_vertex_not[edge2];
  712. vnot3 = stl->neighbors_start[facet].which_vertex_not[edge3];
  713. if(neighbor1 >= 0){
  714. stl->neighbors_start[neighbor1].neighbor[(vnot1 + 1) % 3] = neighbor2;
  715. stl->neighbors_start[neighbor1].which_vertex_not[(vnot1 + 1) % 3] = vnot2;
  716. }
  717. if(neighbor2 >= 0){
  718. stl->neighbors_start[neighbor2].neighbor[(vnot2 + 1) % 3] = neighbor1;
  719. stl->neighbors_start[neighbor2].which_vertex_not[(vnot2 + 1) % 3] = vnot1;
  720. }
  721. stl_remove_facet(stl, facet);
  722. if(neighbor3 >= 0) {
  723. stl_update_connects_remove_1(stl, neighbor3);
  724. stl->neighbors_start[neighbor3].neighbor[(vnot3 + 1) % 3] = -1;
  725. }
  726. }
  727. void
  728. stl_update_connects_remove_1(stl_file *stl, int facet_num) {
  729. int j;
  730. if (stl->error) return;
  731. /* Update list of connected edges */
  732. j = ((stl->neighbors_start[facet_num].neighbor[0] == -1) +
  733. (stl->neighbors_start[facet_num].neighbor[1] == -1) +
  734. (stl->neighbors_start[facet_num].neighbor[2] == -1));
  735. if(j == 0) { /* Facet has 3 neighbors */
  736. stl->stats.connected_facets_3_edge -= 1;
  737. } else if(j == 1) { /* Facet has 2 neighbors */
  738. stl->stats.connected_facets_2_edge -= 1;
  739. } else if(j == 2) { /* Facet has 1 neighbor */
  740. stl->stats.connected_facets_1_edge -= 1;
  741. }
  742. }
  743. void
  744. stl_fill_holes(stl_file *stl) {
  745. stl_facet facet;
  746. stl_facet new_facet;
  747. int neighbors_initial[3];
  748. stl_hash_edge edge;
  749. int first_facet;
  750. int direction;
  751. int facet_num;
  752. int vnot;
  753. int next_edge;
  754. int pivot_vertex;
  755. int next_facet;
  756. int i;
  757. int j;
  758. int k;
  759. if (stl->error) return;
  760. /* Insert all unconnected edges into hash list */
  761. stl_initialize_facet_check_nearby(stl);
  762. for(i = 0; i < stl->stats.number_of_facets; i++) {
  763. facet = stl->facet_start[i];
  764. for(j = 0; j < 3; j++) {
  765. if(stl->neighbors_start[i].neighbor[j] != -1) continue;
  766. edge.facet_number = i;
  767. edge.which_edge = j;
  768. stl_load_edge_exact(stl, &edge, &facet.vertex[j],
  769. &facet.vertex[(j + 1) % 3]);
  770. insert_hash_edge(stl, edge, stl_match_neighbors_exact);
  771. }
  772. }
  773. for(i = 0; i < stl->stats.number_of_facets; i++) {
  774. facet = stl->facet_start[i];
  775. neighbors_initial[0] = stl->neighbors_start[i].neighbor[0];
  776. neighbors_initial[1] = stl->neighbors_start[i].neighbor[1];
  777. neighbors_initial[2] = stl->neighbors_start[i].neighbor[2];
  778. first_facet = i;
  779. for(j = 0; j < 3; j++) {
  780. if(stl->neighbors_start[i].neighbor[j] != -1) continue;
  781. new_facet.vertex[0] = facet.vertex[j];
  782. new_facet.vertex[1] = facet.vertex[(j + 1) % 3];
  783. if(neighbors_initial[(j + 2) % 3] == -1) {
  784. direction = 1;
  785. } else {
  786. direction = 0;
  787. }
  788. facet_num = i;
  789. vnot = (j + 2) % 3;
  790. for(;;) {
  791. if(vnot > 2) {
  792. if(direction == 0) {
  793. pivot_vertex = (vnot + 2) % 3;
  794. next_edge = pivot_vertex;
  795. direction = 1;
  796. } else {
  797. pivot_vertex = (vnot + 1) % 3;
  798. next_edge = vnot % 3;
  799. direction = 0;
  800. }
  801. } else {
  802. if(direction == 0) {
  803. pivot_vertex = (vnot + 1) % 3;
  804. next_edge = vnot;
  805. } else {
  806. pivot_vertex = (vnot + 2) % 3;
  807. next_edge = pivot_vertex;
  808. }
  809. }
  810. next_facet = stl->neighbors_start[facet_num].neighbor[next_edge];
  811. if(next_facet == -1) {
  812. new_facet.vertex[2] = stl->facet_start[facet_num].
  813. vertex[vnot % 3];
  814. stl_add_facet(stl, &new_facet);
  815. for(k = 0; k < 3; k++) {
  816. edge.facet_number = stl->stats.number_of_facets - 1;
  817. edge.which_edge = k;
  818. stl_load_edge_exact(stl, &edge, &new_facet.vertex[k],
  819. &new_facet.vertex[(k + 1) % 3]);
  820. insert_hash_edge(stl, edge, stl_match_neighbors_exact);
  821. }
  822. break;
  823. } else {
  824. vnot = stl->neighbors_start[facet_num].
  825. which_vertex_not[next_edge];
  826. facet_num = next_facet;
  827. }
  828. if(facet_num == first_facet) {
  829. /* back to the beginning */
  830. printf("\
  831. Back to the first facet filling holes: probably a mobius part.\n\
  832. Try using a smaller tolerance or don't do a nearby check\n");
  833. return;
  834. }
  835. }
  836. }
  837. }
  838. }
  839. void
  840. stl_add_facet(stl_file *stl, stl_facet *new_facet) {
  841. if (stl->error) return;
  842. stl->stats.facets_added += 1;
  843. if(stl->stats.facets_malloced < stl->stats.number_of_facets + 1) {
  844. stl->facet_start = (stl_facet*)realloc(stl->facet_start,
  845. (sizeof(stl_facet) * (stl->stats.facets_malloced + 256)));
  846. if(stl->facet_start == NULL) perror("stl_add_facet");
  847. stl->neighbors_start = (stl_neighbors*)realloc(stl->neighbors_start,
  848. (sizeof(stl_neighbors) * (stl->stats.facets_malloced + 256)));
  849. if(stl->neighbors_start == NULL) perror("stl_add_facet");
  850. stl->stats.facets_malloced += 256;
  851. }
  852. stl->facet_start[stl->stats.number_of_facets] = *new_facet;
  853. /* note that the normal vector is not set here, just initialized to 0 */
  854. stl->facet_start[stl->stats.number_of_facets].normal.x = 0.0;
  855. stl->facet_start[stl->stats.number_of_facets].normal.y = 0.0;
  856. stl->facet_start[stl->stats.number_of_facets].normal.z = 0.0;
  857. stl->neighbors_start[stl->stats.number_of_facets].neighbor[0] = -1;
  858. stl->neighbors_start[stl->stats.number_of_facets].neighbor[1] = -1;
  859. stl->neighbors_start[stl->stats.number_of_facets].neighbor[2] = -1;
  860. stl->stats.number_of_facets += 1;
  861. }