![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
00001 #include "moab/CartVect.hpp"
00002 #include "moab/BSPTreePoly.hpp"
00003 #include
00004 #include
00005 #include
00006
00007 #undef DEBUG_IDS
00008
00009 namespace moab
00010 {
00011
00012 struct BSPTreePoly::Vertex : public CartVect
00013 {
00014 Vertex( const CartVect& v )
00015 : CartVect( v ), usePtr( 0 ), markVal( 0 )
00016 #ifdef DEBUG_IDS
00017 ,
00018 id( nextID++ )
00019 #endif
00020 {
00021 }
00022 ~Vertex()
00023 {
00024 assert( !usePtr );
00025 }
00026 BSPTreePoly::VertexUse* usePtr;
00027 int markVal;
00028 #ifdef DEBUG_IDS
00029 int id;
00030 static int nextID;
00031 #endif
00032 };
00033
00034 struct BSPTreePoly::VertexUse
00035 {
00036 VertexUse( Edge* edge, Vertex* vtx );
00037 ~VertexUse();
00038
00039 void set_vertex( BSPTreePoly::Vertex*& vtx_ptr );
00040
00041 BSPTreePoly::VertexUse *nextPtr, *prevPtr;
00042 BSPTreePoly::Vertex* vtxPtr;
00043 BSPTreePoly::Edge* edgePtr;
00044 };
00045
00046 struct BSPTreePoly::EdgeUse
00047 {
00048 EdgeUse( Edge* edge );
00049 EdgeUse( Edge* edge, Face* face );
00050 ~EdgeUse();
00051
00052 BSPTreePoly::EdgeUse *prevPtr, *nextPtr;
00053 BSPTreePoly::Edge* edgePtr;
00054 BSPTreePoly::Face* facePtr;
00055
00056 inline BSPTreePoly::Vertex* start() const;
00057 inline BSPTreePoly::Vertex* end() const;
00058 int sense() const;
00059
00060 void insert_after( BSPTreePoly::EdgeUse* prev );
00061 void insert_before( BSPTreePoly::EdgeUse* next );
00062 };
00063
00064 struct BSPTreePoly::Edge
00065 {
00066 BSPTreePoly::VertexUse *startPtr, *endPtr;
00067 BSPTreePoly::EdgeUse *forwardPtr, *reversePtr;
00068 #ifdef DEBUG_IDS
00069 int id;
00070 static int nextID;
00071 #endif
00072
00073 Edge( Vertex* vstart, Vertex* vend )
00074 : forwardPtr( 0 ), reversePtr( 0 )
00075 #ifdef DEBUG_IDS
00076 ,
00077 id( nextID++ )
00078 #endif
00079 {
00080 startPtr = new VertexUse( this, vstart );
00081 endPtr = new VertexUse( this, vend );
00082 }
00083
00084 ~Edge();
00085
00086 BSPTreePoly::Vertex* start() const
00087 {
00088 return startPtr->vtxPtr;
00089 }
00090 BSPTreePoly::Vertex* end() const
00091 {
00092 return endPtr->vtxPtr;
00093 }
00094
00095 BSPTreePoly::Face* forward() const
00096 {
00097 return forwardPtr ? forwardPtr->facePtr : 0;
00098 }
00099 BSPTreePoly::Face* reverse() const
00100 {
00101 return reversePtr ? reversePtr->facePtr : 0;
00102 }
00103
00104 BSPTreePoly::VertexUse* use( BSPTreePoly::Vertex* vtx ) const
00105 {
00106 return ( vtx == startPtr->vtxPtr ) ? startPtr : ( vtx == endPtr->vtxPtr ) ? endPtr : 0;
00107 }
00108 BSPTreePoly::Edge* next( BSPTreePoly::Vertex* about ) const
00109 {
00110 return use( about )->nextPtr->edgePtr;
00111 }
00112 BSPTreePoly::Edge* prev( BSPTreePoly::Vertex* about ) const
00113 {
00114 return use( about )->prevPtr->edgePtr;
00115 }
00116
00117 BSPTreePoly::EdgeUse* use( BSPTreePoly::Face* face ) const
00118 {
00119 return ( face == forwardPtr->facePtr ) ? forwardPtr : ( face == reversePtr->facePtr ) ? reversePtr : 0;
00120 }
00121 BSPTreePoly::Edge* next( BSPTreePoly::Face* about ) const
00122 {
00123 return use( about )->nextPtr->edgePtr;
00124 }
00125 BSPTreePoly::Edge* prev( BSPTreePoly::Face* about ) const
00126 {
00127 return use( about )->prevPtr->edgePtr;
00128 }
00129
00130 BSPTreePoly::VertexUse* other( BSPTreePoly::VertexUse* vuse ) const
00131 {
00132 return vuse == startPtr ? endPtr : vuse == endPtr ? startPtr : 0;
00133 }
00134 BSPTreePoly::EdgeUse* other( BSPTreePoly::EdgeUse* vuse ) const
00135 {
00136 return vuse == forwardPtr ? reversePtr : vuse == reversePtr ? forwardPtr : 0;
00137 }
00138 BSPTreePoly::Vertex* other( BSPTreePoly::Vertex* vtx ) const
00139 {
00140 return vtx == startPtr->vtxPtr ? endPtr->vtxPtr : vtx == endPtr->vtxPtr ? startPtr->vtxPtr : 0;
00141 }
00142 BSPTreePoly::Vertex* common( BSPTreePoly::Edge* eother ) const
00143 {
00144 return start() == eother->start() || start() == eother->end() ? start()
00145 : end() == eother->start() || end() == eother->end() ? end()
00146 : 0;
00147 }
00148
00149 int sense( BSPTreePoly::Face* face ) const;
00150
00151 void remove_from_vertex( BSPTreePoly::Vertex*& vtx_ptr );
00152 void remove_from_face( BSPTreePoly::Face*& face_ptr );
00153 void add_to_vertex( BSPTreePoly::Vertex* vtx_ptr );
00154 };
00155
00156 struct BSPTreePoly::Face
00157 {
00158 Face( Face* next )
00159 : usePtr( 0 ), nextPtr( next )
00160 #ifdef DEBUG_IDS
00161 ,
00162 id( nextID++ )
00163 #endif
00164 {
00165 }
00166 Face()
00167 : usePtr( 0 ), nextPtr( 0 )
00168 #ifdef DEBUG_IDS
00169 ,
00170 id( nextID++ )
00171 #endif
00172 {
00173 }
00174 ~Face();
00175 BSPTreePoly::EdgeUse* usePtr;
00176 BSPTreePoly::Face* nextPtr;
00177 #ifdef DEBUG_IDS
00178 int id;
00179 static int nextID;
00180 #endif
00181 double signed_volume() const;
00182 };
00183
00184 #ifdef DEBUG_IDS
00185 int BSPTreePoly::Vertex::nextID = 1;
00186 int BSPTreePoly::Edge::nextID = 1;
00187 int BSPTreePoly::Face::nextID = 1;
00188 #endif
00189 void BSPTreePoly::reset_debug_ids()
00190 {
00191 #ifdef DEBUG_IDS
00192 BSPTreePoly::Vertex::nextID = 1;
00193 BSPTreePoly::Edge::nextID = 1;
00194 BSPTreePoly::Face::nextID = 1;
00195 #endif
00196 }
00197
00198 // static void merge_edges( BSPTreePoly::Edge* keep_edge,
00199 // BSPTreePoly::Edge* dead_edge );
00200
00201 static BSPTreePoly::Edge* split_edge( BSPTreePoly::Vertex*& new_vtx, BSPTreePoly::Edge* into_edge );
00202
00203 BSPTreePoly::VertexUse::VertexUse( BSPTreePoly::Edge* edge, BSPTreePoly::Vertex* vtx ) : vtxPtr( vtx ), edgePtr( edge )
00204 {
00205 if( !vtx->usePtr )
00206 {
00207 vtx->usePtr = prevPtr = nextPtr = this;
00208 return;
00209 }
00210
00211 nextPtr = vtx->usePtr;
00212 prevPtr = nextPtr->prevPtr;
00213 assert( prevPtr->nextPtr == nextPtr );
00214 nextPtr->prevPtr = this;
00215 prevPtr->nextPtr = this;
00216 }
00217
00218 BSPTreePoly::VertexUse::~VertexUse()
00219 {
00220 if( nextPtr == this )
00221 {
00222 assert( prevPtr == this );
00223 assert( vtxPtr->usePtr == this );
00224 vtxPtr->usePtr = 0;
00225 delete vtxPtr;
00226 }
00227 else if( vtxPtr->usePtr == this )
00228 vtxPtr->usePtr = nextPtr;
00229
00230 nextPtr->prevPtr = prevPtr;
00231 prevPtr->nextPtr = nextPtr;
00232 nextPtr = prevPtr = 0;
00233 }
00234
00235 void BSPTreePoly::VertexUse::set_vertex( BSPTreePoly::Vertex*& vtx )
00236 {
00237 if( vtxPtr )
00238 {
00239 if( nextPtr == prevPtr )
00240 {
00241 assert( nextPtr == this );
00242 vtxPtr->usePtr = 0;
00243 delete vtx;
00244 vtx = 0;
00245 }
00246 else
00247 {
00248 nextPtr->prevPtr = prevPtr;
00249 prevPtr->nextPtr = nextPtr;
00250 if( vtxPtr->usePtr == this ) vtxPtr->usePtr = nextPtr;
00251 }
00252 }
00253
00254 if( vtx )
00255 {
00256 vtxPtr = vtx;
00257 nextPtr = vtxPtr->usePtr->nextPtr;
00258 prevPtr = vtxPtr->usePtr;
00259 nextPtr->prevPtr = this;
00260 vtxPtr->usePtr->nextPtr = this;
00261 }
00262 }
00263
00264 BSPTreePoly::EdgeUse::EdgeUse( BSPTreePoly::Edge* edge ) : prevPtr( 0 ), nextPtr( 0 ), edgePtr( edge ), facePtr( 0 ) {}
00265
00266 BSPTreePoly::EdgeUse::EdgeUse( BSPTreePoly::Edge* edge, BSPTreePoly::Face* face ) : edgePtr( edge ), facePtr( face )
00267 {
00268 assert( !face->usePtr );
00269 face->usePtr = prevPtr = nextPtr = this;
00270
00271 if( !face->usePtr )
00272 {
00273 face->usePtr = prevPtr = nextPtr = this;
00274 return;
00275 }
00276
00277 nextPtr = face->usePtr;
00278 prevPtr = nextPtr->prevPtr;
00279 assert( prevPtr->nextPtr == nextPtr );
00280 nextPtr->prevPtr = this;
00281 prevPtr->nextPtr = this;
00282 }
00283
00284 void BSPTreePoly::EdgeUse::insert_after( BSPTreePoly::EdgeUse* prev )
00285 {
00286 // shouldn't already be in a face
00287 assert( !facePtr );
00288 // adjacent edges should share vertices
00289 assert( start() == prev->end() );
00290
00291 facePtr = prev->facePtr;
00292 nextPtr = prev->nextPtr;
00293 prevPtr = prev;
00294 nextPtr->prevPtr = this;
00295 prevPtr->nextPtr = this;
00296 }
00297
00298 void BSPTreePoly::EdgeUse::insert_before( BSPTreePoly::EdgeUse* next )
00299 {
00300 // shouldn't already be in a face
00301 assert( !facePtr );
00302 // adjacent edges should share vertices
00303 assert( end() == next->start() );
00304
00305 facePtr = next->facePtr;
00306 prevPtr = next->prevPtr;
00307 nextPtr = next;
00308 nextPtr->prevPtr = this;
00309 prevPtr->nextPtr = this;
00310 }
00311
00312 BSPTreePoly::EdgeUse::~EdgeUse()
00313 {
00314 if( facePtr->usePtr == this ) facePtr->usePtr = ( nextPtr == this ) ? 0 : nextPtr;
00315
00316 if( edgePtr->forwardPtr == this ) edgePtr->forwardPtr = 0;
00317 if( edgePtr->reversePtr == this ) edgePtr->reversePtr = 0;
00318
00319 if( !edgePtr->forwardPtr && !edgePtr->reversePtr ) delete edgePtr;
00320
00321 nextPtr->prevPtr = prevPtr;
00322 prevPtr->nextPtr = nextPtr;
00323 nextPtr = prevPtr = 0;
00324 }
00325
00326 int BSPTreePoly::EdgeUse::sense() const
00327 {
00328 if( edgePtr->forwardPtr == this )
00329 return 1;
00330 else if( edgePtr->reversePtr == this )
00331 return -1;
00332 else
00333 return 0;
00334 }
00335
00336 BSPTreePoly::Vertex* BSPTreePoly::EdgeUse::start() const
00337 {
00338 if( edgePtr->forwardPtr == this )
00339 return edgePtr->start();
00340 else if( edgePtr->reversePtr == this )
00341 return edgePtr->end();
00342 else
00343 return 0;
00344 }
00345
00346 BSPTreePoly::Vertex* BSPTreePoly::EdgeUse::end() const
00347 {
00348 if( edgePtr->forwardPtr == this )
00349 return edgePtr->end();
00350 else if( edgePtr->reversePtr == this )
00351 return edgePtr->start();
00352 else
00353 return 0;
00354 }
00355
00356 BSPTreePoly::Edge::~Edge()
00357 {
00358 delete startPtr;
00359 delete endPtr;
00360 delete forwardPtr;
00361 delete reversePtr;
00362 }
00363
00364 int BSPTreePoly::Edge::sense( BSPTreePoly::Face* face ) const
00365 {
00366 if( forwardPtr && forwardPtr->facePtr == face )
00367 return 1;
00368 else if( reversePtr && reversePtr->facePtr == face )
00369 return -1;
00370 else
00371 return 0;
00372 }
00373
00374 BSPTreePoly::Face::~Face()
00375 {
00376 BSPTreePoly::EdgeUse* nextEdgeUsePtr = usePtr;
00377 while( nextEdgeUsePtr )
00378 {
00379 delete nextEdgeUsePtr; // This is tricky: ~EdgeUse() might change the value of usePtr
00380 if( usePtr && usePtr != nextEdgeUsePtr )
00381 nextEdgeUsePtr = usePtr;
00382 else
00383 nextEdgeUsePtr = 0;
00384 }
00385 usePtr = 0;
00386 }
00387
00388 void BSPTreePoly::clear()
00389 {
00390 while( faceList )
00391 {
00392 Face* face = faceList;
00393 faceList = faceList->nextPtr;
00394 delete face;
00395 }
00396 }
00397
00398 ErrorCode BSPTreePoly::set( const CartVect hex_corners[8] )
00399 {
00400 clear();
00401
00402 Vertex* vertices[8];
00403 for( int i = 0; i < 8; ++i )
00404 vertices[i] = new Vertex( hex_corners[i] );
00405
00406 Edge* edges[12];
00407 #ifdef DEBUG_IDS
00408 int start_id = Edge::nextID;
00409 #endif
00410 for( int i = 0; i < 4; ++i )
00411 {
00412 int j = ( i + 1 ) % 4;
00413 edges[i] = new Edge( vertices[i], vertices[j] );
00414 edges[i + 4] = new Edge( vertices[i], vertices[i + 4] );
00415 edges[i + 8] = new Edge( vertices[i + 4], vertices[j + 4] );
00416 }
00417 #ifdef DEBUG_IDS
00418 for( int i = 0; i < 12; ++i )
00419 edges[i]->id = start_id++;
00420 #endif
00421
00422 static const int face_conn[6][4] = { { 0, 5, -8, -4 }, { 1, 6, -9, -5 }, { 2, 7, -10, -6 },
00423 { 3, 4, -11, -7 }, { -3, -2, -1, -12 }, { 8, 9, 10, 11 } };
00424 for( int i = 0; i < 6; ++i )
00425 {
00426 faceList = new Face( faceList );
00427 EdgeUse* prev = 0;
00428 for( int j = 0; j < 4; ++j )
00429 {
00430 int e = face_conn[i][j];
00431 if( e < 0 )
00432 {
00433 e = ( -e ) % 12;
00434 assert( !edges[e]->reversePtr );
00435 if( !prev )
00436 {
00437 edges[e]->reversePtr = new EdgeUse( edges[e], faceList );
00438 }
00439 else
00440 {
00441 edges[e]->reversePtr = new EdgeUse( edges[e] );
00442 edges[e]->reversePtr->insert_after( prev );
00443 }
00444 prev = edges[e]->reversePtr;
00445 }
00446 else
00447 {
00448 assert( !edges[e]->forwardPtr );
00449 if( !prev )
00450 {
00451 edges[e]->forwardPtr = new EdgeUse( edges[e], faceList );
00452 }
00453 else
00454 {
00455 edges[e]->forwardPtr = new EdgeUse( edges[e] );
00456 edges[e]->forwardPtr->insert_after( prev );
00457 }
00458 prev = edges[e]->forwardPtr;
00459 }
00460 }
00461 }
00462
00463 return MB_SUCCESS;
00464 }
00465
00466 void BSPTreePoly::get_faces( std::vector< const Face* >& face_list ) const
00467 {
00468 face_list.clear();
00469 for( Face* face = faceList; face; face = face->nextPtr )
00470 face_list.push_back( face );
00471 }
00472
00473 void BSPTreePoly::get_vertices( const Face* face, std::vector< CartVect >& vertices ) const
00474 {
00475 vertices.clear();
00476 if( !face || !face->usePtr ) return;
00477
00478 EdgeUse* coedge = face->usePtr;
00479 do
00480 {
00481 vertices.push_back( *coedge->end() );
00482 coedge = coedge->nextPtr;
00483 } while( coedge != face->usePtr );
00484 }
00485
00486 double BSPTreePoly::Face::signed_volume() const
00487 {
00488 CartVect sum( 0.0 );
00489 const CartVect* base = usePtr->start();
00490 CartVect d1 = ( *usePtr->end() - *base );
00491 for( EdgeUse* coedge = usePtr->nextPtr; coedge != usePtr; coedge = coedge->nextPtr )
00492 {
00493 CartVect d2 = ( *coedge->end() - *base );
00494 sum += d1 * d2;
00495 d1 = d2;
00496 }
00497 return ( 1.0 / 6.0 ) * ( sum % *base );
00498 }
00499
00500 double BSPTreePoly::volume() const
00501 {
00502 double result = 0;
00503 for( Face* ptr = faceList; ptr; ptr = ptr->nextPtr )
00504 result += ptr->signed_volume();
00505 return result;
00506 }
00507
00508 void BSPTreePoly::set_vertex_marks( int value )
00509 {
00510 for( Face* face = faceList; face; face = face->nextPtr )
00511 {
00512 EdgeUse* edge = face->usePtr;
00513 do
00514 {
00515 edge->edgePtr->start()->markVal = value;
00516 edge->edgePtr->end()->markVal = value;
00517 edge = edge->nextPtr;
00518 } while( edge && edge != face->usePtr );
00519 }
00520 }
00521 /*
00522 static void merge_edges( BSPTreePoly::Edge* keep_edge,
00523 BSPTreePoly::Edge* dead_edge )
00524 {
00525 // edges must share a vertex
00526 BSPTreePoly::Vertex* dead_vtx = keep_edge->common(dead_edge);
00527 assert(dead_vtx);
00528 // vertex may have only two adjacent edges
00529 BSPTreePoly::VertexUse* dead_vtxuse = dead_edge->use(dead_vtx);
00530 assert(dead_vtxuse);
00531 BSPTreePoly::VertexUse* keep_vtxuse = dead_vtxuse->nextPtr;
00532 assert(keep_vtxuse);
00533 assert(keep_vtxuse->edgePtr == keep_edge);
00534 assert(keep_vtxuse->nextPtr == dead_vtxuse);
00535 assert(keep_vtxuse->prevPtr == dead_vtxuse);
00536 assert(dead_vtxuse->prevPtr == keep_vtxuse);
00537
00538 // kept edge now ends with the kept vertex on the dead edge
00539 keep_vtxuse->set_vertex( dead_edge->other(dead_vtx) );
00540
00541 // destructors should take care of everything else
00542 // (including removing dead edge from face loops)
00543 delete dead_edge;
00544 }
00545 */
00546 static BSPTreePoly::Edge* split_edge( BSPTreePoly::Vertex*& new_vtx, BSPTreePoly::Edge* into_edge )
00547 {
00548 // split edge, creating new edge
00549 BSPTreePoly::Edge* new_edge = new BSPTreePoly::Edge( new_vtx, into_edge->end() );
00550 into_edge->endPtr->set_vertex( new_vtx ); // This call might delete new_vtx
00551
00552 // update coedge loops in faces
00553 if( into_edge->forwardPtr )
00554 {
00555 new_edge->forwardPtr = new BSPTreePoly::EdgeUse( new_edge );
00556 new_edge->forwardPtr->insert_after( into_edge->forwardPtr );
00557 }
00558 if( into_edge->reversePtr )
00559 {
00560 new_edge->reversePtr = new BSPTreePoly::EdgeUse( new_edge );
00561 new_edge->reversePtr->insert_before( into_edge->reversePtr );
00562 }
00563
00564 return new_edge;
00565 }
00566
00567 static BSPTreePoly::Face* split_face( BSPTreePoly::EdgeUse* start, BSPTreePoly::EdgeUse* end )
00568 {
00569 BSPTreePoly::Face* face = start->facePtr;
00570 assert( face == end->facePtr );
00571 BSPTreePoly::Face* new_face = new BSPTreePoly::Face;
00572 BSPTreePoly::EdgeUse* keep_start = start->prevPtr;
00573 BSPTreePoly::EdgeUse* keep_end = end->nextPtr;
00574 for( BSPTreePoly::EdgeUse* ptr = start; ptr != keep_end; ptr = ptr->nextPtr )
00575 {
00576 if( face->usePtr == ptr ) face->usePtr = keep_start;
00577 ptr->facePtr = new_face;
00578 }
00579 new_face->usePtr = start;
00580 BSPTreePoly::Edge* edge = new BSPTreePoly::Edge( start->start(), end->end() );
00581 edge->forwardPtr = new BSPTreePoly::EdgeUse( edge );
00582 edge->reversePtr = new BSPTreePoly::EdgeUse( edge );
00583
00584 edge->forwardPtr->facePtr = face;
00585 edge->forwardPtr->prevPtr = keep_start;
00586 keep_start->nextPtr = edge->forwardPtr;
00587 edge->forwardPtr->nextPtr = keep_end;
00588 keep_end->prevPtr = edge->forwardPtr;
00589
00590 edge->reversePtr->facePtr = new_face;
00591 edge->reversePtr->nextPtr = start;
00592 start->prevPtr = edge->reversePtr;
00593 edge->reversePtr->prevPtr = end;
00594 end->nextPtr = edge->reversePtr;
00595
00596 return new_face;
00597 }
00598
00599 bool BSPTreePoly::cut_polyhedron( const CartVect& plane_normal, double plane_coeff )
00600 {
00601 const double EPSILON = 1e-6; // points this close are considered coincident
00602
00603 // scale epsilon rather than normalizing normal vector
00604 const double epsilon = EPSILON * ( plane_normal % plane_normal );
00605
00606 // Classify all points above/below plane and destroy any faces
00607 // that have no vertices below the plane.
00608 const int UNKNOWN = 0;
00609 const int ABOVE = 1;
00610 const int ON = 2;
00611 const int BELOW = 3;
00612 int num_above = 0;
00613 set_vertex_marks( UNKNOWN );
00614
00615 // Classify all points above/below plane and
00616 // split any edge that intersect the plane.
00617 for( Face* face = faceList; face; face = face->nextPtr )
00618 {
00619 EdgeUse* edge = face->usePtr;
00620
00621 do
00622 {
00623 Vertex* start = edge->edgePtr->start();
00624 Vertex* end = edge->edgePtr->end();
00625
00626 if( !start->markVal )
00627 {
00628 double d = plane_normal % *start + plane_coeff;
00629 if( d * d <= epsilon )
00630 start->markVal = ON;
00631 else if( d < 0.0 )
00632 start->markVal = BELOW;
00633 else
00634 {
00635 start->markVal = ABOVE;
00636 ++num_above;
00637 }
00638 }
00639
00640 if( !end->markVal )
00641 {
00642 double d = plane_normal % *end + plane_coeff;
00643 if( d * d <= epsilon )
00644 end->markVal = ON;
00645 else if( d < 0.0 )
00646 end->markVal = BELOW;
00647 else
00648 {
00649 end->markVal = ABOVE;
00650 ++num_above;
00651 }
00652 }
00653
00654 if( ( end->markVal == ABOVE && start->markVal == BELOW ) ||
00655 ( end->markVal == BELOW && start->markVal == ABOVE ) )
00656 {
00657 CartVect dir = *end - *start;
00658 double t = -( plane_normal % *start + plane_coeff ) / ( dir % plane_normal );
00659 Vertex* new_vtx = new Vertex( *start + t * dir );
00660 new_vtx->markVal = ON;
00661 split_edge( new_vtx, edge->edgePtr ); // This call might delete new_vtx
00662 end = new_vtx;
00663 }
00664
00665 edge = edge->nextPtr;
00666 } while( edge && edge != face->usePtr );
00667 }
00668
00669 if( !num_above ) return false;
00670
00671 // Split faces
00672 for( Face* face = faceList; face; face = face->nextPtr )
00673 {
00674 EdgeUse* edge = face->usePtr;
00675
00676 EdgeUse *split_start = 0, *split_end = 0, *other_split = 0;
00677 do
00678 {
00679 if( edge->end()->markVal == ON && edge->start()->markVal != ON )
00680 {
00681 if( !split_start )
00682 split_start = edge->nextPtr;
00683 else if( !split_end )
00684 split_end = edge;
00685 else
00686 other_split = edge;
00687 }
00688
00689 edge = edge->nextPtr;
00690 } while( edge && edge != face->usePtr );
00691
00692 // If two vertices are on plane (but not every vertex)
00693 // then split the face
00694 if( split_end && !other_split )
00695 {
00696 assert( split_start );
00697 Face* new_face = split_face( split_start, split_end );
00698 new_face->nextPtr = faceList;
00699 faceList = new_face;
00700 }
00701 }
00702
00703 // Destroy all faces that are above the plane
00704 Face** lptr = &faceList;
00705 while( *lptr )
00706 {
00707 EdgeUse* edge = ( *lptr )->usePtr;
00708 bool some_above = false;
00709 do
00710 {
00711 if( edge->start()->markVal == ABOVE )
00712 {
00713 some_above = true;
00714 break;
00715 }
00716 edge = edge->nextPtr;
00717 } while( edge && edge != ( *lptr )->usePtr );
00718
00719 if( some_above )
00720 {
00721 Face* dead = *lptr;
00722 *lptr = ( *lptr )->nextPtr;
00723 delete dead;
00724 }
00725 else
00726 {
00727 lptr = &( ( *lptr )->nextPtr );
00728 }
00729 }
00730
00731 // Construct a new face in the cut plane
00732
00733 // First find an edge to start at
00734 Edge* edge_ptr = 0;
00735 for( Face* face = faceList; face && !edge_ptr; face = face->nextPtr )
00736 {
00737 EdgeUse* co_edge = face->usePtr;
00738 do
00739 {
00740 if( 0 == co_edge->edgePtr->other( co_edge ) )
00741 {
00742 edge_ptr = co_edge->edgePtr;
00743 break;
00744 }
00745 co_edge = co_edge->nextPtr;
00746 } while( co_edge && co_edge != face->usePtr );
00747 }
00748 if( !edge_ptr ) return false;
00749
00750 // Constuct new face and first CoEdge
00751 faceList = new Face( faceList );
00752 Vertex *next_vtx, *start_vtx;
00753 EdgeUse* prev_coedge;
00754 if( edge_ptr->forwardPtr )
00755 {
00756 next_vtx = edge_ptr->start();
00757 start_vtx = edge_ptr->end();
00758 assert( !edge_ptr->reversePtr );
00759 prev_coedge = edge_ptr->reversePtr = new EdgeUse( edge_ptr, faceList );
00760 }
00761 else
00762 {
00763 next_vtx = edge_ptr->end();
00764 start_vtx = edge_ptr->start();
00765 prev_coedge = edge_ptr->forwardPtr = new EdgeUse( edge_ptr, faceList );
00766 }
00767
00768 // Construct coedges until loop is closed
00769 while( next_vtx != start_vtx )
00770 {
00771 // find next edge adjacent to vertex with only one adjacent face
00772 VertexUse* this_use = edge_ptr->use( next_vtx );
00773 VertexUse* use = this_use->nextPtr;
00774 while( use != this_use )
00775 {
00776 if( use->edgePtr->forwardPtr == 0 )
00777 {
00778 edge_ptr = use->edgePtr;
00779 assert( edge_ptr->start() == next_vtx );
00780 next_vtx = edge_ptr->end();
00781 edge_ptr->forwardPtr = new EdgeUse( edge_ptr );
00782 edge_ptr->forwardPtr->insert_after( prev_coedge );
00783 prev_coedge = edge_ptr->forwardPtr;
00784 break;
00785 }
00786 else if( use->edgePtr->reversePtr == 0 )
00787 {
00788 edge_ptr = use->edgePtr;
00789 assert( edge_ptr->end() == next_vtx );
00790 next_vtx = edge_ptr->start();
00791 edge_ptr->reversePtr = new EdgeUse( edge_ptr );
00792 edge_ptr->reversePtr->insert_after( prev_coedge );
00793 prev_coedge = edge_ptr->reversePtr;
00794 break;
00795 }
00796
00797 use = use->nextPtr;
00798 assert( use != this_use ); // failed to close loop!
00799 }
00800 }
00801
00802 return true;
00803 }
00804
00805 bool BSPTreePoly::is_valid() const
00806 {
00807 std::set< Face* > list_faces;
00808
00809 int i = 0;
00810 for( Face* ptr = faceList; ptr; ptr = ptr->nextPtr )
00811 {
00812 if( ++i > 10000 ) return false;
00813 if( !list_faces.insert( ptr ).second ) return false;
00814 }
00815
00816 std::set< Vertex* > vertices;
00817 for( Face* face = faceList; face; face = face->nextPtr )
00818 {
00819 i = 0;
00820 EdgeUse* coedge = face->usePtr;
00821 do
00822 {
00823 if( ++i > 10000 ) return false;
00824
00825 if( coedge->facePtr != face ) return false;
00826
00827 Edge* edge = coedge->edgePtr;
00828 if( !edge->startPtr || !edge->endPtr ) return false;
00829
00830 vertices.insert( edge->start() );
00831 vertices.insert( edge->end() );
00832
00833 EdgeUse* other;
00834 if( edge->forwardPtr == coedge )
00835 other = edge->reversePtr;
00836 else if( edge->reversePtr != coedge )
00837 return false;
00838 else
00839 other = edge->forwardPtr;
00840 if( !other ) return false;
00841 if( list_faces.find( other->facePtr ) == list_faces.end() ) return false;
00842
00843 EdgeUse* next = coedge->nextPtr;
00844 if( next->prevPtr != coedge ) return false;
00845 if( coedge->end() != next->start() ) return false;
00846
00847 coedge = next;
00848 } while( coedge != face->usePtr );
00849 }
00850
00851 for( std::set< Vertex* >::iterator j = vertices.begin(); j != vertices.end(); ++j )
00852 {
00853 Vertex* vtx = *j;
00854
00855 i = 0;
00856 VertexUse* use = vtx->usePtr;
00857 do
00858 {
00859 if( ++i > 10000 ) return false;
00860
00861 if( use->vtxPtr != vtx ) return false;
00862
00863 Edge* edge = use->edgePtr;
00864 if( !edge ) return false;
00865 if( edge->startPtr != use && edge->endPtr != use ) return false;
00866
00867 VertexUse* next = use->nextPtr;
00868 if( next->prevPtr != use ) return false;
00869
00870 use = next;
00871 } while( use != vtx->usePtr );
00872 }
00873
00874 return true;
00875 }
00876
00877 bool BSPTreePoly::is_point_contained( const CartVect& point ) const
00878 {
00879 if( !faceList ) // empty (zero-dimension) polyhedron
00880 return false;
00881
00882 const double EPSILON = 1e-6;
00883 // Test that point is below the plane of each face
00884 // NOTE: This will NOT work for polyhedra w/ concavities
00885 for( Face* face = faceList; face; face = face->nextPtr )
00886 {
00887 Vertex *pt1, *pt2, *pt3;
00888 pt1 = face->usePtr->start();
00889 pt2 = face->usePtr->end();
00890 pt3 = face->usePtr->nextPtr->end();
00891
00892 if( pt3 == pt1 ) // degenerate
00893 continue;
00894
00895 CartVect norm = ( *pt3 - *pt2 ) * ( *pt1 - *pt2 );
00896 double coeff = -( norm % *pt2 );
00897 if( ( norm % point + coeff ) > EPSILON ) // if above plane, with some -epsilon
00898 return false;
00899 }
00900
00901 return true;
00902 }
00903
00904 } // namespace moab