main.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <math.h>
  5. #include <assert.h>
  6. void translate(const char* file);;
  7. int main(int argc, char** argv)
  8. {
  9. for (int i = 1; (i < argc); i++)
  10. translate(argv[i]);
  11. return 0;
  12. }
  13. struct Vertex
  14. {
  15. Vertex(void)
  16. :
  17. cUsed(0)
  18. {
  19. }
  20. double xyz[3];
  21. int id;
  22. int cUsed;
  23. };
  24. struct Face
  25. {
  26. int ids[3];
  27. };
  28. void swap(double g[3][4], int i, int j)
  29. {
  30. for (int k = 0; (k < 4); k++)
  31. {
  32. double t = g[i][k];
  33. g[i][k] = g[j][k];
  34. g[j][k] = t;
  35. }
  36. }
  37. void subtract(double g[3][4], double f, int i, int j)
  38. {
  39. for (int k = 0; (k < 4); k++)
  40. {
  41. g[i][k] -= g[j][k] * f;
  42. }
  43. }
  44. bool reduce(double g[3][4])
  45. {
  46. if (fabs(g[1][0]) > fabs(g[0][0]))
  47. swap(g, 0, 1);
  48. if (fabs(g[2][0]) > fabs(g[0][0]))
  49. swap(g, 0, 2);
  50. if (fabs(g[0][0]) < 1.0e-4)
  51. return false;
  52. //Reduce the first column
  53. subtract(g, g[1][0] / g[0][0], 1, 0);
  54. g[1][0] = 0.0;
  55. subtract(g, g[2][0] / g[0][0], 2, 0);
  56. g[2][0] = 0.0;
  57. if (fabs(g[2][1]) > fabs(g[1][1]))
  58. swap(g, 1, 2);
  59. if (fabs(g[1][1]) < 1.0e-4)
  60. return false;
  61. //Reduce the second column
  62. subtract(g, g[2][1] / g[1][1], 2, 1);
  63. g[2][1] = 0.0;
  64. //Back solve ...
  65. if (fabs(g[2][2]) < 1.0e-4)
  66. return false;
  67. g[2][3] = g[2][3] / g[2][2];
  68. g[2][2] = 1.0;
  69. subtract(g, g[1][2], 1, 2);
  70. g[1][2] = 0.0f;
  71. subtract(g, g[0][2], 0, 2);
  72. g[0][2] = 0.0f;
  73. assert (g[1][1] != 0.0f);
  74. g[1][3] = g[1][3] / g[1][1];
  75. g[1][1] = 1.0;
  76. subtract(g, g[0][1], 0, 1);
  77. assert (g[0][0] != 0.0f);
  78. g[0][3] = g[0][3] / g[0][0];
  79. g[0][0] = 1.0;
  80. return true;
  81. }
  82. const int c_maxVertices = 10000;
  83. const int c_maxFaces = 1000;
  84. Vertex vertices[c_maxVertices];
  85. Face faces[c_maxFaces];
  86. int vertexIDs[c_maxVertices];
  87. void addAdjacent(int* nAdjacent,
  88. int adjacent[],
  89. int id)
  90. {
  91. if (vertices[id].cUsed > 2)
  92. {
  93. for (int i = 0; (i < *nAdjacent); i++)
  94. {
  95. if (adjacent[i] == id)
  96. return;
  97. }
  98. adjacent[(*nAdjacent)++] = id;
  99. }
  100. }
  101. void translate(const char* file)
  102. {
  103. FILE* fIn = NULL;
  104. FILE* fOut1 = NULL;
  105. FILE* fOut2 = NULL;
  106. if (strcmp(file, "-") == 0)
  107. {
  108. fIn = stdin;
  109. fOut1 = stdout;
  110. }
  111. else
  112. {
  113. const int c_cbBfr = 512;
  114. char bfr[c_cbBfr];
  115. assert (strlen(file) < c_cbBfr - 10);
  116. strcpy(bfr, file);
  117. strcat(bfr, ".qh");
  118. fIn = fopen(bfr, "r");
  119. if (fIn)
  120. {
  121. strcpy(bfr, file);
  122. strcat(bfr, "_m.x");
  123. fOut1 = fopen(bfr, "w");
  124. strcpy(bfr, file);
  125. strcat(bfr, ".cvh");
  126. fOut2 = fopen(bfr, "w");
  127. }
  128. }
  129. int nVertices = 0;
  130. int nUsedVertices = 0;
  131. int nSingularFaces = 0;
  132. int nFaces = 0;
  133. if (fIn)
  134. {
  135. const int c_cbLine = 512;
  136. char line[c_cbLine];
  137. fgets(line, c_cbLine, fIn); //Skip 1st line
  138. fgets(line, c_cbLine, fIn);
  139. sscanf(line, "%d %d", &nVertices, &nFaces);
  140. //Read in all of the vertices
  141. {
  142. for (int i = 0; (i < nVertices); i++)
  143. {
  144. fgets(line, c_cbLine, fIn);
  145. sscanf(line, "%lf %lf %lf",
  146. &(vertices[i].xyz[0]),
  147. &(vertices[i].xyz[1]),
  148. &(vertices[i].xyz[2]));
  149. }
  150. }
  151. //Read in all of the faces
  152. {
  153. int faceID = 0; //possibly more than one face/line
  154. for (int i = 0; (i < nFaces); i++)
  155. {
  156. fgets(line, c_cbLine, fIn);
  157. int n = atoi(line);
  158. const int c_maxIDs = 20;
  159. assert (n >= 3);
  160. assert (n < c_maxIDs);
  161. int ids[c_maxIDs];
  162. {
  163. const char* p = line;
  164. for (int j = 0; (j < n); j++)
  165. {
  166. p = strchr(p, ' ');
  167. assert (p);
  168. ids[j] = atoi(++p);
  169. }
  170. }
  171. if ((n & 0x01) == 1)
  172. {
  173. //Odd number of vertices
  174. //Remove the last vertex from consideration
  175. faces[faceID].ids[0] = ids[n-2];
  176. faces[faceID].ids[1] = ids[n-1];
  177. faces[faceID].ids[2] = ids[0];
  178. faceID++;
  179. n--;
  180. }
  181. assert ((n & 0x01) == 0);
  182. int p0 = 0;
  183. int p1 = 1;
  184. int p2 = n - 2;
  185. int p3 = n - 1;
  186. while (p2 > p1)
  187. {
  188. faces[faceID].ids[0] = ids[p0];
  189. faces[faceID].ids[1] = ids[p1];
  190. faces[faceID].ids[2] = ids[p2];
  191. faceID++;
  192. faces[faceID].ids[0] = ids[p2];
  193. faces[faceID].ids[1] = ids[p3];
  194. faces[faceID].ids[2] = ids[p0];
  195. faceID++;
  196. p0++;
  197. p1++;
  198. p2--;
  199. p3--;
  200. }
  201. }
  202. nFaces = faceID;
  203. }
  204. //Mark the vertices actually used by faces
  205. {
  206. for (int i = 0; (i < nFaces); i++)
  207. {
  208. for (int j = 0; (j < 3); j++)
  209. vertices[faces[i].ids[j]].cUsed++;
  210. }
  211. }
  212. //Generate IDs for the vertices that are used
  213. {
  214. int vertexID = 0;
  215. for (int i = 0; (i < nVertices); i++)
  216. {
  217. if (vertices[i].cUsed > 2)
  218. {
  219. vertexIDs[vertexID] = i;
  220. vertices[i].id = vertexID++;
  221. }
  222. else
  223. nSingularFaces += vertices[i].cUsed;
  224. }
  225. nUsedVertices = vertexID;
  226. }
  227. }
  228. if (fOut1)
  229. {
  230. fprintf(fOut1, "xof 0303txt 0032\nHeader { 1; 0; 1; }\nMesh\n{\n%d;\n", nUsedVertices); //}
  231. //Only print the vertices actually used by the convex hull
  232. {
  233. bool firstF = true;
  234. for (int i = 0; (i < nVertices); i++)
  235. {
  236. if (vertices[i].cUsed > 2)
  237. {
  238. if (firstF)
  239. firstF = false;
  240. else
  241. fputs(",\n", fOut1);
  242. fprintf(fOut1, "%14.6f;%14.6f;%14.6f;",
  243. vertices[i].xyz[0],
  244. vertices[i].xyz[1],
  245. vertices[i].xyz[2]);
  246. }
  247. }
  248. }
  249. //Print the faces with the correct vertex IDs
  250. {
  251. fprintf(fOut1, ";\n\n%d;\n", nFaces - nSingularFaces);
  252. bool first = true;
  253. for (int i = 0; (i < nFaces); i++)
  254. {
  255. if ((vertices[faces[i].ids[2]].cUsed > 2) &&
  256. (vertices[faces[i].ids[1]].cUsed > 2) &&
  257. (vertices[faces[0].ids[1]].cUsed > 2))
  258. {
  259. if (first)
  260. first = false;
  261. else
  262. fputs(",\n", fOut1);
  263. fprintf(fOut1, "3;%d,%d,%d;",
  264. vertices[faces[i].ids[2]].id,
  265. vertices[faces[i].ids[1]].id,
  266. vertices[faces[i].ids[0]].id);
  267. }
  268. }
  269. fputs(";\n", fOut1);
  270. }
  271. fprintf(fOut1, /*{*/"}\n");
  272. }
  273. if (fOut2)
  274. {
  275. double radius = 0.0;
  276. double xyzMax[3] = {0.0, 0.0, 0.0};
  277. {
  278. //Find the most distance vertex in the model
  279. for (int i = 0; (i < nUsedVertices); i++)
  280. {
  281. int vertexID = vertexIDs[i];
  282. double r = vertices[vertexID].xyz[0] * vertices[vertexID].xyz[0] +
  283. vertices[vertexID].xyz[1] * vertices[vertexID].xyz[1] +
  284. vertices[vertexID].xyz[2] * vertices[vertexID].xyz[2];
  285. if (r > radius)
  286. radius = r;
  287. for (int j = 0; (j < 3); j++)
  288. {
  289. double f = fabs(vertices[vertexID].xyz[j]);
  290. if (f > xyzMax[j])
  291. xyzMax[j] = f;
  292. }
  293. }
  294. }
  295. radius = sqrt(radius);
  296. //First attempt: find the best sphere
  297. double aBest = radius;
  298. double bBest = radius;
  299. double cBest = radius;
  300. double vBest = aBest * bBest * cBest;
  301. //Second attempt: find the best ellipse with the same aspect ratio as the bounding box
  302. {
  303. double a = xyzMax[0];
  304. double b = xyzMax[1];
  305. double c = xyzMax[2];
  306. double a2 = a * a;
  307. double b2 = b * b;
  308. double c2 = c * c;
  309. //Now find the fudge factor to make everything "fit"
  310. double rMax = 0.0;
  311. for (int i = 0; (i < nUsedVertices); i++)
  312. {
  313. int vertexID = vertexIDs[i];
  314. double r = (vertices[vertexID].xyz[0] * vertices[vertexID].xyz[0]) / a2 +
  315. (vertices[vertexID].xyz[1] * vertices[vertexID].xyz[1]) / b2 +
  316. (vertices[vertexID].xyz[2] * vertices[vertexID].xyz[2]) / c2;
  317. if (r > rMax)
  318. rMax = r;
  319. }
  320. rMax = sqrt(rMax);
  321. a *= rMax;
  322. b *= rMax;
  323. c *= rMax;
  324. double v = a * b * c;
  325. if (v < vBest)
  326. {
  327. vBest = v;
  328. aBest = a;
  329. bBest = b;
  330. cBest = c;
  331. }
  332. }
  333. //Third attempt ... try to find a better ellipse from the data
  334. {
  335. //Generate the best ellipse (minimum volume) ellipse that contains all of the points.
  336. //Do it the real expensive way: look at all point triples and deduce the radii of the axes
  337. //and then pick the one with the smallest volume
  338. //Ellipse equation:
  339. // (x/a)^2 + (y/b)^2 + (z/c)^2 = 1
  340. //We actually want to solve:
  341. // Minimize: 1.0 / (ra * rb * rc) such that
  342. // ra * x1^2 + rb * y1^2 + rc * z1^2 <= 1
  343. // ...
  344. // ra * xN^2 + rb * yN^2 + rc * zN^2 <= 1
  345. //but since it is too early in the morning to crank out a simplex algorithm, fake it:
  346. //Try all sets of 3 points, find the corresponding ellipse and see if it contains all the
  347. //other points.
  348. double* xyzs[3];
  349. for (int i = 0; (i < nUsedVertices - 2); i++)
  350. {
  351. xyzs[0] = vertices[vertexIDs[i]].xyz;
  352. for (int j = i + 1; (j < nUsedVertices - 1); j++)
  353. {
  354. xyzs[1] = vertices[vertexIDs[j]].xyz;
  355. for (int k = j + 1; (k < nUsedVertices); k++)
  356. {
  357. xyzs[2] = vertices[vertexIDs[k]].xyz;
  358. //Rewrite the ellipse equation
  359. //from: (x/a)^2 + (y/b)^2 + (z/c)^2 = 1
  360. //to: ra x^2 + rb y^2 + rc z^2 = 1 ra = 1.0/a^2; a = sqrt(1.0/ra);
  361. //and solve for xyz1, 2 & 3.
  362. //Setup the gaussian matrix (? ... boy, it has been awhile)
  363. double g[3][4];
  364. {
  365. for (int m = 0; (m < 3); m++)
  366. {
  367. for (int n = 0; (n < 3); n++)
  368. g[m][n] = xyzs[m][n] * xyzs[m][n];
  369. g[m][3] = 1.0f;
  370. }
  371. }
  372. //Reduce the gaussian
  373. if (reduce(g) &&
  374. (g[0][3] > 1.0e-4) &&
  375. (g[1][3] > 1.0e-4) &&
  376. (g[2][3] > 1.0e-4))
  377. {
  378. double a = sqrt(1.0 / g[0][3]);
  379. double b = sqrt(1.0 / g[1][3]);
  380. double c = sqrt(1.0 / g[2][3]);
  381. double v = a * b * c;
  382. if (v < vBest)
  383. {
  384. //Vertify that all of the other points in the convex hull are properly contained.
  385. for (int m = 0; (m < nUsedVertices); m++)
  386. {
  387. double x = vertices[vertexIDs[m]].xyz[0] / a;
  388. double y = vertices[vertexIDs[m]].xyz[1] / b;
  389. double z = vertices[vertexIDs[m]].xyz[2] / c;
  390. if (x*x + y*y + z*z > 1.01f) //Allow a bit of fudging
  391. break;
  392. }
  393. if (m == nUsedVertices)
  394. {
  395. vBest = v;
  396. aBest = a;
  397. bBest = b;
  398. cBest = c;
  399. }
  400. }
  401. }
  402. }
  403. }
  404. }
  405. }
  406. int nAdjacencies = 2 * (nUsedVertices + nFaces - nSingularFaces - 2);
  407. fprintf(fOut2, "%5d%5d%14.6f%14.6f%14.6f%14.6f%14.6f\n", nUsedVertices, nAdjacencies,
  408. radius,
  409. aBest, bBest, cBest, ((aBest > bBest)
  410. ? ((aBest > cBest) ? aBest : cBest)
  411. : ((bBest > cBest) ? bBest : cBest)) / radius);
  412. //Only print the vertices actually used by the convex hull
  413. {
  414. bool firstF = true;
  415. for (int vertexID = 0; (vertexID < nVertices); vertexID++)
  416. {
  417. if (vertices[vertexID].cUsed > 2)
  418. {
  419. fprintf(fOut2, "%14.6f%14.6f%14.6f",
  420. vertices[vertexID].xyz[0],
  421. vertices[vertexID].xyz[1],
  422. vertices[vertexID].xyz[2]);
  423. //print the adjacent vertices
  424. const int c_maxAdjacent = c_maxVertices;
  425. int adjacent[c_maxAdjacent];
  426. int nAdjacent = 0;
  427. for (int faceID = 0; (faceID < nFaces); faceID++)
  428. {
  429. //Does this face contain this vertex?
  430. if (vertexID == faces[faceID].ids[0])
  431. {
  432. addAdjacent(&nAdjacent, adjacent, faces[faceID].ids[1]);
  433. addAdjacent(&nAdjacent, adjacent, faces[faceID].ids[2]);
  434. }
  435. else if (vertexID == faces[faceID].ids[1])
  436. {
  437. addAdjacent(&nAdjacent, adjacent, faces[faceID].ids[0]);
  438. addAdjacent(&nAdjacent, adjacent, faces[faceID].ids[2]);
  439. }
  440. else if (vertexID == faces[faceID].ids[2])
  441. {
  442. addAdjacent(&nAdjacent, adjacent, faces[faceID].ids[0]);
  443. addAdjacent(&nAdjacent, adjacent, faces[faceID].ids[1]);
  444. }
  445. }
  446. fprintf(fOut2, "%5d\n", nAdjacent);
  447. for (int a = 0; (a < nAdjacent); a++)
  448. fprintf(fOut2, "%5d", vertices[adjacent[a]].id);
  449. fputc('\n', fOut2);
  450. nAdjacencies -= nAdjacent;
  451. }
  452. }
  453. }
  454. if (nAdjacencies != 0)
  455. {
  456. printf("Error constructing %s.cvh\n", file);
  457. exit(1);
  458. }
  459. }
  460. if (fIn && (fIn != stdin))
  461. fclose(fIn);
  462. if (fOut1 && (fOut1 != stdout))
  463. fclose(fOut1);
  464. if (fOut2)
  465. fclose(fOut2);
  466. }