PageRenderTime 57ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/contrib/Netgen/libsrc/meshing/bisect.cpp

https://bitbucket.org/lge/gmsh
C++ | 4071 lines | 2648 code | 642 blank | 781 comment | 574 complexity | 39f68cbc0bf590cd14518d2f28aafb5b MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. #include <mystdlib.h>
  2. #include "meshing.hpp"
  3. #define noDEBUG
  4. namespace netgen
  5. {
  6. //#include "../interface/writeuser.hpp"
  7. class MarkedTet;
  8. class MarkedPrism;
  9. class MarkedIdentification;
  10. class MarkedTri;
  11. class MarkedQuad;
  12. typedef MoveableArray<MarkedTet> T_MTETS;
  13. typedef MoveableArray<MarkedPrism> T_MPRISMS;
  14. typedef MoveableArray<MarkedIdentification> T_MIDS;
  15. typedef MoveableArray<MarkedTri> T_MTRIS;
  16. typedef MoveableArray<MarkedQuad> T_MQUADS;
  17. class MarkedTet
  18. {
  19. public:
  20. /// pnums of tet
  21. PointIndex pnums[4];
  22. /// material number
  23. int matindex;
  24. /// element marked for refinement
  25. /// marked = 1: marked by element marker, marked = 2 due to closure
  26. unsigned int marked:2;
  27. /// flag of Arnold-Mukherjee algorithm
  28. unsigned int flagged:1;
  29. /// tetedge (local coordinates 0..3)
  30. unsigned int tetedge1:3;
  31. unsigned int tetedge2:3;
  32. // marked edge of faces
  33. // face_j : face without node j,
  34. // mark_k : edge without node k
  35. char faceedges[4];
  36. // unsigned char faceedges[4];
  37. bool incorder;
  38. unsigned int order:6;
  39. MarkedTet()
  40. {
  41. for (int i = 0; i < 4; i++) { faceedges[i] = 255; }
  42. }
  43. };
  44. ostream & operator<< (ostream & ost, const MarkedTet & mt)
  45. {
  46. for(int i=0; i<4; i++)
  47. ost << mt.pnums[i] << " ";
  48. ost << mt.matindex << " " << int(mt.marked) << " " << int(mt.flagged) << " " << int(mt.tetedge1) << " " << int(mt.tetedge2) << " ";
  49. ost << "faceedges = ";
  50. for(int i=0; i<4; i++)
  51. ost << int(mt.faceedges[i]) << " ";
  52. ost << " order = ";
  53. ost << mt.incorder << " " << int(mt.order) << "\n";
  54. return ost;
  55. }
  56. istream & operator>> (istream & ost, MarkedTet & mt)
  57. {
  58. for(int i=0; i<4; i++)
  59. ost >> mt.pnums[i];
  60. ost >> mt.matindex;
  61. int auxint;
  62. ost >> auxint;
  63. mt.marked = auxint;
  64. ost >> auxint;
  65. mt.flagged = auxint;
  66. ost >> auxint;
  67. mt.tetedge1 = auxint;
  68. ost >> auxint;
  69. mt.tetedge2 = auxint;
  70. char auxchar;
  71. for(int i=0; i<4; i++)
  72. {
  73. ost >> auxchar;
  74. mt.faceedges[i] = auxchar;
  75. }
  76. ost >> mt.incorder;
  77. ost >> auxint;
  78. mt.order = auxint;
  79. return ost;
  80. }
  81. class MarkedPrism
  82. {
  83. public:
  84. /// 6 point numbers
  85. PointIndex pnums[6];
  86. /// material number
  87. int matindex;
  88. /// marked for refinement
  89. int marked;
  90. /// edge without node k (0,1,2)
  91. int markededge;
  92. bool incorder;
  93. unsigned int order:6;
  94. };
  95. ostream & operator<< (ostream & ost, const MarkedPrism & mp)
  96. {
  97. for(int i=0; i<6; i++)
  98. ost << mp.pnums[i] << " ";
  99. ost << mp.matindex << " " << mp.marked << " " << mp.markededge << " " << mp.incorder << " " << int(mp.order) << "\n";
  100. return ost;
  101. }
  102. istream & operator>> (istream & ist, MarkedPrism & mp)
  103. {
  104. for(int i=0; i<6; i++)
  105. ist >> mp.pnums[i];
  106. ist >> mp.matindex >> mp.marked >> mp.markededge >> mp.incorder;
  107. int auxint;
  108. ist >> auxint;
  109. mp.order = auxint;
  110. return ist;
  111. }
  112. class MarkedIdentification
  113. {
  114. public:
  115. // number of points of one face (3 or 4)
  116. int np;
  117. /// 6 or 8 point numbers
  118. PointIndex pnums[8];
  119. /// marked for refinement
  120. int marked;
  121. /// edge starting with node k (0,1,2, or 3)
  122. int markededge;
  123. bool incorder;
  124. unsigned int order:6;
  125. };
  126. ostream & operator<< (ostream & ost, const MarkedIdentification & mi)
  127. {
  128. ost << mi.np << " ";
  129. for(int i=0; i<2*mi.np; i++)
  130. ost << mi.pnums[i] << " ";
  131. ost << mi.marked << " " << mi.markededge << " " << mi.incorder << " " << int(mi.order) << "\n";
  132. return ost;
  133. }
  134. istream & operator>> (istream & ist, MarkedIdentification & mi)
  135. {
  136. ist >> mi.np;
  137. for(int i=0; i<2*mi.np; i++)
  138. ist >> mi.pnums[i];
  139. ist >> mi.marked >> mi.markededge >> mi.incorder;
  140. int auxint;
  141. ist >> auxint;
  142. mi.order = auxint;
  143. return ist;
  144. }
  145. class MarkedTri
  146. {
  147. public:
  148. /// three point numbers
  149. PointIndex pnums[3];
  150. /// three geominfos
  151. PointGeomInfo pgeominfo[3];
  152. /// marked for refinement
  153. int marked;
  154. /// edge without node k
  155. int markededge;
  156. /// surface id
  157. int surfid;
  158. bool incorder;
  159. unsigned int order:6;
  160. };
  161. ostream & operator<< (ostream & ost, const MarkedTri & mt)
  162. {
  163. for(int i=0; i<3; i++)
  164. ost << mt.pnums[i] << " ";
  165. for(int i=0; i<3; i++)
  166. ost << mt.pgeominfo[i] << " ";
  167. ost << mt.marked << " " << mt.markededge << " " << mt.surfid << " " << mt.incorder << " " << int(mt.order) << "\n";
  168. return ost;
  169. }
  170. istream & operator>> (istream & ist, MarkedTri & mt)
  171. {
  172. for(int i=0; i<3; i++)
  173. ist >> mt.pnums[i];
  174. for(int i=0; i<3; i++)
  175. ist >> mt.pgeominfo[i];
  176. ist >> mt.marked >> mt.markededge >> mt.surfid >> mt.incorder;
  177. int auxint;
  178. ist >> auxint;
  179. mt.order = auxint;
  180. return ist;
  181. }
  182. class MarkedQuad
  183. {
  184. public:
  185. /// point numbers
  186. PointIndex pnums[4];
  187. ///
  188. PointGeomInfo pgeominfo[4];
  189. /// marked for refinement
  190. int marked;
  191. /// marked edge: 0/2 = vertical, 1/3 = horizontal
  192. int markededge;
  193. /// surface id
  194. int surfid;
  195. bool incorder;
  196. unsigned int order:6;
  197. };
  198. ostream & operator<< (ostream & ost, const MarkedQuad & mt)
  199. {
  200. for(int i=0; i<4; i++)
  201. ost << mt.pnums[i] << " ";
  202. for(int i=0; i<4; i++)
  203. ost << mt.pgeominfo[i] << " ";
  204. ost << mt.marked << " " << mt.markededge << " " << mt.surfid << " " << mt.incorder << " " << int(mt.order) << "\n";
  205. return ost;
  206. }
  207. istream & operator>> (istream & ist, MarkedQuad & mt)
  208. {
  209. for(int i=0; i<4; i++)
  210. ist >> mt.pnums[i];
  211. for(int i=0; i<4; i++)
  212. ist >> mt.pgeominfo[i];
  213. ist >> mt.marked >> mt.markededge >> mt.surfid >> mt.incorder;
  214. int auxint;
  215. ist >> auxint;
  216. mt.order = auxint;
  217. return ist;
  218. }
  219. void PrettyPrint(ostream & ost, const MarkedTet & mt)
  220. {
  221. int te1 = mt.tetedge1;
  222. int te2 = mt.tetedge2;
  223. int order = mt.order;
  224. ost << "MT: " << mt.pnums[0] << " - " << mt.pnums[1] << " - "
  225. << mt.pnums[2] << " - " << mt.pnums[3] << endl
  226. << "marked edge: " << te1 << " - " << te2
  227. << ", order = " << order << endl;
  228. //for (int k = 0; k < 4; k++)
  229. // ost << int(mt.faceedges[k]) << " ";
  230. for (int k = 0; k < 4; k++)
  231. {
  232. ost << "face";
  233. for (int j=0; j<4; j++)
  234. if(j != k)
  235. ost << " " << mt.pnums[j];
  236. for(int i=0; i<3; i++)
  237. for(int j=i+1; j<4; j++)
  238. if(i != k && j != k && int(mt.faceedges[k]) == 6-k-i-j)
  239. ost << " marked edge " << mt.pnums[i] << " " << mt.pnums[j] << endl;
  240. }
  241. ost << endl;
  242. }
  243. int BTSortEdges (const Mesh & mesh,
  244. const Array< Array<int,PointIndex::BASE>* > & idmaps,
  245. INDEX_2_CLOSED_HASHTABLE<int> & edgenumber)
  246. {
  247. PrintMessage(4,"sorting ... ");
  248. // if (mesh.PureTetMesh())
  249. if (1)
  250. {
  251. // new, fast version
  252. Array<INDEX_2> edges;
  253. Array<int> eclasses;
  254. int i, j, k;
  255. int cntedges = 0;
  256. int go_on;
  257. int ned(0);
  258. // enumerate edges:
  259. for (i = 1; i <= mesh.GetNE(); i++)
  260. {
  261. const Element & el = mesh.VolumeElement (i);
  262. static int tetedges[6][2] =
  263. { { 1, 2 },
  264. { 1, 3 },
  265. { 1, 4 },
  266. { 2, 3 },
  267. { 2, 4 },
  268. { 3, 4 } } ;
  269. static int prismedges[9][2] =
  270. { { 1, 2 },
  271. { 1, 3 },
  272. { 2, 3 },
  273. { 4, 5 },
  274. { 4, 6 },
  275. { 5, 6 },
  276. { 1, 4 },
  277. { 2, 5 },
  278. { 3, 6 } };
  279. int pyramidedges[6][2] =
  280. { { 1, 2 },
  281. { 3, 4 },
  282. { 1, 5 },
  283. { 2, 5 },
  284. { 3, 5 },
  285. { 4, 5 } };
  286. int (*tip)[2] = NULL;
  287. switch (el.GetType())
  288. {
  289. case TET:
  290. case TET10:
  291. {
  292. tip = tetedges;
  293. ned = 6;
  294. break;
  295. }
  296. case PRISM:
  297. case PRISM12:
  298. {
  299. tip = prismedges;
  300. ned = 6;
  301. break;
  302. }
  303. case PYRAMID:
  304. {
  305. tip = pyramidedges;
  306. ned = 6;
  307. break;
  308. }
  309. default:
  310. throw NgException("Bisect, element type not handled in switch");
  311. }
  312. for (j = 0; j < ned; j++)
  313. {
  314. INDEX_2 i2(el.PNum(tip[j][0]), el.PNum(tip[j][1]));
  315. i2.Sort();
  316. //(*testout) << "edge " << i2 << endl;
  317. if (!edgenumber.Used(i2))
  318. {
  319. cntedges++;
  320. edges.Append (i2);
  321. edgenumber.Set(i2, cntedges);
  322. }
  323. }
  324. }
  325. // additional surface edges:
  326. for (i = 1; i <= mesh.GetNSE(); i++)
  327. {
  328. const Element2d & el = mesh.SurfaceElement (i);
  329. static int trigedges[3][2] =
  330. { { 1, 2 },
  331. { 2, 3 },
  332. { 3, 1 } };
  333. static int quadedges[4][2] =
  334. { { 1, 2 },
  335. { 2, 3 },
  336. { 3, 4 },
  337. { 4, 1 } };
  338. int (*tip)[2] = NULL;
  339. switch (el.GetType())
  340. {
  341. case TRIG:
  342. case TRIG6:
  343. {
  344. tip = trigedges;
  345. ned = 3;
  346. break;
  347. }
  348. case QUAD:
  349. case QUAD6:
  350. {
  351. tip = quadedges;
  352. ned = 4;
  353. break;
  354. }
  355. default:
  356. {
  357. cerr << "Error: Sort for Bisect, SE has " << el.GetNP() << " points" << endl;
  358. ned = 0;
  359. }
  360. }
  361. for (j = 0; j < ned; j++)
  362. {
  363. INDEX_2 i2(el.PNum(tip[j][0]), el.PNum(tip[j][1]));
  364. i2.Sort();
  365. if (!edgenumber.Used(i2))
  366. {
  367. cntedges++;
  368. edges.Append (i2);
  369. edgenumber.Set(i2, cntedges);
  370. }
  371. }
  372. }
  373. eclasses.SetSize (cntedges);
  374. for (i = 1; i <= cntedges; i++)
  375. eclasses.Elem(i) = i;
  376. // identify edges in element stack
  377. do
  378. {
  379. go_on = 0;
  380. for (i = 1; i <= mesh.GetNE(); i++)
  381. {
  382. const Element & el = mesh.VolumeElement (i);
  383. if (el.GetType() != PRISM &&
  384. el.GetType() != PRISM12 &&
  385. el.GetType() != PYRAMID)
  386. continue;
  387. int prismpairs[3][4] =
  388. { { 1, 2, 4, 5 },
  389. { 2, 3, 5, 6 },
  390. { 1, 3, 4, 6 } };
  391. int pyramidpairs[3][4] =
  392. { { 1, 2, 4, 3 },
  393. { 1, 5, 4, 5 },
  394. { 2, 5, 3, 5 } };
  395. int (*pairs)[4] = NULL;
  396. switch (el.GetType())
  397. {
  398. case PRISM:
  399. case PRISM12:
  400. {
  401. pairs = prismpairs;
  402. break;
  403. }
  404. case PYRAMID:
  405. {
  406. pairs = pyramidpairs;
  407. break;
  408. }
  409. default:
  410. throw NgException("Bisect, element type not handled in switch, 2");
  411. }
  412. for (j = 0; j < 3; j++)
  413. {
  414. INDEX_2 e1 (el.PNum(pairs[j][0]),
  415. el.PNum(pairs[j][1]));
  416. INDEX_2 e2 (el.PNum(pairs[j][2]),
  417. el.PNum(pairs[j][3]));
  418. e1.Sort();
  419. e2.Sort();
  420. int eclass1 = edgenumber.Get (e1);
  421. int eclass2 = edgenumber.Get (e2);
  422. // (*testout) << "identify edges " << eclass1 << "-" << eclass2 << endl;
  423. if (eclasses.Get(eclass1) >
  424. eclasses.Get(eclass2))
  425. {
  426. eclasses.Elem(eclass1) =
  427. eclasses.Get(eclass2);
  428. go_on = 1;
  429. }
  430. else if (eclasses.Get(eclass2) >
  431. eclasses.Get(eclass1))
  432. {
  433. eclasses.Elem(eclass2) =
  434. eclasses.Get(eclass1);
  435. go_on = 1;
  436. }
  437. }
  438. }
  439. for(SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++)
  440. {
  441. const Element2d & el2d = mesh[sei];
  442. for(i = 0; i < el2d.GetNP(); i++)
  443. {
  444. INDEX_2 e1(el2d[i], el2d[(i+1) % el2d.GetNP()]);
  445. e1.Sort();
  446. INDEX_2 e2;
  447. for(k = 0; k < idmaps.Size(); k++)
  448. {
  449. e2.I1() = (*idmaps[k])[e1.I1()];
  450. e2.I2() = (*idmaps[k])[e1.I2()];
  451. if(e2.I1() == 0 || e2.I2() == 0 ||
  452. e1.I1() == e2.I1() || e1.I2() == e2.I2())
  453. continue;
  454. e2.Sort();
  455. if(!edgenumber.Used(e2))
  456. continue;
  457. int eclass1 = edgenumber.Get (e1);
  458. int eclass2 = edgenumber.Get (e2);
  459. if (eclasses.Get(eclass1) >
  460. eclasses.Get(eclass2))
  461. {
  462. eclasses.Elem(eclass1) =
  463. eclasses.Get(eclass2);
  464. go_on = 1;
  465. }
  466. else if (eclasses.Get(eclass2) >
  467. eclasses.Get(eclass1))
  468. {
  469. eclasses.Elem(eclass2) =
  470. eclasses.Get(eclass1);
  471. go_on = 1;
  472. }
  473. }
  474. }
  475. }
  476. }
  477. while (go_on);
  478. // for (i = 1; i <= cntedges; i++)
  479. // {
  480. // (*testout) << "edge " << i << ": "
  481. // << edges.Get(i).I1() << "-" << edges.Get(i).I2()
  482. // << ", class = " << eclasses.Get(i) << endl;
  483. // }
  484. // compute classlength:
  485. Array<double> edgelength(cntedges);
  486. /*
  487. for (i = 1; i <= cntedges; i++)
  488. edgelength.Elem(i) = 1e20;
  489. */
  490. for (i = 1; i <= cntedges; i++)
  491. {
  492. INDEX_2 edge = edges.Get(i);
  493. double elen = Dist (mesh.Point(edge.I1()),
  494. mesh.Point(edge.I2()));
  495. edgelength.Elem (i) = elen;
  496. }
  497. /*
  498. for (i = 1; i <= mesh.GetNE(); i++)
  499. {
  500. const Element & el = mesh.VolumeElement (i);
  501. if (el.GetType() == TET)
  502. {
  503. for (j = 1; j <= 3; j++)
  504. for (k = j+1; k <= 4; k++)
  505. {
  506. INDEX_2 i2(el.PNum(j), el.PNum(k));
  507. i2.Sort();
  508. int enr = edgenumber.Get(i2);
  509. double elen = Dist (mesh.Point (i2.I1()), mesh.Point (i2.I2()));
  510. if (elen < edgelength.Get(enr))
  511. edgelength.Set (enr, elen);
  512. }
  513. }
  514. else if (el.GetType() == PRISM)
  515. {
  516. for (j = 1; j <= 3; j++)
  517. {
  518. k = (j % 3) + 1;
  519. INDEX_2 i2(el.PNum(j), el.PNum(k));
  520. i2.Sort();
  521. int enr = edgenumber.Get(i2);
  522. double elen = Dist (mesh.Point (i2.I1()), mesh.Point (i2.I2()));
  523. if (elen < edgelength.Get(enr))
  524. edgelength.Set (enr, elen);
  525. i2 = INDEX_2(el.PNum(j+3), el.PNum(k+3));
  526. i2.Sort();
  527. enr = edgenumber.Get(i2);
  528. elen = Dist (mesh.Point (i2.I1()), mesh.Point (i2.I2()));
  529. if (elen < edgelength.Get(enr))
  530. edgelength.Set (enr, elen);
  531. if (!edgenumber.Used(i2))
  532. {
  533. cntedges++;
  534. edgenumber.Set(i2, cntedges);
  535. }
  536. i2 = INDEX_2(el.PNum(j), el.PNum(j+3));
  537. i2.Sort();
  538. enr = edgenumber.Get(i2);
  539. elen = Dist (mesh.Point (i2.I1()), mesh.Point (i2.I2()));
  540. if (elen < edgelength.Get(enr))
  541. edgelength.Set (enr, elen);
  542. }
  543. }
  544. }
  545. */
  546. for (i = 1; i <= cntedges; i++)
  547. {
  548. if (eclasses.Get(i) != i)
  549. {
  550. if (edgelength.Get(i) < edgelength.Get(eclasses.Get(i)))
  551. edgelength.Elem(eclasses.Get(i)) = edgelength.Get(i);
  552. edgelength.Elem(i) = 1e20;
  553. }
  554. }
  555. TABLE<int> eclasstab(cntedges);
  556. for (i = 1; i <= cntedges; i++)
  557. eclasstab.Add1 (eclasses.Get(i), i);
  558. // sort edges:
  559. Array<int> sorted(cntedges);
  560. QuickSort (edgelength, sorted);
  561. int cnt = 0;
  562. for (i = 1; i <= cntedges; i++)
  563. {
  564. int ii = sorted.Get(i);
  565. for (j = 1; j <= eclasstab.EntrySize(ii); j++)
  566. {
  567. cnt++;
  568. edgenumber.Set (edges.Get(eclasstab.Get(ii, j)), cnt);
  569. }
  570. }
  571. return cnt;
  572. }
  573. else
  574. {
  575. // old version
  576. int i, j;
  577. int cnt = 0;
  578. int found;
  579. double len2, maxlen2;
  580. INDEX_2 ep;
  581. // sort edges by length, parallel edges (on prisms)
  582. // are added in blocks
  583. do
  584. {
  585. found = 0;
  586. maxlen2 = 1e30;
  587. for (i = 1; i <= mesh.GetNE(); i++)
  588. {
  589. const Element & el = mesh.VolumeElement (i);
  590. int ned;
  591. int tetedges[6][2] =
  592. { { 1, 2 },
  593. { 1, 3 },
  594. { 1, 4 },
  595. { 2, 3 },
  596. { 2, 4 },
  597. { 3, 4 } };
  598. int prismedges[6][2] =
  599. { { 1, 2 },
  600. { 1, 3 },
  601. { 2, 4 },
  602. { 4, 5 },
  603. { 4, 6 },
  604. { 5, 6 } };
  605. int pyramidedges[6][2] =
  606. { { 1, 2 },
  607. { 3, 4 },
  608. { 1, 5 },
  609. { 2, 5 },
  610. { 3, 5 },
  611. { 4, 5 } };
  612. int (*tip)[2];
  613. switch (el.GetType())
  614. {
  615. case TET:
  616. {
  617. tip = tetedges;
  618. ned = 6;
  619. break;
  620. }
  621. case PRISM:
  622. {
  623. tip = prismedges;
  624. ned = 6;
  625. break;
  626. }
  627. case PYRAMID:
  628. {
  629. tip = pyramidedges;
  630. ned = 6;
  631. break;
  632. }
  633. default:
  634. throw NgException("Bisect, element type not handled in switch, 3");
  635. }
  636. for (j = 0; j < ned; j++)
  637. {
  638. INDEX_2 i2(el.PNum(tip[j][0]), el.PNum(tip[j][1]));
  639. i2.Sort();
  640. if (!edgenumber.Used(i2))
  641. {
  642. len2 = Dist (mesh.Point (i2.I1()),
  643. mesh.Point (i2.I2()));
  644. if (len2 < maxlen2)
  645. {
  646. maxlen2 = len2;
  647. ep = i2;
  648. found = 1;
  649. }
  650. }
  651. }
  652. }
  653. if (found)
  654. {
  655. cnt++;
  656. edgenumber.Set (ep, cnt);
  657. // find connected edges:
  658. int go_on = 0;
  659. do
  660. {
  661. go_on = 0;
  662. for (i = 1; i <= mesh.GetNE(); i++)
  663. {
  664. const Element & el = mesh.VolumeElement (i);
  665. if (el.GetNP() != 6) continue;
  666. int prismpairs[3][4] =
  667. { { 1, 2, 4, 5 },
  668. { 2, 3, 5, 6 },
  669. { 1, 3, 4, 6 } };
  670. int pyramidpairs[3][4] =
  671. { { 1, 2, 4, 3 },
  672. { 1, 5, 4, 5 },
  673. { 2, 5, 3, 5 } };
  674. int (*pairs)[4];
  675. switch (el.GetType())
  676. {
  677. case PRISM:
  678. {
  679. pairs = prismpairs;
  680. break;
  681. }
  682. case PYRAMID:
  683. {
  684. pairs = pyramidpairs;
  685. break;
  686. }
  687. default:
  688. throw NgException("Bisect, element type not handled in switch, 3a");
  689. }
  690. for (j = 0; j < 3; j++)
  691. {
  692. INDEX_2 e1 (el.PNum(pairs[j][0]),
  693. el.PNum(pairs[j][1]));
  694. INDEX_2 e2 (el.PNum(pairs[j][2]),
  695. el.PNum(pairs[j][3]));
  696. e1.Sort();
  697. e2.Sort();
  698. int used1 = edgenumber.Used (e1);
  699. int used2 = edgenumber.Used (e2);
  700. if (used1 && !used2)
  701. {
  702. cnt++;
  703. edgenumber.Set (e2, cnt);
  704. go_on = 1;
  705. }
  706. if (used2 && !used1)
  707. {
  708. cnt++;
  709. edgenumber.Set (e1, cnt);
  710. go_on = 1;
  711. }
  712. }
  713. }
  714. }
  715. while (go_on);
  716. }
  717. }
  718. while (found);
  719. return cnt;
  720. }
  721. }
  722. void BTDefineMarkedTet (const Element & el,
  723. INDEX_2_CLOSED_HASHTABLE<int> & edgenumber,
  724. MarkedTet & mt)
  725. {
  726. int i, j, k;
  727. for (i = 0; i < 4; i++)
  728. mt.pnums[i] = el[i];
  729. mt.marked = 0;
  730. mt.flagged = 0;
  731. mt.incorder = 0;
  732. mt.order = 1;
  733. int val = 0;
  734. // find marked edge of tet:
  735. for (i = 0; i < 3; i++)
  736. for (j = i+1; j < 4; j++)
  737. {
  738. INDEX_2 i2(mt.pnums[i], mt.pnums[j]);
  739. i2.Sort();
  740. int hval = edgenumber.Get(i2);
  741. if (hval > val)
  742. {
  743. val = hval;
  744. mt.tetedge1 = i;
  745. mt.tetedge2 = j;
  746. }
  747. }
  748. // find marked edges of faces:
  749. for (k = 0; k < 4; k++)
  750. {
  751. val = 0;
  752. for (i = 0; i < 3; i++)
  753. for (j = i+1; j < 4; j++)
  754. if (i != k && j != k)
  755. {
  756. INDEX_2 i2(mt.pnums[i], mt.pnums[j]);
  757. i2.Sort();
  758. int hval = edgenumber.Get(i2);
  759. if (hval > val)
  760. {
  761. val = hval;
  762. int hi = 6 - k - i - j;
  763. mt.faceedges[k] = char(hi);
  764. }
  765. }
  766. }
  767. }
  768. void BTDefineMarkedPrism (const Element & el,
  769. INDEX_2_CLOSED_HASHTABLE<int> & edgenumber,
  770. MarkedPrism & mp)
  771. {
  772. int i, j;
  773. if (el.GetType() == PRISM ||
  774. el.GetType() == PRISM12)
  775. {
  776. for (i = 0; i < 6; i++)
  777. mp.pnums[i] = el[i];
  778. }
  779. else if (el.GetType() == PYRAMID)
  780. {
  781. static int map[6] =
  782. { 1, 2, 5, 4, 3, 5 };
  783. for (i = 0; i < 6; i++)
  784. mp.pnums[i] = el.PNum(map[i]);
  785. }
  786. else if (el.GetType() == TET ||
  787. el.GetType() == TET10)
  788. {
  789. static int map[6] =
  790. { 1, 4, 3, 2, 4, 3 };
  791. for (i = 0; i < 6; i++)
  792. mp.pnums[i] = el.PNum(map[i]);
  793. }
  794. else
  795. {
  796. PrintSysError ("Define marked prism called for non-prism and non-pyramid");
  797. }
  798. mp.marked = 0;
  799. mp.incorder = 0;
  800. mp.order = 1;
  801. int val = 0;
  802. for (i = 0; i < 2; i++)
  803. for (j = i+1; j < 3; j++)
  804. {
  805. INDEX_2 i2(mp.pnums[i], mp.pnums[j]);
  806. i2.Sort();
  807. int hval = edgenumber.Get(i2);
  808. if (hval > val)
  809. {
  810. val = hval;
  811. mp.markededge = 3 - i - j;
  812. }
  813. }
  814. }
  815. bool BTDefineMarkedId(const Element2d & el,
  816. INDEX_2_CLOSED_HASHTABLE<int> & edgenumber,
  817. const Array<int,PointIndex::BASE> & idmap,
  818. MarkedIdentification & mi)
  819. {
  820. bool identified = true;
  821. mi.np = el.GetNP();
  822. int min1(0),min2(0);
  823. for(int j = 0; identified && j < mi.np; j++)
  824. {
  825. mi.pnums[j] = el[j];
  826. mi.pnums[j+mi.np] = idmap[el[j]];
  827. if(j == 0 || el[j] < min1)
  828. min1 = el[j];
  829. if(j == 0 || mi.pnums[j+mi.np] < min2)
  830. min2 = mi.pnums[j+mi.np];
  831. identified = (mi.pnums[j+mi.np] != 0 && mi.pnums[j+mi.np] != mi.pnums[j]);
  832. }
  833. identified = identified && (min1 < min2);
  834. if(identified)
  835. {
  836. mi.marked = 0;
  837. mi.incorder = 0;
  838. mi.order = 1;
  839. int val = 0;
  840. for (int i = 0; i < mi.np; i++)
  841. {
  842. INDEX_2 i2(mi.pnums[i], mi.pnums[(i+1)%mi.np]);
  843. i2.Sort();
  844. int hval = edgenumber.Get(i2);
  845. if (hval > val)
  846. {
  847. val = hval;
  848. mi.markededge = i;
  849. }
  850. }
  851. }
  852. return identified;
  853. }
  854. void BTDefineMarkedTri (const Element2d & el,
  855. INDEX_2_CLOSED_HASHTABLE<int> & edgenumber,
  856. MarkedTri & mt)
  857. {
  858. int i, j;
  859. for (i = 0; i < 3; i++)
  860. {
  861. mt.pnums[i] = el[i];
  862. mt.pgeominfo[i] = el.GeomInfoPi (i+1);
  863. }
  864. mt.marked = 0;
  865. mt.surfid = el.GetIndex();
  866. mt.incorder = 0;
  867. mt.order = 1;
  868. int val = 0;
  869. for (i = 0; i < 2; i++)
  870. for (j = i+1; j < 3; j++)
  871. {
  872. INDEX_2 i2(mt.pnums[i], mt.pnums[j]);
  873. i2.Sort();
  874. int hval = edgenumber.Get(i2);
  875. if (hval > val)
  876. {
  877. val = hval;
  878. mt.markededge = 3 - i - j;
  879. }
  880. }
  881. }
  882. void PrettyPrint(ostream & ost, const MarkedTri & mt)
  883. {
  884. ost << "MarkedTrig: " << endl;
  885. ost << " pnums = "; for (int i=0; i<3; i++) ost << mt.pnums[i] << " "; ost << endl;
  886. ost << " marked = " << mt.marked << ", markededge=" << mt.markededge << endl;
  887. for(int i=0; i<2; i++)
  888. for(int j=i+1; j<3; j++)
  889. if(mt.markededge == 3-i-j)
  890. ost << " marked edge pnums = " << mt.pnums[i] << " " << mt.pnums[j] << endl;
  891. }
  892. void PrettyPrint(ostream & ost, const MarkedQuad & mq)
  893. {
  894. ost << "MarkedQuad: " << endl;
  895. ost << " pnums = "; for (int i=0; i<4; i++) ost << mq.pnums[i] << " "; ost << endl;
  896. ost << " marked = " << mq.marked << ", markededge=" << mq.markededge << endl;
  897. }
  898. void BTDefineMarkedQuad (const Element2d & el,
  899. INDEX_2_CLOSED_HASHTABLE<int> & edgenumber,
  900. MarkedQuad & mq)
  901. {
  902. int i;
  903. for (i = 0; i < 4; i++)
  904. mq.pnums[i] = el[i];
  905. Swap (mq.pnums[2], mq.pnums[3]);
  906. mq.marked = 0;
  907. mq.markededge = 0;
  908. mq.surfid = el.GetIndex();
  909. }
  910. // mark elements due to local h
  911. int BTMarkTets (T_MTETS & mtets,
  912. T_MPRISMS & mprisms,
  913. const Mesh & mesh)
  914. {
  915. int marked = 0;
  916. int np = mesh.GetNP();
  917. Vector hv(np);
  918. for (int i = 0; i < np; i++)
  919. hv(i) = mesh.GetH (mesh.Point(i+1));
  920. double hfac = 1;
  921. for (int step = 1; step <= 2; step++)
  922. {
  923. for (int i = 1; i <= mtets.Size(); i++)
  924. {
  925. double h = 0;
  926. for (int j = 0; j < 3; j++)
  927. for (int k = j+1; k < 4; k++)
  928. {
  929. const Point<3> & p1 = mesh.Point (mtets.Get(i).pnums[j]);
  930. const Point<3> & p2 = mesh.Point (mtets.Get(i).pnums[k]);
  931. double hh = Dist2 (p1, p2);
  932. if (hh > h) h = hh;
  933. }
  934. h = sqrt (h);
  935. double hshould = 1e10;
  936. for (int j = 0; j < 4; j++)
  937. {
  938. double hi = hv (mtets.Get(i).pnums[j]-1);
  939. if (hi < hshould)
  940. hshould = hi;
  941. }
  942. if (step == 1)
  943. {
  944. if (h / hshould > hfac)
  945. hfac = h / hshould;
  946. }
  947. else
  948. {
  949. if (h > hshould * hfac)
  950. {
  951. mtets.Elem(i).marked = 1;
  952. marked = 1;
  953. }
  954. else
  955. mtets.Elem(i).marked = 0;
  956. }
  957. }
  958. for (int i = 1; i <= mprisms.Size(); i++)
  959. {
  960. double h = 0;
  961. for (int j = 0; j < 2; j++)
  962. for (int k = j+1; k < 3; k++)
  963. {
  964. const Point<3> & p1 = mesh.Point (mprisms.Get(i).pnums[j]);
  965. const Point<3> & p2 = mesh.Point (mprisms.Get(i).pnums[k]);
  966. double hh = Dist2 (p1, p2);
  967. if (hh > h) h = hh;
  968. }
  969. h = sqrt (h);
  970. double hshould = 1e10;
  971. for (int j = 0; j < 6; j++)
  972. {
  973. double hi = hv (mprisms.Get(i).pnums[j]-1);
  974. if (hi < hshould)
  975. hshould = hi;
  976. }
  977. if (step == 1)
  978. {
  979. if (h / hshould > hfac)
  980. hfac = h / hshould;
  981. }
  982. else
  983. {
  984. if (h > hshould * hfac)
  985. {
  986. mprisms.Elem(i).marked = 1;
  987. marked = 1;
  988. }
  989. else
  990. mprisms.Elem(i).marked = 0;
  991. }
  992. }
  993. if (step == 1)
  994. {
  995. if (hfac > 2)
  996. hfac /= 2;
  997. else
  998. hfac = 1;
  999. }
  1000. }
  1001. return marked;
  1002. }
  1003. void BTBisectTet (const MarkedTet & oldtet, int newp,
  1004. MarkedTet & newtet1, MarkedTet & newtet2)
  1005. {
  1006. #ifdef DEBUG
  1007. *testout << "bisect tet " << oldtet << endl;
  1008. #endif
  1009. int i, j, k;
  1010. // points vis a vis from tet-edge
  1011. int vis1, vis2;
  1012. vis1 = 0;
  1013. while (vis1 == oldtet.tetedge1 || vis1 == oldtet.tetedge2)
  1014. vis1++;
  1015. vis2 = 6 - vis1 - oldtet.tetedge1 - oldtet.tetedge2;
  1016. // is tet of type P ?
  1017. int istypep = 0;
  1018. for (i = 0; i < 4; i++)
  1019. {
  1020. int cnt = 0;
  1021. for (j = 0; j < 4; j++)
  1022. if (oldtet.faceedges[j] == i)
  1023. cnt++;
  1024. if (cnt == 3)
  1025. istypep = 1;
  1026. }
  1027. for (i = 0; i < 4; i++)
  1028. {
  1029. newtet1.pnums[i] = oldtet.pnums[i];
  1030. newtet2.pnums[i] = oldtet.pnums[i];
  1031. }
  1032. newtet1.flagged = istypep && !oldtet.flagged;
  1033. newtet2.flagged = istypep && !oldtet.flagged;
  1034. int nm = oldtet.marked - 1;
  1035. if (nm < 0) nm = 0;
  1036. newtet1.marked = nm;
  1037. newtet2.marked = nm;
  1038. #ifdef DEBUG
  1039. *testout << "newtet1,before = " << newtet1 << endl;
  1040. *testout << "newtet2,before = " << newtet2 << endl;
  1041. #endif
  1042. for (i = 0; i < 4; i++)
  1043. {
  1044. if (i == oldtet.tetedge1)
  1045. {
  1046. newtet2.pnums[i] = newp;
  1047. newtet2.faceedges[i] = oldtet.faceedges[i]; // inherited face
  1048. newtet2.faceedges[vis1] = i; // cut faces
  1049. newtet2.faceedges[vis2] = i;
  1050. j = 0;
  1051. while (j == i || j == oldtet.faceedges[i])
  1052. j++;
  1053. k = 6 - i - oldtet.faceedges[i] - j;
  1054. newtet2.tetedge1 = j; // tet-edge
  1055. newtet2.tetedge2 = k;
  1056. // new face:
  1057. if (istypep && oldtet.flagged)
  1058. {
  1059. int hi = 6 - oldtet.tetedge1 - j - k;
  1060. newtet2.faceedges[oldtet.tetedge2] = char(hi);
  1061. }
  1062. else
  1063. newtet2.faceedges[oldtet.tetedge2] = oldtet.tetedge1;
  1064. #ifdef DEBUG
  1065. *testout << "i = " << i << ", j = " << j << " k = " << k
  1066. << " oldtet.tetedge1 = " << oldtet.tetedge1
  1067. << " oldtet.tetedge2 = " << oldtet.tetedge2
  1068. << " 6-oldtet.tetedge1-j-k = " << 6 - oldtet.tetedge1 - j - k
  1069. << " 6-oldtet.tetedge1-j-k = " << short(6 - oldtet.tetedge1 - j - k)
  1070. << endl;
  1071. *testout << "vis1 = " << vis1 << ", vis2 = " << vis2 << endl;
  1072. for (int j = 0; j < 4; j++)
  1073. if (newtet2.faceedges[j] > 3)
  1074. {
  1075. *testout << "ERROR1" << endl;
  1076. }
  1077. #endif
  1078. }
  1079. if (i == oldtet.tetedge2)
  1080. {
  1081. newtet1.pnums[i] = newp;
  1082. newtet1.faceedges[i] = oldtet.faceedges[i]; // inherited face
  1083. newtet1.faceedges[vis1] = i;
  1084. newtet1.faceedges[vis2] = i;
  1085. j = 0;
  1086. while (j == i || j == oldtet.faceedges[i])
  1087. j++;
  1088. k = 6 - i - oldtet.faceedges[i] - j;
  1089. newtet1.tetedge1 = j;
  1090. newtet1.tetedge2 = k;
  1091. // new face:
  1092. if (istypep && oldtet.flagged)
  1093. {
  1094. int hi = 6 - oldtet.tetedge2 - j - k;
  1095. newtet1.faceedges[oldtet.tetedge1] = char(hi);
  1096. }
  1097. else
  1098. newtet1.faceedges[oldtet.tetedge1] = oldtet.tetedge2;
  1099. #ifdef DEBUG
  1100. for (int j = 0; j < 4; j++)
  1101. if (newtet2.faceedges[j] > 3)
  1102. {
  1103. *testout << "ERROR2" << endl;
  1104. }
  1105. #endif
  1106. }
  1107. }
  1108. newtet1.matindex = oldtet.matindex;
  1109. newtet2.matindex = oldtet.matindex;
  1110. newtet1.incorder = 0;
  1111. newtet1.order = oldtet.order;
  1112. newtet2.incorder = 0;
  1113. newtet2.order = oldtet.order;
  1114. *testout << "newtet1 = " << newtet1 << endl;
  1115. *testout << "newtet2 = " << newtet2 << endl;
  1116. }
  1117. void BTBisectPrism (const MarkedPrism & oldprism, int newp1, int newp2,
  1118. MarkedPrism & newprism1, MarkedPrism & newprism2)
  1119. {
  1120. int i;
  1121. for (i = 0; i < 6; i++)
  1122. {
  1123. newprism1.pnums[i] = oldprism.pnums[i];
  1124. newprism2.pnums[i] = oldprism.pnums[i];
  1125. }
  1126. int pe1, pe2;
  1127. pe1 = 0;
  1128. if (pe1 == oldprism.markededge)
  1129. pe1++;
  1130. pe2 = 3 - oldprism.markededge - pe1;
  1131. newprism1.pnums[pe2] = newp1;
  1132. newprism1.pnums[pe2+3] = newp2;
  1133. newprism1.markededge = pe2;
  1134. newprism2.pnums[pe1] = newp1;
  1135. newprism2.pnums[pe1+3] = newp2;
  1136. newprism2.markededge = pe1;
  1137. newprism1.matindex = oldprism.matindex;
  1138. newprism2.matindex = oldprism.matindex;
  1139. int nm = oldprism.marked - 1;
  1140. if (nm < 0) nm = 0;
  1141. newprism1.marked = nm;
  1142. newprism2.marked = nm;
  1143. newprism1.incorder = 0;
  1144. newprism1.order = oldprism.order;
  1145. newprism2.incorder = 0;
  1146. newprism2.order = oldprism.order;
  1147. }
  1148. void BTBisectIdentification (const MarkedIdentification & oldid,
  1149. Array<int> & newp,
  1150. MarkedIdentification & newid1,
  1151. MarkedIdentification & newid2)
  1152. {
  1153. for(int i=0; i<2*oldid.np; i++)
  1154. {
  1155. newid1.pnums[i] = oldid.pnums[i];
  1156. newid2.pnums[i] = oldid.pnums[i];
  1157. }
  1158. newid1.np = newid2.np = oldid.np;
  1159. if(oldid.np == 3)
  1160. {
  1161. newid1.pnums[(oldid.markededge+1)%3] = newp[0];
  1162. newid1.pnums[(oldid.markededge+1)%3+3] = newp[1];
  1163. newid1.markededge = (oldid.markededge+2)%3;
  1164. newid2.pnums[oldid.markededge] = newp[0];
  1165. newid2.pnums[oldid.markededge+3] = newp[1];
  1166. newid2.markededge = (oldid.markededge+1)%3;
  1167. }
  1168. else if(oldid.np == 4)
  1169. {
  1170. newid1.pnums[(oldid.markededge+1)%4] = newp[0];
  1171. newid1.pnums[(oldid.markededge+2)%4] = newp[2];
  1172. newid1.pnums[(oldid.markededge+1)%4+4] = newp[1];
  1173. newid1.pnums[(oldid.markededge+2)%4+4] = newp[3];
  1174. newid1.markededge = (oldid.markededge+3)%4;
  1175. newid2.pnums[oldid.markededge] = newp[0];
  1176. newid2.pnums[(oldid.markededge+3)%4] = newp[2];
  1177. newid2.pnums[oldid.markededge+4] = newp[1];
  1178. newid2.pnums[(oldid.markededge+3)%4+4] = newp[3];
  1179. newid2.markededge = (oldid.markededge+1)%4;
  1180. }
  1181. int nm = oldid.marked - 1;
  1182. if (nm < 0) nm = 0;
  1183. newid1.marked = newid2.marked = nm;
  1184. newid1.incorder = newid2.incorder = 0;
  1185. newid1.order = newid2.order = oldid.order;
  1186. }
  1187. void BTBisectTri (const MarkedTri & oldtri, int newp, const PointGeomInfo & newpgi,
  1188. MarkedTri & newtri1, MarkedTri & newtri2)
  1189. {
  1190. int i;
  1191. for (i = 0; i < 3; i++)
  1192. {
  1193. newtri1.pnums[i] = oldtri.pnums[i];
  1194. newtri1.pgeominfo[i] = oldtri.pgeominfo[i];
  1195. newtri2.pnums[i] = oldtri.pnums[i];
  1196. newtri2.pgeominfo[i] = oldtri.pgeominfo[i];
  1197. }
  1198. int pe1, pe2;
  1199. pe1 = 0;
  1200. if (pe1 == oldtri.markededge)
  1201. pe1++;
  1202. pe2 = 3 - oldtri.markededge - pe1;
  1203. newtri1.pnums[pe2] = newp;
  1204. newtri1.pgeominfo[pe2] = newpgi;
  1205. newtri1.markededge = pe2;
  1206. newtri2.pnums[pe1] = newp;
  1207. newtri2.pgeominfo[pe1] = newpgi;
  1208. newtri2.markededge = pe1;
  1209. newtri1.surfid = oldtri.surfid;
  1210. newtri2.surfid = oldtri.surfid;
  1211. int nm = oldtri.marked - 1;
  1212. if (nm < 0) nm = 0;
  1213. newtri1.marked = nm;
  1214. newtri2.marked = nm;
  1215. newtri1.incorder = 0;
  1216. newtri1.order = oldtri.order;
  1217. newtri2.incorder = 0;
  1218. newtri2.order = oldtri.order;
  1219. }
  1220. void BTBisectQuad (const MarkedQuad & oldquad,
  1221. int newp1, const PointGeomInfo & npgi1,
  1222. int newp2, const PointGeomInfo & npgi2,
  1223. MarkedQuad & newquad1, MarkedQuad & newquad2)
  1224. {
  1225. int i;
  1226. for (i = 0; i < 4; i++)
  1227. {
  1228. newquad1.pnums[i] = oldquad.pnums[i];
  1229. newquad1.pgeominfo[i] = oldquad.pgeominfo[i];
  1230. newquad2.pnums[i] = oldquad.pnums[i];
  1231. newquad2.pgeominfo[i] = oldquad.pgeominfo[i];
  1232. }
  1233. /* if (oldquad.marked==1) // he/sz: 2d quads or 3d prism
  1234. {
  1235. newquad1.pnums[1] = newp1;
  1236. newquad1.pgeominfo[1] = npgi1;
  1237. newquad1.pnums[3] = newp2;
  1238. newquad1.pgeominfo[3] = npgi2;
  1239. newquad2.pnums[0] = newp1;
  1240. newquad2.pgeominfo[0] = npgi1;
  1241. newquad2.pnums[2] = newp2;
  1242. newquad2.pgeominfo[2] = npgi2;
  1243. }
  1244. else if (oldquad.marked==2) // he/sz: 2d quads only
  1245. {
  1246. newquad1.pnums[0] = newp1;
  1247. newquad1.pnums[1] = newp2;
  1248. newquad1.pnums[3] = oldquad.pnums[2];
  1249. newquad1.pnums[2] = oldquad.pnums[0];
  1250. newquad1.pgeominfo[0] = npgi1;
  1251. newquad1.pgeominfo[1] = npgi2;
  1252. newquad1.pgeominfo[3] = oldquad.pgeominfo[2];
  1253. newquad1.pgeominfo[2] = oldquad.pgeominfo[0];
  1254. newquad2.pnums[0] = newp2;
  1255. newquad2.pnums[1] = newp1;
  1256. newquad2.pnums[3] = oldquad.pnums[1];
  1257. newquad2.pnums[2] = oldquad.pnums[3];
  1258. newquad2.pgeominfo[0] = npgi2;
  1259. newquad2.pgeominfo[1] = npgi1;
  1260. newquad2.pgeominfo[3] = oldquad.pgeominfo[1];
  1261. newquad2.pgeominfo[2] = oldquad.pgeominfo[3];
  1262. }
  1263. */
  1264. if (oldquad.markededge==0 || oldquad.markededge==2)
  1265. {
  1266. newquad1.pnums[1] = newp1;
  1267. newquad1.pgeominfo[1] = npgi1;
  1268. newquad1.pnums[3] = newp2;
  1269. newquad1.pgeominfo[3] = npgi2;
  1270. newquad2.pnums[0] = newp1;
  1271. newquad2.pgeominfo[0] = npgi1;
  1272. newquad2.pnums[2] = newp2;
  1273. newquad2.pgeominfo[2] = npgi2;
  1274. }
  1275. else // 1 || 3
  1276. {
  1277. newquad1.pnums[2] = newp1;
  1278. newquad1.pgeominfo[2] = npgi1;
  1279. newquad1.pnums[3] = newp2;
  1280. newquad1.pgeominfo[3] = npgi2;
  1281. newquad2.pnums[0] = newp1;
  1282. newquad2.pgeominfo[0] = npgi1;
  1283. newquad2.pnums[1] = newp2;
  1284. newquad2.pgeominfo[1] = npgi2;
  1285. }
  1286. newquad1.surfid = oldquad.surfid;
  1287. newquad2.surfid = oldquad.surfid;
  1288. int nm = oldquad.marked - 1;
  1289. if (nm < 0) nm = 0;
  1290. newquad1.marked = nm;
  1291. newquad2.marked = nm;
  1292. if (nm==1)
  1293. {
  1294. newquad1.markededge=1;
  1295. newquad2.markededge=1;
  1296. }
  1297. else
  1298. {
  1299. newquad1.markededge=0;
  1300. newquad2.markededge=0;
  1301. }
  1302. }
  1303. int MarkHangingIdentifications(T_MIDS & mids,
  1304. const INDEX_2_CLOSED_HASHTABLE<int> & cutedges)
  1305. {
  1306. int i, j;
  1307. int hanging = 0;
  1308. for (i = 1; i <= mids.Size(); i++)
  1309. {
  1310. if (mids.Elem(i).marked)
  1311. {
  1312. hanging = 1;
  1313. continue;
  1314. }
  1315. const int np = mids.Get(i).np;
  1316. for(j = 0; j < np; j++)
  1317. {
  1318. INDEX_2 edge1(mids.Get(i).pnums[j],
  1319. mids.Get(i).pnums[(j+1) % np]);
  1320. INDEX_2 edge2(mids.Get(i).pnums[j+np],
  1321. mids.Get(i).pnums[((j+1) % np) + np]);
  1322. edge1.Sort();
  1323. edge2.Sort();
  1324. if (cutedges.Used (edge1) ||
  1325. cutedges.Used (edge2))
  1326. {
  1327. mids.Elem(i).marked = 1;
  1328. hanging = 1;
  1329. }
  1330. }
  1331. }
  1332. return hanging;
  1333. }
  1334. /*
  1335. void IdentifyCutEdges(Mesh & mesh,
  1336. INDEX_2_CLOSED_HASHTABLE<int> & cutedges)
  1337. {
  1338. int i,j,k;
  1339. Array< Array<int,PointIndex::BASE>* > idmaps;
  1340. for(i=1; i<=mesh.GetIdentifications().GetMaxNr(); i++)
  1341. {
  1342. idmaps.Append(new Array<int,PointIndex::BASE>);
  1343. mesh.GetIdentifications().GetMap(i,*idmaps.Last());
  1344. }
  1345. for(SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++)
  1346. {
  1347. const Element2d & el2d = mesh[sei];
  1348. for(i = 0; i < el2d.GetNP(); i++)
  1349. {
  1350. INDEX_2 e1(el2d[i], el2d[(i+1) % el2d.GetNP()]);
  1351. e1.Sort();
  1352. if(!cutedges.Used(e1))
  1353. continue;
  1354. for(k = 0; k < idmaps.Size(); k++)
  1355. {
  1356. INDEX_2 e2((*idmaps[k])[e1.I1()],
  1357. (*idmaps[k])[e1.I2()]);
  1358. if(e2.I1() == 0 || e2.I2() == 0 ||
  1359. e1.I1() == e2.I1() || e1.I2() == e2.I2())
  1360. continue;
  1361. e2.Sort();
  1362. if(cutedges.Used(e2))
  1363. continue;
  1364. Point3d np = Center(mesh.Point(e2.I1()),
  1365. mesh.Point(e2.I2()));
  1366. int newp = mesh.AddPoint(np);
  1367. cutedges.Set(e2,newp);
  1368. (*testout) << "DAAA" << endl;
  1369. }
  1370. }
  1371. }
  1372. for(i=0; i<idmaps.Size(); i++)
  1373. delete idmaps[i];
  1374. idmaps.DeleteAll();
  1375. }
  1376. */
  1377. int MarkHangingTets (T_MTETS & mtets,
  1378. const INDEX_2_CLOSED_HASHTABLE<int> & cutedges)
  1379. {
  1380. int i, j, k;
  1381. int hanging = 0;
  1382. for (i = 1; i <= mtets.Size(); i++)
  1383. {
  1384. MarkedTet & teti = mtets.Elem(i);
  1385. if (teti.marked)
  1386. {
  1387. hanging = 1;
  1388. continue;
  1389. }
  1390. for (j = 0; j < 3; j++)
  1391. for (k = j+1; k < 4; k++)
  1392. {
  1393. INDEX_2 edge(teti.pnums[j],
  1394. teti.pnums[k]);
  1395. edge.Sort();
  1396. if (cutedges.Used (edge))
  1397. {
  1398. teti.marked = 1;
  1399. hanging = 1;
  1400. }
  1401. }
  1402. }
  1403. return hanging;
  1404. }
  1405. int MarkHangingPrisms (T_MPRISMS & mprisms,
  1406. const INDEX_2_CLOSED_HASHTABLE<int> & cutedges)
  1407. {
  1408. int i, j, k;
  1409. int hanging = 0;
  1410. for (i = 1; i <= mprisms.Size(); i++)
  1411. {
  1412. if (mprisms.Elem(i).marked)
  1413. {
  1414. hanging = 1;
  1415. continue;
  1416. }
  1417. for (j = 0; j < 2; j++)
  1418. for (k = j+1; k < 3; k++)
  1419. {
  1420. INDEX_2 edge1(mprisms.Get(i).pnums[j],
  1421. mprisms.Get(i).pnums[k]);
  1422. INDEX_2 edge2(mprisms.Get(i).pnums[j+3],
  1423. mprisms.Get(i).pnums[k+3]);
  1424. edge1.Sort();
  1425. edge2.Sort();
  1426. if (cutedges.Used (edge1) ||
  1427. cutedges.Used (edge2))
  1428. {
  1429. mprisms.Elem(i).marked = 1;
  1430. hanging = 1;
  1431. }
  1432. }
  1433. }
  1434. return hanging;
  1435. }
  1436. int MarkHangingTris (T_MTRIS & mtris,
  1437. const INDEX_2_CLOSED_HASHTABLE<int> & cutedges)
  1438. {
  1439. int i, j, k;
  1440. int hanging = 0;
  1441. for (i = 1; i <= mtris.Size(); i++)
  1442. {
  1443. if (mtris.Get(i).marked)
  1444. {
  1445. hanging = 1;
  1446. continue;
  1447. }
  1448. for (j = 0; j < 2; j++)
  1449. for (k = j+1; k < 3; k++)
  1450. {
  1451. INDEX_2 edge(mtris.Get(i).pnums[j],
  1452. mtris.Get(i).pnums[k]);
  1453. edge.Sort();
  1454. if (cutedges.Used (edge))
  1455. {
  1456. mtris.Elem(i).marked = 1;
  1457. hanging = 1;
  1458. }
  1459. }
  1460. }
  1461. return hanging;
  1462. }
  1463. int MarkHangingQuads (T_MQUADS & mquads,
  1464. const INDEX_2_CLOSED_HASHTABLE<int> & cutedges)
  1465. {
  1466. int i;
  1467. int hanging = 0;
  1468. for (i = 1; i <= mquads.Size(); i++)
  1469. {
  1470. if (mquads.Elem(i).marked)
  1471. {
  1472. hanging = 1;
  1473. continue;
  1474. }
  1475. INDEX_2 edge1(mquads.Get(i).pnums[0],
  1476. mquads.Get(i).pnums[1]);
  1477. INDEX_2 edge2(mquads.Get(i).pnums[2],
  1478. mquads.Get(i).pnums[3]);
  1479. edge1.Sort();
  1480. edge2.Sort();
  1481. if (cutedges.Used (edge1) ||
  1482. cutedges.Used (edge2))
  1483. {
  1484. mquads.Elem(i).marked = 1;
  1485. mquads.Elem(i).markededge = 0;
  1486. hanging = 1;
  1487. continue;
  1488. }
  1489. // he/sz: second case: split horizontally
  1490. INDEX_2 edge3(mquads.Get(i).pnums[1],
  1491. mquads.Get(i).pnums[3]);
  1492. INDEX_2 edge4(mquads.Get(i).pnums[2],
  1493. mquads.Get(i).pnums[0]);
  1494. edge3.Sort();
  1495. edge4.Sort();
  1496. if (cutedges.Used (edge3) ||
  1497. cutedges.Used (edge4))
  1498. {
  1499. mquads.Elem(i).marked = 1;
  1500. mquads.Elem(i).markededge = 1;
  1501. hanging = 1;
  1502. continue;
  1503. }
  1504. }
  1505. return hanging;
  1506. }
  1507. void ConnectToNodeRec (int node, int tonode,
  1508. const TABLE<int> & conto, Array<int> & connecttonode)
  1509. {
  1510. int i, n2;
  1511. // (*testout) << "connect " << node << " to " << tonode << endl;
  1512. for (i = 1; i <= conto.EntrySize(node); i++)
  1513. {
  1514. n2 = conto.Get(node, i);
  1515. if (!connecttonode.Get(n2))
  1516. {
  1517. connecttonode.Elem(n2) = tonode;
  1518. ConnectToNodeRec (n2, tonode, conto, connecttonode);
  1519. }
  1520. }
  1521. }
  1522. T_MTETS mtets;
  1523. T_MPRISMS mprisms;
  1524. T_MIDS mids;
  1525. T_MTRIS mtris;
  1526. T_MQUADS mquads;
  1527. void WriteMarkedElements(ostream & ost)
  1528. {
  1529. ost << "Marked Elements\n";
  1530. ost << mtets.Size() << "\n";
  1531. for(int i=0; i<mtets.Size(); i++)
  1532. ost << mtets[i];
  1533. ost << mprisms.Size() << "\n";
  1534. for(int i=0; i<mprisms.Size(); i++)
  1535. ost << mprisms[i];
  1536. ost << mids.Size() << "\n";
  1537. for(int i=0; i<mids.Size(); i++)
  1538. ost << mids[i];
  1539. ost << mtris.Size() << "\n";
  1540. for(int i=0; i<mtris.Size(); i++)
  1541. ost << mtris[i];
  1542. ost << mquads.Size() << "\n";
  1543. for(int i=0; i<mquads.Size(); i++)
  1544. ost << mquads[i];
  1545. ost << endl;
  1546. }
  1547. bool ReadMarkedElements(istream & ist, const Mesh & mesh)
  1548. {
  1549. string auxstring("");
  1550. if(ist)
  1551. ist >> auxstring;
  1552. if(auxstring != "Marked")
  1553. return false;
  1554. if(ist)
  1555. ist >> auxstring;
  1556. if(auxstring != "Elements")
  1557. return false;
  1558. int size;
  1559. ist >> size;
  1560. mtets.SetSize(size);
  1561. for(int i=0; i<size; i++)
  1562. {
  1563. ist >> mtets[i];
  1564. if(mtets[i].pnums[0] > mesh.GetNV() ||
  1565. mtets[i].pnums[1] > mesh.GetNV() ||
  1566. mtets[i].pnums[2] > mesh.GetNV() ||
  1567. mtets[i].pnums[3] > mesh.GetNV())
  1568. return false;
  1569. }
  1570. ist >> size;
  1571. mprisms.SetSize(size);
  1572. for(int i=0; i<size; i++)
  1573. ist >> mprisms[i];
  1574. ist >> size;
  1575. mids.SetSize(size);
  1576. for(int i=0; i<size; i++)
  1577. ist >> mids[i];
  1578. ist >> size;
  1579. mtris.SetSize(size);
  1580. for(int i=0; i<size; i++)
  1581. ist >> mtris[i];
  1582. ist >> size;
  1583. mquads.SetSize(size);
  1584. for(int i=0; i<size; i++)
  1585. ist >> mquads[i];
  1586. return true;
  1587. }
  1588. void BisectTetsCopyMesh (Mesh & mesh, const class CSGeometry *,
  1589. BisectionOptions & opt,
  1590. const Array< Array<int,PointIndex::BASE>* > & idmaps,
  1591. const string & refinfofile)
  1592. {
  1593. mtets.SetName ("bisection, tets");
  1594. mprisms.SetName ("bisection, prisms");
  1595. mtris.SetName ("bisection, trigs");
  1596. mquads.SetName ("bisection, quads");
  1597. mids.SetName ("bisection, identifications");
  1598. //int np = mesh.GetNP();
  1599. int ne = mesh.GetNE();
  1600. int nse = mesh.GetNSE();
  1601. int i, j, k, l, m;
  1602. /*
  1603. if (mtets.Size() + mprisms.Size() == mesh.GetNE())
  1604. return;
  1605. */
  1606. bool readok = false;
  1607. if(refinfofile != "")
  1608. {
  1609. PrintMessage(3,"Reading marked-element information from \"",refinfofile,"\"");
  1610. ifstream ist(refinfofile.c_str());
  1611. readok = ReadMarkedElements(ist,mesh);
  1612. ist.close();
  1613. }
  1614. if(!readok)
  1615. {
  1616. PrintMessage(3,"resetting marked-element information");
  1617. mtets.SetSize(0);
  1618. mprisms.SetSize(0);
  1619. mids.SetSize(0);
  1620. mtris.SetSize(0);
  1621. mquads.SetSize(0);
  1622. INDEX_2_HASHTABLE<int> shortedges(100);
  1623. for (i = 1; i <= ne; i++)
  1624. {
  1625. const Element & el = mesh.VolumeElement(i);
  1626. if (el.GetType() == PRISM ||
  1627. el.GetType() == PRISM12)
  1628. {
  1629. for (j = 1; j <= 3; j++)
  1630. {
  1631. INDEX_2 se(el.PNum(j), el.PNum(j+3));
  1632. se.Sort();
  1633. shortedges.Set (se, 1);
  1634. }
  1635. }
  1636. }
  1637. // INDEX_2_HASHTABLE<int> edgenumber(np);
  1638. INDEX_2_CLOSED_HASHTABLE<int> edgenumber(9*ne+4*nse);
  1639. BTSortEdges (mesh, idmaps, edgenumber);
  1640. for (i = 1; i <= ne; i++)
  1641. {
  1642. const Element & el = mesh.VolumeElement(i);
  1643. switch (el.GetType())
  1644. {
  1645. case TET:
  1646. case TET10:
  1647. {
  1648. // if tet has short edge, it is handled as degenerated prism
  1649. int foundse = 0;
  1650. for (j = 1; j <= 3; j++)
  1651. for (k = j+1; k <= 4; k++)
  1652. {
  1653. INDEX_2 se(el.PNum(j), el.PNum(k));
  1654. se.Sort();
  1655. if (shortedges.Used (se))
  1656. {
  1657. // cout << "tet converted to prism" << endl;
  1658. foundse = 1;
  1659. int p3 = 1;
  1660. while (p3 == j || p3 == k)
  1661. p3++;
  1662. int p4 = 10 - j - k - p3;
  1663. // even permutation ?
  1664. int pi[4];
  1665. pi[0] = j;
  1666. pi[1] = k;
  1667. pi[2] = p3;
  1668. pi[3] = p4;
  1669. int cnt = 0;
  1670. for (l = 1; l <= 4; l++)
  1671. for (m = 0; m < 3; m++)
  1672. if (pi[m] > pi[m+1])
  1673. {
  1674. Swap (pi[m], pi[m+1]);
  1675. cnt++;
  1676. }
  1677. if (cnt % 2)
  1678. Swap (p3, p4);
  1679. Element hel = el;
  1680. hel.PNum(1) = el.PNum(j);
  1681. hel.PNum(2) = el.PNum(k);
  1682. hel.PNum(3) = el.PNum(p3);
  1683. hel.PNum(4) = el.PNum(p4);
  1684. MarkedPrism mp;
  1685. BTDefineMarkedPrism (hel, edgenumber, mp);
  1686. mp.matindex = el.GetIndex();
  1687. mprisms.Append (mp);
  1688. }
  1689. }
  1690. if (!foundse)
  1691. {
  1692. MarkedTet mt;
  1693. BTDefineMarkedTet (el, edgenumber, mt);
  1694. mt.matindex = el.GetIndex();
  1695. mtets.Append (mt);
  1696. }
  1697. break;
  1698. }
  1699. case PYRAMID:
  1700. {
  1701. // eventually rotate
  1702. MarkedPrism mp;
  1703. INDEX_2 se(el.PNum(1), el.PNum(2));
  1704. se.Sort();
  1705. if (shortedges.Used (se))
  1706. {
  1707. Element hel = el;
  1708. hel.PNum(1) = el.PNum(2);
  1709. hel.PNum(2) = el.PNum(3);
  1710. hel.PNum(3) = el.PNum(4);
  1711. hel.PNum(4) = el.PNum(1);
  1712. BTDefineMarkedPrism (hel, edgenumber, mp);
  1713. }
  1714. else
  1715. {
  1716. BTDefineMarkedPrism (el, edgenumber, mp);
  1717. }
  1718. mp.matindex = el.GetIndex();
  1719. mprisms.Append (mp);
  1720. break;
  1721. }
  1722. case PRISM:
  1723. case PRISM12:
  1724. {
  1725. MarkedPrism mp;
  1726. BTDefineMarkedPrism (el, edgenumber, mp);
  1727. mp.matindex = el.GetIndex();
  1728. mprisms.Append (mp);
  1729. break;
  1730. }
  1731. default:
  1732. throw NgException("Bisect, element type not handled in switch, 4");
  1733. }
  1734. }
  1735. for (i = 1; i <= nse; i++)
  1736. {
  1737. const Element2d & el = mesh.SurfaceElement(i);
  1738. if (el.GetType() == TRIG ||
  1739. el.GetType() == TRIG6)
  1740. {
  1741. MarkedTri mt;
  1742. BTDefineMarkedTri (el, edgenumber, mt);
  1743. mtris.Append (mt);
  1744. }
  1745. else
  1746. {
  1747. MarkedQuad mq;
  1748. BTDefineMarkedQuad (el, edgenumber, mq);
  1749. mquads.Append (mq);
  1750. }
  1751. MarkedIdentification mi;
  1752. for(j=0; j<idmaps.Size(); j++)
  1753. if(BTDefineMarkedId(el, edgenumber, *idmaps[j], mi))
  1754. mids.Append(mi);
  1755. }
  1756. }
  1757. mesh.mlparentelement.SetSize(ne);
  1758. for (i = 1; i <= ne; i++)
  1759. mesh.mlparentelement.Elem(i) = 0;
  1760. mesh.mlparentsurfaceelement.SetSize(nse);
  1761. for (i = 1; i <= nse; i++)
  1762. mesh.mlparentsurfaceelement.Elem(i) = 0;
  1763. if (printmessage_importance>0)
  1764. {
  1765. ostringstream str1,str2;
  1766. str1 << "copied " << mtets.Size() << " tets, " << mprisms.Size() << " prisms";
  1767. str2 << " " << mtris.Size() << " trigs, " << mquads.Size() << " quads";
  1768. PrintMessage(4,str1.str());
  1769. PrintMessage(4,str2.str());
  1770. }
  1771. }
  1772. /*
  1773. void UpdateEdgeMarks2(Mesh & mesh,
  1774. const Array< Array<int,PointIndex::BASE>* > & idmaps)
  1775. {
  1776. Array< Array<MarkedTet>*,PointIndex::BASE > mtets_old(mesh.GetNP());
  1777. Array< Array<MarkedPrism>*,PointIndex::BASE > mprisms_old(mesh.GetNP());
  1778. Array< Array<MarkedIdentification>*,PointIndex::BASE > mids_old(mesh.GetNP());
  1779. Array< Array<MarkedTri>*,PointIndex::BASE > mtris_old(mesh.GetNP());
  1780. Array< Array<MarkedQuad>*,PointIndex::BASE > mquads_old(mesh.GetNP());
  1781. for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++)
  1782. mtets_old[i] = new Array<MarkedTet>;
  1783. for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++)
  1784. mprisms_old[i] = new Array<MarkedPrism>;
  1785. for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++)
  1786. mids_old[i] = new Array<MarkedIdentification>;
  1787. for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++)
  1788. mtris_old[i] = new Array<MarkedTri>;
  1789. for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++)
  1790. mquads_old[i] = new Array<MarkedQuad>;
  1791. for(int i=0; i<mtets.Size(); i++)
  1792. mtets_old[mtets[i].pnums[0]]->Append(mtets[i]);
  1793. for(int i=0; i<mprisms.Size(); i++)
  1794. mprisms_old[mprisms[i].pnums[0]]->Append(mprisms[i]);
  1795. for(int i=0; i<mids.Size(); i++)
  1796. mids_old[mids[i].pnums[0]]->Append(mids[i]);
  1797. for(int i=0; i<mtris.Size(); i++)
  1798. {
  1799. (*testout) << "i " << i << endl;
  1800. (*testout) << "mtris[i] " << mtris[i].pnums[0] << " " << mtris[i].pnums[1] << " " << mtris[i].pnums[2] << endl;
  1801. mtris_old[mtris[i].pnums[0]]->Append(mtris[i]);
  1802. }
  1803. for(int i=0; i<mquads.Size(); i++)
  1804. mquads_old[mquads[i].pnums[0]]->Append(mquads[i]);
  1805. int np = mesh.GetNP();
  1806. int ne = mesh.GetNE();
  1807. int nse = mesh.GetNSE();
  1808. int i, j, k, l, m;
  1809. // if (mtets.Size() + mprisms.Size() == mesh.GetNE())
  1810. // return;
  1811. mtets.SetSize(0);
  1812. mprisms.SetSize(0);
  1813. mids.SetSize(0);
  1814. mtris.SetSize(0);
  1815. mquads.SetSize(0);
  1816. INDEX_2_HASHTABLE<int> shortedges(100);
  1817. for (i = 1; i <= ne; i++)
  1818. {
  1819. const Element & el = mesh.VolumeElement(i);
  1820. if (el.GetType() == PRISM ||
  1821. el.GetType() == PRISM12)
  1822. {
  1823. for (j = 1; j <= 3; j++)
  1824. {
  1825. INDEX_2 se(el.PNum(j), el.PNum(j+3));
  1826. se.Sort();
  1827. shortedges.Set (se, 1);
  1828. }
  1829. }
  1830. }
  1831. // INDEX_2_HASHTABLE<int> edgenumber(np);
  1832. INDEX_2_CLOSED_HASHTABLE<int> edgenumber(9*ne+4*nse);
  1833. BTSortEdges (mesh, idmaps, edgenumber);
  1834. for (i = 1; i <= ne; i++)
  1835. {
  1836. const Element & el = mesh.VolumeElement(i);
  1837. switch (el.GetType())
  1838. {
  1839. case TET:
  1840. case TET10:
  1841. {
  1842. // if tet has short edge, it is handled as degenerated prism
  1843. int foundse = 0;
  1844. for (j = 1; j <= 3; j++)
  1845. for (k = j+1; k <= 4; k++)
  1846. {
  1847. INDEX_2 se(el.PNum(j), el.PNum(k));
  1848. se.Sort();
  1849. if (shortedges.Used (se))
  1850. {
  1851. // cout << "tet converted to prism" << endl;
  1852. foundse = 1;
  1853. int p3 = 1;
  1854. while (p3 == j || p3 == k)
  1855. p3++;
  1856. int p4 = 10 - j - k - p3;
  1857. // even permutation ?
  1858. int pi[4];
  1859. pi[0] = j;
  1860. pi[1] = k;
  1861. pi[2] = p3;
  1862. pi[3] = p4;
  1863. int cnt = 0;
  1864. for (l = 1; l <= 4; l++)
  1865. for (m = 0; m < 3; m++)
  1866. if (pi[m] > pi[m+1])
  1867. {
  1868. Swap (pi[m], pi[m+1]);
  1869. cnt++;
  1870. }
  1871. if (cnt % 2)
  1872. Swap (p3, p4);
  1873. Element hel = el;
  1874. hel.PNum(1) = el.PNum(j);
  1875. hel.PNum(2) = el.PNum(k);
  1876. hel.PNum(3) = el.PNum(p3);
  1877. hel.PNum(4) = el.PNum(p4);
  1878. MarkedPrism mp;
  1879. BTDefineMarkedPrism (hel, edgenumber, mp);
  1880. mp.matindex = el.GetIndex();
  1881. mprisms.Append (mp);
  1882. }
  1883. }
  1884. if (!foundse)
  1885. {
  1886. MarkedTet mt;
  1887. int oldind = -1;
  1888. for(l = 0; oldind < 0 && l<mtets_old[el[0]]->Size(); l++)
  1889. if(el[1] == (*mtets_old[el[0]])[l].pnums[1] &&
  1890. el[2] == (*mtets_old[el[0]])[l].pnums[2] &&
  1891. el[3] == (*mtets_old[el[0]])[l].pnums[3])
  1892. oldind = l;
  1893. if(oldind >= 0)
  1894. mtets.Append((*mtets_old[el[0]])[oldind]);
  1895. else
  1896. {
  1897. BTDefineMarkedTet (el, edgenumber, mt);
  1898. mt.matindex = el.GetIndex();
  1899. mtets.Append (mt);
  1900. }
  1901. }
  1902. break;
  1903. }
  1904. case PYRAMID:
  1905. {
  1906. // eventually rotate
  1907. MarkedPrism mp;
  1908. INDEX_2 se(el.PNum(1), el.PNum(2));
  1909. se.Sort();
  1910. if (shortedges.Used (se))
  1911. {
  1912. Element hel = el;
  1913. hel.PNum(1) = el.PNum(2);
  1914. hel.PNum(2) = el.PNum(3);
  1915. hel.PNum(3) = el.PNum(4);
  1916. hel.PNum(4) = el.PNum(1);
  1917. BTDefineMa…

Large files files are truncated, but you can click here to view the full file