PageRenderTime 95ms CodeModel.GetById 1ms RepoModel.GetById 0ms app.codeStats 1ms

/contrib/Netgen/libsrc/stlgeom/stlgeom.cpp

https://bitbucket.org/lge/gmsh
C++ | 3506 lines | 2425 code | 564 blank | 517 comment | 608 complexity | c9efdd8c1eb92e185901b6f00e324a99 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, BSD-3-Clause
  1. #include <meshing.hpp>
  2. #include "stlgeom.hpp"
  3. namespace netgen
  4. {
  5. //globalen searchtree fuer gesamte geometry aktivieren
  6. int geomsearchtreeon = 0;
  7. int usechartnormal = 1;
  8. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  9. void STLMeshing (STLGeometry & geom,
  10. Mesh & mesh)
  11. {
  12. geom.Clear();
  13. geom.BuildEdges();
  14. geom.MakeAtlas(mesh);
  15. geom.CalcFaceNums();
  16. geom.AddFaceEdges();
  17. geom.LinkEdges();
  18. mesh.ClearFaceDescriptors();
  19. for (int i = 1; i <= geom.GetNOFaces(); i++)
  20. mesh.AddFaceDescriptor (FaceDescriptor (i, 1, 0, 0));
  21. }
  22. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  23. //+++++++++++++++++++ STL GEOMETRY ++++++++++++++++++++++++++++
  24. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  25. STLGeometry :: STLGeometry()
  26. /*
  27. : edges(), edgesperpoint(),
  28. normals(), externaledges(),
  29. atlas(), chartmark(),
  30. lines(), outerchartspertrig(), vicinity(), markedtrigs(), markedsegs(),
  31. lineendpoints(), spiralpoints(), selectedmultiedge()
  32. */
  33. {
  34. edgedata = new STLEdgeDataList(*this);
  35. externaledges.SetSize(0);
  36. Clear();
  37. meshchart = 0; // initialize all ?? JS
  38. if (geomsearchtreeon)
  39. searchtree = new Box3dTree (GetBoundingBox().PMin() - Vec3d(1,1,1),
  40. GetBoundingBox().PMax() + Vec3d(1,1,1));
  41. else
  42. searchtree = NULL;
  43. status = STL_GOOD;
  44. statustext = "Good Geometry";
  45. smoothedges = NULL;
  46. }
  47. STLGeometry :: ~STLGeometry()
  48. {
  49. delete edgedata;
  50. }
  51. void STLGeometry :: Save (string filename) const
  52. {
  53. const char * cfilename = filename.c_str();
  54. if (strlen(cfilename) < 4)
  55. throw NgException ("illegal filename");
  56. if (strlen(cfilename) > 3 &&
  57. strcmp (&cfilename[strlen(cfilename)-3], "stl") == 0)
  58. {
  59. STLTopology::Save (cfilename);
  60. }
  61. else if (strlen(cfilename) > 4 &&
  62. strcmp (&cfilename[strlen(cfilename)-4], "stlb") == 0)
  63. {
  64. SaveBinary (cfilename,"Binary STL Geometry");
  65. }
  66. else if (strlen(cfilename) > 4 &&
  67. strcmp (&cfilename[strlen(cfilename)-4], "stle") == 0)
  68. {
  69. SaveSTLE (cfilename);
  70. }
  71. }
  72. int STLGeometry :: GenerateMesh (Mesh*& mesh, MeshingParameters & mparam,
  73. int perfstepsstart, int perfstepsend)
  74. {
  75. return STLMeshingDummy (this, mesh, mparam, perfstepsstart, perfstepsend);
  76. }
  77. const Refinement & STLGeometry :: GetRefinement () const
  78. {
  79. return RefinementSTLGeometry (*this);
  80. }
  81. void STLGeometry :: STLInfo(double* data)
  82. {
  83. data[0] = GetNT();
  84. Box<3> b = GetBoundingBox();
  85. data[1] = b.PMin()(0);
  86. data[2] = b.PMax()(0);
  87. data[3] = b.PMin()(1);
  88. data[4] = b.PMax()(1);
  89. data[5] = b.PMin()(2);
  90. data[6] = b.PMax()(2);
  91. int i;
  92. int cons = 1;
  93. for (i = 1; i <= GetNT(); i++)
  94. {
  95. if (NONeighbourTrigs(i) != 3) {cons = 0;}
  96. }
  97. data[7] = cons;
  98. }
  99. void STLGeometry :: MarkNonSmoothNormals()
  100. {
  101. PrintFnStart("Mark Non-Smooth Normals");
  102. int i,j;
  103. markedtrigs.SetSize(GetNT());
  104. for (i = 1; i <= GetNT(); i++)
  105. {
  106. SetMarkedTrig(i, 0);
  107. }
  108. double dirtyangle = stlparam.yangle/180.*M_PI;
  109. int cnt = 0;
  110. int lp1,lp2;
  111. for (i = 1; i <= GetNT(); i++)
  112. {
  113. for (j = 1; j <= NONeighbourTrigs(i); j++)
  114. {
  115. if (GetAngle(i, NeighbourTrig(i,j)) > dirtyangle)
  116. {
  117. GetTriangle(i).GetNeighbourPoints(GetTriangle(NeighbourTrig(i,j)), lp1, lp2);
  118. if (!IsEdge(lp1,lp2))
  119. {
  120. if (!IsMarkedTrig(i)) {SetMarkedTrig(i,1); cnt++;}
  121. }
  122. }
  123. }
  124. }
  125. PrintMessage(5,"marked ",cnt," non-smooth trig-normals");
  126. }
  127. void STLGeometry :: SmoothNormals()
  128. {
  129. multithread.terminate = 0;
  130. // UseExternalEdges();
  131. BuildEdges();
  132. DenseMatrix m(3), hm(3);
  133. Vector rhs(3), sol(3), hv(3), hv2(3);
  134. Vec<3> ri;
  135. double wnb = stldoctor.smoothnormalsweight; // neigbour normal weight
  136. double wgeom = 1-wnb; // geometry normal weight
  137. // minimize
  138. // wgeom sum_T \sum ri \| ri^T (n - n_geom) \|^2
  139. // + wnb sum_SE \| ri x (n - n_nb) \|^2
  140. int i, j, k, l;
  141. int nt = GetNT();
  142. PushStatusF("Smooth Normals");
  143. //int testmode;
  144. for (i = 1; i <= nt; i++)
  145. {
  146. SetThreadPercent( 100.0 * (double)i / (double)nt);
  147. const STLTriangle & trig = GetTriangle (i);
  148. m = 0;
  149. rhs = 0;
  150. // normal of geometry:
  151. Vec<3> ngeom = trig.GeomNormal(points);
  152. ngeom.Normalize();
  153. for (j = 1; j <= 3; j++)
  154. {
  155. int pi1 = trig.PNumMod (j);
  156. int pi2 = trig.PNumMod (j+1);
  157. // edge vector
  158. ri = GetPoint (pi2) - GetPoint (pi1);
  159. for (k = 0; k < 3; k++)
  160. for (l = 0; l < 3; l++)
  161. hm.Elem(k+1, l+1) = wgeom * ri(k) * ri(l);
  162. for (k = 0; k < 3; k++)
  163. hv(k) = ngeom(k);
  164. hm.Mult (hv, hv2);
  165. /*
  166. if (testmode)
  167. (*testout) << "add vec " << hv2 << endl
  168. << " add m " << hm << endl;
  169. */
  170. rhs.Add (1, hv2);
  171. m += hm;
  172. int nbt = 0;
  173. int fp1,fp2;
  174. for (k = 1; k <= NONeighbourTrigs(i); k++)
  175. {
  176. trig.GetNeighbourPoints(GetTriangle(NeighbourTrig(i, k)),fp1,fp2);
  177. if (fp1 == pi1 && fp2 == pi2)
  178. {
  179. nbt = NeighbourTrig(i, k);
  180. }
  181. }
  182. if (!nbt)
  183. {
  184. cerr << "ERROR: stlgeom::Smoothnormals, nbt = 0" << endl;
  185. }
  186. // smoothed normal
  187. Vec<3> nnb = GetTriangle(nbt).Normal(); // neighbour normal
  188. nnb.Normalize();
  189. if (!IsEdge(pi1,pi2))
  190. {
  191. double lr2 = ri * ri;
  192. for (k = 0; k < 3; k++)
  193. {
  194. for (l = 0; l < k; l++)
  195. {
  196. hm.Elem(k+1, l+1) = -wnb * ri(k) * ri(l);
  197. hm.Elem(l+1, k+1) = -wnb * ri(k) * ri(l);
  198. }
  199. hm.Elem(k+1, k+1) = wnb * (lr2 - ri(k) * ri(k));
  200. }
  201. for (k = 0; k < 3; k++)
  202. hv(k) = nnb(k);
  203. hm.Mult (hv, hv2);
  204. /*
  205. if (testmode)
  206. (*testout) << "add nb vec " << hv2 << endl
  207. << " add nb m " << hm << endl;
  208. */
  209. rhs.Add (1, hv2);
  210. m += hm;
  211. }
  212. }
  213. m.Solve (rhs, sol);
  214. Vec3d newn(sol(0), sol(1), sol(2));
  215. newn /= (newn.Length() + 1e-24);
  216. GetTriangle(i).SetNormal(newn);
  217. // setnormal (sol);
  218. }
  219. /*
  220. for (i = 1; i <= nt; i++)
  221. SetMarkedTrig(i, 0);
  222. int crloop;
  223. for (crloop = 1; crloop <= 3; crloop++)
  224. {
  225. // find critical:
  226. Array<INDEX_2> critpairs;
  227. for (i = 1; i <= nt; i++)
  228. {
  229. const STLTriangle & trig = GetTriangle (i);
  230. Vec3d ngeom = GetTriangleNormal (i); // trig.Normal(points);
  231. ngeom /= (ngeom.Length() + 1e-24);
  232. for (j = 1; j <= 3; j++)
  233. {
  234. int pi1 = trig.PNumMod (j);
  235. int pi2 = trig.PNumMod (j+1);
  236. int nbt = 0;
  237. int fp1,fp2;
  238. for (k = 1; k <= NONeighbourTrigs(i); k++)
  239. {
  240. trig.GetNeighbourPoints(GetTriangle(NeighbourTrig(i, k)),fp1,fp2);
  241. if (fp1 == pi1 && fp2 == pi2)
  242. {
  243. nbt = NeighbourTrig(i, k);
  244. }
  245. }
  246. if (!nbt)
  247. {
  248. cerr << "ERROR: stlgeom::Smoothnormals, nbt = 0" << endl;
  249. }
  250. Vec3d nnb = GetTriangleNormal(nbt); // neighbour normal
  251. nnb /= (nnb.Length() + 1e-24);
  252. if (!IsEdge(pi1,pi2))
  253. {
  254. if (Angle (nnb, ngeom) > 150 * M_PI/180)
  255. {
  256. SetMarkedTrig(i, 1);
  257. SetMarkedTrig(nbt, 1);
  258. critpairs.Append (INDEX_2 (i, nbt));
  259. }
  260. }
  261. }
  262. }
  263. if (!critpairs.Size())
  264. {
  265. break;
  266. }
  267. if (critpairs.Size())
  268. {
  269. Array<int> friends;
  270. double area1 = 0, area2 = 0;
  271. for (i = 1; i <= critpairs.Size(); i++)
  272. {
  273. int tnr1 = critpairs.Get(i).I1();
  274. int tnr2 = critpairs.Get(i).I2();
  275. (*testout) << "t1 = " << tnr1 << ", t2 = " << tnr2
  276. << " angle = " << Angle (GetTriangleNormal (tnr1),
  277. GetTriangleNormal (tnr2))
  278. << endl;
  279. // who has more friends ?
  280. int side;
  281. area1 = 0;
  282. area2 = 0;
  283. for (side = 1; side <= 2; side++)
  284. {
  285. friends.SetSize (0);
  286. friends.Append ( (side == 1) ? tnr1 : tnr2);
  287. for (j = 1; j <= 3; j++)
  288. {
  289. int fsize = friends.Size();
  290. for (k = 1; k <= fsize; k++)
  291. {
  292. int testtnr = friends.Get(k);
  293. Vec3d ntt = GetTriangleNormal(testtnr);
  294. ntt /= (ntt.Length() + 1e-24);
  295. for (l = 1; l <= NONeighbourTrigs(testtnr); l++)
  296. {
  297. int testnbnr = NeighbourTrig(testtnr, l);
  298. Vec3d nbt = GetTriangleNormal(testnbnr);
  299. nbt /= (nbt.Length() + 1e-24);
  300. if (Angle (nbt, ntt) < 15 * M_PI/180)
  301. {
  302. int ii;
  303. int found = 0;
  304. for (ii = 1; ii <= friends.Size(); ii++)
  305. {
  306. if (friends.Get(ii) == testnbnr)
  307. {
  308. found = 1;
  309. break;
  310. }
  311. }
  312. if (!found)
  313. friends.Append (testnbnr);
  314. }
  315. }
  316. }
  317. }
  318. // compute area:
  319. for (k = 1; k <= friends.Size(); k++)
  320. {
  321. double area =
  322. GetTriangle (friends.Get(k)).Area(points);
  323. if (side == 1)
  324. area1 += area;
  325. else
  326. area2 += area;
  327. }
  328. }
  329. (*testout) << "area1 = " << area1 << " area2 = " << area2 << endl;
  330. if (area1 < 0.1 * area2)
  331. {
  332. Vec3d n = GetTriangleNormal (tnr1);
  333. n *= -1;
  334. SetTriangleNormal(tnr1, n);
  335. }
  336. if (area2 < 0.1 * area1)
  337. {
  338. Vec3d n = GetTriangleNormal (tnr2);
  339. n *= -1;
  340. SetTriangleNormal(tnr2, n);
  341. }
  342. }
  343. }
  344. }
  345. */
  346. calcedgedataanglesnew = 1;
  347. PopStatus();
  348. }
  349. int STLGeometry :: AddEdge(int ap1, int ap2)
  350. {
  351. STLEdge e(ap1,ap2);
  352. e.SetLeftTrig(GetLeftTrig(ap1,ap2));
  353. e.SetRightTrig(GetRightTrig(ap1,ap2));
  354. return edges.Append(e);
  355. }
  356. void STLGeometry :: STLDoctorConfirmEdge()
  357. {
  358. StoreEdgeData();
  359. if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT() && GetNodeOfSelTrig())
  360. {
  361. if (stldoctor.selectmode == 1)
  362. {
  363. int ap1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig());
  364. int ap2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1);
  365. edgedata->Elem(edgedata->GetEdgeNum(ap1,ap2)).SetStatus (ED_CONFIRMED);
  366. }
  367. else if (stldoctor.selectmode == 3 || stldoctor.selectmode == 4)
  368. {
  369. int i;
  370. for (i = 1; i <= selectedmultiedge.Size(); i++)
  371. {
  372. int ap1 = selectedmultiedge.Get(i).i1;
  373. int ap2 = selectedmultiedge.Get(i).i2;
  374. edgedata->Elem(edgedata->GetEdgeNum(ap1,ap2)).SetStatus (ED_CONFIRMED);
  375. }
  376. }
  377. }
  378. }
  379. void STLGeometry :: STLDoctorCandidateEdge()
  380. {
  381. StoreEdgeData();
  382. if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT() && GetNodeOfSelTrig())
  383. {
  384. if (stldoctor.selectmode == 1)
  385. {
  386. int ap1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig());
  387. int ap2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1);
  388. edgedata->Elem(edgedata->GetEdgeNum(ap1,ap2)).SetStatus (ED_CANDIDATE);
  389. }
  390. else if (stldoctor.selectmode == 3 || stldoctor.selectmode == 4)
  391. {
  392. int i;
  393. for (i = 1; i <= selectedmultiedge.Size(); i++)
  394. {
  395. int ap1 = selectedmultiedge.Get(i).i1;
  396. int ap2 = selectedmultiedge.Get(i).i2;
  397. edgedata->Elem(edgedata->GetEdgeNum(ap1,ap2)).SetStatus (ED_CANDIDATE);
  398. }
  399. }
  400. }
  401. }
  402. void STLGeometry :: STLDoctorExcludeEdge()
  403. {
  404. StoreEdgeData();
  405. if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT() && GetNodeOfSelTrig())
  406. {
  407. if (stldoctor.selectmode == 1)
  408. {
  409. int ap1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig());
  410. int ap2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1);
  411. edgedata->Elem(edgedata->GetEdgeNum(ap1,ap2)).SetStatus(ED_EXCLUDED);
  412. }
  413. else if (stldoctor.selectmode == 3 || stldoctor.selectmode == 4)
  414. {
  415. int i;
  416. for (i = 1; i <= selectedmultiedge.Size(); i++)
  417. {
  418. int ap1 = selectedmultiedge.Get(i).i1;
  419. int ap2 = selectedmultiedge.Get(i).i2;
  420. edgedata->Elem(edgedata->GetEdgeNum(ap1,ap2)).SetStatus(ED_EXCLUDED);
  421. }
  422. }
  423. }
  424. }
  425. void STLGeometry :: STLDoctorUndefinedEdge()
  426. {
  427. StoreEdgeData();
  428. if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT() && GetNodeOfSelTrig())
  429. {
  430. if (stldoctor.selectmode == 1)
  431. {
  432. int ap1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig());
  433. int ap2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1);
  434. edgedata->Elem(edgedata->GetEdgeNum(ap1,ap2)).SetStatus(ED_UNDEFINED);
  435. }
  436. else if (stldoctor.selectmode == 3 || stldoctor.selectmode == 4)
  437. {
  438. int i;
  439. for (i = 1; i <= selectedmultiedge.Size(); i++)
  440. {
  441. int ap1 = selectedmultiedge.Get(i).i1;
  442. int ap2 = selectedmultiedge.Get(i).i2;
  443. edgedata->Elem(edgedata->GetEdgeNum(ap1,ap2)).SetStatus(ED_UNDEFINED);
  444. }
  445. }
  446. }
  447. }
  448. void STLGeometry :: STLDoctorSetAllUndefinedEdges()
  449. {
  450. edgedata->ResetAll();
  451. }
  452. void STLGeometry :: STLDoctorEraseCandidateEdges()
  453. {
  454. StoreEdgeData();
  455. edgedata->ChangeStatus(ED_CANDIDATE, ED_UNDEFINED);
  456. }
  457. void STLGeometry :: STLDoctorConfirmCandidateEdges()
  458. {
  459. StoreEdgeData();
  460. edgedata->ChangeStatus(ED_CANDIDATE, ED_CONFIRMED);
  461. }
  462. void STLGeometry :: STLDoctorConfirmedToCandidateEdges()
  463. {
  464. StoreEdgeData();
  465. edgedata->ChangeStatus(ED_CONFIRMED, ED_CANDIDATE);
  466. }
  467. void STLGeometry :: STLDoctorDirtyEdgesToCandidates()
  468. {
  469. StoreEdgeData();
  470. }
  471. void STLGeometry :: STLDoctorLongLinesToCandidates()
  472. {
  473. StoreEdgeData();
  474. }
  475. twoint STLGeometry :: GetNearestSelectedDefinedEdge()
  476. {
  477. Point<3> pestimate = Center(GetTriangle(GetSelectTrig()).center,
  478. GetPoint(GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig())));
  479. //Point3d pestimate = GetTriangle(GetSelectTrig()).center;
  480. int i, j, en;
  481. Array<int> vic;
  482. GetVicinity(GetSelectTrig(),4,vic);
  483. twoint fedg;
  484. fedg.i1 = 0;
  485. fedg.i2 = 0;
  486. double mindist = 1E50;
  487. double dist;
  488. Point<3> p;
  489. for (i = 1; i <= vic.Size(); i++)
  490. {
  491. const STLTriangle& t = GetTriangle(vic.Get(i));
  492. for (j = 1; j <= 3; j++)
  493. {
  494. en = edgedata->GetEdgeNum(t.PNum(j),t.PNumMod(j+1));
  495. if (edgedata->Get(en).GetStatus() != ED_UNDEFINED)
  496. {
  497. p = pestimate;
  498. dist = GetDistFromLine(GetPoint(t.PNum(j)),GetPoint(t.PNumMod(j+1)),p);
  499. if (dist < mindist)
  500. {
  501. mindist = dist;
  502. fedg.i1 = t.PNum(j);
  503. fedg.i2 = t.PNumMod(j+1);
  504. }
  505. }
  506. }
  507. }
  508. return fedg;
  509. }
  510. void STLGeometry :: BuildSelectedMultiEdge(twoint ep)
  511. {
  512. if (edgedata->Size() == 0 ||
  513. !GetEPPSize())
  514. {
  515. return;
  516. }
  517. selectedmultiedge.SetSize(0);
  518. int tenum = GetTopEdgeNum (ep.i1, ep.i2);
  519. if (edgedata->Get(tenum).GetStatus() == ED_UNDEFINED)
  520. {
  521. twoint epnew = GetNearestSelectedDefinedEdge();
  522. if (epnew.i1)
  523. {
  524. ep = epnew;
  525. tenum = GetTopEdgeNum (ep.i1, ep.i2);
  526. }
  527. }
  528. selectedmultiedge.Append(twoint(ep));
  529. if (edgedata->Get(tenum).GetStatus() == ED_UNDEFINED)
  530. {
  531. return;
  532. }
  533. edgedata->BuildLineWithEdge(ep.i1,ep.i2,selectedmultiedge);
  534. }
  535. void STLGeometry :: BuildSelectedEdge(twoint ep)
  536. {
  537. if (edgedata->Size() == 0 ||
  538. !GetEPPSize())
  539. {
  540. return;
  541. }
  542. selectedmultiedge.SetSize(0);
  543. selectedmultiedge.Append(twoint(ep));
  544. }
  545. void STLGeometry :: BuildSelectedCluster(twoint ep)
  546. {
  547. if (edgedata->Size() == 0 ||
  548. !GetEPPSize())
  549. {
  550. return;
  551. }
  552. selectedmultiedge.SetSize(0);
  553. int tenum = GetTopEdgeNum (ep.i1, ep.i2);
  554. if (edgedata->Get(tenum).GetStatus() == ED_UNDEFINED)
  555. {
  556. twoint epnew = GetNearestSelectedDefinedEdge();
  557. if (epnew.i1)
  558. {
  559. ep = epnew;
  560. tenum = GetTopEdgeNum (ep.i1, ep.i2);
  561. }
  562. }
  563. selectedmultiedge.Append(twoint(ep));
  564. if (edgedata->Get(tenum).GetStatus() == ED_UNDEFINED)
  565. {
  566. return;
  567. }
  568. edgedata->BuildClusterWithEdge(ep.i1,ep.i2,selectedmultiedge);
  569. }
  570. void STLGeometry :: ImportEdges()
  571. {
  572. StoreEdgeData();
  573. PrintMessage(5, "import edges from file 'edges.ng'");
  574. ifstream fin("edges.ng");
  575. int ne;
  576. fin >> ne;
  577. Array<Point<3> > eps;
  578. int i;
  579. Point<3> p;
  580. for (i = 1; i <= 2*ne; i++)
  581. {
  582. fin >> p(0);
  583. fin >> p(1);
  584. fin >> p(2);
  585. eps.Append(p);
  586. }
  587. AddEdges(eps);
  588. }
  589. void STLGeometry :: AddEdges(const Array<Point<3> >& eps)
  590. {
  591. int i;
  592. int ne = eps.Size()/2;
  593. Array<int> epsi;
  594. Box<3> bb = GetBoundingBox();
  595. bb.Increase(1);
  596. Point3dTree ptree (bb.PMin(),
  597. bb.PMax());
  598. Array<int> pintersect;
  599. double gtol = GetBoundingBox().Diam()/1.E10;
  600. Point<3> p;
  601. for (i = 1; i <= GetNP(); i++)
  602. {
  603. p = GetPoint(i);
  604. ptree.Insert (p, i);
  605. }
  606. int error = 0;
  607. for (i = 1; i <= 2*ne; i++)
  608. {
  609. p = eps.Get(i);
  610. Point3d pmin = p - Vec3d (gtol, gtol, gtol);
  611. Point3d pmax = p + Vec3d (gtol, gtol, gtol);
  612. ptree.GetIntersecting (pmin, pmax, pintersect);
  613. if (pintersect.Size() > 1)
  614. {
  615. PrintError("Found too much points in epsilon-dist");
  616. error = 1;
  617. }
  618. else if (pintersect.Size() == 0)
  619. {
  620. error = 1;
  621. PrintError("edgepoint does not exist!");
  622. PrintMessage(5,"p=",Point3d(eps.Get(i)));
  623. }
  624. else
  625. {
  626. epsi.Append(pintersect.Get(1));
  627. }
  628. }
  629. if (error) return;
  630. int en;
  631. for (i = 1; i <= ne; i++)
  632. {
  633. if (epsi.Get(2*i-1) == epsi.Get(2*i)) {PrintError("Edge with zero length!");}
  634. else
  635. {
  636. en = edgedata->GetEdgeNum(epsi.Get(2*i-1),epsi.Get(2*i));
  637. edgedata->Elem(en).SetStatus (ED_CONFIRMED);
  638. }
  639. }
  640. }
  641. void STLGeometry :: ImportExternalEdges(const char * filename)
  642. {
  643. //AVL edges!!!!!!
  644. ifstream inf (filename);
  645. char ch;
  646. //int cnt = 0;
  647. int records, units, i, j;
  648. PrintFnStart("Import edges from ",filename);
  649. const int flen=30;
  650. char filter[flen+1];
  651. filter[flen] = 0;
  652. char buf[20];
  653. Array<Point3d> importpoints;
  654. Array<int> importlines;
  655. Array<int> importpnums;
  656. while (inf.good())
  657. {
  658. inf.get(ch);
  659. // (*testout) << cnt << ": " << ch << endl;
  660. for (i = 0; i < flen; i++)
  661. filter[i] = filter[i+1];
  662. filter[flen-1] = ch;
  663. // (*testout) << filter << endl;
  664. if (strcmp (filter+flen-7, "RECORDS") == 0)
  665. {
  666. inf.get(ch); // '='
  667. inf >> records;
  668. }
  669. if (strcmp (filter+flen-5, "UNITS") == 0)
  670. {
  671. inf.get(ch); // '='
  672. inf >> units;
  673. }
  674. if (strcmp (filter+flen-17, "EDGE NODE NUMBERS") == 0)
  675. {
  676. int nodenr;
  677. importlines.SetSize (units);
  678. for (i = 1; i <= units; i++)
  679. {
  680. inf >> nodenr;
  681. importlines.Elem(i) = nodenr;
  682. // (*testout) << nodenr << endl;
  683. }
  684. }
  685. if (strcmp (filter+flen-23, "EDGE POINT COORD IN DIR") == 0)
  686. {
  687. int coord;
  688. inf >> coord;
  689. importpoints.SetSize (units);
  690. inf >> ch;
  691. inf.putback (ch);
  692. for (i = 1; i <= units; i++)
  693. {
  694. for (j = 0; j < 12; j++)
  695. inf.get (buf[j]);
  696. buf[12] = 0;
  697. importpoints.Elem(i).X(coord) = 1000 * atof (buf);
  698. }
  699. }
  700. }
  701. /*
  702. (*testout) << "lines: " << endl;
  703. for (i = 1; i <= importlines.Size(); i++)
  704. (*testout) << importlines.Get(i) << endl;
  705. (*testout) << "points: " << endl;
  706. for (i = 1; i <= importpoints.Size(); i++)
  707. (*testout) << importpoints.Get(i) << endl;
  708. */
  709. importpnums.SetSize (importpoints.Size());
  710. Box3d bb (GetBoundingBox().PMin() + Vec3d (-1,-1,-1),
  711. GetBoundingBox().PMax() + Vec3d (1, 1, 1));
  712. Point3dTree ptree (bb.PMin(),
  713. bb.PMax());
  714. PrintMessage(7,"stl - bb: ",bb.PMin(), " - ", bb.PMax());
  715. Box3d ebb;
  716. ebb.SetPoint (importpoints.Get(1));
  717. for (i = 1; i <= importpoints.Size(); i++)
  718. ebb.AddPoint (importpoints.Get(i));
  719. PrintMessage(7,"edgep - bb: ", ebb.PMin(), " - ", ebb.PMax());
  720. Array<int> pintersect;
  721. double gtol = GetBoundingBox().Diam()/1.E6;
  722. for (i = 1; i <= GetNP(); i++)
  723. {
  724. Point3d p = GetPoint(i);
  725. // (*testout) << "stlpt: " << p << endl;
  726. ptree.Insert (p, i);
  727. }
  728. for (i = 1; i <= importpoints.Size(); i++)
  729. {
  730. Point3d p = importpoints.Get(i);
  731. Point3d pmin = p - Vec3d (gtol, gtol, gtol);
  732. Point3d pmax = p + Vec3d (gtol, gtol, gtol);
  733. ptree.GetIntersecting (pmin, pmax, pintersect);
  734. if (pintersect.Size() > 1)
  735. {
  736. importpnums.Elem(i) = 0;
  737. PrintError("Found too many points in epsilon-dist");
  738. }
  739. else if (pintersect.Size() == 0)
  740. {
  741. importpnums.Elem(i) = 0;
  742. PrintError("Edgepoint does not exist!");
  743. }
  744. else
  745. {
  746. importpnums.Elem(i) = pintersect.Get(1);
  747. }
  748. }
  749. // if (!error)
  750. {
  751. PrintMessage(7,"found all edge points in stl file");
  752. StoreEdgeData();
  753. int oldp = 0;
  754. for (i = 1; i <= importlines.Size(); i++)
  755. {
  756. int newp = importlines.Get(i);
  757. if (!importpnums.Get(abs(newp)))
  758. newp = 0;
  759. if (oldp && newp)
  760. {
  761. int en = edgedata->GetEdgeNum(importpnums.Get(oldp),
  762. importpnums.Get(abs(newp)));
  763. edgedata->Elem(en).SetStatus (ED_CONFIRMED);
  764. }
  765. if (newp < 0)
  766. oldp = 0;
  767. else
  768. oldp = newp;
  769. }
  770. }
  771. }
  772. void STLGeometry :: ExportEdges()
  773. {
  774. PrintFnStart("Save edges to file 'edges.ng'");
  775. ofstream fout("edges.ng");
  776. fout.precision(16);
  777. int n = edgedata->GetNConfEdges();
  778. fout << n << endl;
  779. int i;
  780. for (i = 1; i <= edgedata->Size(); i++)
  781. {
  782. if (edgedata->Get(i).GetStatus() == ED_CONFIRMED)
  783. {
  784. const STLTopEdge & e = edgedata->Get(i);
  785. fout << GetPoint(e.PNum(1))(0) << " " << GetPoint(e.PNum(1))(1) << " " << GetPoint(e.PNum(1))(2) << endl;
  786. fout << GetPoint(e.PNum(2))(0) << " " << GetPoint(e.PNum(2))(1) << " " << GetPoint(e.PNum(2))(2) << endl;
  787. }
  788. }
  789. }
  790. void STLGeometry :: LoadEdgeData(const char* file)
  791. {
  792. StoreEdgeData();
  793. PrintFnStart("Load edges from file '", file, "'");
  794. ifstream fin(file);
  795. edgedata->Read(fin);
  796. // calcedgedataanglesnew = 1;
  797. }
  798. void STLGeometry :: SaveEdgeData(const char* file)
  799. {
  800. PrintFnStart("save edges to file '", file, "'");
  801. ofstream fout(file);
  802. edgedata->Write(fout);
  803. }
  804. /*
  805. void STLGeometry :: SaveExternalEdges()
  806. {
  807. ofstream fout("externaledgesp3.ng");
  808. fout.precision(16);
  809. int n = NOExternalEdges();
  810. fout << n << endl;
  811. int i;
  812. for (i = 1; i <= n; i++)
  813. {
  814. twoint e = GetExternalEdge(i);
  815. fout << GetPoint(e.i1)(0) << " " << GetPoint(e.i1)(1) << " " << GetPoint(e.i1)(2) << endl;
  816. fout << GetPoint(e.i2)(0) << " " << GetPoint(e.i2)(1) << " " << GetPoint(e.i2)(2) << endl;
  817. }
  818. }
  819. */
  820. void STLGeometry :: StoreExternalEdges()
  821. {
  822. storedexternaledges.SetSize(0);
  823. undoexternaledges = 1;
  824. int i;
  825. for (i = 1; i <= externaledges.Size(); i++)
  826. {
  827. storedexternaledges.Append(externaledges.Get(i));
  828. }
  829. }
  830. void STLGeometry :: UndoExternalEdges()
  831. {
  832. if (!undoexternaledges)
  833. {
  834. PrintMessage(1, "undo not further possible!");
  835. return;
  836. }
  837. RestoreExternalEdges();
  838. undoexternaledges = 0;
  839. }
  840. void STLGeometry :: RestoreExternalEdges()
  841. {
  842. externaledges.SetSize(0);
  843. int i;
  844. for (i = 1; i <= storedexternaledges.Size(); i++)
  845. {
  846. externaledges.Append(storedexternaledges.Get(i));
  847. }
  848. }
  849. void STLGeometry :: AddExternalEdgeAtSelected()
  850. {
  851. StoreExternalEdges();
  852. if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT())
  853. {
  854. int ap1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig());
  855. int ap2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1);
  856. if (!IsExternalEdge(ap1,ap2)) {AddExternalEdge(ap1,ap2);}
  857. }
  858. }
  859. void STLGeometry :: AddClosedLinesToExternalEdges()
  860. {
  861. StoreExternalEdges();
  862. int i, j;
  863. for (i = 1; i <= GetNLines(); i++)
  864. {
  865. STLLine* l = GetLine(i);
  866. if (l->StartP() == l->EndP())
  867. {
  868. for (j = 1; j < l->NP(); j++)
  869. {
  870. int ap1 = l->PNum(j);
  871. int ap2 = l->PNum(j+1);
  872. if (!IsExternalEdge(ap1,ap2)) {AddExternalEdge(ap1,ap2);}
  873. }
  874. }
  875. }
  876. }
  877. void STLGeometry :: AddLongLinesToExternalEdges()
  878. {
  879. StoreExternalEdges();
  880. double diamfact = stldoctor.dirtytrigfact;
  881. double diam = GetBoundingBox().Diam();
  882. int i, j;
  883. for (i = 1; i <= GetNLines(); i++)
  884. {
  885. STLLine* l = GetLine(i);
  886. if (l->GetLength(points) >= diamfact*diam)
  887. {
  888. for (j = 1; j < l->NP(); j++)
  889. {
  890. int ap1 = l->PNum(j);
  891. int ap2 = l->PNum(j+1);
  892. if (!IsExternalEdge(ap1,ap2)) {AddExternalEdge(ap1,ap2);}
  893. }
  894. }
  895. }
  896. }
  897. void STLGeometry :: AddAllNotSingleLinesToExternalEdges()
  898. {
  899. StoreExternalEdges();
  900. int i, j;
  901. for (i = 1; i <= GetNLines(); i++)
  902. {
  903. STLLine* l = GetLine(i);
  904. if (GetNEPP(l->StartP()) > 1 || GetNEPP(l->EndP()) > 1)
  905. {
  906. for (j = 1; j < l->NP(); j++)
  907. {
  908. int ap1 = l->PNum(j);
  909. int ap2 = l->PNum(j+1);
  910. if (!IsExternalEdge(ap1,ap2)) {AddExternalEdge(ap1,ap2);}
  911. }
  912. }
  913. }
  914. }
  915. void STLGeometry :: DeleteDirtyExternalEdges()
  916. {
  917. //delete single triangle edges and single edge-lines in clusters"
  918. StoreExternalEdges();
  919. int i, j;
  920. for (i = 1; i <= GetNLines(); i++)
  921. {
  922. STLLine* l = GetLine(i);
  923. if (l->NP() <= 3 || (l->StartP() == l->EndP() && l->NP() == 4))
  924. {
  925. for (j = 1; j < l->NP(); j++)
  926. {
  927. int ap1 = l->PNum(j);
  928. int ap2 = l->PNum(j+1);
  929. if (IsExternalEdge(ap1,ap2)) {DeleteExternalEdge(ap1,ap2);}
  930. }
  931. }
  932. }
  933. }
  934. void STLGeometry :: AddExternalEdgesFromGeomLine()
  935. {
  936. StoreExternalEdges();
  937. if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT())
  938. {
  939. int ap1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig());
  940. int ap2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1);
  941. if (IsEdge(ap1,ap2))
  942. {
  943. int edgenum = IsEdgeNum(ap1,ap2);
  944. if (!IsExternalEdge(ap1,ap2)) {AddExternalEdge(ap1,ap2);}
  945. int noend = 1;
  946. int startp = ap1;
  947. int laste = edgenum;
  948. int np1, np2;
  949. while (noend)
  950. {
  951. if (GetNEPP(startp) == 2)
  952. {
  953. if (GetEdgePP(startp,1) != laste) {laste = GetEdgePP(startp,1);}
  954. else {laste = GetEdgePP(startp,2);}
  955. np1 = GetEdge(laste).PNum(1);
  956. np2 = GetEdge(laste).PNum(2);
  957. if (!IsExternalEdge(np1, np2)) {AddExternalEdge(np1, np2);}
  958. else {noend = 0;}
  959. if (np1 != startp) {startp = np1;}
  960. else {startp = np2;}
  961. }
  962. else {noend = 0;}
  963. }
  964. startp = ap2;
  965. laste = edgenum;
  966. noend = 1;
  967. while (noend)
  968. {
  969. if (GetNEPP(startp) == 2)
  970. {
  971. if (GetEdgePP(startp,1) != laste) {laste = GetEdgePP(startp,1);}
  972. else {laste = GetEdgePP(startp,2);}
  973. np1 = GetEdge(laste).PNum(1);
  974. np2 = GetEdge(laste).PNum(2);
  975. if (!IsExternalEdge(np1, np2)) {AddExternalEdge(np1, np2);}
  976. else {noend = 0;}
  977. if (np1 != startp) {startp = np1;}
  978. else {startp = np2;}
  979. }
  980. else {noend = 0;}
  981. }
  982. }
  983. }
  984. }
  985. void STLGeometry :: ClearEdges()
  986. {
  987. edgesfound = 0;
  988. edges.SetSize(0);
  989. //edgedata->SetSize(0);
  990. // externaledges.SetSize(0);
  991. edgesperpoint.SetSize(0);
  992. undoexternaledges = 0;
  993. }
  994. void STLGeometry :: STLDoctorBuildEdges()
  995. {
  996. // if (!trigsconverted) {return;}
  997. ClearEdges();
  998. meshlines.SetSize(0);
  999. FindEdgesFromAngles();
  1000. }
  1001. void STLGeometry :: DeleteExternalEdgeAtSelected()
  1002. {
  1003. StoreExternalEdges();
  1004. if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT())
  1005. {
  1006. int ap1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig());
  1007. int ap2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1);
  1008. if (IsExternalEdge(ap1,ap2)) {DeleteExternalEdge(ap1,ap2);}
  1009. }
  1010. }
  1011. void STLGeometry :: DeleteExternalEdgeInVicinity()
  1012. {
  1013. StoreExternalEdges();
  1014. if (!stldoctor.showvicinity || vicinity.Size() != GetNT()) {return;}
  1015. int i, j, ap1, ap2;
  1016. for (i = 1; i <= GetNT(); i++)
  1017. {
  1018. if (vicinity.Elem(i))
  1019. {
  1020. for (j = 1; j <= 3; j++)
  1021. {
  1022. ap1 = GetTriangle(i).PNum(j);
  1023. ap2 = GetTriangle(i).PNumMod(j+1);
  1024. if (IsExternalEdge(ap1,ap2))
  1025. {
  1026. DeleteExternalEdge(ap1,ap2);
  1027. }
  1028. }
  1029. }
  1030. }
  1031. }
  1032. void STLGeometry :: BuildExternalEdgesFromEdges()
  1033. {
  1034. StoreExternalEdges();
  1035. if (GetNE() == 0) {PrintWarning("Edges possibly not generated!");}
  1036. int i;
  1037. externaledges.SetSize(0);
  1038. for (i = 1; i <= GetNE(); i++)
  1039. {
  1040. STLEdge e = GetEdge(i);
  1041. AddExternalEdge(e.PNum(1), e.PNum(2));
  1042. }
  1043. }
  1044. void STLGeometry :: AddExternalEdge(int ap1, int ap2)
  1045. {
  1046. externaledges.Append(twoint(ap1,ap2));
  1047. }
  1048. void STLGeometry :: DeleteExternalEdge(int ap1, int ap2)
  1049. {
  1050. int i;
  1051. int found = 0;
  1052. for (i = 1; i <= NOExternalEdges(); i++)
  1053. {
  1054. if ((GetExternalEdge(i).i1 == ap1 && GetExternalEdge(i).i2 == ap2) ||
  1055. (GetExternalEdge(i).i1 == ap2 && GetExternalEdge(i).i2 == ap1)) {found = 1;};
  1056. if (found && i < NOExternalEdges())
  1057. {
  1058. externaledges.Elem(i) = externaledges.Get(i+1);
  1059. }
  1060. }
  1061. if (!found) {PrintWarning("edge not found");}
  1062. else
  1063. {
  1064. externaledges.SetSize(externaledges.Size()-1);
  1065. }
  1066. }
  1067. int STLGeometry :: IsExternalEdge(int ap1, int ap2)
  1068. {
  1069. int i;
  1070. for (i = 1; i <= NOExternalEdges(); i++)
  1071. {
  1072. if ((GetExternalEdge(i).i1 == ap1 && GetExternalEdge(i).i2 == ap2) ||
  1073. (GetExternalEdge(i).i1 == ap2 && GetExternalEdge(i).i2 == ap1)) {return 1;};
  1074. }
  1075. return 0;
  1076. }
  1077. void STLGeometry :: DestroyDirtyTrigs()
  1078. {
  1079. PrintFnStart("Destroy dirty triangles");
  1080. PrintMessage(5,"original number of triangles=", GetNT());
  1081. //destroy every triangle with other than 3 neighbours;
  1082. int changed = 1;
  1083. int i, j, k;
  1084. while (changed)
  1085. {
  1086. changed = 0;
  1087. Clear();
  1088. for (i = 1; i <= GetNT(); i++)
  1089. {
  1090. int dirty = NONeighbourTrigs(i) < 3;
  1091. for (j = 1; j <= 3; j++)
  1092. {
  1093. int pnum = GetTriangle(i).PNum(j);
  1094. /*
  1095. if (pnum == 1546)
  1096. {
  1097. // for (k = 1; k <= NOTrigsPerPoint(pnum); k++)
  1098. }
  1099. */
  1100. if (NOTrigsPerPoint(pnum) <= 2)
  1101. dirty = 1;
  1102. }
  1103. int pi1 = GetTriangle(i).PNum(1);
  1104. int pi2 = GetTriangle(i).PNum(2);
  1105. int pi3 = GetTriangle(i).PNum(3);
  1106. if (pi1 == pi2 || pi1 == pi3 || pi2 == pi3)
  1107. {
  1108. PrintMessage(5,"triangle with Volume 0: ", i, " nodes: ", pi1, ", ", pi2, ", ", pi3);
  1109. dirty = 1;
  1110. }
  1111. if (dirty)
  1112. {
  1113. for (k = i+1; k <= GetNT(); k++)
  1114. {
  1115. trias.Elem(k-1) = trias.Get(k);
  1116. // readtrias: not longer permanent, JS
  1117. // readtrias.Elem(k-1) = readtrias.Get(k);
  1118. }
  1119. int size = GetNT();
  1120. trias.SetSize(size-1);
  1121. // readtrias.SetSize(size-1);
  1122. changed = 1;
  1123. break;
  1124. }
  1125. }
  1126. }
  1127. FindNeighbourTrigs();
  1128. PrintMessage(5,"final number of triangles=", GetNT());
  1129. }
  1130. void STLGeometry :: CalcNormalsFromGeometry()
  1131. {
  1132. int i;
  1133. for (i = 1; i <= GetNT(); i++)
  1134. {
  1135. const STLTriangle & tr = GetTriangle(i);
  1136. const Point3d& ap1 = GetPoint(tr.PNum(1));
  1137. const Point3d& ap2 = GetPoint(tr.PNum(2));
  1138. const Point3d& ap3 = GetPoint(tr.PNum(3));
  1139. Vec3d normal = Cross (ap2-ap1, ap3-ap1);
  1140. if (normal.Length() != 0)
  1141. {
  1142. normal /= (normal.Length());
  1143. }
  1144. GetTriangle(i).SetNormal(normal);
  1145. }
  1146. PrintMessage(5,"Normals calculated from geometry!!!");
  1147. calcedgedataanglesnew = 1;
  1148. }
  1149. void STLGeometry :: SetSelectTrig(int trig)
  1150. {
  1151. stldoctor.selecttrig = trig;
  1152. }
  1153. int STLGeometry :: GetSelectTrig() const
  1154. {
  1155. return stldoctor.selecttrig;
  1156. }
  1157. void STLGeometry :: SetNodeOfSelTrig(int n)
  1158. {
  1159. stldoctor.nodeofseltrig = n;
  1160. }
  1161. int STLGeometry :: GetNodeOfSelTrig() const
  1162. {
  1163. return stldoctor.nodeofseltrig;
  1164. }
  1165. void STLGeometry :: MoveSelectedPointToMiddle()
  1166. {
  1167. if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT())
  1168. {
  1169. int p = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig());
  1170. Point<3> pm(0.,0.,0.); //Middlevector;
  1171. Point<3> p0(0.,0.,0.);
  1172. PrintMessage(5,"original point=", Point3d(GetPoint(p)));
  1173. int i;
  1174. int cnt = 0;
  1175. for (i = 1; i <= trigsperpoint.EntrySize(p); i++)
  1176. {
  1177. const STLTriangle& tr = GetTriangle(trigsperpoint.Get(p,i));
  1178. int j;
  1179. for (j = 1; j <= 3; j++)
  1180. {
  1181. if (tr.PNum(j) != p)
  1182. {
  1183. cnt++;
  1184. pm(0) += GetPoint(tr.PNum(j))(0);
  1185. pm(1) += GetPoint(tr.PNum(j))(1);
  1186. pm(2) += GetPoint(tr.PNum(j))(2);
  1187. }
  1188. }
  1189. }
  1190. Point<3> origp = GetPoint(p);
  1191. double fact = 0.2;
  1192. SetPoint(p, p0 + fact*(1./(double)cnt)*(pm-p0)+(1.-fact)*(origp-p0));
  1193. PrintMessage(5,"middle point=", Point3d (GetPoint(p)));
  1194. PrintMessage(5,"moved point ", Point3d (p));
  1195. }
  1196. }
  1197. void STLGeometry :: PrintSelectInfo()
  1198. {
  1199. //int trig = GetSelectTrig();
  1200. //int p = GetTriangle(trig).PNum(GetNodeOfSelTrig());
  1201. PrintMessage(1,"touch triangle ", GetSelectTrig()
  1202. , ", local node ", GetNodeOfSelTrig()
  1203. , " (=", GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig()), ")");
  1204. if (AtlasMade() && GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT())
  1205. {
  1206. PrintMessage(1," chartnum=",GetChartNr(GetSelectTrig()));
  1207. /*
  1208. PointBetween(Center(Center(GetPoint(GetTriangle(270).PNum(1)),
  1209. GetPoint(GetTriangle(270).PNum(2))),
  1210. GetPoint(GetTriangle(270).PNum(3))),270,
  1211. Center(Center(GetPoint(GetTriangle(trig).PNum(1)),
  1212. GetPoint(GetTriangle(trig).PNum(2))),
  1213. GetPoint(GetTriangle(trig).PNum(3))),trig);
  1214. */
  1215. //PointBetween(Point3d(5.7818, 7.52768, 4.14879),260,Point3d(6.80292, 6.55392, 4.70184),233);
  1216. }
  1217. }
  1218. void STLGeometry :: ShowSelectedTrigChartnum()
  1219. {
  1220. int st = GetSelectTrig();
  1221. if (st >= 1 && st <= GetNT() && AtlasMade())
  1222. PrintMessage(1,"selected trig ", st, " has chartnumber ", GetChartNr(st));
  1223. }
  1224. void STLGeometry :: ShowSelectedTrigCoords()
  1225. {
  1226. int st = GetSelectTrig();
  1227. /*
  1228. //testing!!!!
  1229. Array<int> trigs;
  1230. GetSortedTrianglesAroundPoint(GetTriangle(st).PNum(GetNodeOfSelTrig()),st,trigs);
  1231. */
  1232. if (st >= 1 && st <= GetNT())
  1233. {
  1234. PrintMessage(1, "coordinates of selected trig ", st, ":");
  1235. PrintMessage(1, " p1 = ", GetTriangle(st).PNum(1), " = ",
  1236. Point3d (GetPoint(GetTriangle(st).PNum(1))));
  1237. PrintMessage(1, " p2 = ", GetTriangle(st).PNum(2), " = ",
  1238. Point3d (GetPoint(GetTriangle(st).PNum(2))));
  1239. PrintMessage(1, " p3 = ", GetTriangle(st).PNum(3), " = ",
  1240. Point3d (GetPoint(GetTriangle(st).PNum(3))));
  1241. }
  1242. }
  1243. void STLGeometry :: LoadMarkedTrigs()
  1244. {
  1245. PrintFnStart("load marked trigs from file 'markedtrigs.ng'");
  1246. ifstream fin("markedtrigs.ng");
  1247. int n;
  1248. fin >> n;
  1249. if (n != GetNT() || n == 0) {PrintError("Not a suitable marked-trig-file!"); return;}
  1250. int i, m;
  1251. for (i = 1; i <= n; i++)
  1252. {
  1253. fin >> m;
  1254. SetMarkedTrig(i, m);
  1255. }
  1256. fin >> n;
  1257. if (n != 0)
  1258. {
  1259. Point<3> ap1, ap2;
  1260. for (i = 1; i <= n; i++)
  1261. {
  1262. fin >> ap1(0); fin >> ap1(1); fin >> ap1(2);
  1263. fin >> ap2(0); fin >> ap2(1); fin >> ap2(2);
  1264. AddMarkedSeg(ap1,ap2);
  1265. }
  1266. }
  1267. }
  1268. void STLGeometry :: SaveMarkedTrigs()
  1269. {
  1270. PrintFnStart("save marked trigs to file 'markedtrigs.ng'");
  1271. ofstream fout("markedtrigs.ng");
  1272. int n = GetNT();
  1273. fout << n << endl;
  1274. int i;
  1275. for (i = 1; i <= n; i++)
  1276. {
  1277. fout << IsMarkedTrig(i) << "\n";
  1278. }
  1279. n = GetNMarkedSegs();
  1280. fout << n << endl;
  1281. Point<3> ap1,ap2;
  1282. for (i = 1; i <= n; i++)
  1283. {
  1284. GetMarkedSeg(i,ap1,ap2);
  1285. fout << ap1(0) << " " << ap1(1) << " " << ap1(2) << " ";
  1286. fout << ap2(0) << " " << ap2(1) << " " << ap2(2) << " " << "\n";
  1287. }
  1288. }
  1289. void STLGeometry :: NeighbourAnglesOfSelectedTrig()
  1290. {
  1291. int st = GetSelectTrig();
  1292. if (st >= 1 && st <= GetNT())
  1293. {
  1294. int i;
  1295. PrintMessage(1,"Angle to triangle ", st, ":");
  1296. for (i = 1; i <= NONeighbourTrigs(st); i++)
  1297. {
  1298. PrintMessage(1," triangle ", NeighbourTrig(st,i), ": angle = ",
  1299. 180./M_PI*GetAngle(st, NeighbourTrig(st,i)), "°",
  1300. ", calculated = ", 180./M_PI*Angle(GetTriangle(st).GeomNormal(points),
  1301. GetTriangle(NeighbourTrig(st,i)).GeomNormal(points)), "°");
  1302. }
  1303. }
  1304. }
  1305. void STLGeometry :: GetVicinity(int starttrig, int size, Array<int>& vic)
  1306. {
  1307. if (starttrig == 0 || starttrig > GetNT()) {return;}
  1308. Array<int> vicarray;
  1309. vicarray.SetSize(GetNT());
  1310. int i;
  1311. for (i = 1; i <= vicarray.Size(); i++)
  1312. {
  1313. vicarray.Elem(i) = 0;
  1314. }
  1315. vicarray.Elem(starttrig) = 1;
  1316. int j = 0,k;
  1317. Array <int> list1;
  1318. list1.SetSize(0);
  1319. Array <int> list2;
  1320. list2.SetSize(0);
  1321. list1.Append(starttrig);
  1322. while (j < size)
  1323. {
  1324. j++;
  1325. for (i = 1; i <= list1.Size(); i++)
  1326. {
  1327. for (k = 1; k <= NONeighbourTrigs(i); k++)
  1328. {
  1329. int nbtrig = NeighbourTrig(list1.Get(i),k);
  1330. if (nbtrig && vicarray.Get(nbtrig) == 0)
  1331. {
  1332. list2.Append(nbtrig);
  1333. vicarray.Elem(nbtrig) = 1;
  1334. }
  1335. }
  1336. }
  1337. list1.SetSize(0);
  1338. for (i = 1; i <= list2.Size(); i++)
  1339. {
  1340. list1.Append(list2.Get(i));
  1341. }
  1342. list2.SetSize(0);
  1343. }
  1344. vic.SetSize(0);
  1345. for (i = 1; i <= vicarray.Size(); i++)
  1346. {
  1347. if (vicarray.Get(i)) {vic.Append(i);}
  1348. }
  1349. }
  1350. void STLGeometry :: CalcVicinity(int starttrig)
  1351. {
  1352. if (starttrig == 0 || starttrig > GetNT()) {return;}
  1353. vicinity.SetSize(GetNT());
  1354. if (!stldoctor.showvicinity) {return;}
  1355. int i;
  1356. for (i = 1; i <= vicinity.Size(); i++)
  1357. {
  1358. vicinity.Elem(i) = 0;
  1359. }
  1360. vicinity.Elem(starttrig) = 1;
  1361. int j = 0,k;
  1362. Array <int> list1;
  1363. list1.SetSize(0);
  1364. Array <int> list2;
  1365. list2.SetSize(0);
  1366. list1.Append(starttrig);
  1367. // int cnt = 1;
  1368. while (j < stldoctor.vicinity)
  1369. {
  1370. j++;
  1371. for (i = 1; i <= list1.Size(); i++)
  1372. {
  1373. for (k = 1; k <= NONeighbourTrigs(i); k++)
  1374. {
  1375. int nbtrig = NeighbourTrig(list1.Get(i),k);
  1376. if (nbtrig && vicinity.Get(nbtrig) == 0)
  1377. {
  1378. list2.Append(nbtrig);
  1379. vicinity.Elem(nbtrig) = 1;
  1380. //cnt++;
  1381. }
  1382. }
  1383. }
  1384. list1.SetSize(0);
  1385. for (i = 1; i <= list2.Size(); i++)
  1386. {
  1387. list1.Append(list2.Get(i));
  1388. }
  1389. list2.SetSize(0);
  1390. }
  1391. }
  1392. int STLGeometry :: Vicinity(int trig) const
  1393. {
  1394. if (trig <= vicinity.Size() && trig >=1)
  1395. {
  1396. return vicinity.Get(trig);
  1397. }
  1398. else {PrintSysError("In STLGeometry::Vicinity");}
  1399. return 0;
  1400. }
  1401. void STLGeometry :: InitMarkedTrigs()
  1402. {
  1403. markedtrigs.SetSize(GetNT());
  1404. int i;
  1405. for (i = 1; i <= GetNT(); i++)
  1406. {
  1407. SetMarkedTrig(i, 0);
  1408. }
  1409. }
  1410. void STLGeometry :: MarkDirtyTrigs()
  1411. {
  1412. PrintFnStart("mark dirty trigs");
  1413. int i,j;
  1414. markedtrigs.SetSize(GetNT());
  1415. for (i = 1; i <= GetNT(); i++)
  1416. {
  1417. SetMarkedTrig(i, 0);
  1418. }
  1419. int found;
  1420. double dirtyangle = stlparam.yangle/2./180.*M_PI;
  1421. int cnt = 0;
  1422. for (i = 1; i <= GetNT(); i++)
  1423. {
  1424. found = 0;
  1425. for (j = 1; j <= NONeighbourTrigs(i); j++)
  1426. {
  1427. if (GetAngle(i, NeighbourTrig(i,j)) > dirtyangle)
  1428. {
  1429. found++;
  1430. }
  1431. }
  1432. if (found && GetTriangle(i).MinHeight(points) <
  1433. stldoctor.dirtytrigfact*GetTriangle(i).MaxLength(points))
  1434. {
  1435. SetMarkedTrig(i, 1); cnt++;
  1436. }
  1437. /*
  1438. else if (found == 3)
  1439. {
  1440. SetMarkedTrig(i, 1); cnt++;
  1441. }
  1442. */
  1443. }
  1444. PrintMessage(1, "marked ", cnt, " dirty trigs");
  1445. }
  1446. void STLGeometry :: MarkTopErrorTrigs()
  1447. {
  1448. int cnt = 0;
  1449. markedtrigs.SetSize(GetNT());
  1450. for (int i = 1; i <= GetNT(); i++)
  1451. {
  1452. const STLTriangle & trig = GetTriangle(i);
  1453. SetMarkedTrig(i, trig.flags.toperror);
  1454. if (trig.flags.toperror) cnt++;
  1455. }
  1456. PrintMessage(1,"marked ", cnt, " inconsistent triangles");
  1457. }
  1458. double STLGeometry :: CalcTrigBadness(int i)
  1459. {
  1460. int j;
  1461. double maxbadness = 0;
  1462. int ap1, ap2;
  1463. for (j = 1; j <= NONeighbourTrigs(i); j++)
  1464. {
  1465. GetTriangle(i).GetNeighbourPoints(GetTriangle(NeighbourTrig(i,j)), ap1, ap2);
  1466. if (!IsEdge(ap1,ap2) && GetGeomAngle(i, NeighbourTrig(i,j)) > maxbadness)
  1467. {
  1468. maxbadness = GetGeomAngle(i, NeighbourTrig(i,j));
  1469. }
  1470. }
  1471. return maxbadness;
  1472. }
  1473. void STLGeometry :: GeomSmoothRevertedTrigs()
  1474. {
  1475. //double revertedangle = stldoctor.smoothangle/180.*M_PI;
  1476. double fact = stldoctor.dirtytrigfact;
  1477. MarkRevertedTrigs();
  1478. int i, j, k, l, p;
  1479. for (i = 1; i <= GetNT(); i++)
  1480. {
  1481. if (IsMarkedTrig(i))
  1482. {
  1483. for (j = 1; j <= 3; j++)
  1484. {
  1485. double origbadness = CalcTrigBadness(i);
  1486. p = GetTriangle(i).PNum(j);
  1487. Point<3> pm(0.,0.,0.); //Middlevector;
  1488. Point<3> p0(0.,0.,0.);
  1489. int cnt = 0;
  1490. for (k = 1; k <= trigsperpoint.EntrySize(p); k++)
  1491. {
  1492. const STLTriangle& tr = GetTriangle(trigsperpoint.Get(p,k));
  1493. for (l = 1; l <= 3; l++)
  1494. {
  1495. if (tr.PNum(l) != p)
  1496. {
  1497. cnt++;
  1498. pm(0) += GetPoint(tr.PNum(l))(0);
  1499. pm(1) += GetPoint(tr.PNum(l))(1);
  1500. pm(2) += GetPoint(tr.PNum(l))(2);
  1501. }
  1502. }
  1503. }
  1504. Point3d origp = GetPoint(p);
  1505. Point3d newp = p0 + fact*(1./(double)cnt)*(pm-p0)+(1.-fact)*(origp-p0);
  1506. SetPoint(p, newp);
  1507. if (CalcTrigBadness(i) > 0.9*origbadness) {SetPoint(p,origp); PrintDot('f');}
  1508. else {PrintDot('s');}
  1509. }
  1510. }
  1511. }
  1512. MarkRevertedTrigs();
  1513. }
  1514. void STLGeometry :: MarkRevertedTrigs()
  1515. {
  1516. int i,j;
  1517. if (edgesperpoint.Size() != GetNP()) {BuildEdges();}
  1518. PrintFnStart("mark reverted trigs");
  1519. InitMarkedTrigs();
  1520. int found;
  1521. double revertedangle = stldoctor.smoothangle/180.*M_PI;
  1522. int cnt = 0;
  1523. int ap1, ap2;
  1524. for (i = 1; i <= GetNT(); i++)
  1525. {
  1526. found = 0;
  1527. for (j = 1; j <= NONeighbourTrigs(i); j++)
  1528. {
  1529. GetTriangle(i).GetNeighbourPoints(GetTriangle(NeighbourTrig(i,j)), ap1, ap2);
  1530. if (!IsEdge(ap1,ap2))
  1531. {
  1532. if (GetGeomAngle(i, NeighbourTrig(i,j)) > revertedangle)
  1533. {
  1534. found = 1;
  1535. break;
  1536. }
  1537. }
  1538. }
  1539. if (found)
  1540. {
  1541. SetMarkedTrig(i, 1); cnt++;
  1542. }
  1543. }
  1544. PrintMessage(5, "found ", cnt, " reverted trigs");
  1545. }
  1546. void STLGeometry :: SmoothDirtyTrigs()
  1547. {
  1548. PrintFnStart("smooth dirty trigs");
  1549. MarkDirtyTrigs();
  1550. int i,j;
  1551. int changed = 1;
  1552. int ap1, ap2;
  1553. while (changed)
  1554. {
  1555. changed = 0;
  1556. for (i = 1; i <= GetNT(); i++)
  1557. {
  1558. if (IsMarkedTrig(i))
  1559. {
  1560. int foundtrig = 0;
  1561. double maxlen = 0;
  1562. // JS: darf normalvector nicht ueber kurze Seite erben
  1563. maxlen = GetTriangle(i).MaxLength(GetPoints()) / 2.1; //JG: bei flachem dreieck auch kurze Seite
  1564. for (j = 1; j <= NONeighbourTrigs(i); j++)
  1565. {
  1566. if (!IsMarkedTrig(NeighbourTrig(i,j)))
  1567. {
  1568. GetTriangle(i).GetNeighbourPoints(GetTriangle(NeighbourTrig(i,j)),ap1,ap2);
  1569. if (Dist(GetPoint(ap1),GetPoint(ap2)) >= maxlen)
  1570. {
  1571. foundtrig = NeighbourTrig(i,j);
  1572. maxlen = Dist(GetPoint(ap1),GetPoint(ap2));
  1573. }
  1574. }
  1575. }
  1576. if (foundtrig)
  1577. {
  1578. GetTriangle(i).SetNormal(GetTriangle(foundtrig).Normal());
  1579. changed = 1;
  1580. SetMarkedTrig(i,0);
  1581. }
  1582. }
  1583. }
  1584. }
  1585. calcedgedataanglesnew = 1;
  1586. MarkDirtyTrigs();
  1587. int cnt = 0;
  1588. for (i = 1; i <= GetNT(); i++)
  1589. {
  1590. if (IsMarkedTrig(i)) {cnt++;}
  1591. }
  1592. PrintMessage(5,"NO marked dirty trigs=", cnt);
  1593. }
  1594. int STLGeometry :: IsMarkedTrig(int trig) const
  1595. {
  1596. if (trig <= markedtrigs.Size() && trig >=1)
  1597. {
  1598. return markedtrigs.Get(trig);
  1599. }
  1600. else {PrintSysError("In STLGeometry::IsMarkedTrig");}
  1601. return 0;
  1602. }
  1603. void STLGeometry :: SetMarkedTrig(int trig, int num)
  1604. {
  1605. if (trig <= markedtrigs.Size() && trig >=1)
  1606. {
  1607. markedtrigs.Elem(trig) = num;
  1608. }
  1609. else {PrintSysError("In STLGeometry::SetMarkedTrig");}
  1610. }
  1611. void STLGeometry :: Clear()
  1612. {
  1613. PrintFnStart("Clear");
  1614. surfacemeshed = 0;
  1615. surfaceoptimized = 0;
  1616. volumemeshed = 0;
  1617. selectedmultiedge.SetSize(0);
  1618. meshlines.SetSize(0);
  1619. // neighbourtrigs.SetSize(0);
  1620. outerchartspertrig.SetSize(0);
  1621. atlas.SetSize(0);
  1622. ClearMarkedSegs();
  1623. ClearSpiralPoints();
  1624. ClearLineEndPoints();
  1625. SetSelectTrig(0);
  1626. SetNodeOfSelTrig(1);
  1627. facecnt = 0;
  1628. SetThreadPercent(100.);
  1629. ClearEdges();
  1630. }
  1631. double STLGeometry :: Area()
  1632. {
  1633. double ar = 0;
  1634. int i;
  1635. for (i = 1; i <= GetNT(); i++)
  1636. {
  1637. ar += GetTriangle(i).Area(points);
  1638. }
  1639. return ar;
  1640. }
  1641. double STLGeometry :: GetAngle(int t1, int t2)
  1642. {
  1643. return Angle(GetTriangle(t1).Normal(),GetTriangle(t2).Normal());
  1644. }
  1645. double STLGeometry :: GetGeomAngle(int t1, int t2)
  1646. {
  1647. Vec3d n1 = GetTriangle(t1).GeomNormal(points);
  1648. Vec3d n2 = GetTriangle(t2).GeomNormal(points);
  1649. return Angle(n1,n2);
  1650. }
  1651. void STLGeometry :: InitSTLGeometry(const Array<STLReadTriangle> & readtrias)
  1652. {
  1653. PrintFnStart("Init STL Geometry");
  1654. STLTopology::InitSTLGeometry(readtrias);
  1655. int i, k;
  1656. //const double geometry_tol_fact = 1E8; //distances lower than max_box_size/tol are ignored
  1657. int np = GetNP();
  1658. PrintMessage(5,"NO points= ", GetNP());
  1659. normals.SetSize(GetNP());
  1660. Array<int> normal_cnt(GetNP()); // counts number of added normals in a point
  1661. for (i = 1; i <= np; i++)
  1662. {
  1663. normal_cnt.Elem(i) = 0;
  1664. normals.Elem(i) = Vec3d (0,0,0);
  1665. }
  1666. for(i = 1; i <= GetNT(); i++)
  1667. {
  1668. // STLReadTriangle t = GetReadTriangle(i);
  1669. // STLTriangle st;
  1670. Vec<3> n = GetTriangle(i).Normal ();
  1671. for (k = 1; k <= 3; k++)
  1672. {
  1673. int pi = GetTriangle(i).PNum(k);
  1674. normal_cnt.Elem(pi)++;
  1675. SetNormal(pi, GetNormal(pi) + n);
  1676. }
  1677. }
  1678. //normalize the normals
  1679. for (i = 1; i <= GetNP(); i++)
  1680. {
  1681. SetNormal(i,1./(double)normal_cnt.Get(i)*GetNormal(i));
  1682. }
  1683. trigsconverted = 1;
  1684. vicinity.SetSize(GetNT());
  1685. markedtrigs.SetSize(GetNT());
  1686. for (i = 1; i <= GetNT(); i++)
  1687. {
  1688. markedtrigs.Elem(i) = 0;
  1689. vicinity.Elem(i) = 1;
  1690. }
  1691. ha_points.SetSize(GetNP());
  1692. for (i = 1; i <= GetNP(); i++)
  1693. ha_points.Elem(i) = 0;
  1694. calcedgedataanglesnew = 0;
  1695. edgedatastored = 0;
  1696. edgedata->Clear();
  1697. if (GetStatus() == STL_ERROR) return;
  1698. CalcEdgeData();
  1699. CalcEdgeDataAngles();
  1700. ClearLineEndPoints();
  1701. CheckGeometryOverlapping();
  1702. }
  1703. void STLGeometry :: TopologyChanged()
  1704. {
  1705. calcedgedataanglesnew = 1;
  1706. }
  1707. int STLGeometry :: CheckGeometryOverlapping()
  1708. {
  1709. int i, j, k;
  1710. Box<3> geombox = GetBoundingBox();
  1711. Point<3> pmin = geombox.PMin();
  1712. Point<3> pmax = geombox.PMax();
  1713. Box3dTree setree(pmin, pmax);
  1714. Array<int> inters;
  1715. int oltrigs = 0;
  1716. markedtrigs.SetSize(GetNT());
  1717. for (i = 1; i <= GetNT(); i++)
  1718. SetMarkedTrig(i, 0);
  1719. for (i = 1; i <= GetNT(); i++)
  1720. {
  1721. const STLTriangle & tri = GetTriangle(i);
  1722. Point<3> tpmin = tri.box.PMin();
  1723. Point<3> tpmax = tri.box.PMax();
  1724. Vec<3> diag = tpmax - tpmin;
  1725. tpmax = tpmax + 0.001 * diag;
  1726. tpmin = tpmin - 0.001 * diag;
  1727. setree.Insert (tpmin, tpmax, i);
  1728. }
  1729. for (i = 1; i <= GetNT(); i++)
  1730. {
  1731. const STLTriangle & tri = GetTriangle(i);
  1732. Point<3> tpmin = tri.box.PMin();
  1733. Point<3> tpmax = tri.box.PMax();
  1734. setree.GetIntersecting (tpmin, tpmax, inters);
  1735. for (j = 1; j <= inters.Size(); j++)
  1736. {
  1737. const STLTriangle & tri2 = GetTriangle(inters.Get(j));
  1738. const Point<3> *trip1[3], *trip2[3];
  1739. Point<3> hptri1[3], hptri2[3];
  1740. /*
  1741. for (k = 1; k <= 3; k++)
  1742. {
  1743. trip1[k-1] = &GetPoint (tri.PNum(k));
  1744. trip2[k-1] = &GetPoint (tri2.PNum(k));
  1745. }
  1746. */
  1747. for (k = 0; k < 3; k++)
  1748. {
  1749. hptri1[k] = GetPoint (tri[k]);
  1750. hptri2[k] = GetPoint (tri2[k]);
  1751. trip1[k] = &hptri1[k];
  1752. trip2[k] = &hptri2[k];
  1753. }
  1754. if (IntersectTriangleTriangle (&trip1[0], &trip2[0]))
  1755. {
  1756. oltrigs++;
  1757. PrintMessage(5,"Intersecting Triangles: trig ",i," with ",inters.Get(j),"!");
  1758. SetMarkedTrig(i, 1);
  1759. SetMarkedTrig(inters.Get(j), 1);
  1760. }
  1761. }
  1762. }
  1763. PrintMessage(3,"Check Geometry Overlapping: overlapping triangles = ",oltrigs);
  1764. return oltrigs;
  1765. }
  1766. /*
  1767. void STLGeometry :: InitSTLGeometry()
  1768. {
  1769. STLTopology::InitSTLGeometry();
  1770. int i, j, k;
  1771. const double geometry_tol_fact = 1E8; //distances lower than max_box_size/tol are ignored
  1772. trias.SetSize(0);
  1773. points.SetSize(0);
  1774. normals.SetSize(0);
  1775. Array<int> normal_cnt; // counts number of added normals in a point
  1776. Box3d bb (GetBoundingBox().PMin() + Vec3d (-1,-1,-1),
  1777. GetBoundingBox().PMax() + Vec3d (1, 1, 1));
  1778. Point3dTree pointtree (bb.PMin(),
  1779. bb.PMax());
  1780. Array<int> pintersect;
  1781. double gtol = GetBoundingBox().CalcDiam()/geometry_tol_fact;
  1782. for(i = 1; i <= GetReadNT(); i++)
  1783. {
  1784. //if (i%500==499) {(*mycout) << (double)i/(double)GetReadNT()*100. << "%" << endl;}
  1785. STLReadTriangle t = GetReadTriangle(i);
  1786. STLTriangle st;
  1787. Vec3d n = t.normal;
  1788. for (k = 0; k < 3; k++)
  1789. {
  1790. Point3d p = t.pts[k];
  1791. Point3d pmin = p - Vec3d (gtol, gtol, gtol);
  1792. Point3d pmax = p + Vec3d (gtol, gtol, gtol);
  1793. pointtree.GetIntersecting (pmin, pmax, pintersect);
  1794. if (pintersect.Size() > 1)
  1795. (*mycout) << "found too much " << char(7) << endl;
  1796. int foundpos = 0;
  1797. if (pintersect.Size())
  1798. foundpos = pintersect.Get(1);
  1799. if (foundpos)
  1800. {
  1801. normal_cnt[foundpos]++;
  1802. SetNormal(foundpos,GetNormal(foundpos)+n);
  1803. // (*testout) << "found p " << p << endl;
  1804. }
  1805. else
  1806. {
  1807. foundpos = AddPoint(p);
  1808. AddNormal(n);
  1809. normal_cnt.Append(1);
  1810. pointtree.Insert (p, foundpos);
  1811. }
  1812. //(*mycout) << "foundpos=" << foundpos << endl;
  1813. st.pts[k] = foundpos;
  1814. }
  1815. if ( (st.pts[0] == st.pts[1]) ||
  1816. (st.pts[0] == st.pts[2]) ||
  1817. (st.pts[1] == st.pts[2]) )
  1818. {
  1819. (*mycout) << "ERROR: STL Triangle degenerated" << endl;
  1820. }
  1821. else
  1822. {
  1823. // do not add ? js
  1824. AddTriangle(st);
  1825. }
  1826. //(*mycout) << "TRIG" << i << " = " << st << endl;
  1827. }
  1828. //normal the normals
  1829. for (i = 1; i <= GetNP(); i++)
  1830. {
  1831. SetNormal(i,1./(double)normal_cnt[i]*GetNormal(i));
  1832. }
  1833. trigsconverted = 1;
  1834. vicinity.SetSize(GetNT());
  1835. markedtrigs.SetSize(GetNT());
  1836. for (i = 1; i <= GetNT(); i++)
  1837. {
  1838. markedtrigs.Elem(i) = 0;
  1839. vicinity.Elem(i) = 1;
  1840. }
  1841. ha_points.SetSize(GetNP());
  1842. for (i = 1; i <= GetNP(); i++)
  1843. ha_points.Elem(i) = 0;
  1844. calcedgedataanglesnew = 0;
  1845. edgedatastored = 0;
  1846. edgedata->Clear();
  1847. CalcEdgeData();
  1848. CalcEdgeDataAngles();
  1849. ClearLineEndPoints();
  1850. (*mycout) << "done" << endl;
  1851. }
  1852. */
  1853. void STLGeometry :: SetLineEndPoint(int pn)
  1854. {
  1855. if (pn <1 || pn > lineendpoints.Size()) {PrintSysError("Illegal pnum in SetLineEndPoint!!!"); return; }
  1856. lineendpoints.Elem(pn) = 1;
  1857. }
  1858. int STLGeometry :: IsLineEndPoint(int pn)
  1859. {
  1860. // return 0;
  1861. if (pn <1 || pn > lineendpoints.Size())
  1862. {PrintSysError("Illegal pnum in IsLineEndPoint!!!"); return 0;}
  1863. return lineendpoints.Get(pn);
  1864. }
  1865. void STLGeometry :: ClearLineEndPoints()
  1866. {
  1867. lineendpoints.SetSize(GetNP());
  1868. int i;
  1869. for (i = 1; i <= GetNP(); i++)
  1870. {
  1871. lineendpoints.Elem(i) = 0;
  1872. }
  1873. }
  1874. int STLGeometry :: IsEdge(int ap1, int ap2)
  1875. {
  1876. int i,j;
  1877. for (i = 1; i <= GetNEPP(ap1); i++)
  1878. {
  1879. for (j = 1; j <= GetNEPP(ap2); j++)
  1880. {
  1881. if (GetEdgePP(ap1,i) == GetEdgePP(ap2,j)) {return 1;}
  1882. }
  1883. }
  1884. return 0;
  1885. }
  1886. int STLGeometry :: IsEdgeNum(int ap1, int ap2)
  1887. {
  1888. int i,j;
  1889. for (i = 1; i <= GetNEPP(ap1); i++)
  1890. {
  1891. for (j = 1; j <= GetNEPP(ap2); j++)
  1892. {
  1893. if (GetEdgePP(ap1,i) == GetEdgePP(ap2,j)) {return GetEdgePP(ap1,i);}
  1894. }
  1895. }
  1896. return 0;
  1897. }
  1898. void STLGeometry :: BuildEdges()
  1899. {
  1900. //PrintFnStart("build edges");
  1901. edges.SetSize(0);
  1902. meshlines.SetSize(0);
  1903. FindEdgesFromAngles();
  1904. }
  1905. void STLGeometry :: UseExternalEdges()
  1906. {
  1907. int i;
  1908. for (i = 1; i <= NOExternalEdges(); i++)
  1909. {
  1910. AddEdge(GetExternalEdge(i).i1,GetExternalEdge(i).i2);
  1911. }
  1912. //BuildEdgesPerPointy();
  1913. }
  1914. void STLGeometry :: UndoEdgeChange()
  1915. {
  1916. if (edgedatastored)
  1917. {
  1918. RestoreEdgeData();
  1919. }
  1920. else
  1921. {
  1922. PrintWarning("no edge undo possible");
  1923. }
  1924. }
  1925. void STLGeometry :: StoreEdgeData()
  1926. {
  1927. // edgedata_store = *edgedata;
  1928. edgedata->Store();
  1929. edgedatastored = 1;
  1930. // put stlgeom-edgedata to stltopology edgedata
  1931. /*
  1932. int i;
  1933. for (i = 1; i <= GetNTE(); i++)
  1934. {
  1935. const STLTopEdge & topedge = GetTopEdge (i);
  1936. int ednum = edgedata->GetEdgeNum (topedge.PNum(1),
  1937. topedge.PNum(2));
  1938. topedges.Elem(i).SetStatus (edgedata->Get (ednum).status);
  1939. }
  1940. */
  1941. }
  1942. void STLGeometry :: RestoreEdgeData()
  1943. {
  1944. // *edgedata = edgedata_store;
  1945. edgedata->Restore();
  1946. edgedatastored=0;
  1947. }
  1948. void STLGeometry :: CalcEdgeData()
  1949. {
  1950. PushStatus("Calc Edge Data");
  1951. int np1, np2;
  1952. int i;
  1953. int ecnt = 0;
  1954. edgedata->SetSize(GetNT()/2*3);
  1955. for (i = 1; i <= GetNT(); i++)
  1956. {
  1957. SetThreadPercent((double)i/(double)GetNT()*100.);
  1958. const STLTriangle & t1 = GetTriangle(i);
  1959. for (int j = 1; j <= NONeighbourTrigs(i); j++)
  1960. {
  1961. int nbti = NeighbourTrig(i,j);
  1962. if (nbti > i)
  1963. {
  1964. const STLTriangle & t2 = GetTriangle(nbti);
  1965. if (t1.IsNeighbourFrom(t2))
  1966. {
  1967. ecnt++; if (ecnt > edgedata->Size()) {PrintError("In Calc edge data, illegal geometry");}
  1968. t1.GetNeighbourPoints(t2,np1,np2);
  1969. /* ang = GetAngle(i,nbti);
  1970. if (ang < -M_PI) {ang += 2*M_PI;}*/
  1971. // edgedata->Add(STLEdgeData(0, np1, np2, i, nbti),ecnt);
  1972. edgedata->Elem(ecnt).SetStatus(ED_UNDEFINED);
  1973. // edgedata->Elem(ecnt).top = this;
  1974. // edgedata->Elem(ecnt).topedgenr = GetTopEdgeNum (np1, np2);
  1975. }
  1976. }
  1977. }
  1978. }
  1979. //BuildEdgesPerPoint();
  1980. PopStatus();
  1981. }
  1982. void STLGeometry :: CalcEdgeDataAngles()
  1983. {
  1984. PrintMessage(5,"calc edge data angles");
  1985. int i;
  1986. for (i = 1; i <= GetNTE(); i++)
  1987. {
  1988. STLTopEdge & edge = GetTopEdge (i);
  1989. double cosang =
  1990. GetTriangle(edge.TrigNum(1)).Normal() *
  1991. GetTriangle(edge.TrigNum(2)).Normal();
  1992. edge.SetCosAngle (cosang);
  1993. }
  1994. for (i = 1; i <= edgedata->Size(); i++)
  1995. {
  1996. /*
  1997. const STLEdgeData& e = edgedata->Get(i);
  1998. ang = GetAngle(e.lt,e.rt);
  1999. if (ang < -M_PI) {ang += 2*M_PI;}
  2000. edgedata->Elem(i).angle = fabs(ang);
  2001. */
  2002. }
  2003. }
  2004. void STLGeometry :: FindEdgesFromAngles()
  2005. {
  2006. // PrintFnStart("find edges from angles");
  2007. double min_edge_angle = stlparam.yangle/180.*M_PI;
  2008. double cont_min_edge_angle = stlparam.contyangle/180.*M_PI;
  2009. double cos_min_edge_angle = cos (min_edge_angle);
  2010. double cos_cont_min_edge_angle = cos (cont_min_edge_angle);
  2011. if (calcedgedataanglesnew) {CalcEdgeDataAngles(); calcedgedataanglesnew = 0;}
  2012. int i;
  2013. for (i = 1; i <= edgedata->Size(); i++)
  2014. {
  2015. STLTopEdge & sed = edgedata->Elem(i);
  2016. if (sed.GetStatus() == ED_CANDIDATE ||
  2017. sed.GetStatus() == ED_UNDEFINED)
  2018. {
  2019. if (sed.CosAngle() <= cos_min_edge_angle)
  2020. {
  2021. sed.SetStatus (ED_CANDIDATE);
  2022. }
  2023. else
  2024. {
  2025. sed.SetStatus(ED_UNDEFINED);
  2026. }
  2027. }
  2028. }
  2029. if (stlparam.contyangle < stlparam.yangle)
  2030. {
  2031. int changed = 1;
  2032. int its = 0;
  2033. while (changed && stlparam.contyangle < stlparam.yangle)
  2034. {
  2035. its++;
  2036. //(*mycout) << "." << flush;
  2037. changed = 0;
  2038. for (i = 1; i <= edgedata->Size(); i++)
  2039. {
  2040. STLTopEdge & sed = edgedata->Elem(i);
  2041. if (sed.CosAngle() <= cos_cont_min_edge_angle
  2042. && sed.GetStatus() == ED_UNDEFINED &&
  2043. (edgedata->GetNConfCandEPP(sed.PNum(1)) == 1 ||
  2044. edgedata->GetNConfCandEPP(sed.PNum(2)) == 1))
  2045. {
  2046. changed = 1;
  2047. sed.SetStatus (ED_CANDIDATE);
  2048. }
  2049. }
  2050. }
  2051. }
  2052. int confcand = 0;
  2053. if (edgedata->GetNConfEdges() == 0)
  2054. {
  2055. confcand = 1;
  2056. }
  2057. for (i = 1; i <= edgedata->Size(); i++)
  2058. {
  2059. STLTopEdge & sed = edgedata->Elem(i);
  2060. if (sed.GetStatus() == ED_CONFIRMED ||
  2061. (sed.GetStatus() == ED_CANDIDATE && confcand))
  2062. {
  2063. STLEdge se(sed.PNum(1),sed.PNum(2));
  2064. se.SetLeftTrig(sed.TrigNum(1));
  2065. se.SetRightTrig(sed.TrigNum(2));
  2066. AddEdge(se);
  2067. }
  2068. }
  2069. BuildEdgesPerPoint();
  2070. //(*mycout) << "its for continued angle = " << its << endl;
  2071. PrintMessage(5,"built ", GetNE(), " edges with yellow angle = ", stlparam.yangle, " degree");
  2072. }
  2073. /*
  2074. void STLGeometry :: FindEdgesFromAngles()
  2075. {
  2076. double yangle = stlparam.yangle;
  2077. char * savetask = multithread.task;
  2078. multithread.task = "find edges";
  2079. const double min_edge_angle = yangle/180.*M_PI;
  2080. int np1, np2;
  2081. double ang;
  2082. int i;
  2083. //(*mycout) << "area=" << Area() << endl;
  2084. for (i = 1; i <= GetNT(); i++)
  2085. {
  2086. multithread.percent = (double)i/(double)GetReadNT()*100.;
  2087. const STLTriangle & t1 = GetTriangle(i);
  2088. //NeighbourTrigs(nt,i);
  2089. for (int j = 1; j <= NONeighbourTrigs(i); j++)
  2090. {
  2091. int nbti = NeighbourTrig(i,j);
  2092. if (nbti > i)
  2093. {
  2094. const STLTriangle & t2 = GetTriangle(nbti);
  2095. if (t1.IsNeighbourFrom(t2))
  2096. {
  2097. ang = GetAngle(i,nbti);
  2098. if (ang < -M_PI*0.5) {ang += 2*M_PI;}
  2099. t1.GetNeighbourPoints(t2,np1,np2);
  2100. if (fabs(ang) >= min_edge_angle)
  2101. {
  2102. STLEdge se(np1,np2);
  2103. se.SetLeftTrig(i);
  2104. se.SetRightTrig(nbti);
  2105. AddEdge(se);
  2106. }
  2107. }
  2108. }
  2109. }
  2110. }
  2111. (*mycout) << "added " << GetNE() << " edges" << endl;
  2112. //BuildEdgesPerPoint();
  2113. multithread.percent = 100.;
  2114. multithread.task = savetask;
  2115. }
  2116. */
  2117. void STLGeometry :: BuildEdgesPerPoint()
  2118. {
  2119. //cout << "*** build edges per point" << endl;
  2120. edgesperpoint.SetSize(GetNP());
  2121. //add edges to points
  2122. int i;
  2123. for (i = 1; i <= GetNE(); i++)
  2124. {
  2125. //(*mycout) << "EDGE " << GetEdge(i).PNum(1) << " - " << GetEdge(i).PNum(2) << endl;
  2126. for (int j = 1; j <= 2; j++)
  2127. {
  2128. AddEdgePP(GetEdge(i).PNum(j),i);
  2129. }
  2130. }
  2131. }
  2132. void STLGeometry :: AddFaceEdges()
  2133. {
  2134. PrintFnStart("Add starting edges for faces");
  2135. //für Kugel eine STLLine hinzufügen (Vorteil: verfeinerbar, unabhängig von Auflösung der Geometrie!!!):
  2136. //Grenze von 1. gefundener chart
  2137. Array<int> edgecnt;
  2138. Array<int> chartindex;
  2139. edgecnt.SetSize(GetNOFaces());
  2140. chartindex.SetSize(GetNOFaces());
  2141. int i,j;
  2142. for (i = 1; i <= GetNOFaces(); i++)
  2143. {
  2144. edgecnt.Elem(i) = 0;
  2145. chartindex.Elem(i) = 0;
  2146. }
  2147. for (i = 1; i <= GetNT(); i++)
  2148. {
  2149. int fn = GetTriangle(i).GetFaceNum();
  2150. if (!chartindex.Get(fn)) {chartindex.Elem(fn) = GetChartNr(i);}
  2151. for (j = 1; j <= 3; j++)
  2152. {
  2153. edgecnt.Elem(fn) += GetNEPP(GetTriangle(i).PNum(j));
  2154. }
  2155. }
  2156. for (i = 1; i <= GetNOFaces(); i++)
  2157. {
  2158. if (!edgecnt.Get(i)) {PrintMessage(5,"Face", i, " has no edge!");}
  2159. }
  2160. int changed = 0;
  2161. int k, ap1, ap2;
  2162. for (i = 1; i <= GetNOFaces(); i++)
  2163. {
  2164. if (!edgecnt.Get(i))
  2165. {
  2166. const STLChart& c = GetChart(chartindex.Get(i));
  2167. for (j = 1; j <= c.GetNChartT(); j++)
  2168. {
  2169. const STLTriangle& t1 = GetTriangle(c.GetChartTrig(j));
  2170. for (k = 1; k <= 3; k++)
  2171. {
  2172. int nt = NeighbourTrig(c.GetChartTrig(j),k);
  2173. if (GetChartNr(nt) != chartindex.Get(i))
  2174. {
  2175. t1.GetNeighbourPoints(GetTriangle(nt),ap1,ap2);
  2176. AddEdge(ap1,ap2);
  2177. changed = 1;
  2178. }
  2179. }
  2180. }
  2181. }
  2182. }
  2183. if (changed) BuildEdgesPerPoint();
  2184. }
  2185. void STLGeometry :: LinkEdges()
  2186. {
  2187. PushStatusF("Link Edges");
  2188. PrintMessage(5,"have now ", GetNE(), " edges with yellow angle = ", stlparam.yangle, " degree");
  2189. int i;
  2190. lines.SetSize(0);
  2191. int starte(0);
  2192. int edgecnt = 0;
  2193. int found;
  2194. int rev(0); //indicates, that edge is inserted reverse
  2195. //worked edges
  2196. Array<int> we(GetNE());
  2197. //setlineendpoints; wenn 180°, dann keine endpunkte
  2198. //nur punkte mit 2 edges kommen in frage, da bei mehr oder weniger punkten ohnehin ein meshpoint hinkommt
  2199. Vec3d v1,v2;
  2200. double cos_eca = cos(stlparam.edgecornerangle/180.*M_PI);
  2201. int ecnt = 0;
  2202. int lp1, lp2;
  2203. if (stlparam.edgecornerangle < 180)
  2204. {
  2205. for (i = 1; i <= GetNP(); i++)
  2206. {
  2207. if (GetNEPP(i) == 2)
  2208. {
  2209. if (GetEdge(GetEdgePP(i,1)).PNum(2) == GetEdge(GetEdgePP(i,2)).PNum(1) ||
  2210. GetEdge(GetEdgePP(i,1)).PNum(1) == GetEdge(GetEdgePP(i,2)).PNum(2))
  2211. {
  2212. lp1 = 1; lp2 = 2;
  2213. }
  2214. else
  2215. {
  2216. lp1 = 2; lp2 = 1;
  2217. }
  2218. v1 = Vec3d(GetPoint(GetEdge(GetEdgePP(i,1)).PNum(1)),
  2219. GetPoint(GetEdge(GetEdgePP(i,1)).PNum(2)));
  2220. v2 = Vec3d(GetPoint(GetEdge(GetEdgePP(i,2)).PNum(lp1)),
  2221. GetPoint(GetEdge(GetEdgePP(i,2)).PNum(lp2)));
  2222. if ((v1*v2)/sqrt(v1.Length2()*v2.Length2()) < cos_eca)
  2223. {
  2224. //(*testout) << "add edgepoint " << i << endl;
  2225. SetLineEndPoint(i);
  2226. ecnt++;
  2227. }
  2228. }
  2229. }
  2230. }
  2231. PrintMessage(5, "added ", ecnt, " mesh_points due to edge corner angle (",
  2232. stlparam.edgecornerangle, " degree)");
  2233. for (i = 1; i <= GetNE(); i++) {we.Elem(i) = 0;}
  2234. while(edgecnt < GetNE())
  2235. {
  2236. SetThreadPercent((double)edgecnt/(double)GetNE()*100.);
  2237. STLLine* line = new STLLine(this);
  2238. //find start edge
  2239. int j = 1;
  2240. found = 0;
  2241. //try second time, if only rings are left!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  2242. int second = 0;
  2243. //find a starting edge at point with 1 or more than 2 edges or at lineendpoint
  2244. while (!found && j<=GetNE())
  2245. {
  2246. if (!we.Get(j))
  2247. {
  2248. if (GetNEPP(GetEdge(j).PNum(1)) != 2 || IsLineEndPoint(GetEdge(j).PNum(1)))
  2249. {
  2250. starte = j;
  2251. found = 1;
  2252. rev = 0;
  2253. }
  2254. else
  2255. if (GetNEPP(GetEdge(j).PNum(2)) != 2 || IsLineEndPoint(GetEdge(j).PNum(2)))
  2256. {
  2257. starte = j;
  2258. found = 1;
  2259. rev = 1;
  2260. }
  2261. else if (second)
  2262. {
  2263. starte = j;
  2264. found = 1;
  2265. rev = 0; //0 or 1 are possible
  2266. }
  2267. }
  2268. j++;
  2269. if (!second && j == GetNE()) {second = 1; j = 1;}
  2270. }
  2271. if (!found) {PrintSysError("No starting edge found, edgecnt=", edgecnt, ", GETNE=", GetNE());}
  2272. line->AddPoint(GetEdge(starte).PNum(1+rev));
  2273. line->AddPoint(GetEdge(starte).PNum(2-rev));
  2274. if (!rev)
  2275. {
  2276. line->AddLeftTrig(GetEdge(starte).LeftTrig());
  2277. line->AddRightTrig(GetEdge(starte).RightTrig());
  2278. }
  2279. else
  2280. {
  2281. line->AddLeftTrig(GetEdge(starte).RightTrig());
  2282. line->AddRightTrig(GetEdge(starte).LeftTrig());
  2283. }
  2284. edgecnt++; we.Elem(starte) = 1;
  2285. //add segments to line as long as segments other than starting edge are found or lineendpoint is reached
  2286. found = 1;
  2287. int other;
  2288. while(found)
  2289. {
  2290. found = 0;
  2291. int fp = GetEdge(starte).PNum(2-rev);
  2292. if (GetNEPP(fp) == 2 && !IsLineEndPoint(fp))
  2293. {
  2294. //find the "other" edge of point fp
  2295. other = 0;
  2296. if (GetEdgePP(fp,1) == starte) {other = 1;}
  2297. starte = GetEdgePP(fp,1+other);
  2298. //falls ring -> aufhoeren !!!!!!!!!!!
  2299. if (!we.Elem(starte))
  2300. {
  2301. found = 1;
  2302. rev = 0;
  2303. if (GetEdge(starte).PNum(2) == fp) {rev = 1;}
  2304. else if (GetEdge(starte).PNum(1) != fp) {PrintSysError("In Link Edges!");}
  2305. line->AddPoint(GetEdge(starte).PNum(2-rev));
  2306. if (!rev)
  2307. {
  2308. line->AddLeftTrig(GetEdge(starte).LeftTrig());
  2309. line->AddRightTrig(GetEdge(starte).RightTrig());
  2310. }
  2311. else
  2312. {
  2313. line->AddLeftTrig(GetEdge(starte).RightTrig());
  2314. line->AddRightTrig(GetEdge(starte).LeftTrig());
  2315. }
  2316. edgecnt++; we.Elem(starte) = 1;
  2317. }
  2318. }
  2319. }
  2320. AddLine(line);
  2321. }
  2322. PrintMessage(5,"number of lines generated = ", GetNLines());
  2323. //check, which lines must have at least one midpoint
  2324. INDEX_2_HASHTABLE<int> lineht(GetNLines()+1);
  2325. for (i = 1; i <= GetNLines(); i++)
  2326. {
  2327. if (GetLine(i)->StartP() == GetLine(i)->EndP())
  2328. {
  2329. GetLine(i)->DoSplit();
  2330. }
  2331. }
  2332. for (i = 1; i <= GetNLines(); i++)
  2333. {
  2334. INDEX_2 lineep (GetLine(i)->StartP(),GetLine(i)->EndP());
  2335. lineep.Sort();
  2336. if (lineht.Used (lineep))
  2337. {
  2338. GetLine(i)->DoSplit();
  2339. int other = lineht.Get(lineep);
  2340. GetLine(other)->DoSplit();
  2341. }
  2342. else
  2343. {
  2344. lineht.Set (lineep, i);
  2345. }
  2346. }
  2347. for (i = 1; i <= GetNLines(); i++)
  2348. {
  2349. STLLine* line = GetLine(i);
  2350. for (int ii = 1; ii <= line->GetNS(); ii++)
  2351. {
  2352. int ap1, ap2;
  2353. line->GetSeg(ii,ap1,ap2);
  2354. // (*mycout) << "SEG " << p1 << " - " << p2 << endl;
  2355. }
  2356. }
  2357. PopStatus();
  2358. }
  2359. int STLGeometry :: GetNOBodys()
  2360. {
  2361. int markedtrigs1 = 0;
  2362. int starttrig = 1;
  2363. int i, k, nnt;
  2364. int bodycnt = 0;
  2365. Array<int> bodynum(GetNT());
  2366. for (i = 1; i <= GetNT(); i++)
  2367. bodynum.Elem(i)=0;
  2368. while (markedtrigs1 < GetNT())
  2369. {
  2370. for (i = starttrig; i <= GetNT(); i++)
  2371. {
  2372. if (!bodynum.Get(i))
  2373. {
  2374. starttrig = i;
  2375. break;
  2376. }
  2377. }
  2378. //add all triangles around starttriangle, which is reachable without going over an edge
  2379. Array<int> todolist;
  2380. Array<int> nextlist;
  2381. bodycnt++;
  2382. markedtrigs1++;
  2383. bodynum.Elem(starttrig) = bodycnt;
  2384. todolist.Append(starttrig);
  2385. while(todolist.Size())
  2386. {
  2387. for (i = 1; i <= todolist.Size(); i++)
  2388. {
  2389. //const STLTriangle& tt = GetTriangle(todolist.Get(i));
  2390. for (k = 1; k <= NONeighbourTrigs(todolist.Get(i)); k++)
  2391. {
  2392. nnt = NeighbourTrig(todolist.Get(i),k);
  2393. if (!bodynum.Get(nnt))
  2394. {
  2395. nextlist.Append(nnt);
  2396. bodynum.Elem(nnt) = bodycnt;
  2397. markedtrigs1++;
  2398. }
  2399. }
  2400. }
  2401. todolist.SetSize(0);
  2402. for (i = 1; i <= nextlist.Size(); i++)
  2403. {
  2404. todolist.Append(nextlist.Get(i));
  2405. }
  2406. nextlist.SetSize(0);
  2407. }
  2408. }
  2409. PrintMessage(3, "Geometry has ", bodycnt, " separated bodys");
  2410. return bodycnt;
  2411. }
  2412. void STLGeometry :: CalcFaceNums()
  2413. {
  2414. int markedtrigs1 = 0;
  2415. int starttrig(0);
  2416. int laststarttrig = 1;
  2417. int i, k, nnt;
  2418. facecnt = 0;
  2419. for (i = 1; i <= GetNT(); i++)
  2420. GetTriangle(i).SetFaceNum(0);
  2421. while (markedtrigs1 < GetNT())
  2422. {
  2423. for (i = laststarttrig; i <= GetNT(); i++)
  2424. {
  2425. if (!GetTriangle(i).GetFaceNum())
  2426. {
  2427. starttrig = i;
  2428. laststarttrig = i;
  2429. break;
  2430. }
  2431. }
  2432. //add all triangles around starttriangle, which is reachable without going over an edge
  2433. Array<int> todolist;
  2434. Array<int> nextlist;
  2435. facecnt++;
  2436. markedtrigs1++;
  2437. GetTriangle(starttrig).SetFaceNum(facecnt);
  2438. todolist.Append(starttrig);
  2439. int ap1, ap2;
  2440. while(todolist.Size())
  2441. {
  2442. for (i = 1; i <= todolist.Size(); i++)
  2443. {
  2444. const STLTriangle& tt = GetTriangle(todolist.Get(i));
  2445. for (k = 1; k <= NONeighbourTrigs(todolist.Get(i)); k++)
  2446. {
  2447. nnt = NeighbourTrig(todolist.Get(i),k);
  2448. STLTriangle& nt = GetTriangle(nnt);
  2449. if (!nt.GetFaceNum())
  2450. {
  2451. tt.GetNeighbourPoints(nt,ap1,ap2);
  2452. if (!IsEdge(ap1,ap2))
  2453. {
  2454. nextlist.Append(nnt);
  2455. nt.SetFaceNum(facecnt);
  2456. markedtrigs1++;
  2457. }
  2458. }
  2459. }
  2460. }
  2461. todolist.SetSize(0);
  2462. for (i = 1; i <= nextlist.Size(); i++)
  2463. {
  2464. todolist.Append(nextlist.Get(i));
  2465. }
  2466. nextlist.SetSize(0);
  2467. }
  2468. }
  2469. GetNOBodys();
  2470. PrintMessage(3,"generated ", facecnt, " faces");
  2471. }
  2472. void STLGeometry :: ClearSpiralPoints()
  2473. {
  2474. spiralpoints.SetSize(GetNP());
  2475. int i;
  2476. for (i = 1; i <= spiralpoints.Size(); i++)
  2477. {
  2478. spiralpoints.Elem(i) = 0;
  2479. }
  2480. }
  2481. void STLGeometry :: BuildSmoothEdges ()
  2482. {
  2483. if (smoothedges) delete smoothedges;
  2484. smoothedges = new INDEX_2_HASHTABLE<int> (GetNE()/10 + 1);
  2485. // Jack: Ok ?
  2486. // UseExternalEdges();
  2487. PushStatusF("Build Smooth Edges");
  2488. int i, j;//, k, l;
  2489. int nt = GetNT();
  2490. Vec3d ng1, ng2;
  2491. for (i = 1; i <= nt; i++)
  2492. {
  2493. if (multithread.terminate)
  2494. {PopStatus();return;}
  2495. SetThreadPercent(100.0 * (double)i / (double)nt);
  2496. const STLTriangle & trig = GetTriangle (i);
  2497. ng1 = trig.GeomNormal(points);
  2498. ng1 /= (ng1.Length() + 1e-24);
  2499. for (j = 1; j <= 3; j++)
  2500. {
  2501. int nbt = NeighbourTrig (i, j);
  2502. ng2 = GetTriangle(nbt).GeomNormal(points);
  2503. ng2 /= (ng2.Length() + 1e-24);
  2504. int pi1, pi2;
  2505. trig.GetNeighbourPoints(GetTriangle(nbt), pi1, pi2);
  2506. if (!IsEdge(pi1,pi2))
  2507. {
  2508. if (ng1 * ng2 < 0)
  2509. {
  2510. PrintMessage(7,"smoothedge found");
  2511. INDEX_2 i2(pi1, pi2);
  2512. i2.Sort();
  2513. smoothedges->Set (i2, 1);
  2514. }
  2515. }
  2516. }
  2517. }
  2518. PopStatus();
  2519. }
  2520. int STLGeometry :: IsSmoothEdge (int pi1, int pi2) const
  2521. {
  2522. if (!smoothedges)
  2523. return 0;
  2524. INDEX_2 i2(pi1, pi2);
  2525. i2.Sort();
  2526. return smoothedges->Used (i2);
  2527. }
  2528. //function is not used now
  2529. int IsInArray(int n, const Array<int>& ia)
  2530. {
  2531. int i;
  2532. for (i = 1; i <= ia.Size(); i++)
  2533. {
  2534. if (ia.Get(i) == n) {return 1;}
  2535. }
  2536. return 0;
  2537. }
  2538. void STLGeometry :: AddConeAndSpiralEdges()
  2539. {
  2540. PrintMessage(5,"have now ", GetNE(), " edges with yellow angle = ", stlparam.yangle, " degree");
  2541. PrintFnStart("AddConeAndSpiralEdges");
  2542. int i,j,k,n;
  2543. // int changed = 0;
  2544. //check edges, where inner chart and no outer chart come together without an edge
  2545. int np1, np2, nt;
  2546. int cnt = 0;
  2547. for (i = 1; i <= GetNOCharts(); i++)
  2548. {
  2549. STLChart& chart = GetChart(i);
  2550. for (j = 1; j <= chart.GetNChartT(); j++)
  2551. {
  2552. int t = chart.GetChartTrig(j);
  2553. const STLTriangle& tt = GetTriangle(t);
  2554. for (k = 1; k <= 3; k++)
  2555. {
  2556. nt = NeighbourTrig(t,k);
  2557. if (GetChartNr(nt) != i && !TrigIsInOC(nt,i))
  2558. {
  2559. tt.GetNeighbourPoints(GetTriangle(nt),np1,np2);
  2560. if (!IsEdge(np1,np2))
  2561. {
  2562. STLEdge se(np1,np2);
  2563. se.SetLeftTrig(t);
  2564. se.SetRightTrig(nt);
  2565. int edgenum = AddEdge(se);
  2566. AddEdgePP(np1,edgenum);
  2567. AddEdgePP(np2,edgenum);
  2568. //changed = 1;
  2569. PrintWarning("Found a spiral like structure: chart=", i,
  2570. ", trig=", t, ", p1=", np1, ", p2=", np2);
  2571. cnt++;
  2572. }
  2573. }
  2574. }
  2575. }
  2576. }
  2577. PrintMessage(5, "found ", cnt, " spiral like structures");
  2578. PrintMessage(5, "added ", cnt, " edges due to spiral like structures");
  2579. cnt = 0;
  2580. int edgecnt = 0;
  2581. Array<int> trigsaroundp;
  2582. Array<int> chartpointchecked; //gets number of chart, if in this chart already checked
  2583. chartpointchecked.SetSize(GetNP());
  2584. for (i = 1; i <= GetNP(); i++)
  2585. {
  2586. chartpointchecked.Elem(i) = 0;
  2587. }
  2588. int onoc, notonoc, tpp, pn;
  2589. int ap1, ap2, tn1, tn2, l, problem;
  2590. if (!stldoctor.conecheck) {PrintWarning("++++++++++++ \ncone checking deactivated by user!!!!!\n+++++++++++++++"); return ;}
  2591. PushStatus("Find Critical Points");
  2592. int addedges = 0;
  2593. for (i = 1; i <= GetNOCharts(); i++)
  2594. {
  2595. SetThreadPercent((double)i/(double)GetNOCharts()*100.);
  2596. if (multithread.terminate)
  2597. {PopStatus();return;}
  2598. STLChart& chart = GetChart(i);
  2599. for (j = 1; j <= chart.GetNChartT(); j++)
  2600. {
  2601. int t = chart.GetChartTrig(j);
  2602. const STLTriangle& tt = GetTriangle(t);
  2603. for (k = 1; k <= 3; k++)
  2604. {
  2605. pn = tt.PNum(k);
  2606. if (chartpointchecked.Get(pn) == i)
  2607. {continue;}
  2608. int checkpoint = 0;
  2609. for (n = 1; n <= trigsperpoint.EntrySize(pn); n++)
  2610. {
  2611. if (trigsperpoint.Get(pn,n) != t &&
  2612. GetChartNr(trigsperpoint.Get(pn,n)) != i &&
  2613. !TrigIsInOC(trigsperpoint.Get(pn,n),i)) {checkpoint = 1;};
  2614. }
  2615. if (checkpoint)
  2616. {
  2617. chartpointchecked.Elem(pn) = i;
  2618. int worked = 0;
  2619. int spworked = 0;
  2620. GetSortedTrianglesAroundPoint(pn,t,trigsaroundp);
  2621. trigsaroundp.Append(t);
  2622. problem = 0;
  2623. for (l = 2; l <= trigsaroundp.Size()-1; l++)
  2624. {
  2625. tn1 = trigsaroundp.Get(l-1);
  2626. tn2 = trigsaroundp.Get(l);
  2627. const STLTriangle& t1 = GetTriangle(tn1);
  2628. const STLTriangle& t2 = GetTriangle(tn2);
  2629. t1.GetNeighbourPoints(t2, ap1, ap2);
  2630. if (IsEdge(ap1,ap2)) break;
  2631. if (GetChartNr(tn2) != i && !TrigIsInOC(tn2,i)) {problem = 1;}
  2632. }
  2633. if (problem)
  2634. {
  2635. for (l = 2; l <= trigsaroundp.Size()-1; l++)
  2636. {
  2637. tn1 = trigsaroundp.Get(l-1);
  2638. tn2 = trigsaroundp.Get(l);
  2639. const STLTriangle& t1 = GetTriangle(tn1);
  2640. const STLTriangle& t2 = GetTriangle(tn2);
  2641. t1.GetNeighbourPoints(t2, ap1, ap2);
  2642. if (IsEdge(ap1,ap2)) break;
  2643. if ((GetChartNr(tn1) == i && GetChartNr(tn2) != i && TrigIsInOC(tn2,i)) ||
  2644. (GetChartNr(tn2) == i && GetChartNr(tn1) != i && TrigIsInOC(tn1,i)))
  2645. {
  2646. if (addedges || !GetNEPP(pn))
  2647. {
  2648. STLEdge se(ap1,ap2);
  2649. se.SetLeftTrig(tn1);
  2650. se.SetRightTrig(tn2);
  2651. int edgenum = AddEdge(se);
  2652. AddEdgePP(ap1,edgenum);
  2653. AddEdgePP(ap2,edgenum);
  2654. edgecnt++;
  2655. }
  2656. if (!addedges && !GetSpiralPoint(pn))
  2657. {
  2658. SetSpiralPoint(pn);
  2659. spworked = 1;
  2660. }
  2661. worked = 1;
  2662. }
  2663. }
  2664. }
  2665. //backwards:
  2666. problem = 0;
  2667. for (l = trigsaroundp.Size()-1; l >= 2; l--)
  2668. {
  2669. tn1 = trigsaroundp.Get(l+1);
  2670. tn2 = trigsaroundp.Get(l);
  2671. const STLTriangle& t1 = GetTriangle(tn1);
  2672. const STLTriangle& t2 = GetTriangle(tn2);
  2673. t1.GetNeighbourPoints(t2, ap1, ap2);
  2674. if (IsEdge(ap1,ap2)) break;
  2675. if (GetChartNr(tn2) != i && !TrigIsInOC(tn2,i)) {problem = 1;}
  2676. }
  2677. if (problem)
  2678. for (l = trigsaroundp.Size()-1; l >= 2; l--)
  2679. {
  2680. tn1 = trigsaroundp.Get(l+1);
  2681. tn2 = trigsaroundp.Get(l);
  2682. const STLTriangle& t1 = GetTriangle(tn1);
  2683. const STLTriangle& t2 = GetTriangle(tn2);
  2684. t1.GetNeighbourPoints(t2, ap1, ap2);
  2685. if (IsEdge(ap1,ap2)) break;
  2686. if ((GetChartNr(tn1) == i && GetChartNr(tn2) != i && TrigIsInOC(tn2,i)) ||
  2687. (GetChartNr(tn2) == i && GetChartNr(tn1) != i && TrigIsInOC(tn1,i)))
  2688. {
  2689. if (addedges || !GetNEPP(pn))
  2690. {
  2691. STLEdge se(ap1,ap2);
  2692. se.SetLeftTrig(tn1);
  2693. se.SetRightTrig(tn2);
  2694. int edgenum = AddEdge(se);
  2695. AddEdgePP(ap1,edgenum);
  2696. AddEdgePP(ap2,edgenum);
  2697. edgecnt++;
  2698. }
  2699. if (!addedges && !GetSpiralPoint(pn))
  2700. {
  2701. SetSpiralPoint(pn);
  2702. spworked = 1;
  2703. //if (GetNEPP(pn) == 0) {(*mycout) << "ERROR: spiralpoint with no edge found!" << endl;}
  2704. }
  2705. worked = 1;
  2706. }
  2707. }
  2708. if (worked)
  2709. {
  2710. //(*testout) << "set edgepoint due to spirals: pn=" << i << endl;
  2711. SetLineEndPoint(pn);
  2712. }
  2713. if (spworked)
  2714. {
  2715. /*
  2716. (*mycout) << "Warning: Critical Point " << tt.PNum(k)
  2717. << "( chart " << i << ", trig " << t
  2718. << ") has been neutralized!!!" << endl;
  2719. */
  2720. cnt++;
  2721. }
  2722. // markedpoints.Elem(tt.PNum(k)) = 1;
  2723. }
  2724. }
  2725. }
  2726. }
  2727. PrintMessage(5, "found ", cnt, " critical points!");
  2728. PrintMessage(5, "added ", edgecnt, " edges due to critical points!");
  2729. PopStatus();
  2730. //search points where inner chart and outer chart and "no chart" trig come together at edge-point
  2731. PrintMessage(7,"search for special chart points");
  2732. for (i = 1; i <= GetNOCharts(); i++)
  2733. {
  2734. STLChart& chart = GetChart(i);
  2735. for (j = 1; j <= chart.GetNChartT(); j++)
  2736. {
  2737. int t = chart.GetChartTrig(j);
  2738. const STLTriangle& tt = GetTriangle(t);
  2739. for (k = 1; k <= 3; k++)
  2740. {
  2741. pn = tt.PNum(k);
  2742. if (GetNEPP(pn) == 2)
  2743. {
  2744. onoc = 0;
  2745. notonoc = 0;
  2746. for (n = 1; n <= trigsperpoint.EntrySize(pn); n++)
  2747. {
  2748. tpp = trigsperpoint.Get(pn,n);
  2749. if (tpp != t && GetChartNr(tpp) != i)
  2750. {
  2751. if (TrigIsInOC(tpp,i)) {onoc = 1;}
  2752. if (!TrigIsInOC(tpp,i)) {notonoc = 1;}
  2753. }
  2754. }
  2755. if (onoc && notonoc && !IsLineEndPoint(pn))
  2756. {
  2757. GetSortedTrianglesAroundPoint(pn,t,trigsaroundp);
  2758. int here = 1; //we start on this side of edge, !here = there
  2759. int thereOC = 0;
  2760. int thereNotOC = 0;
  2761. for (l = 2; l <= trigsaroundp.Size(); l++)
  2762. {
  2763. GetTriangle(trigsaroundp.Get(l-1)).
  2764. GetNeighbourPoints(GetTriangle(trigsaroundp.Get(l)), ap1, ap2);
  2765. if (IsEdge(ap1,ap2)) {here = (here+1)%2;}
  2766. if (!here && TrigIsInOC(trigsaroundp.Get(l),i)) {thereOC = 1;}
  2767. if (!here && !TrigIsInOC(trigsaroundp.Get(l),i)) {thereNotOC = 1;}
  2768. }
  2769. if (thereOC && thereNotOC)
  2770. {
  2771. //(*mycout) << "Special OCICnotC - point " << pn << " found!" << endl;
  2772. //(*testout) << "set edgepoint due to spirals: pn=" << i << endl;
  2773. SetLineEndPoint(pn);
  2774. }
  2775. }
  2776. }
  2777. }
  2778. }
  2779. }
  2780. PrintMessage(5,"have now ", GetNE(), " edges with yellow angle = ", stlparam.yangle, " degree");
  2781. }
  2782. //get trigs at a point, started with starttrig, then every left
  2783. void STLGeometry :: GetSortedTrianglesAroundPoint(int p, int starttrig, Array<int>& trigs)
  2784. {
  2785. int acttrig = starttrig;
  2786. trigs.SetAllocSize(trigsperpoint.EntrySize(p));
  2787. trigs.SetSize(0);
  2788. trigs.Append(acttrig);
  2789. int i, j, t, ap1, ap2, locindex1(0), locindex2(0);
  2790. //(*mycout) << "trigs around point " << p << endl;
  2791. int end = 0;
  2792. while (!end)
  2793. {
  2794. const STLTriangle& at = GetTriangle(acttrig);
  2795. for (i = 1; i <= trigsperpoint.EntrySize(p); i++)
  2796. {
  2797. t = trigsperpoint.Get(p,i);
  2798. const STLTriangle& nt = GetTriangle(t);
  2799. if (at.IsNeighbourFrom(nt))
  2800. {
  2801. at.GetNeighbourPoints(nt, ap1, ap2);
  2802. if (ap2 == p) {Swap(ap1,ap2);}
  2803. if (ap1 != p) {PrintSysError("In GetSortedTrianglesAroundPoint!!!");}
  2804. for (j = 1; j <= 3; j++)
  2805. {
  2806. if (at.PNum(j) == ap1) {locindex1 = j;};
  2807. if (at.PNum(j) == ap2) {locindex2 = j;};
  2808. }
  2809. if ((locindex2+1)%3+1 == locindex1)
  2810. {
  2811. if (t != starttrig)
  2812. {
  2813. trigs.Append(t);
  2814. // (*mycout) << "trig " << t << endl;
  2815. acttrig = t;
  2816. }
  2817. else
  2818. {
  2819. end = 1;
  2820. }
  2821. break;
  2822. }
  2823. }
  2824. }
  2825. }
  2826. }
  2827. /*
  2828. int STLGeometry :: NeighbourTrig(int trig, int nr) const
  2829. {
  2830. return neighbourtrigs.Get(trig,nr);
  2831. }
  2832. */
  2833. void STLGeometry :: SmoothGeometry ()
  2834. {
  2835. int i, j, k;
  2836. double maxerr0, maxerr;
  2837. for (i = 1; i <= GetNP(); i++)
  2838. {
  2839. if (GetNEPP(i)) continue;
  2840. maxerr0 = 0;
  2841. for (j = 1; j <= NOTrigsPerPoint(i); j++)
  2842. {
  2843. int tnum = TrigPerPoint(i, j);
  2844. double err = Angle (GetTriangle(tnum).Normal (),
  2845. GetTriangle(tnum).GeomNormal(GetPoints()));
  2846. if (err > maxerr0)
  2847. maxerr0 = err;
  2848. }
  2849. Point3d pi = GetPoint (i);
  2850. if (maxerr0 < 1.1) continue; // about 60 degree
  2851. maxerr0 /= 2; // should be at least halfen
  2852. for (k = 1; k <= NOTrigsPerPoint(i); k++)
  2853. {
  2854. const STLTriangle & trig = GetTriangle (TrigPerPoint (i, k));
  2855. Point3d c = Center(GetPoint (trig.PNum(1)),
  2856. GetPoint (trig.PNum(2)),
  2857. GetPoint (trig.PNum(3)));
  2858. Point3d np = pi + 0.1 * (c - pi);
  2859. SetPoint (i, np);
  2860. maxerr = 0;
  2861. for (j = 1; j <= NOTrigsPerPoint(i); j++)
  2862. {
  2863. int tnum = TrigPerPoint(i, j);
  2864. double err = Angle (GetTriangle(tnum).Normal (),
  2865. GetTriangle(tnum).GeomNormal(GetPoints()));
  2866. if (err > maxerr)
  2867. maxerr = err;
  2868. }
  2869. if (maxerr < maxerr0)
  2870. {
  2871. pi = np;
  2872. }
  2873. }
  2874. SetPoint (i, pi);
  2875. }
  2876. }
  2877. }