cgma
|
00001 //------------------------------------------------------------------------- 00002 // Filename : PST_Data.hpp 00003 // 00004 // Purpose : Classes for representing geometry facets. Used by 00005 // PartSurfTess to find the graphis faceting for 00006 // PartitionSurfaces. 00007 // 00008 // Special Notes : 00009 // 00010 // Creator : Jason Kraftcheck 00011 // 00012 // Creation Date : 05/17/01 00013 //------------------------------------------------------------------------- 00014 #ifndef PST_DATA_HPP 00015 #define PST_DATA_HPP 00016 #include <vector> 00017 00018 #include "CubitVector.hpp" 00019 #include "CubitDefines.h" 00020 #include "DLIList.hpp" 00021 #include "CubitPlane.hpp" 00022 00023 #define PST_OTHER(A,B,C) (((A)==(B))?(C):(((A)==(C))?(B):0)) 00024 00025 class PST_CoEdge; 00026 class PST_Edge; 00027 class PST_Point; 00028 class PST_Face; 00029 class GMem; 00030 00031 class PST_Entity; 00032 00033 class PST_EntityOwner { 00034 public: 00035 virtual void 00036 notify_split( PST_Entity* old_entity, PST_Entity* new_entity ) = 0; 00037 }; 00038 00039 class PST_Entity 00040 { 00041 public: 00042 00043 inline PST_EntityOwner* owner() const; 00044 00045 inline void owner( PST_EntityOwner* ); 00046 00047 protected: 00048 00049 inline PST_Entity(); 00050 00051 virtual ~PST_Entity() = 0; 00052 00053 private: 00054 00055 PST_EntityOwner* myOwner; 00056 }; 00057 00058 00059 //------------------------------------------------------------------------- 00060 // Purpose : Class representing a vertex in facet data structure 00061 // 00062 // Special Notes : 00063 // 00064 // Creator : Jason Kraftcheck 00065 // 00066 // Creation Date : 05/16/01 00067 //------------------------------------------------------------------------- 00068 class PST_Point : public CubitVector, public PST_Entity 00069 { 00070 friend class PST_Edge; 00071 00072 public: 00073 00074 PST_Point( const CubitVector& position ) 00075 : CubitVector( position ), 00076 mark(0), private_mark_(false), edge_(0) 00077 { } 00078 00079 ~PST_Point() ; 00080 //- Destroys this point, and all edges and faces that 00081 //- the point exists in. 00082 00083 PST_Edge* edge() 00084 { return edge_; } 00085 00086 inline PST_Edge* next( PST_Edge* prev ); 00087 00088 PST_Edge* common( PST_Point* pt ); 00089 00090 int faces( DLIList<PST_Face*>* list = 0 ); 00091 00092 //PST_Face* boundary_face(); 00093 00094 void debug_draw( int color = 1, bool flush = true ); 00095 static void debug_draw_points( DLIList<PST_Point*>& list, 00096 int color, bool flush = true ); 00097 00098 int validate( CubitBoolean print = CUBIT_FALSE ); 00099 00100 void print(); 00101 00102 int mark; 00103 00104 int sequence; 00105 00106 private: 00107 cBit private_mark_ : 1; 00108 00109 PST_Edge* edge_; 00110 }; 00111 00112 //------------------------------------------------------------------------- 00113 // Purpose : Association between a PST_Edge and a PST_Face 00114 // 00115 // Special Notes : Allocated inline in PST_Edge -- Do NOT memory manage! 00116 // 00117 // Creator : Jason Kraftcheck 00118 // 00119 // Creation Date : 05/16/01 00120 //------------------------------------------------------------------------- 00121 class PST_CoEdge 00122 { 00123 friend class PST_Edge; 00124 00125 public: 00126 00127 PST_CoEdge* next() 00128 { return next_; } 00129 00130 PST_Edge* edge() 00131 { return edge_; } 00132 00133 PST_Face* face() 00134 { return face_; } 00135 00136 inline CubitSense sense(); 00137 00138 inline PST_Point* start_point(); 00139 inline PST_Point* end_point(); 00140 inline PST_Point* common( PST_CoEdge* coedge ); 00141 inline PST_Point* other( PST_Point* point ); 00142 00143 inline const CubitVector& start_coord(); 00144 inline const CubitVector& end_coord(); 00145 inline CubitVector direction(); 00146 00147 inline PST_CoEdge* other(); 00148 00149 PST_CoEdge* previous(); 00150 00151 int validate( CubitBoolean print = CUBIT_FALSE ); 00152 00153 private: 00154 00155 PST_CoEdge() 00156 : next_(0), edge_(0), face_(0) 00157 { } 00158 00159 PST_CoEdge( PST_Edge* owner ) 00160 : next_(0), edge_(owner), face_(0) 00161 { } 00162 00163 ~PST_CoEdge() 00164 { assert( !face_ ); } 00165 00166 PST_CoEdge* next_; 00167 PST_Edge* edge_; 00168 PST_Face* face_; 00169 }; 00170 00171 00172 //------------------------------------------------------------------------- 00173 // Purpose : Edge in facet data structure 00174 // 00175 // Special Notes : 00176 // 00177 // Creator : Jason Kraftcheck 00178 // 00179 // Creation Date : 05/16/01 00180 //------------------------------------------------------------------------- 00181 class PST_Edge : public PST_Entity 00182 { 00183 public: 00184 00185 static void make_gmem( GMem& gmem, DLIList<PST_Face*>& facets ); 00186 static void make_gmem( GMem& gmem, DLIList<PST_Edge*>& edges ); 00187 static void make_facets( GMem& gmem, double tolerance, 00188 DLIList<PST_Edge*>& edges ); 00189 static void make_facets( 00190 const std::vector<double>& coordinates, 00191 const std::vector<int>& connections, 00192 double tolerance, 00193 DLIList<PST_Edge*>& edge_list ); 00194 00195 PST_Edge( PST_Point* start_pt, PST_Point* end_pt ) 00196 : mark(0), private_mark_(false), 00197 start_(0), end_(0) 00198 { 00199 assert( start_pt != end_pt ); 00200 set_start_point( start_pt ); 00201 set_end_point( end_pt ); 00202 forward_ = PST_CoEdge(this); 00203 reverse_ = PST_CoEdge(this); 00204 } 00205 00206 00207 static PST_Face* create_face( PST_Point* p1, 00208 PST_Point* p2, 00209 PST_Point* p3 ); 00210 00211 static PST_Edge* split_face( PST_Point* start, 00212 PST_Point* end, 00213 PST_Face* hint = 0 ); 00214 //- This method splits a face by creating an edge 00215 //- between two existing points on that face. 00216 //- If the face to split is not specified, both 00217 //- points must have exactly one face in common. 00218 //- If the points do not have a common face, have 00219 //- more than one common face and no face is 00220 //- specified, do not exist in the passed face, 00221 //- or already have a common edge, NULL is returned. 00222 00223 static PST_Edge* split_face( PST_CoEdge* after_coedge_1, 00224 PST_CoEdge* after_coedge_2 ); 00225 //- Split a face with an edge from the end of the first 00226 //- coedge to the end of the second coedge. NULL is 00227 //- returned if the coedges do not have a common face, 00228 //- or the desired edge already exists. 00229 00230 static PST_Edge* insert_in_face( PST_Point* end, 00231 PST_CoEdge* after_this ); 00232 //- Create a non-manifold edge in a face. The edge is 00233 //- inserted starting at the end of the passed coedge, 00234 //- and terminating at the passed point. If the 00235 //- passed point already exists in a face, null is 00236 //- returned. 00237 00238 PST_Edge* split( PST_Point* point ); 00239 //- Split an existing edge. Creates a new edge in the 00240 //- same face(s) as the existing edge. Returns null 00241 //- if the passed already exists in any face. 00242 00243 ~PST_Edge(); 00244 //- Destroy this edge, splitting or merging faces as 00245 //- necessary. Does NOT destroy unused points. 00246 00247 PST_Point* start_point() 00248 { return start_; } 00249 00250 PST_Point* end_point() 00251 { return end_; } 00252 00253 const CubitVector& start_coord() 00254 { return *start_; } 00255 00256 const CubitVector& end_coord() 00257 { return *end_; } 00258 00259 CubitVector direction() 00260 { return end_coord() - start_coord(); } 00261 00262 00263 CubitVector position( double t ) 00264 { return start_coord() + t * direction(); } 00265 00266 double closest_on_line( const CubitVector& pos ); 00267 double closest_on_edge( const CubitVector& pos ); 00268 // Parameter of the closest position on 00269 // a) the line containing this edge or 00270 // b) this bounded edge. 00271 00272 double closest_on_line( const CubitVector& base, 00273 const CubitVector& direction ); 00274 // The parameter of the closest position on 00275 // the line containing this edge to the passed line. 00276 // Use position(..) function above to get coordinates. 00277 00278 PST_Point* other( PST_Point* pt ) 00279 { return PST_OTHER(pt,start_,end_); } 00280 00281 inline PST_Point* common_point( PST_Edge* edge ); 00282 00283 PST_CoEdge* forward() 00284 { return &forward_; } 00285 00286 PST_CoEdge* reverse() 00287 { return &reverse_; } 00288 00289 PST_CoEdge* other( PST_CoEdge* coedge ) 00290 { return PST_OTHER(coedge,&forward_,&reverse_); } 00291 00292 inline PST_CoEdge* coedge( PST_Face* face ); 00293 00294 00295 PST_Face* other( PST_Face* face ) 00296 { return PST_OTHER(face,forward_.face(),reverse_.face()); } 00297 00298 00299 inline PST_Face* common_face( PST_Edge* edge ); 00300 00301 inline CubitSense sense( PST_Face* face ); 00302 00303 CubitSense sense( PST_CoEdge* coedge ) 00304 { return coedge == forward() ? CUBIT_FORWARD : 00305 coedge == reverse() ? CUBIT_REVERSED : CUBIT_UNKNOWN; } 00306 00307 PST_Edge* other( PST_Point* point, PST_Face* face ); 00308 // Find the other edge in the passed face that 00309 // shares the passed point. Returns NULL if multiple 00310 // matches in a non-manifold face. 00311 00312 PST_Edge* next( PST_Point* pt ) 00313 { return pt == start_ ? start_next_ : 00314 pt == end_ ? end_next_ : 0; } 00315 00316 //inline bool boundary(); 00317 00318 static void faces( DLIList<PST_Edge*>& edges, DLIList<PST_Face*>& faces ); 00319 static void edges( DLIList<PST_Face*>& faces, DLIList<PST_Edge*>& edges ); 00320 static void edges( DLIList<PST_Point*>& pts, DLIList<PST_Edge*>& edges ); 00321 static void points( DLIList<PST_Edge*>& edges, DLIList<PST_Point*>& pts ); 00322 00323 void debug_draw( int color = 1, bool flush = true ); 00324 static void debug_draw_points( DLIList<PST_Edge*>& list, 00325 int color, int bcolor = 0, bool flush = true ); 00326 static void debug_draw_edges ( DLIList<PST_Edge*>& list, 00327 int color, int bcolor = 0, bool flush = true ); 00328 static void debug_draw_faces ( DLIList<PST_Edge*>& list, 00329 int color, bool flush = true ); 00330 00331 static int validate( DLIList<PST_Edge*>& edges, CubitBoolean print = CUBIT_FALSE ); 00332 int validate( CubitBoolean print = CUBIT_FALSE ); 00333 00334 void print(); 00335 00336 int mark; 00337 00338 private: 00339 cBit private_mark_ : 1; 00340 00341 void remove_point( PST_Point*& ptr, PST_Edge*& next ); 00342 void remove_start_point() { remove_point( start_, start_next_ ); } 00343 void remove_end_point() { remove_point( end_, end_next_); } 00344 00345 void set_point( PST_Point* pt, PST_Point*& ptr, PST_Edge*& next ); 00346 void set_start_point( PST_Point* pt ) 00347 { set_point( pt, start_, start_next_ ); } 00348 void set_end_point( PST_Point* pt ) 00349 { set_point( pt, end_, end_next_ ); } 00350 00351 PST_Point* start_; 00352 PST_Point* end_; 00353 PST_Edge* start_next_; 00354 PST_Edge* end_next_; 00355 00356 PST_CoEdge forward_; 00357 PST_CoEdge reverse_; 00358 }; 00359 00360 //------------------------------------------------------------------------- 00361 // Purpose : Face in facet data structure 00362 // 00363 // Special Notes : 00364 // 00365 // Creator : Jason Kraftcheck 00366 // 00367 // Creation Date : 05/16/01 00368 //------------------------------------------------------------------------- 00369 class PST_Face : public PST_Entity 00370 { 00371 friend class PST_Edge; 00372 friend class PST_Point; 00373 00374 public: 00375 00376 const CubitPlane& plane() 00377 { 00378 if( update_plane_ ) 00379 calculate_plane(); 00380 return plane_; 00381 } 00382 00383 CubitVector normal() 00384 { return plane().normal(); } 00385 00386 00387 double bounding_length(); 00388 00389 PST_CoEdge* first_coedge() 00390 { return coedge_; } 00391 00392 void append_points( DLIList<PST_Point*>& result_list ); 00393 00394 PST_Point* opposite( PST_Edge* edge ); 00395 PST_Edge* opposite( PST_Point* point ); 00396 // for triangles 00397 00398 bool two_edges( PST_Point* point, PST_Edge*& edge1, PST_Edge*& edge2 ); 00399 00400 bool modified() 00401 { return modified_; } 00402 00403 void modified( bool b ) 00404 { 00405 modified_ = b; 00406 if( b ) update_plane_ = 1; 00407 } 00408 00409 void debug_draw( int color = 1, bool flush = true ); 00410 static void debug_draw_faces( DLIList<PST_Face*>& list, 00411 int color, bool flush = true ); 00412 00413 int validate( CubitBoolean print = CUBIT_FALSE ); 00414 00415 void print(); 00416 00417 int mark; 00418 00419 int sequence; 00420 00421 int parent; 00422 00423 private: 00424 00425 PST_Face( PST_CoEdge* coedge ) 00426 : mark(0), sequence(0), parent(0), 00427 coedge_(coedge), 00428 //boundary_(0), 00429 modified_(0), 00430 update_plane_(1), 00431 private_mark_(false) 00432 00433 { } 00434 00435 PST_Face( PST_CoEdge* coedge, PST_Face* split_from ) 00436 : mark(0), sequence(0), parent(0), 00437 coedge_(coedge), 00438 //boundary_(split_from->boundary()), 00439 modified_(0), 00440 update_plane_(1), 00441 private_mark_(false) 00442 { split_from->modified(true); } 00443 00444 ~PST_Face() 00445 { assert( !coedge_ ); } 00446 00447 bool calculate_plane(); 00448 00449 PST_CoEdge* coedge_; 00450 CubitPlane plane_; 00451 00452 //cBit boundary_ : 1; 00453 cBit modified_ : 1; 00454 cBit update_plane_ : 1; 00455 cBit private_mark_ : 1; 00456 }; 00457 00458 /************************************************************************* 00459 * PST_Point 00460 ************************************************************************/ 00461 00462 inline PST_Edge* PST_Point::next( PST_Edge* prev ) 00463 { 00464 return prev->next(this); 00465 } 00466 00467 /************************************************************************* 00468 * PST_CoEdge 00469 ************************************************************************/ 00470 00471 inline CubitSense PST_CoEdge::sense() 00472 { 00473 return edge_->sense(this); 00474 } 00475 00476 inline PST_Point* PST_CoEdge::start_point() 00477 { 00478 return sense() == CUBIT_FORWARD ? edge_->start_point() : edge_->end_point(); 00479 } 00480 00481 inline PST_Point* PST_CoEdge::end_point() 00482 { 00483 return sense() == CUBIT_FORWARD ? edge_->end_point() : edge_->start_point(); 00484 } 00485 00486 inline PST_Point* PST_CoEdge::other( PST_Point* point ) 00487 { 00488 return edge_->other( point ); 00489 } 00490 00491 inline const CubitVector& PST_CoEdge::start_coord() 00492 { 00493 return sense() == CUBIT_FORWARD ? edge_->start_coord() : edge_->end_coord(); 00494 } 00495 00496 inline const CubitVector& PST_CoEdge::end_coord() 00497 { 00498 return sense() == CUBIT_FORWARD ? edge_->end_coord() : edge_->start_coord(); 00499 } 00500 00501 inline CubitVector PST_CoEdge::direction() 00502 { 00503 return sense() == CUBIT_FORWARD ? 00504 edge_->end_coord() - edge_->start_coord() : 00505 edge_->start_coord() - edge_->end_coord() ; 00506 } 00507 00508 inline PST_CoEdge* PST_CoEdge::other() 00509 { 00510 return edge_->other(this); 00511 } 00512 00513 00514 00515 /************************************************************************* 00516 * PST_Edge 00517 ************************************************************************/ 00518 00519 inline PST_Point* PST_Edge::common_point( PST_Edge* edge ) 00520 { 00521 PST_Point* result = 0; 00522 00523 if( (edge->start_ == start_) || 00524 (edge->end_ == start_) ) 00525 result = start_; 00526 00527 if( (edge->start_ == end_) || 00528 (edge->end_ == end_) ) 00529 result = result ? 0 : end_; 00530 00531 return result; 00532 } 00533 00534 inline PST_CoEdge* PST_Edge::coedge( PST_Face* face ) 00535 { 00536 PST_CoEdge* result = 0; 00537 00538 if( forward_.face_ == face ) 00539 result = &forward_; 00540 00541 if( reverse_.face_ == face ) 00542 result = result ? 0 : &reverse_; 00543 00544 return result; 00545 } 00546 00547 inline CubitSense PST_Edge::sense( PST_Face* face ) 00548 { 00549 CubitSense result = CUBIT_UNKNOWN; 00550 00551 if( forward_.face_ == face ) 00552 result = CUBIT_FORWARD; 00553 00554 if( reverse_.face_ == face ) 00555 result = (result != CUBIT_UNKNOWN) ? CUBIT_UNKNOWN : CUBIT_REVERSED; 00556 00557 return result; 00558 } 00559 00560 inline PST_Entity::PST_Entity() : myOwner(0) { ; } 00561 00562 inline PST_EntityOwner* PST_Entity::owner() const 00563 { return myOwner; } 00564 00565 inline void PST_Entity::owner( PST_EntityOwner* ent ) 00566 { myOwner = ent; } 00567 00568 00569 /************************************************************************* 00570 * PST_Face 00571 ************************************************************************/ 00572 00573 // find the minimum edge length and use this for the bounding length 00574 inline double PST_Face::bounding_length() 00575 { 00576 // The coedges appear to be stored in a circular list so 00577 // get the length of the first edge and then iterate 00578 PST_CoEdge* coe = this->first_coedge(); 00579 CubitVector pos1 = coe->start_coord(); 00580 CubitVector pos2 = coe->end_coord(); 00581 CubitVector dist = pos1 - pos2; 00582 double length = dist.length_squared(); 00583 00584 // start the chain at the next coedge 00585 coe = coe->next(); 00586 00587 // walk through the coedges till we get back to the first 00588 // and find the minimum length edge 00589 double l; 00590 for ( ; coe != this->first_coedge(); coe = coe->next() ) 00591 { 00592 pos1 = coe->start_coord(); 00593 pos2 = coe->end_coord(); 00594 dist = pos1 - pos2; 00595 l = dist.length_squared(); 00596 if ( l < length) 00597 length = l; 00598 } 00599 00600 return sqrt(length); 00601 } 00602 00603 #endif 00604