/src/BSPTreePoly.cpp

https://bitbucket.org/danwu/moab · C++ · 828 lines · 665 code · 114 blank · 49 comment · 206 complexity · 4ed7710924835d9256b970ef9c64c894 MD5 · raw file

  1. #include "moab/CartVect.hpp"
  2. #include "moab/BSPTreePoly.hpp"
  3. #include <assert.h>
  4. #include <stdlib.h>
  5. #include <set>
  6. #undef DEBUG_IDS
  7. namespace moab {
  8. struct BSPTreePoly::Vertex : public CartVect {
  9. Vertex( const CartVect& v ) : CartVect(v), usePtr(0)
  10. #ifdef DEBUG_IDS
  11. , id(nextID++)
  12. #endif
  13. {}
  14. ~Vertex() { assert(!usePtr); }
  15. BSPTreePoly::VertexUse* usePtr;
  16. int markVal;
  17. #ifdef DEBUG_IDS
  18. int id;
  19. static int nextID;
  20. #endif
  21. };
  22. struct BSPTreePoly::VertexUse {
  23. VertexUse( Edge* edge, Vertex* vtx );
  24. ~VertexUse();
  25. void set_vertex( BSPTreePoly::Vertex* vtx_ptr );
  26. BSPTreePoly::VertexUse *nextPtr, *prevPtr;
  27. BSPTreePoly::Vertex* vtxPtr;
  28. BSPTreePoly::Edge* edgePtr;
  29. };
  30. struct BSPTreePoly::EdgeUse {
  31. EdgeUse( Edge* edge );
  32. EdgeUse( Edge* edge, Face* face );
  33. ~EdgeUse();
  34. BSPTreePoly::EdgeUse *prevPtr, *nextPtr;
  35. BSPTreePoly::Edge* edgePtr;
  36. BSPTreePoly::Face* facePtr;
  37. inline BSPTreePoly::Vertex* start() const;
  38. inline BSPTreePoly::Vertex* end() const;
  39. int sense() const;
  40. void insert_after( BSPTreePoly::EdgeUse* prev );
  41. void insert_before( BSPTreePoly::EdgeUse* next );
  42. };
  43. struct BSPTreePoly::Edge {
  44. BSPTreePoly::VertexUse *startPtr, *endPtr;
  45. BSPTreePoly::EdgeUse *forwardPtr, *reversePtr;
  46. #ifdef DEBUG_IDS
  47. int id;
  48. static int nextID;
  49. #endif
  50. Edge( Vertex* vstart, Vertex* vend )
  51. : forwardPtr(0), reversePtr(0)
  52. #ifdef DEBUG_IDS
  53. , id(nextID++)
  54. #endif
  55. {
  56. startPtr = new VertexUse( this, vstart );
  57. endPtr = new VertexUse( this, vend );
  58. }
  59. ~Edge();
  60. BSPTreePoly::Vertex* start() const
  61. { return startPtr->vtxPtr; }
  62. BSPTreePoly::Vertex* end() const
  63. { return endPtr->vtxPtr; }
  64. BSPTreePoly::Face* forward() const
  65. { return forwardPtr ? forwardPtr->facePtr : 0; }
  66. BSPTreePoly::Face* reverse() const
  67. { return reversePtr ? reversePtr->facePtr : 0; }
  68. BSPTreePoly::VertexUse* use( BSPTreePoly::Vertex* vtx ) const
  69. { return (vtx == startPtr->vtxPtr) ? startPtr : (vtx == endPtr->vtxPtr) ? endPtr : 0; }
  70. BSPTreePoly::Edge* next( BSPTreePoly::Vertex* about ) const
  71. { return use(about)->nextPtr->edgePtr; }
  72. BSPTreePoly::Edge* prev( BSPTreePoly::Vertex* about ) const
  73. { return use(about)->prevPtr->edgePtr; }
  74. BSPTreePoly::EdgeUse* use( BSPTreePoly::Face* face ) const
  75. { return (face == forwardPtr->facePtr) ? forwardPtr : (face == reversePtr->facePtr) ? reversePtr : 0; }
  76. BSPTreePoly::Edge* next( BSPTreePoly::Face* about ) const
  77. { return use(about)->nextPtr->edgePtr; }
  78. BSPTreePoly::Edge* prev( BSPTreePoly::Face* about ) const
  79. { return use(about)->prevPtr->edgePtr; }
  80. BSPTreePoly::VertexUse* other( BSPTreePoly::VertexUse* vuse ) const
  81. { return vuse == startPtr ? endPtr : vuse == endPtr ? startPtr : 0; }
  82. BSPTreePoly::EdgeUse* other( BSPTreePoly::EdgeUse* vuse ) const
  83. { return vuse == forwardPtr ? reversePtr : vuse == reversePtr ? forwardPtr : 0; }
  84. BSPTreePoly::Vertex* other( BSPTreePoly::Vertex* vtx ) const
  85. { return vtx == startPtr->vtxPtr ? endPtr->vtxPtr :
  86. vtx == endPtr->vtxPtr ? startPtr->vtxPtr : 0; }
  87. BSPTreePoly::Vertex* common( BSPTreePoly::Edge* eother ) const
  88. { return start() == eother->start() || start() == eother->end() ? start() :
  89. end() == eother->start() || end() == eother->end() ? end() : 0; }
  90. int sense( BSPTreePoly::Face* face ) const;
  91. void remove_from_vertex( BSPTreePoly::Vertex*& vtx_ptr );
  92. void remove_from_face( BSPTreePoly::Face*& face_ptr );
  93. void add_to_vertex( BSPTreePoly::Vertex* vtx_ptr );
  94. };
  95. struct BSPTreePoly::Face {
  96. Face(Face* next) : usePtr(0), nextPtr(next)
  97. #ifdef DEBUG_IDS
  98. , id(nextID++)
  99. #endif
  100. {}
  101. Face() : usePtr(0), nextPtr(0)
  102. #ifdef DEBUG_IDS
  103. , id(nextID++)
  104. #endif
  105. {}
  106. ~Face();
  107. BSPTreePoly::EdgeUse* usePtr;
  108. BSPTreePoly::Face* nextPtr;
  109. #ifdef DEBUG_IDS
  110. int id;
  111. static int nextID;
  112. #endif
  113. double signed_volume() const;
  114. };
  115. #ifdef DEBUG_IDS
  116. int BSPTreePoly::Vertex::nextID = 1;
  117. int BSPTreePoly::Edge::nextID = 1;
  118. int BSPTreePoly::Face::nextID = 1;
  119. #endif
  120. void BSPTreePoly::reset_debug_ids() {
  121. #ifdef DEBUG_IDS
  122. BSPTreePoly::Vertex::nextID = 1;
  123. BSPTreePoly::Edge::nextID = 1;
  124. BSPTreePoly::Face::nextID = 1;
  125. #endif
  126. }
  127. //static void merge_edges( BSPTreePoly::Edge* keep_edge,
  128. // BSPTreePoly::Edge* dead_edge );
  129. static BSPTreePoly::Edge* split_edge( BSPTreePoly::Vertex* new_vtx,
  130. BSPTreePoly::Edge* into_edge );
  131. BSPTreePoly::VertexUse::VertexUse( BSPTreePoly::Edge* edge, BSPTreePoly::Vertex* vtx )
  132. : vtxPtr(vtx), edgePtr(edge)
  133. {
  134. if (!vtx->usePtr) {
  135. vtx->usePtr = prevPtr = nextPtr = this;
  136. return;
  137. }
  138. nextPtr = vtx->usePtr;
  139. prevPtr = nextPtr->prevPtr;
  140. assert( prevPtr->nextPtr == nextPtr );
  141. nextPtr->prevPtr = this;
  142. prevPtr->nextPtr = this;
  143. }
  144. BSPTreePoly::VertexUse::~VertexUse()
  145. {
  146. if (nextPtr == this) {
  147. assert(prevPtr == this);
  148. assert(vtxPtr->usePtr == this);
  149. vtxPtr->usePtr = 0;
  150. delete vtxPtr;
  151. }
  152. else if (vtxPtr->usePtr == this)
  153. vtxPtr->usePtr = nextPtr;
  154. nextPtr->prevPtr = prevPtr;
  155. prevPtr->nextPtr = nextPtr;
  156. nextPtr = prevPtr = 0;
  157. }
  158. void BSPTreePoly::VertexUse::set_vertex( BSPTreePoly::Vertex* vtx )
  159. {
  160. if (vtxPtr) {
  161. if (nextPtr == prevPtr) {
  162. assert(nextPtr == this);
  163. vtxPtr->usePtr = 0;
  164. delete vtx;
  165. }
  166. else {
  167. nextPtr->prevPtr = prevPtr;
  168. prevPtr->nextPtr = nextPtr;
  169. if (vtxPtr->usePtr == this)
  170. vtxPtr->usePtr = nextPtr;
  171. }
  172. }
  173. vtxPtr = vtx;
  174. nextPtr = vtxPtr->usePtr->nextPtr;
  175. prevPtr = vtxPtr->usePtr;
  176. nextPtr->prevPtr = this;
  177. vtxPtr->usePtr->nextPtr = this;
  178. }
  179. BSPTreePoly::EdgeUse::EdgeUse( BSPTreePoly::Edge* edge )
  180. : prevPtr(0), nextPtr(0), edgePtr(edge), facePtr(0)
  181. {}
  182. BSPTreePoly::EdgeUse::EdgeUse( BSPTreePoly::Edge* edge,
  183. BSPTreePoly::Face* face )
  184. : edgePtr(edge), facePtr(face)
  185. {
  186. assert(!face->usePtr);
  187. face->usePtr = prevPtr = nextPtr = this;
  188. if (!face->usePtr) {
  189. face->usePtr = prevPtr = nextPtr = this;
  190. return;
  191. }
  192. nextPtr = face->usePtr;
  193. prevPtr = nextPtr->prevPtr;
  194. assert( prevPtr->nextPtr == nextPtr );
  195. nextPtr->prevPtr = this;
  196. prevPtr->nextPtr = this;
  197. }
  198. void BSPTreePoly::EdgeUse::insert_after( BSPTreePoly::EdgeUse* prev )
  199. {
  200. // shouldn't aready be in a face
  201. assert(!facePtr);
  202. // adjacent edges should share vertices
  203. assert( start() == prev->end() );
  204. facePtr = prev->facePtr;
  205. nextPtr = prev->nextPtr;
  206. prevPtr = prev;
  207. nextPtr->prevPtr = this;
  208. prevPtr->nextPtr = this;
  209. }
  210. void BSPTreePoly::EdgeUse::insert_before( BSPTreePoly::EdgeUse* next )
  211. {
  212. // shouldn't aready be in a face
  213. assert(!facePtr);
  214. // adjacent edges should share vertices
  215. assert( end() == next->start() );
  216. facePtr = next->facePtr;
  217. prevPtr = next->prevPtr;
  218. nextPtr = next;
  219. nextPtr->prevPtr = this;
  220. prevPtr->nextPtr = this;
  221. }
  222. BSPTreePoly::EdgeUse::~EdgeUse()
  223. {
  224. if (facePtr->usePtr == this)
  225. facePtr->usePtr = (nextPtr == this) ? 0 : nextPtr;
  226. if (edgePtr->forwardPtr == this)
  227. edgePtr->forwardPtr = 0;
  228. if (edgePtr->reversePtr == this)
  229. edgePtr->reversePtr = 0;
  230. if (!edgePtr->forwardPtr && !edgePtr->reversePtr)
  231. delete edgePtr;
  232. nextPtr->prevPtr = prevPtr;
  233. prevPtr->nextPtr = nextPtr;
  234. nextPtr = prevPtr = 0;
  235. }
  236. int BSPTreePoly::EdgeUse::sense() const
  237. {
  238. if (edgePtr->forwardPtr == this)
  239. return 1;
  240. else if (edgePtr->reversePtr == this)
  241. return -1;
  242. else
  243. return 0;
  244. }
  245. BSPTreePoly::Vertex* BSPTreePoly::EdgeUse::start() const
  246. {
  247. if (edgePtr->forwardPtr == this)
  248. return edgePtr->start();
  249. else if (edgePtr->reversePtr == this)
  250. return edgePtr->end();
  251. else
  252. return 0;
  253. }
  254. BSPTreePoly::Vertex* BSPTreePoly::EdgeUse::end() const
  255. {
  256. if (edgePtr->forwardPtr == this)
  257. return edgePtr->end();
  258. else if (edgePtr->reversePtr == this)
  259. return edgePtr->start();
  260. else
  261. return 0;
  262. }
  263. BSPTreePoly::Edge::~Edge()
  264. {
  265. delete startPtr;
  266. delete endPtr;
  267. delete forwardPtr;
  268. delete reversePtr;
  269. }
  270. int BSPTreePoly::Edge::sense( BSPTreePoly::Face* face ) const
  271. {
  272. if (forwardPtr && forwardPtr->facePtr == face)
  273. return 1;
  274. else if (reversePtr && reversePtr->facePtr == face)
  275. return -1;
  276. else
  277. return 0;
  278. }
  279. BSPTreePoly::Face::~Face()
  280. {
  281. while (usePtr)
  282. delete usePtr;
  283. }
  284. void BSPTreePoly::clear() {
  285. while (faceList) {
  286. Face* face = faceList;
  287. faceList = faceList->nextPtr;
  288. delete face;
  289. }
  290. }
  291. ErrorCode BSPTreePoly::set( const CartVect hex_corners[8] )
  292. {
  293. clear();
  294. Vertex* vertices[8];
  295. for (int i = 0; i < 8; ++i)
  296. vertices[i] = new Vertex(hex_corners[i]);
  297. Edge* edges[12];
  298. #ifdef DEBUG_IDS
  299. int start_id = Edge::nextID;
  300. #endif
  301. for (int i = 0; i < 4; ++i) {
  302. int j= (i+1)%4;
  303. edges[i ] = new Edge( vertices[i ], vertices[j ] );
  304. edges[i+4] = new Edge( vertices[i ], vertices[i+4] );
  305. edges[i+8] = new Edge( vertices[i+4], vertices[j+4] );
  306. }
  307. #ifdef DEBUG_IDS
  308. for (int i = 0; i < 12; ++i)
  309. edges[i]->id = start_id++;
  310. #endif
  311. static const int face_conn[6][4] = { { 0, 5, -8, -4 },
  312. { 1, 6, -9, -5 },
  313. { 2, 7, -10, -6 },
  314. { 3, 4, -11, -7 },
  315. { -3, -2, -1,-12 },
  316. { 8, 9, 10, 11 } };
  317. for (int i = 0; i < 6; ++i) {
  318. faceList = new Face(faceList);
  319. EdgeUse* prev = 0;
  320. for (int j = 0; j < 4; ++j) {
  321. int e = face_conn[i][j];
  322. if (e < 0) {
  323. e = (-e) % 12;
  324. assert(!edges[e]->reversePtr);
  325. if (!prev) {
  326. edges[e]->reversePtr = new EdgeUse( edges[e], faceList );
  327. }
  328. else {
  329. edges[e]->reversePtr = new EdgeUse( edges[e] );
  330. edges[e]->reversePtr->insert_after( prev );
  331. }
  332. prev = edges[e]->reversePtr;
  333. }
  334. else {
  335. assert(!edges[e]->forwardPtr);
  336. if (!prev) {
  337. edges[e]->forwardPtr = new EdgeUse( edges[e], faceList );
  338. }
  339. else {
  340. edges[e]->forwardPtr = new EdgeUse( edges[e] );
  341. edges[e]->forwardPtr->insert_after( prev );
  342. }
  343. prev = edges[e]->forwardPtr;
  344. }
  345. }
  346. }
  347. return MB_SUCCESS;
  348. }
  349. void BSPTreePoly::get_faces( std::vector<const Face*>& face_list ) const
  350. {
  351. face_list.clear();
  352. for (Face* face = faceList; face; face = face->nextPtr)
  353. face_list.push_back( face );
  354. }
  355. void BSPTreePoly::get_vertices( const Face* face,
  356. std::vector<CartVect>& vertices ) const
  357. {
  358. vertices.clear();
  359. if (!face || !face->usePtr)
  360. return;
  361. EdgeUse* coedge = face->usePtr;
  362. do {
  363. vertices.push_back( *coedge->end() );
  364. coedge = coedge->nextPtr;
  365. } while (coedge != face->usePtr);
  366. }
  367. double BSPTreePoly::Face::signed_volume() const
  368. {
  369. CartVect sum(0.0);
  370. const CartVect* base = usePtr->start();
  371. CartVect d1 = (*usePtr->end() - *base);
  372. for (EdgeUse* coedge = usePtr->nextPtr; coedge != usePtr; coedge = coedge->nextPtr) {
  373. CartVect d2 = (*coedge->end() - *base);
  374. sum += d1 * d2;
  375. d1 = d2;
  376. }
  377. return (1.0/6.0) * (sum % *base);
  378. }
  379. double BSPTreePoly::volume() const
  380. {
  381. double result = 0;
  382. for (Face* ptr = faceList; ptr; ptr = ptr->nextPtr)
  383. result += ptr->signed_volume();
  384. return result;
  385. }
  386. void BSPTreePoly::set_vertex_marks( int value )
  387. {
  388. for (Face* face = faceList; face; face = face->nextPtr) {
  389. EdgeUse* edge = face->usePtr;
  390. do {
  391. edge->edgePtr->start()->markVal = value;
  392. edge->edgePtr->end()->markVal = value;
  393. edge = edge->nextPtr;
  394. } while (edge && edge != face->usePtr);
  395. }
  396. }
  397. /*
  398. static void merge_edges( BSPTreePoly::Edge* keep_edge,
  399. BSPTreePoly::Edge* dead_edge )
  400. {
  401. // edges must share a vertex
  402. BSPTreePoly::Vertex* dead_vtx = keep_edge->common(dead_edge);
  403. assert(dead_vtx);
  404. // vertex may have only two adjacent edges
  405. BSPTreePoly::VertexUse* dead_vtxuse = dead_edge->use(dead_vtx);
  406. assert(dead_vtxuse);
  407. BSPTreePoly::VertexUse* keep_vtxuse = dead_vtxuse->nextPtr;
  408. assert(keep_vtxuse);
  409. assert(keep_vtxuse->edgePtr == keep_edge);
  410. assert(keep_vtxuse->nextPtr == dead_vtxuse);
  411. assert(keep_vtxuse->prevPtr == dead_vtxuse);
  412. assert(dead_vtxuse->prevPtr == keep_vtxuse);
  413. // kept edge now ends with the kept vertex on the dead edge
  414. keep_vtxuse->set_vertex( dead_edge->other(dead_vtx) );
  415. // destructors should take care of everything else
  416. // (including removing dead edge from face loops)
  417. delete dead_edge;
  418. }
  419. */
  420. static BSPTreePoly::Edge* split_edge( BSPTreePoly::Vertex* new_vtx,
  421. BSPTreePoly::Edge* into_edge )
  422. {
  423. // split edge, creating new edge
  424. BSPTreePoly::Edge* new_edge = new BSPTreePoly::Edge( new_vtx, into_edge->end() );
  425. into_edge->endPtr->set_vertex( new_vtx );
  426. // update coedge loops in faces
  427. if (into_edge->forwardPtr) {
  428. new_edge->forwardPtr = new BSPTreePoly::EdgeUse( new_edge );
  429. new_edge->forwardPtr->insert_after( into_edge->forwardPtr );
  430. }
  431. if (into_edge->reversePtr) {
  432. new_edge->reversePtr = new BSPTreePoly::EdgeUse( new_edge );
  433. new_edge->reversePtr->insert_before( into_edge->reversePtr );
  434. }
  435. return new_edge;
  436. }
  437. static BSPTreePoly::Face* split_face( BSPTreePoly::EdgeUse* start,
  438. BSPTreePoly::EdgeUse* end )
  439. {
  440. BSPTreePoly::Face* face = start->facePtr;
  441. assert(face == end->facePtr);
  442. BSPTreePoly::Face* new_face = new BSPTreePoly::Face;
  443. BSPTreePoly::EdgeUse* keep_start = start->prevPtr;
  444. BSPTreePoly::EdgeUse* keep_end = end->nextPtr;
  445. for (BSPTreePoly::EdgeUse* ptr = start; ptr != keep_end; ptr = ptr->nextPtr) {
  446. if (face->usePtr == ptr)
  447. face->usePtr = keep_start;
  448. ptr->facePtr = new_face;
  449. }
  450. new_face->usePtr = start;
  451. BSPTreePoly::Edge* edge = new BSPTreePoly::Edge( start->start(), end->end() );
  452. edge->forwardPtr = new BSPTreePoly::EdgeUse( edge );
  453. edge->reversePtr = new BSPTreePoly::EdgeUse( edge );
  454. edge->forwardPtr->facePtr = face;
  455. edge->forwardPtr->prevPtr = keep_start;
  456. keep_start->nextPtr = edge->forwardPtr;
  457. edge->forwardPtr->nextPtr = keep_end;
  458. keep_end->prevPtr = edge->forwardPtr;
  459. edge->reversePtr->facePtr = new_face;
  460. edge->reversePtr->nextPtr = start;
  461. start->prevPtr = edge->reversePtr;
  462. edge->reversePtr->prevPtr = end;
  463. end->nextPtr = edge->reversePtr;
  464. return new_face;
  465. }
  466. bool BSPTreePoly::cut_polyhedron( const CartVect& plane_normal,
  467. double plane_coeff )
  468. {
  469. const double EPSILON = 1e-6; // points this close are considered coincident
  470. // scale epsilon rather than normalizing normal vector
  471. const double epsilon = EPSILON * (plane_normal % plane_normal);
  472. // Classify all points above/below plane and destroy any faces
  473. // that have no vertices below the plane.
  474. const int UNKNOWN = 0;
  475. const int ABOVE = 1;
  476. const int ON = 2;
  477. const int BELOW = 3;
  478. int num_above = 0;
  479. set_vertex_marks( UNKNOWN );
  480. // Classify all points above/below plane and
  481. // split any edge that intersect the plane.
  482. for (Face* face = faceList; face; face = face->nextPtr) {
  483. EdgeUse* edge = face->usePtr;
  484. do {
  485. Vertex* start = edge->edgePtr->start();
  486. Vertex* end = edge->edgePtr->end();
  487. if (!start->markVal) {
  488. double d = plane_normal % *start + plane_coeff;
  489. if (d*d <= epsilon)
  490. start->markVal = ON;
  491. else if (d < 0.0)
  492. start->markVal = BELOW;
  493. else {
  494. start->markVal = ABOVE;
  495. ++num_above;
  496. }
  497. }
  498. if (!end->markVal) {
  499. double d = plane_normal % *end + plane_coeff;
  500. if (d*d <= epsilon)
  501. end->markVal = ON;
  502. else if (d < 0.0)
  503. end->markVal = BELOW;
  504. else {
  505. end->markVal = ABOVE;
  506. ++num_above;
  507. }
  508. }
  509. if ((end->markVal == ABOVE && start->markVal == BELOW) ||
  510. (end->markVal == BELOW && start->markVal == ABOVE)) {
  511. CartVect dir = *end - *start;
  512. double t = -(plane_normal % *start + plane_coeff) / (dir % plane_normal);
  513. Vertex* new_vtx = new Vertex( *start + t*dir );
  514. new_vtx->markVal = ON;
  515. split_edge( new_vtx, edge->edgePtr );
  516. end = new_vtx;
  517. }
  518. edge = edge->nextPtr;
  519. } while (edge && edge != face->usePtr);
  520. }
  521. if (!num_above)
  522. return false;
  523. // Split faces
  524. for (Face* face = faceList; face; face = face->nextPtr) {
  525. EdgeUse* edge = face->usePtr;
  526. EdgeUse *split_start = 0, *split_end = 0, *other_split = 0;
  527. do {
  528. if (edge->end()->markVal == ON && edge->start()->markVal != ON) {
  529. if (!split_start)
  530. split_start = edge->nextPtr;
  531. else if (!split_end)
  532. split_end = edge;
  533. else
  534. other_split = edge;
  535. }
  536. edge = edge->nextPtr;
  537. } while (edge && edge != face->usePtr);
  538. // If two vertices are on plane (but not every vertex)
  539. // then split the face
  540. if (split_end && !other_split) {
  541. assert(split_start);
  542. Face* new_face = split_face( split_start, split_end );
  543. new_face->nextPtr = faceList;
  544. faceList = new_face;
  545. }
  546. }
  547. // Destroy all faces that are above the plane
  548. Face** lptr = &faceList;
  549. while (*lptr) {
  550. EdgeUse* edge = (*lptr)->usePtr;
  551. bool some_above = false;
  552. do {
  553. if (edge->start()->markVal == ABOVE) {
  554. some_above = true;
  555. break;
  556. }
  557. edge = edge->nextPtr;
  558. } while (edge && edge != (*lptr)->usePtr);
  559. if (some_above) {
  560. Face* dead = *lptr;
  561. *lptr = (*lptr)->nextPtr;
  562. delete dead;
  563. }
  564. else {
  565. lptr = &((*lptr)->nextPtr);
  566. }
  567. }
  568. // Construct a new face in the cut plane
  569. // First find an edge to start at
  570. Edge* edge_ptr = 0;
  571. for (Face* face = faceList; face && !edge_ptr; face = face->nextPtr) {
  572. EdgeUse* co_edge = face->usePtr;
  573. do {
  574. if (0 == co_edge->edgePtr->other(co_edge)) {
  575. edge_ptr = co_edge->edgePtr;
  576. break;
  577. }
  578. co_edge = co_edge->nextPtr;
  579. } while (co_edge && co_edge != face->usePtr);
  580. }
  581. if (!edge_ptr) return false;
  582. // Constuct new face and first CoEdge
  583. faceList = new Face( faceList );
  584. Vertex *next_vtx, *start_vtx;
  585. EdgeUse* prev_coedge;
  586. if (edge_ptr->forwardPtr) {
  587. next_vtx = edge_ptr->start();
  588. start_vtx = edge_ptr->end();
  589. assert(!edge_ptr->reversePtr);
  590. prev_coedge = edge_ptr->reversePtr = new EdgeUse( edge_ptr, faceList );
  591. }
  592. else {
  593. next_vtx = edge_ptr->end();
  594. start_vtx = edge_ptr->start();
  595. prev_coedge = edge_ptr->forwardPtr = new EdgeUse( edge_ptr, faceList );
  596. }
  597. // Construct coedges until loop is closed
  598. while (next_vtx != start_vtx) {
  599. // find next edge adjacent to vertex with only one adjacent face
  600. VertexUse* this_use = edge_ptr->use( next_vtx );
  601. VertexUse* use = this_use->nextPtr;
  602. while (use != this_use) {
  603. if (use->edgePtr->forwardPtr == 0) {
  604. edge_ptr = use->edgePtr;
  605. assert(edge_ptr->start() == next_vtx);
  606. next_vtx = edge_ptr->end();
  607. edge_ptr->forwardPtr = new EdgeUse( edge_ptr );
  608. edge_ptr->forwardPtr->insert_after( prev_coedge );
  609. prev_coedge = edge_ptr->forwardPtr;
  610. break;
  611. }
  612. else if (use->edgePtr->reversePtr == 0) {
  613. edge_ptr = use->edgePtr;
  614. assert(edge_ptr->end() == next_vtx);
  615. next_vtx = edge_ptr->start();
  616. edge_ptr->reversePtr = new EdgeUse( edge_ptr );
  617. edge_ptr->reversePtr->insert_after( prev_coedge );
  618. prev_coedge = edge_ptr->reversePtr;
  619. break;
  620. }
  621. use = use->nextPtr;
  622. assert( use != this_use ); // failed to close loop!
  623. }
  624. }
  625. return true;
  626. }
  627. bool BSPTreePoly::is_valid() const
  628. {
  629. std::set<Face*> list_faces;
  630. int i = 0;
  631. for (Face* ptr = faceList; ptr; ptr = ptr->nextPtr) {
  632. if (++i > 10000)
  633. return false;
  634. if (!list_faces.insert(ptr).second)
  635. return false;
  636. }
  637. std::set<Vertex*> vertices;
  638. for (Face* face = faceList; face; face = face->nextPtr) {
  639. i = 0;
  640. EdgeUse* coedge = face->usePtr;
  641. do {
  642. if (++i > 10000)
  643. return false;
  644. if (coedge->facePtr != face)
  645. return false;
  646. Edge* edge = coedge->edgePtr;
  647. if (!edge->startPtr || !edge->endPtr)
  648. return false;
  649. vertices.insert( edge->start() );
  650. vertices.insert( edge->end() );
  651. EdgeUse* other;
  652. if (edge->forwardPtr == coedge)
  653. other = edge->reversePtr;
  654. else if (edge->reversePtr != coedge)
  655. return false;
  656. else
  657. other = edge->forwardPtr;
  658. if (!other)
  659. return false;
  660. if (list_faces.find( other->facePtr ) == list_faces.end())
  661. return false;
  662. EdgeUse* next = coedge->nextPtr;
  663. if (next->prevPtr != coedge)
  664. return false;
  665. if (coedge->end() != next->start())
  666. return false;
  667. coedge = next;
  668. } while (coedge != face->usePtr);
  669. }
  670. for (std::set<Vertex*>::iterator j = vertices.begin(); j != vertices.end(); ++j) {
  671. Vertex* vtx = *j;
  672. i = 0;
  673. VertexUse* use = vtx->usePtr;
  674. do {
  675. if (++i > 10000)
  676. return false;
  677. if (use->vtxPtr != vtx)
  678. return false;
  679. Edge* edge = use->edgePtr;
  680. if (!edge)
  681. return false;
  682. if (edge->startPtr != use && edge->endPtr != use)
  683. return false;
  684. VertexUse* next = use->nextPtr;
  685. if (next->prevPtr != use)
  686. return false;
  687. use = next;
  688. } while (use != vtx->usePtr);
  689. }
  690. return true;
  691. }
  692. bool BSPTreePoly::is_point_contained( const CartVect& point ) const
  693. {
  694. if (!faceList) // empty (zero-dimension) polyhedron
  695. return false;
  696. // Test that point is below the plane of each face
  697. // NOTE: This will NOT work for polyhedra w/ concavities
  698. for (Face* face = faceList; face; face = face->nextPtr) {
  699. Vertex *pt1, *pt2, *pt3;
  700. pt1 = face->usePtr->start();
  701. pt2 = face->usePtr->end();
  702. pt3 = face->usePtr->nextPtr->end();
  703. if (pt3 == pt1) // degenerate
  704. continue;
  705. CartVect norm = (*pt3 - *pt2) * (*pt1 - *pt2);
  706. double coeff = -(norm % *pt2);
  707. if (norm % point > -coeff) // if above plane
  708. return false;
  709. }
  710. return true;
  711. }
  712. } // namespace moab