cgma
|
00001 //- Class: FacetDataUtil 00002 //- Description: static library of general functions for querying and/or 00003 //- modifying facet entities 00004 //- Owner: Steve Owen 00005 //- Checked by: 00006 //- Version: 00007 00008 #include "FacetDataUtil.hpp" 00009 #include "FacetEvalTool.hpp" 00010 #include "CubitFacet.hpp" 00011 #include "CubitFacetEdge.hpp" 00012 #include "CubitPoint.hpp" 00013 #include "CubitPointData.hpp" 00014 #include "CubitFacetData.hpp" 00015 #include "CubitFacetEdgeData.hpp" 00016 #include "CubitQuadFacet.hpp" 00017 #include "GeometryDefines.h" 00018 #include "ChollaDebug.hpp" 00019 #include "GfxDebug.hpp" 00020 #include "KDDTree.hpp" 00021 00022 //=========================================================================== 00023 //Function Name: edges_by_count 00024 //Description: find edges that are shared by "count" number of facets 00025 //Author: bwhanks 00026 //Date: 2003 00027 //=========================================================================== 00028 void FacetDataUtil::edges_by_count(DLIList<CubitFacet*> &facets, 00029 unsigned int count, 00030 DLIList<CubitFacetEdge*> &edges) 00031 { 00032 int i; 00033 int j; 00034 00035 // get a list of all edges from the facets 00036 DLIList<CubitFacetEdge*> edge_list; 00037 facets.reset(); 00038 for (i=facets.size(); i>0; i--) 00039 { 00040 CubitFacet* p_facet = facets.get_and_step(); 00041 for (j=0; j<3; j++) 00042 { 00043 edge_list.append(p_facet->edge(j)); 00044 } 00045 } 00046 00047 // reset edge marks 00048 edge_list.reset(); 00049 for (i=edge_list.size(); i>0; i--) 00050 edge_list.get_and_step()->marked(0); 00051 00052 // mark with the hit count 00053 edge_list.reset(); 00054 for (i=edge_list.size(); i>0; i--) 00055 { 00056 CubitFacetEdge* p_edge = edge_list.get_and_step(); 00057 p_edge->marked(p_edge->marked() + 1); 00058 } 00059 00060 // create the output list of edges hit the number of times passed in 00061 edge_list.reset(); 00062 for (i=edge_list.size(); i>0; i--) 00063 { 00064 CubitFacetEdge* p_edge = edge_list.get_and_step(); 00065 if (static_cast<unsigned>(p_edge->marked()) == count) 00066 edges.append(p_edge); 00067 } 00068 00069 // reset edge marks 00070 edge_list.reset(); 00071 for (i=edge_list.size(); i>0; i--) 00072 edge_list.get_and_step()->marked(0); 00073 } 00074 00075 //=========================================================================== 00076 //Function Name: ordered_point_edge_bdry 00077 //Description: get an ordered list of points and edges around the boundary 00078 // of a set of facets. The output "chain" consists of point - 00079 // edge - point - edge - ... around the boundary of the input 00080 // facets. Having the ordered points as well as the edges 00081 // helps provides sense information for the bounding edges. 00082 //Author: bwhanks 00083 //Date: 2003 00084 //=========================================================================== 00085 void FacetDataUtil::ordered_point_edge_bdry(DLIList<CubitFacet*> &facets, 00086 DLIList<FacetEntity*> &point_edge_chain) 00087 { 00088 assert(point_edge_chain.size() == 0); 00089 DLIList<CubitFacetEdge*> unordered_edges; 00090 00091 int use_count = 1; // get boundary edges (used only once by facets in the facet list) 00092 FacetDataUtil::edges_by_count(facets, use_count, unordered_edges); 00093 00094 // Adds the start_edge to the list of boundary_edges and then attempts to find the 00095 // next edge by getting all of the edges belonging to the second point on this 00096 // edge and searching for an unmarked (-1) boundary edge. Does this until it can't 00097 // find another edge. 00098 00099 00100 // mark all edges connected to points of boundary edges with -2 00101 // NOTE: using negative marks, since as boundary edges are added to the ordered list they 00102 // get marked with the order in which they are found 00103 00104 // TODO - this seems very inefficient 00105 int i; 00106 int j; 00107 int k; 00108 DLIList<CubitFacetEdge*> pt_edge_list; 00109 CubitFacetEdge* cur_edge; 00110 unordered_edges.reset(); 00111 for (i=unordered_edges.size(); i>0; i--) 00112 { 00113 cur_edge = unordered_edges.get_and_step(); 00114 for (j=0; j<2; j++) 00115 { 00116 pt_edge_list.clean_out(); 00117 cur_edge->point(j)->edges(pt_edge_list); 00118 pt_edge_list.reset(); 00119 for (k=pt_edge_list.size(); k>0; k--) 00120 pt_edge_list.get_and_step()->marked(-2); 00121 } 00122 } 00123 00124 // mark all boundary edges with -1 00125 unordered_edges.reset(); 00126 for (i=unordered_edges.size(); i>0; i--) 00127 unordered_edges.get_and_step()->marked(-1); 00128 00129 00130 00131 00132 CubitPoint *edge_pt1, *edge_pt2, *pt2, *originalpt1; 00133 CubitFacetEdge *start_edge; 00134 CubitFacetEdge *this_edge; 00135 CubitBoolean keepgoing; 00136 00137 int i_found_some = 0; 00138 unordered_edges.reset(); 00139 start_edge = unordered_edges.get(); 00140 00141 // find the orientation of the first edge with respect to one of the facets 00142 // then order the edges accordingly 00143 facets.reset(); 00144 int e_index; 00145 int start_edge_sense = 0; 00146 for (i=facets.size(); i>0; i--) 00147 { 00148 CubitFacet* p_facet = facets.get_and_step(); 00149 if ( (e_index = p_facet->edge_index(start_edge)) >= 0 ) 00150 { 00151 start_edge_sense = p_facet->edge_use(e_index); 00152 break; 00153 } 00154 } 00155 00156 00157 start_edge->marked(i_found_some); 00158 i_found_some += 1; 00159 if (1 == start_edge_sense) 00160 { 00161 originalpt1 = start_edge->point(0); 00162 point_edge_chain.append(originalpt1); 00163 point_edge_chain.append(start_edge); 00164 pt2 = start_edge->point(1); 00165 } 00166 else 00167 { 00168 assert(-1 == start_edge_sense); 00169 originalpt1 = start_edge->point(1); 00170 point_edge_chain.append(originalpt1); 00171 point_edge_chain.append(start_edge); 00172 pt2 = start_edge->point(0); 00173 } 00174 00175 00176 // Look for an edge having pt2 as a point and also being on the boundary. 00177 pt_edge_list.clean_out(); 00178 pt2->edges(pt_edge_list); 00179 00180 keepgoing = CUBIT_TRUE; 00181 pt_edge_list.reset(); 00182 while ( keepgoing == CUBIT_TRUE ) { 00183 keepgoing = CUBIT_FALSE; 00184 for ( i = pt_edge_list.size(); i > 0; i-- ) { 00185 this_edge = pt_edge_list.get_and_step(); 00186 if ( this_edge->marked() == -1 ) { 00187 i_found_some += 1; 00188 this_edge->marked(i_found_some); 00189 point_edge_chain.append(pt2); 00190 point_edge_chain.append(this_edge); 00191 00192 edge_pt1 = this_edge->point(0); 00193 edge_pt2 = this_edge->point(1); 00194 if (pt2 == edge_pt1) 00195 { 00196 pt2 = edge_pt2; 00197 } 00198 else 00199 { 00200 assert(pt2 == edge_pt2); 00201 pt2 = edge_pt1; 00202 } 00203 00204 00205 keepgoing = CUBIT_TRUE; 00206 pt_edge_list.clean_out(); 00207 pt2->edges(pt_edge_list); 00208 break; 00209 } 00210 } 00211 } 00212 00213 // clear marks 00214 for (i=unordered_edges.size(); i>0; i--) 00215 { 00216 cur_edge = unordered_edges.get_and_step(); 00217 for (j=0; j<2; j++) 00218 { 00219 pt_edge_list.clean_out(); 00220 cur_edge->point(j)->edges(pt_edge_list); 00221 pt_edge_list.reset(); 00222 for (k=pt_edge_list.size(); k>0; k--) 00223 pt_edge_list.get_and_step()->marked(0); 00224 } 00225 } 00226 00227 assert(pt2 == originalpt1); 00228 } 00229 00230 //=========================================================================== 00231 //Function Name: partial_chain 00232 //Description: given an ordered point - edge boundary and a start and end 00233 // point on the boundary, return the point - edge chain between 00234 // the two points, inclusive. 00235 //Author: bwhanks 00236 //Date: 2003 00237 //=========================================================================== 00238 CubitStatus FacetDataUtil::partial_chain(DLIList<FacetEntity*> &point_edge_chain, 00239 FacetEntity* point1, 00240 FacetEntity* point2, 00241 DLIList<FacetEntity*> &chain_between) 00242 { 00243 // make sure the edges_between list is empty 00244 assert(chain_between.size() == 0); 00245 assert(point1 != point2); 00246 00247 // find the start point in the list 00248 int pt1_index = point_edge_chain.where_is_item(point1); 00249 00250 if (-1 == pt1_index) 00251 return CUBIT_FAILURE; 00252 00253 point_edge_chain.reset(); 00254 point_edge_chain.step(pt1_index); 00255 00256 CubitBoolean b_done = CUBIT_FALSE; 00257 while (!b_done) 00258 { 00259 if (point_edge_chain.get() == point2) 00260 b_done = CUBIT_TRUE; 00261 00262 chain_between.append(point_edge_chain.get_and_step()); 00263 } 00264 00265 return CUBIT_SUCCESS; 00266 } 00267 00268 //=========================================================================== 00269 //Function Name: get_facet_points 00270 //Description: return a unique list of the points from a given set of facets 00271 //Author: bwhanks 00272 //Date: 2003 00273 //=========================================================================== 00274 void FacetDataUtil::get_facet_points(DLIList<CubitFacet*> &cubit_facets, 00275 DLIList<CubitPoint*> &facet_points) 00276 { 00277 int i; 00278 DLIList<CubitPoint*> cubit_points(cubit_facets.size() * 3); 00279 for( i = cubit_facets.size(); i--; ) 00280 { 00281 CubitFacet* facet = cubit_facets.step_and_get(); 00282 for( int j = 0; j < 3; j++ ) 00283 { 00284 CubitPoint* pt = dynamic_cast<CubitPoint*>(facet->point(j)); 00285 assert(!!pt); 00286 pt->marked(0); 00287 cubit_points.append(pt); 00288 } 00289 } 00290 for( i = cubit_points.size(); i--; ) 00291 { 00292 CubitPoint* pt = cubit_points.step_and_get(); 00293 pt->marked( pt->marked() + 1); 00294 } 00295 for( i = cubit_points.size(); i--; ) 00296 { 00297 CubitPoint* pt = cubit_points.step_and_get(); 00298 pt->marked( pt->marked() - 1 ); 00299 if( pt->marked() > 0 ) 00300 cubit_points.change_to(0); 00301 } 00302 cubit_points.remove_all_with_value(0); 00303 00304 facet_points = cubit_points; 00305 } 00306 00307 //=========================================================================== 00308 //Function Name: get_boundary_points 00309 //Description: return the boundary points from a list of facets (unordered) 00310 // assumes edges exist on the facets 00311 //Author: bwhanks 00312 //Date: 2003 00313 //=========================================================================== 00314 void FacetDataUtil::get_boundary_points(DLIList<CubitFacet*> &facet_list, 00315 DLIList<CubitPoint*> &point_list) 00316 { 00317 int ii, jj; 00318 CubitPoint *pt; 00319 CubitFacetEdge *edge; 00320 CubitFacet *facet; 00321 DLIList<CubitFacetEdge *>edge_list; 00322 for(ii=0; ii<facet_list.size(); ii++) 00323 { 00324 facet = facet_list.get_and_step(); 00325 for(jj=0; jj<3; jj++) 00326 { 00327 edge = facet->edge( jj ); 00328 if (1 == edge->num_adj_facets()) 00329 { 00330 edge_list.append(edge); 00331 edge->point( 0 )->marked( 0 ); 00332 edge->point( 1 )->marked( 0 ); 00333 } 00334 } 00335 } 00336 for(ii=0; ii<edge_list.size(); ii++) 00337 { 00338 edge = edge_list.get_and_step(); 00339 pt = edge->point( 0 ); 00340 if (pt->marked() == 0) 00341 { 00342 pt->marked( 1 ); 00343 point_list.append( pt ); 00344 } 00345 pt = edge->point( 1 ); 00346 if (pt->marked() == 0) 00347 { 00348 pt->marked( 1 ); 00349 point_list.append( pt ); 00350 } 00351 } 00352 for(ii=0; ii<point_list.size(); ii++) 00353 point_list.get_and_step()->marked(0); 00354 00355 } 00356 00357 //=========================================================================== 00358 //Function Name: get_boundary_edges 00359 //Description: return an unordered list of edges at the boundary of a 00360 // set of facets 00361 //Author: sjowen 00362 //Date: 1/19/2004 00363 //=========================================================================== 00364 void FacetDataUtil::get_boundary_edges(DLIList<CubitFacet*> &facet_list, 00365 DLIList<CubitFacetEdge*> &edge_list) 00366 { 00367 int ii, jj; 00368 CubitFacetEdge *edge; 00369 CubitFacet *facet; 00370 for(ii=0; ii<facet_list.size(); ii++) 00371 { 00372 facet = facet_list.get_and_step(); 00373 for(jj=0; jj<3; jj++) 00374 { 00375 edge = facet->edge( jj ); 00376 if (1 == edge->num_adj_facets()) 00377 { 00378 edge_list.append(edge); 00379 } 00380 } 00381 } 00382 } 00383 00384 //=========================================================================== 00385 //Function Name: get_points 00386 //Description: get a unique set of points from facets 00387 //Author: sjowen 00388 //Date: 9/11/03 00389 //=========================================================================== 00390 void FacetDataUtil::get_points(DLIList<CubitFacet*> &facet_list, 00391 DLIList<CubitPoint*> &point_list) 00392 { 00393 CubitFacet *facet; 00394 CubitPoint *pt; 00395 int ii, jj; 00396 for(ii=0; ii<facet_list.size(); ii++) 00397 { 00398 facet = facet_list.get_and_step(); 00399 facet->point( 0 )->marked( 0 ); 00400 facet->point( 1 )->marked( 0 ); 00401 facet->point( 2 )->marked( 0 ); 00402 } 00403 00404 for (ii=0; ii<facet_list.size(); ii++) 00405 { 00406 facet = facet_list.get_and_step(); 00407 for(jj=0; jj<3; jj++) 00408 { 00409 pt = facet->point(jj); 00410 if (pt->marked() == 0) 00411 { 00412 pt->marked(1); 00413 point_list.append(pt); 00414 } 00415 } 00416 } 00417 00418 for(ii=0; ii<facet_list.size(); ii++) 00419 { 00420 facet = facet_list.get_and_step(); 00421 facet->point( 0 )->marked( 0 ); 00422 facet->point( 1 )->marked( 0 ); 00423 facet->point( 2 )->marked( 0 ); 00424 } 00425 } 00426 00427 //=========================================================================== 00428 //Function Name: copy_facets 00429 //Description: make a complete copy of facets, points and edges 00430 //Note: copies edges and points with their "feature" flag 00431 //Author: sjowen 00432 //Date: 9/11/03 00433 //=========================================================================== 00434 void FacetDataUtil::copy_facets(DLIList<CubitFacet*> &old_facet_list, 00435 DLIList<CubitFacet*> &new_facet_list, 00436 DLIList<CubitPoint*> &new_point_list, 00437 DLIList<CubitFacetEdge*> &new_edge_list) 00438 { 00439 // get a unique set of points from the facets 00440 00441 DLIList<CubitPoint *> old_point_list; 00442 get_points(old_facet_list, old_point_list); 00443 CubitPoint **point_array = new CubitPoint* [old_point_list.size()]; 00444 00445 //- copy the points 00446 00447 int ii; 00448 old_point_list.reset(); 00449 CubitPoint *new_point, *the_point; 00450 for(ii=0; ii<old_point_list.size(); ii++) 00451 { 00452 the_point = old_point_list.get_and_step(); 00453 new_point = new CubitPointData( the_point->coordinates() ); 00454 the_point->marked( ii ); 00455 new_point_list.append( new_point ); 00456 point_array[ii] = new_point; 00457 if (the_point->is_feature()) 00458 new_point->set_as_feature(); 00459 } 00460 00461 //- copy the facets 00462 00463 int jj, idx; 00464 CubitFacet *new_facet, *the_facet; 00465 CubitPoint *points[3]; 00466 00467 old_facet_list.reset(); 00468 for (ii=0; ii<old_facet_list.size(); ii++) 00469 { 00470 the_facet = old_facet_list.get_and_step(); 00471 for (jj=0; jj<3; jj++) 00472 { 00473 idx = the_facet->point(jj)->marked(); 00474 points[jj] = point_array[idx]; 00475 } 00476 new_facet = new CubitFacetData( points[0], points[1], points[2] ); 00477 new_facet_list.append( new_facet ); 00478 } 00479 00480 //- copy the edges 00481 00482 int idx0, idx1; 00483 CubitFacetEdge *new_edge; 00484 CubitFacetEdge *old_edge; 00485 DLIList<CubitFacetEdge *>old_edge_list; 00486 get_edges(old_facet_list, old_edge_list); 00487 for(ii=0; ii<old_edge_list.size(); ii++) 00488 { 00489 old_edge = old_edge_list.get_and_step(); 00490 idx0 = old_edge->point(0)->marked(); 00491 idx1 = old_edge->point(1)->marked(); 00492 new_edge = new CubitFacetEdgeData( point_array[idx0], point_array[idx1] ); 00493 if (old_edge->is_feature()) 00494 new_edge->set_as_feature(); 00495 new_edge_list.append( new_edge ); 00496 } 00497 00498 delete [] point_array; 00499 00500 } 00501 00502 //=========================================================================== 00503 //Function Name: get_edges 00504 //Description: Populates the edge list from the list of facets - creates the 00505 // edges if necessary 00506 //Author: sjowen 00507 //Date: 9/11/03 00508 //=========================================================================== 00509 void FacetDataUtil::get_edges( 00510 DLIList<CubitFacet *> &facet_list, 00511 DLIList<CubitFacetEdge *> &edge_list ) 00512 { 00513 int i, j; 00514 CubitPoint *p0, *p1; 00515 CubitFacet *facet_ptr; 00516 CubitFacetEdge *edge_ptr; 00517 DLIList<CubitFacet *> adj_facet_list; 00518 00519 // mark the edges and create any that are missing 00520 facet_list.reset(); //have to reset this list to that the CubitFacetEdgeData's 00521 //get constructed correctly 00522 for ( i = 0; i < facet_list.size(); i++) 00523 { 00524 facet_ptr = facet_list.get_and_step(); 00525 for (j=0; j<3; j++) { 00526 edge_ptr = facet_ptr->edge(j); 00527 if (!(edge_ptr)) 00528 { 00529 facet_ptr->get_edge_pts(j, p0, p1); 00530 edge_ptr = (CubitFacetEdge *) new CubitFacetEdgeData( p0, p1 ); 00531 } 00532 edge_ptr->set_flag( 0 ); 00533 } 00534 } 00535 00536 // create a unique list of edges 00537 00538 for ( i = 0; i < facet_list.size(); i++) 00539 { 00540 facet_ptr = facet_list.get_and_step(); 00541 for (j=0; j<3; j++) 00542 { 00543 edge_ptr = facet_ptr->edge(j); 00544 if(edge_ptr && 0 == edge_ptr->get_flag()) 00545 { 00546 edge_ptr->set_flag( 1 ); 00547 edge_list.append( edge_ptr ); 00548 } 00549 } 00550 } 00551 00552 // reset the flags on the edges 00553 00554 for ( i = 0; i < facet_list.size(); i++) 00555 { 00556 facet_ptr = facet_list.get_and_step(); 00557 for (j=0; j<3; j++) 00558 { 00559 edge_ptr = facet_ptr->edge(j); 00560 if( edge_ptr ) 00561 edge_ptr->set_flag( 0 ); 00562 } 00563 } 00564 } 00565 00566 //============================================================================ 00567 // Function: quality 00568 // Author: sjowen 00569 // Description: this is the S.H. Lo metric for triangles that also takes into 00570 // account a surface normal. 00571 // Date: 2/2003 00572 //============================================================================ 00573 double FacetDataUtil::quality(CubitVector &c1, CubitVector &c2, CubitVector &c3, 00574 CubitVector &surf_normal) 00575 { 00576 #define TWO_ROOT_THREE 3.46410161514 00577 double area2, alpha; 00578 double length1, length2, length3; 00579 CubitVector edge1, edge2, edge3; 00580 00581 // create edges from the vertices 00582 00583 edge1 = c3 - c2; 00584 edge2 = c3 - c1; 00585 edge3 = c2 - c1; 00586 00587 // compute twice the area 00588 00589 CubitVector normal = edge3 * edge2; 00590 area2 = normal.length(); 00591 00592 length1 = edge1.length_squared(); 00593 length2 = edge2.length_squared(); 00594 length3 = edge3.length_squared(); 00595 00596 alpha = TWO_ROOT_THREE * area2 / (length1 + length2 + length3); 00597 00598 // modify the alpha metric by the dot product of the triangle normal 00599 // with the surface normal. 00600 00601 if (fabs(area2) < CUBIT_RESABS) 00602 alpha = 0.0; 00603 else 00604 { 00605 normal /= area2; 00606 double dot = normal % surf_normal; 00607 double penalty = pow(dot, 5); 00608 alpha *= penalty; 00609 } 00610 00611 return alpha; 00612 } 00613 00614 //================================================================================ 00615 // Description: compares length of two edges. 00616 // Notes: used for DLIList sort 00617 // Author : Steve Owen 00618 // Date : 9/27/2003 00619 //================================================================================ 00620 int FacetDataUtil::edge_compare(CubitFacetEdge *&ea, CubitFacetEdge *&eb) 00621 { 00622 double la = ea->length(); 00623 double lb = eb->length(); 00624 if (la < lb) 00625 return -1; 00626 else if (lb < la) 00627 return 1; 00628 return 0; 00629 } 00630 00631 //================================================================================ 00632 // Description: collapse edges that are smaller than 10% the average length 00633 // Notes: non_manifold_only=true indicates that only edges that are attached 00634 // to more than two edges will be candidates for collapse. 00635 // Author : Steve Owen 00636 // Date : 9/27/2003 00637 //================================================================================ 00638 CubitStatus FacetDataUtil::collapse_short_edges( 00639 DLIList<CubitFacet*> &facet_list, 00640 CubitBoolean non_manifold_only) 00641 { 00642 #define COLLAPSE_TOLERANCE 0.3 00643 00644 CubitStatus rv = CUBIT_SUCCESS; 00645 int ncollapse = 0; 00646 00647 // get the edges 00648 00649 DLIList <CubitFacetEdge *>edge_list; 00650 DLIList <CubitPoint *> point_list; 00651 DLIList <CubitFacet *> one_facet; 00652 DLIList <CubitFacetEdge *> facet_edges; 00653 FacetDataUtil::get_edges( facet_list, edge_list ); 00654 FacetDataUtil::get_points( facet_list, point_list ); 00655 00656 // determine average length and get the collapse threshold 00657 00658 int ii, jj, kk; 00659 double len; 00660 double tot_len = 0.0; 00661 for(ii=0; ii<point_list.size(); ii++) 00662 point_list.get_and_step()->marked(0); 00663 CubitFacetEdge *edge; 00664 for(ii=0; ii<edge_list.size(); ii++) 00665 { 00666 edge = edge_list.get_and_step(); 00667 len = edge->length(); 00668 tot_len += len; 00669 edge->marked(0); 00670 } 00671 len = tot_len / edge_list.size(); 00672 double collapse_tol = COLLAPSE_TOLERANCE * len; 00673 //check(edge_list, facet_list); 00674 00675 // get a list of the edges that qualify for collapse 00676 00677 DLIList<CubitFacetEdge *>short_edges; 00678 for(ii=0; ii<edge_list.size(); ii++) 00679 { 00680 edge = edge_list.get_and_step(); 00681 if (non_manifold_only && edge->num_adj_facets() == 2) 00682 continue; 00683 len = edge->length(); 00684 if (len < collapse_tol) 00685 { 00686 short_edges.append(edge); 00687 } 00688 } 00689 //sort them 00690 00691 short_edges.sort(FacetDataUtil::edge_compare); 00692 00693 // main loop 00694 00695 int nedges = short_edges.size(); 00696 for(ii=0; ii<nedges; ii++) 00697 { 00698 edge = short_edges.get_and_step(); 00699 if (edge->marked() == 1) 00700 continue; 00701 len = edge->length(); 00702 00703 bool collapse = true; 00704 CubitPoint *pt[2]; 00705 CubitPoint *pt1, *pt2; 00706 pt[0] = edge->point(0); 00707 pt[1] = edge->point(1); 00708 00709 // compute a new candidate location for the merged points 00710 00711 CubitVector new_location; 00712 CubitVector cpt[2]; 00713 cpt[0] = pt[0]->coordinates(); 00714 cpt[1] = pt[1]->coordinates(); 00715 new_location = (cpt[0] + cpt[1]) * 0.5; 00716 00717 for (jj=0; jj<2 && collapse; jj++) 00718 { 00719 DLIList<CubitFacet *> adjfacets; 00720 pt[jj]->facets( adjfacets ); 00721 00722 // check all facets adjacent this point that don't contain the edge 00723 // to make sure the resulting facet will be valid (we aren't inverting anything) 00724 00725 for(kk=0; kk<adjfacets.size() && collapse; kk++) 00726 { 00727 CubitFacet *facet = adjfacets.get_and_step(); 00728 pt1 = facet->next_node( pt[jj] ); 00729 pt2 = facet->next_node( pt1 ); 00730 int eidx = facet->edge_index( edge ); 00731 if (eidx < 0) 00732 // don't check facets that have the current edge - they'll be deleted anyway 00733 { 00734 00735 CubitVector cpt1 = pt1->coordinates(); 00736 CubitVector cpt2 = pt2->coordinates(); 00737 CubitVector norm = facet->normal(); 00738 double q0 = FacetDataUtil::quality(cpt[jj], cpt1, cpt2, norm); 00739 double q1 = FacetDataUtil::quality(new_location, cpt1, cpt2, norm); 00740 if (!(q1 > 0.0 || q1 > q0)) 00741 { 00742 collapse = false; 00743 } 00744 } 00745 } 00746 } 00747 00748 if (collapse) 00749 { 00750 DLIList<CubitFacet *> new_facets; 00751 CubitPoint *collpt = pt[0]; 00752 CubitPoint *delpt = pt[1]; 00753 DLIList<CubitFacetEdge *> adjedges; 00754 CubitFacetEdge *adjedge; 00755 delpt->edges( adjedges ); 00756 CubitFacet *facet; 00757 00758 00759 int mydebug = 0; 00760 if (mydebug) 00761 { 00762 dcolor(4); 00763 draw_edge( edge ); 00764 dview(); 00765 } 00766 00767 collpt->set(new_location); 00768 00769 // delete all facets adjacent to the delpt. 00770 00771 DLIList<CubitFacet *> adjfacets; 00772 delpt->facets( adjfacets ); 00773 00774 for(jj=0; jj<adjfacets.size(); jj++) 00775 { 00776 facet = adjfacets.get_and_step(); 00777 pt1 = facet->next_node(delpt); 00778 pt2 = facet->next_node(pt1); 00779 int eidx = facet->edge_index( edge ); 00780 facet_list.move_to(facet); 00781 delete facet; 00782 facet = NULL; 00783 if (eidx >= 0) 00784 { 00785 //if this facet is adjecnt the edge, then just remove it from the list 00786 facet_list.extract(); 00787 } 00788 else 00789 { 00790 00791 // get or create edges as needed 00792 00793 CubitFacetEdge *e[3]; 00794 e[0] = collpt->get_edge( pt1 ); 00795 e[1] = pt1->get_edge( pt2 ); 00796 e[2] = pt2->get_edge( collpt ); 00797 for (kk=0; kk<3; kk++) 00798 { 00799 if (!(e[kk])) 00800 { 00801 switch (kk) 00802 { 00803 case 0: e[kk] = (CubitFacetEdge *) new CubitFacetEdgeData( collpt, pt1 ); break; 00804 case 1: e[kk] = (CubitFacetEdge *) new CubitFacetEdgeData( pt1, pt2 ); break; 00805 case 2: e[kk] = (CubitFacetEdge *) new CubitFacetEdgeData( pt2, collpt ); break; 00806 } 00807 edge_list.append( e[kk] ); 00808 } 00809 } 00810 00811 // create a new facet with the points from the old facet and the collpt 00812 00813 facet = new CubitFacetData( e[0], e[1], e[2] ); 00814 new_facets.append(facet); 00815 00816 // create edges on the facet 00817 00818 facet_list.change_to( facet ); 00819 } 00820 } 00821 00822 for(jj=0; jj<adjedges.size(); jj++) 00823 { 00824 adjedge = adjedges.get_and_step(); 00825 adjedge->marked(1); // mark it for deletion later 00826 assert(adjedge->num_adj_facets() == 0); 00827 } 00828 assert(delpt->num_adj_facets() == 0); 00829 ncollapse++; 00830 00831 //check(edge_list, facet_list); 00832 } 00833 00834 } 00835 00836 PRINT_INFO("Collapsed %d short edges in triangulation\n", ncollapse); 00837 00838 // delete points and edges that aren't used 00839 if (ncollapse > 0) 00840 { 00841 for(ii=0; ii<edge_list.size(); ii++) 00842 { 00843 edge = edge_list.get_and_step(); 00844 if (edge->marked()) 00845 { 00846 assert(edge->num_adj_facets() == 0); 00847 delete edge; 00848 } 00849 else if(edge->num_adj_facets() < 2){ 00850 PRINT_ERROR("Unexpected result while collapsing an edge.\n"); 00851 return CUBIT_FAILURE; 00852 //assert(edge->num_adj_facets() >= 2); 00853 } 00854 } 00855 CubitPoint *point; 00856 for(ii=0; ii<point_list.size(); ii++) 00857 { 00858 point = point_list.get_and_step(); 00859 if (point->num_adj_facets() == 0) 00860 { 00861 delete point; 00862 } 00863 } 00864 } 00865 00866 return rv; 00867 } 00868 00869 //=========================================================================== 00870 // Function: check 00871 // Purpose: debugging only 00872 // Date: 10/2003 00873 // Author: sjowen 00874 //=========================================================================== 00875 void FacetDataUtil::check(DLIList<CubitFacetEdge *> &edge_list, 00876 DLIList<CubitFacet *> &facet_list) 00877 { 00878 00879 CubitBox box; 00880 CubitFacetEdge *edge; 00881 int ii; 00882 int nedges = 0; 00883 for(ii=0; ii<edge_list.size(); ii++) 00884 { 00885 edge = edge_list.get_and_step(); 00886 if (edge->marked() == 1) 00887 continue; 00888 int nadj = edge->num_adj_facets(); 00889 if (nadj <= 1) 00890 { 00891 CubitVector v0 = edge->point(0)->coordinates(); 00892 CubitVector v1 = edge->point(1)->coordinates(); 00893 CubitVector min(CUBIT_MIN(v0.x(), v1.x()), CUBIT_MIN(v0.y(), v1.y()), CUBIT_MIN(v0.z(), v1.z())); 00894 CubitVector max(CUBIT_MAX(v0.x(), v1.x()), CUBIT_MAX(v0.y(), v1.y()), CUBIT_MAX(v0.z(), v1.z())); 00895 CubitBox ebox(min, max); 00896 if (nedges == 0) 00897 box.reset(min, max); 00898 else 00899 box |= ebox; 00900 // dcolor(3); 00901 // dfldraw(facet_list); 00902 dcolor(4); 00903 dedraw(edge); 00904 dpoint(v0); 00905 dpoint(v1); 00906 nedges++; 00907 } 00908 } 00909 if (nedges > 0) 00910 { 00911 dzoom(box); 00912 dview(); 00913 } 00914 } 00915 00916 //=========================================================================== 00917 // Function: draw_edge 00918 // Purpose: 00919 // Date: 10/2003 00920 // Author: sjowen 00921 //=========================================================================== 00922 void FacetDataUtil::draw_edge( CubitFacetEdge *edge ) 00923 { 00924 DLIList<CubitFacet *>adjfacets; 00925 edge->facets( adjfacets ); 00926 int ii,jj; 00927 CubitFacet *facet; 00928 CubitBox box; 00929 for(jj=0; jj<2; jj++) 00930 { 00931 CubitPoint *p = edge->point(jj); 00932 adjfacets.clean_out(); 00933 p->facets( adjfacets ); 00934 for(ii=0; ii<adjfacets.size(); ii++) 00935 { 00936 facet = adjfacets.get_and_step(); 00937 if (jj==0 && ii==0) 00938 box = facet->bounding_box(); 00939 else 00940 box |= facet->bounding_box(); 00941 dfdraw(facet); 00942 } 00943 dpoint(p->coordinates()); 00944 dpoint(p->coordinates()); 00945 } 00946 dzoom(box); 00947 } 00948 00949 //============================================================================= 00950 //Function: is_point_in_polyhedron 00951 //Description: point-in-polyhedron test; polyhedron must be water-tight, 00952 // manifold, triangle-tiled. Casts a random ray in positive 00953 // x, y, and z. Counts crossings. Starts over with a recast 00954 // if a triangle is perpendicular to the ray or if the ray 00955 // hits a triangle edge or vertex. 00956 // Also tests for point on polyhedron. 00957 //Author: John Fowler 00958 //Date: 9/30/03 00959 //============================================================================= 00960 CubitStatus FacetDataUtil::is_point_in_polyhedron( 00961 DLIList<CubitFacet *> &tfacet_list, 00962 CubitVector &point_coords, 00963 CubitPointContainment &is_point_in) 00964 { 00965 unsigned int i; 00966 CubitBox bbox; 00967 CubitFacet *facet; 00968 CubitVector bbox_min, bbox_max, ray; 00969 CubitStatus status; 00970 CubitPointContainment pt_status; 00971 bool is_outside, recast, is_on_plane; 00972 double xpt, ypt, zpt; 00973 double rayx, rayy, rayz; 00974 int number_of_recasts; 00975 00976 point_coords.get_xyz(xpt, ypt, zpt); 00977 recast = true; 00978 number_of_recasts = 0; 00979 while ( (recast == true) && (number_of_recasts < 10) ) { 00980 recast = false; 00981 is_outside = true; 00982 random_positive_ray(ray); // a random positively-pointing ray 00983 ray.get_xyz(rayx,rayy,rayz); 00984 for ( i = tfacet_list.size(); i > 0; i-- ) { 00985 facet = tfacet_list.get_and_step(); 00986 bbox = facet->bounding_box(); 00987 bbox_min = bbox.minimum(); 00988 bbox_max = bbox.maximum(); 00989 // Because the ray is positive in direction, discard bounding boxes 00990 // that are entirely < the starting point. 00991 if ( (xpt-bbox_max.x()) > CUBIT_RESABS ) continue; 00992 if ( (ypt-bbox_max.y()) > CUBIT_RESABS ) continue; 00993 if ( (zpt-bbox_max.z()) > CUBIT_RESABS ) continue; 00994 if ( ray_intersects_boundingbox(point_coords,ray,bbox) == false ) 00995 continue; 00996 CubitPlane plane = facet->plane(); 00997 CubitVector normal = plane.normal(); 00998 double xnorm, ynorm, znorm; 00999 xnorm = normal.x(); 01000 ynorm = normal.y(); 01001 znorm = normal.z(); 01002 // Intersect the ray with the facet plane. If ray is perpendicular to 01003 // facet plane and point is on it, recast the ray and try again. 01004 double denominator = rayx*xnorm + rayy*ynorm + rayz*znorm; 01005 double distanc = xnorm*xpt + ynorm*ypt + znorm*zpt + plane.coefficient(); 01006 if ( fabs(denominator) < GEOMETRY_RESABS ) 01007 { 01008 if ( fabs(distanc) < GEOMETRY_RESABS ) { 01009 recast = true; 01010 break; 01011 } else continue; // point is not on plane and ray is parallel to plane 01012 } 01013 double t, xintpt, yintpt, zintpt; 01014 t = -distanc; 01015 t /= denominator; 01016 if ( fabs(t) < GEOMETRY_RESABS ) is_on_plane = true; 01017 else if ( t < GEOMETRY_RESABS ) continue; 01018 else is_on_plane = false; 01019 xintpt = xpt + t*rayx; 01020 yintpt = ypt + t*rayy; 01021 zintpt = zpt + t*rayz; 01022 CubitPoint *pt; 01023 // We need to project the triangle onto 2D. Use the smaller components of 01024 // the normal to detemine a good projection. 01025 double x0, y0, x1, y1, x2, y2; 01026 if ( (fabs(xnorm) >= fabs(ynorm)) && (fabs(xnorm) >= fabs(znorm)) ){ // Use y,z 01027 pt = facet->point(0); 01028 x0 = pt->y(); y0 = pt->z(); 01029 pt = facet->point(1); 01030 x1 = pt->y(); y1 = pt->z(); 01031 pt = facet->point(2); 01032 x2 = pt->y(); y2 = pt->z(); 01033 status = pt_in_tri_2d(yintpt,zintpt,x0,y0,x1,y1,x2,y2,pt_status); 01034 } else if (fabs(ynorm) >= fabs(znorm)) { // Use z,x 01035 pt = facet->point(0); 01036 x0 = pt->x(); y0 = pt->z(); 01037 pt = facet->point(1); 01038 x1 = pt->x(); y1 = pt->z(); 01039 pt = facet->point(2); 01040 x2 = pt->x(); y2 = pt->z(); 01041 status = pt_in_tri_2d(xintpt,zintpt,x0,y0,x1,y1,x2,y2,pt_status); 01042 } else { // Use x,y 01043 pt = facet->point(0); 01044 x0 = pt->x(); y0 = pt->y(); 01045 pt = facet->point(1); 01046 x1 = pt->x(); y1 = pt->y(); 01047 pt = facet->point(2); 01048 x2 = pt->x(); y2 = pt->y(); 01049 status = pt_in_tri_2d(xintpt,yintpt,x0,y0,x1,y1,x2,y2,pt_status); 01050 } 01051 01052 if ( status == CUBIT_FAILURE ) { 01053 recast = true; 01054 break; 01055 } 01056 if ( pt_status == CUBIT_PNT_OUTSIDE ) continue; 01057 // Is the point on the triangle? 01058 if ( is_on_plane == true ) { 01059 is_point_in = CUBIT_PNT_BOUNDARY; 01060 return CUBIT_SUCCESS; 01061 } 01062 if ( pt_status == CUBIT_PNT_INSIDE ) is_outside = ! is_outside; 01063 else if ( pt_status == CUBIT_PNT_BOUNDARY ) { 01064 recast = true; 01065 break; 01066 } 01067 } 01068 if ( recast == true ) { 01069 tfacet_list.reset(); 01070 number_of_recasts += 1; 01071 } 01072 } 01073 if ( recast == true ) { 01074 PRINT_ERROR("Number of recasts in point-in-polygon exceeded 10.\n"); 01075 return CUBIT_FAILURE; 01076 } 01077 if ( is_outside == false ) is_point_in = CUBIT_PNT_INSIDE; 01078 else is_point_in = CUBIT_PNT_OUTSIDE; 01079 01080 return CUBIT_SUCCESS; 01081 } 01082 01083 //=========================================================================== 01084 // Function: pt_in_tri_2d 01085 // Purpose: 01086 // Date: 10/2003 01087 // Author: John Fowler 01088 //=========================================================================== 01089 CubitStatus FacetDataUtil::pt_in_tri_2d(double xpt, double ypt, 01090 double x0, double y0, 01091 double x1, double y1, 01092 double x2, double y2, 01093 CubitPointContainment &is_point_in) 01094 { 01095 // From Schneider & Eberly, "Geometric Tools for COmputer Graphics", 01096 // Chap. 13.3.1. If triangle is needle-thin, CUBIT_FAILURE might be 01097 // returned, in wich case is_point_in is undefined. 01098 01099 double c0, c1, c2; 01100 double e0x, e1x, e2x, e0y, e1y, e2y; 01101 double n0x, n1x, n2x, n0y, n1y, n2y; 01102 double denom0, denom1, denom2; 01103 01104 e0x = x1 - x0; e0y = y1 - y0; 01105 e1x = x2 - x1; e1y = y2 - y1; 01106 e2x = x0 - x2; e2y = y0 - y2; 01107 n0x = e0y; n0y = -e0x; 01108 n1x = e1y; n1y = -e1x; 01109 n2x = e2y; n2y = -e2x; 01110 denom0 = n1x*e0x + n1y*e0y; 01111 if ( fabs(denom0) < CUBIT_RESABS ) { 01112 PRINT_ERROR("Failure in pt_in_tri_2d; needle-thin triangle encountered.\n"); 01113 return CUBIT_FAILURE; 01114 } 01115 denom1 = n2x*e1x + n2y*e1y; 01116 if ( fabs(denom1) < CUBIT_RESABS ) { 01117 PRINT_ERROR("Failure in pt_in_tri_2d; needle-thin triangle encountered.\n"); 01118 return CUBIT_FAILURE; 01119 } 01120 denom2 = n0x*e2x + n0y*e2y; 01121 if ( fabs(denom2) < CUBIT_RESABS ) { 01122 PRINT_ERROR("Failure in pt_in_tri_2d; needle-thin triangle encountered.\n"); 01123 return CUBIT_FAILURE; 01124 } 01125 01126 c0 = -( n1x*(xpt-x1) + n1y*(ypt-y1) )/denom0; 01127 c1 = -( n2x*(xpt-x2) + n2y*(ypt-y2) )/denom1; 01128 c2 = -( n0x*(xpt-x0) + n0y*(ypt-y0) )/denom2; 01129 01130 if ( (c0 > 0.0) && (c1 > 0.0) && (c2 > 0.0) ) is_point_in = CUBIT_PNT_INSIDE; 01131 else if ( (c0 < 0.0) || (c1 < 0.0) || (c2 < 0.0) ) is_point_in = CUBIT_PNT_OUTSIDE; 01132 else is_point_in = CUBIT_PNT_BOUNDARY; 01133 01134 return CUBIT_SUCCESS; 01135 01136 } 01137 01138 //=========================================================================== 01139 // Function: random_positive_ray 01140 // Purpose: 01141 // Date: 10/2003 01142 // Author: John Fowler 01143 //=========================================================================== 01144 void FacetDataUtil::random_positive_ray(CubitVector& ray) 01145 { 01146 double temp; 01147 double rayx = 0.0, rayy = 0.0, rayz = 0.0; 01148 01149 temp = 0.0; 01150 while ( temp < 1.e-6 ) { 01151 rayx = (double(rand())/(RAND_MAX+1.0)); 01152 rayy = (double(rand())/(RAND_MAX+1.0)); 01153 rayz = (double(rand())/(RAND_MAX+1.0)); 01154 temp = sqrt(rayx*rayx + rayy*rayy + rayz*rayz); 01155 } 01156 rayx /= temp; 01157 rayy /= temp; 01158 rayz /= temp; 01159 01160 ray.set(rayx,rayy,rayz); 01161 01162 } 01163 01164 //=========================================================================== 01165 // Function: ray_intersects_boundingbox 01166 // Purpose: 01167 // Date: 10/2003 01168 // Author: John Fowler 01169 //=========================================================================== 01170 bool FacetDataUtil::ray_intersects_boundingbox(CubitVector& point, CubitVector& ray, const CubitBox& bbox) 01171 { 01172 double t, xtest, ytest, ztest; 01173 double xdir, ydir, zdir, xpt, ypt, zpt, xmin, ymin, zmin, xmax, ymax, zmax; 01174 CubitVector bbox_min, bbox_max; 01175 01176 point.get_xyz(xpt,ypt,zpt); 01177 ray.get_xyz(xdir,ydir,zdir); 01178 bbox_min = bbox.minimum(); 01179 bbox_max = bbox.maximum(); 01180 bbox_min.get_xyz(xmin,ymin,zmin); 01181 bbox_max.get_xyz(xmax,ymax,zmax); 01182 xmin -= GEOMETRY_RESABS; // So we don't miss any. 01183 ymin -= GEOMETRY_RESABS; 01184 zmin -= GEOMETRY_RESABS; 01185 xmax += GEOMETRY_RESABS; 01186 ymax += GEOMETRY_RESABS; 01187 zmax += GEOMETRY_RESABS; 01188 01189 // Notice that we are only interested in bboxes on the non-negative side of t. 01190 if ( fabs(xdir) > CUBIT_RESABS ) { 01191 // test xmin plane 01192 t = (xmin - xpt)/xdir; 01193 if ( t >= 0.0 ) { 01194 ytest = ypt + t*ydir; 01195 ztest = zpt + t*zdir; 01196 if ( (ytest >= ymin) && (ytest <= ymax) && (ztest >= zmin) && (ztest <= zmax) ) 01197 return true; 01198 } 01199 // test xmax plane 01200 t = (xmax - xpt)/xdir; 01201 if ( t > 0.0 ) { 01202 ytest = ypt + t*ydir; 01203 ztest = zpt + t*zdir; 01204 if ( (ytest >= ymin) && (ytest <= ymax) && (ztest >= zmin) && (ztest <= zmax) ) 01205 return true; 01206 } 01207 } 01208 if ( fabs(ydir) > CUBIT_RESABS ) { 01209 // test ymin plane 01210 t = (ymin - ypt)/ydir; 01211 if ( t >= 0.0 ) { 01212 xtest = xpt + t*xdir; 01213 ztest = zpt + t*zdir; 01214 if ( (xtest >= xmin) && (xtest <= xmax) && (ztest >= zmin) && (ztest <= zmax) ) 01215 return true; 01216 } 01217 // test ymax plane 01218 01219 t = (ymax - ypt)/ydir; 01220 if ( t > 0.0 ) { 01221 xtest = xpt + t*xdir; 01222 ztest = zpt + t*zdir; 01223 if ( (xtest >= xmin) && (xtest <= xmax) && (ztest >= zmin) && (ztest <= zmax) ) 01224 return true; 01225 } 01226 } 01227 if ( fabs(zdir) > CUBIT_RESABS ) { 01228 // test zmin plane 01229 t = (zmin - zpt)/zdir; 01230 if ( t > 0.0 ) { 01231 xtest = xpt + t*xdir; 01232 ytest = ypt + t*ydir; 01233 if ( (xtest >= xmin) && (xtest <= xmax) && (ytest >= ymin) && (ytest <= ymax) ) 01234 return true; 01235 } 01236 // test zmax plane 01237 t = (zmax - zpt)/zdir; 01238 if ( t > 0.0 ) { 01239 xtest = xpt + t*xdir; 01240 ytest = ypt + t*ydir; 01241 if ( (xtest >= xmin) && (xtest <= xmax) && (ytest >= ymin) && (ytest <= ymax) ) 01242 return true; 01243 } 01244 } 01245 01246 return false; 01247 } 01248 01249 //=========================================================================== 01250 // Function: write_facets 01251 // Purpose: write a list of facets to a cubit facet file 01252 // Date: 11/28/2002 01253 // Author: sjowen 01254 //=========================================================================== 01255 CubitStatus FacetDataUtil::write_facets( const char *file_name, DLIList<CubitFacet *> &facet_list) 01256 { 01257 FILE *fp = fopen(file_name, "w"); 01258 if (!fp) 01259 { 01260 PRINT_ERROR("Couldn't open file %s for writing a facet file.\n", file_name); 01261 return CUBIT_FAILURE; 01262 } 01263 01264 DLIList<CubitPoint*> point_list; 01265 get_points(facet_list, point_list); 01266 01267 fprintf(fp, "%d %d\n", point_list.size(), facet_list.size()); 01268 CubitPoint *pt; 01269 int ii; 01270 for (ii=1; ii<=point_list.size(); ii++) 01271 { 01272 pt = point_list.get_and_step(); 01273 pt->set_id(ii); 01274 fprintf(fp, "%d %f %f %f\n", ii, pt->x(), pt->y(), pt->z() ); 01275 } 01276 01277 CubitFacet *facet; 01278 for (ii=1; ii<=facet_list.size(); ii++) 01279 { 01280 facet = facet_list.get_and_step(); 01281 fprintf(fp, "%d %d %d %d\n", ii, facet->point(0)->id(), 01282 facet->point(1)->id(), facet->point(2)->id()); 01283 } 01284 01285 fclose(fp); 01286 return CUBIT_SUCCESS; 01287 01288 } 01289 01290 //============================================================================= 01291 //Function: split_into_shells (PUBLIC) 01292 //Description: split this set of facets into multiple surfaces where there are 01293 // may be disjoint regions. 01294 //Author: sjowen 01295 //Date: 8/27/2003 01296 //============================================================================= 01297 CubitStatus FacetDataUtil::split_into_shells( 01298 DLIList<CubitFacet *> &tfacet_list, 01299 DLIList<CubitQuadFacet *> &qfacet_list, 01300 DLIList<DLIList<CubitFacet *> *> &shell_list, 01301 CubitBoolean &is_water_tight) 01302 { 01303 CubitStatus stat = CUBIT_SUCCESS; 01304 //need to init this variable otherwise the caller must have. 01305 is_water_tight = CUBIT_TRUE; 01306 01307 // combine the quads and tri lists 01308 01309 DLIList <CubitFacet *> facet_list = tfacet_list; 01310 int ii; 01311 CubitQuadFacet *qfacet_ptr; 01312 for (ii=0; ii<qfacet_list.size(); ii++) 01313 { 01314 qfacet_ptr = qfacet_list.get_and_step(); 01315 facet_list.append(qfacet_ptr->get_tri_facet( 0 )); 01316 facet_list.append(qfacet_ptr->get_tri_facet( 1 )); 01317 } 01318 01319 // mark all the facets to begin with 01320 01321 CubitFacet *facet_ptr; 01322 for (ii=0; ii<facet_list.size(); ii++) 01323 { 01324 facet_ptr = facet_list.get_and_step(); 01325 facet_ptr->marked( 1 ); 01326 } 01327 01328 // populate the facet edge lists 01329 01330 DLIList<CubitFacetEdge *> edge_list; 01331 FacetDataUtil::get_edges( facet_list, edge_list ); 01332 01333 // some debug stuff to draw the facets 01334 01335 int mydebug=0; 01336 if (mydebug) 01337 { 01338 for (ii=0; ii<facet_list.size(); ii++) 01339 { 01340 facet_ptr = facet_list.get_and_step(); 01341 GfxDebug::draw_facet(facet_ptr,CUBIT_YELLOW_INDEX); 01342 } 01343 GfxDebug::flush(); 01344 GfxDebug::mouse_xforms(); 01345 } 01346 01347 // Go through the surfaceElemList and pull facets off one by one as we 01348 // determine which surface it belongs to. Continue until we have depleted 01349 // the list 01350 01351 int jj; 01352 int num_surfs_created = 0; 01353 int num_facets_remaining = facet_list.size(); 01354 while( num_facets_remaining > 0) 01355 { 01356 // create a new shell to hold the face info 01357 01358 num_surfs_created++; 01359 DLIList<CubitFacet *> *shell_ptr = new DLIList<CubitFacet *>; 01360 01361 // start with the first facet and create a list of all elements 01362 // attached to the facet 01363 01364 CubitBoolean shell_is_water_tight = CUBIT_TRUE; 01365 CubitFacet *start_facet_ptr = facet_list.get_and_step(); 01366 stat = get_adj_facets_on_shell( start_facet_ptr, shell_ptr, 01367 shell_is_water_tight, mydebug ); 01368 if (stat != CUBIT_SUCCESS) 01369 return stat; 01370 if (!shell_is_water_tight) 01371 is_water_tight = CUBIT_FALSE; 01372 01373 shell_list.append( shell_ptr ); 01374 01375 // remove the facets in this shell from the facet list 01376 01377 for( jj = facet_list.size(); jj > 0; jj-- ) 01378 { 01379 facet_ptr = facet_list.get(); 01380 if (facet_ptr->marked() == 0) 01381 { 01382 facet_list.change_to( NULL ); 01383 } 01384 facet_list.step(); 01385 } 01386 facet_list.remove_all_with_value( NULL ); 01387 num_facets_remaining = facet_list.size(); 01388 } 01389 01390 return CUBIT_SUCCESS; 01391 } 01392 01393 //============================================================================= 01394 //Function: get_adj_facets_on_shell (PRIVATE) 01395 //Description: non recursive function that creates a list of all facets connected 01396 // the passed in face that are on the same surface 01397 //Author: sjowen 01398 //Date: 12/22/00 01399 //============================================================================= 01400 CubitStatus FacetDataUtil::get_adj_facets_on_shell( 01401 CubitFacet *start_facet_ptr, 01402 DLIList<CubitFacet *> *shell_ptr, 01403 CubitBoolean &is_water_tight, 01404 int mydebug) 01405 { 01406 int found = 0; 01407 int ii, jj; 01408 CubitStatus stat = CUBIT_SUCCESS; 01409 DLIList<CubitFacet*> temp_list; 01410 CubitFacet *facet_ptr = NULL; 01411 CubitFacet *adj_facet_ptr = NULL; 01412 DLIList<CubitFacetEdge *>edge_list; 01413 CubitFacetEdge *edge_ptr = NULL; 01414 DLIList<CubitFacet *>adj_facet_list; 01415 01416 // add this facet to the list 01417 01418 temp_list.append( start_facet_ptr ); 01419 start_facet_ptr->marked( 0 ); 01420 01421 while (temp_list.size()) 01422 { 01423 facet_ptr = temp_list.pop(); 01424 if (facet_ptr->marked() == 0) 01425 { 01426 shell_ptr->append( facet_ptr ); 01427 if (mydebug) 01428 { 01429 GfxDebug::draw_facet(facet_ptr, CUBIT_RED_INDEX); 01430 GfxDebug::flush(); 01431 } 01432 edge_list.clean_out(); 01433 facet_ptr->edges( edge_list ); 01434 for (ii=0; ii<edge_list.size(); ii++) 01435 { 01436 edge_ptr = edge_list.get_and_step(); 01437 adj_facet_list.clean_out(); 01438 edge_ptr->facets( adj_facet_list ); 01439 found = 0; 01440 01441 for (jj=0; jj<adj_facet_list.size() && !found; jj++) 01442 { 01443 adj_facet_ptr = adj_facet_list.get_and_step(); 01444 if (adj_facet_ptr != facet_ptr) 01445 { 01446 01447 // go to its neighbor if it is part of the surface 01448 01449 if (adj_facet_ptr->marked() == 1) 01450 { 01451 temp_list.append( adj_facet_ptr ); 01452 adj_facet_ptr->marked( 0 ); 01453 found = 1; 01454 } 01455 } 01456 01457 } 01458 if (is_water_tight && adj_facet_list.size() == 1) 01459 { 01460 is_water_tight = CUBIT_FALSE; 01461 } 01462 } 01463 } 01464 } 01465 01466 return stat; 01467 } 01468 01469 //============================================================================= 01470 //Function: stitch_facets (PRIVATE) 01471 //Description: attempt to merge facets to form a watertight model 01472 //Author: sjowen 01473 //Date: 9/9/03 01474 //============================================================================= 01475 CubitStatus FacetDataUtil::stitch_facets( 01476 DLIList<DLIList<CubitFacet *> *> &shell_list, 01477 double tol, 01478 CubitBoolean &is_water_tight, 01479 CubitBoolean write_result) 01480 { 01481 01482 CubitStatus rv = CUBIT_SUCCESS; 01483 int npmerge = 0; 01484 int nemerge = 0; 01485 DLIList<CubitPoint*> unmerged_points; 01486 is_water_tight = CUBIT_FALSE; 01487 01488 rv = merge_coincident_vertices( shell_list, tol, npmerge, nemerge, unmerged_points ); 01489 if (rv != CUBIT_SUCCESS) 01490 return rv; 01491 01492 int nnomerge = unmerged_points.size(); 01493 if (nnomerge == 0) 01494 { 01495 is_water_tight = CUBIT_TRUE; 01496 } 01497 else 01498 { 01499 rv = merge_colinear_vertices( shell_list, tol, unmerged_points, 01500 npmerge, nemerge, nnomerge ); 01501 if (rv != CUBIT_SUCCESS) 01502 return rv; 01503 01504 if (nnomerge == 0) 01505 { 01506 is_water_tight = CUBIT_TRUE; 01507 int mydebug = 0; 01508 if (mydebug) // make sure its really water-tight 01509 { 01510 DLIList<CubitFacet *> *shell_ptr; 01511 DLIList<CubitFacetEdge *>boundary_edges; 01512 for (int ii=0; ii<shell_list.size(); ii++) 01513 { 01514 shell_ptr = shell_list.get_and_step(); 01515 FacetDataUtil::get_boundary_edges(*shell_ptr, boundary_edges); 01516 } 01517 if (boundary_edges.size() > 0) 01518 { 01519 PRINT_ERROR("Not Water-tight!\n"); 01520 } 01521 } 01522 } 01523 } 01524 01525 if (write_result) 01526 { 01527 if (npmerge > 0 || nemerge > 0) 01528 { 01529 PRINT_INFO("%d facet vertices and %d facet edges were successfully merged.\n", 01530 npmerge, nemerge); 01531 } 01532 if (is_water_tight) 01533 { 01534 PRINT_INFO("Facets are water-tight.\n"); 01535 } 01536 else 01537 { 01538 PRINT_INFO("%d facet vertices on model boundary detected that could not be merged.\n", nnomerge); 01539 } 01540 } 01541 01542 return rv; 01543 } 01544 01545 //============================================================================= 01546 //Function: merge_colinear_vertices (PRIVATE) 01547 //Description: check if any vertices fall on a free facet edge. If so - split 01548 // the adjacent facet to merge 01549 //Author: sjowen 01550 //Date: 1/19/2004 01551 //============================================================================= 01552 CubitStatus FacetDataUtil::merge_colinear_vertices( 01553 DLIList<DLIList<CubitFacet *> *> &shell_list, 01554 double tol, 01555 DLIList<CubitPoint *> &merge_point_list, // points to attempt to merge 01556 int &npmerge, // return number of vertices merged 01557 int &nemerge, // return number of edges merged 01558 int &nnomerge) // return number of vertices in list NOT merged 01559 { 01560 nnomerge = 0; 01561 int mydebug = 0; 01562 01563 int ii, jj, kk, ll, mm, pt_shell_id, edge_shell_id; 01564 RTree <CubitFacetEdge*> r_tree(tol); 01565 shell_list.reset(); 01566 DLIList<CubitFacet *> *shell_ptr = NULL; 01567 CubitPoint *pt; 01568 CubitFacetEdge *edge; 01569 DLIList<CubitFacetEdge *>boundary_edges; 01570 for (ii=0; ii<shell_list.size(); ii++) 01571 { 01572 shell_ptr = shell_list.get_and_step(); 01573 01574 // get the boundary edges from the shell - these are candidates for merging. 01575 // note that this won't merge internal facets 01576 01577 DLIList<CubitFacetEdge *>shell_boundary_edges; 01578 FacetDataUtil::get_boundary_edges(*shell_ptr, shell_boundary_edges); 01579 01580 // mark each of the edges with a shell id so we know when to merge shells 01581 // and add them to the kdtree for fast spatial searching 01582 edge_shell_id = ii+1; 01583 for(jj=0; jj<shell_boundary_edges.size(); jj++) 01584 { 01585 edge = shell_boundary_edges.get_and_step(); 01586 edge->point(0)->marked(edge_shell_id); 01587 edge->point(1)->marked(edge_shell_id); 01588 edge->marked(edge_shell_id); 01589 r_tree.add(edge); 01590 boundary_edges.append(edge); 01591 } 01592 for(jj=0; jj<shell_ptr->size(); jj++) 01593 shell_ptr->get_and_step()->marked( edge_shell_id ); 01594 } 01595 01596 // find points in merge_point_list that are colinear with edges in boundary_edges 01597 01598 CubitBox ptbox; 01599 CubitVector ptmin, ptmax, coord; 01600 DLIList<CubitFacetEdge *>close_edges; 01601 CubitFacetEdge *close_edge; 01602 CubitFacet *facet; 01603 CubitPoint *p0, *p1; 01604 DLIList<CubitPoint*>adj_pt_list; 01605 DLIList<CubitPoint*>del_points; 01606 for(ii=0; ii<merge_point_list.size(); ii++) 01607 { 01608 pt = merge_point_list.get_and_step(); 01609 if (pt->marked() < 0) // has already been merged 01610 continue; 01611 01612 // find the closest edges in the rtree 01613 01614 coord = pt->coordinates(); 01615 ptmin.set( coord.x() - tol, coord.y() - tol, coord.z() - tol ); 01616 ptmax.set( coord.x() + tol, coord.y() + tol, coord.z() + tol ); 01617 ptbox.reset( ptmin, ptmax ); 01618 close_edges.clean_out(); 01619 r_tree.find(ptbox, close_edges); 01620 01621 01622 //remove any close edges that already share the merge point 01623 DLIList<CubitFacetEdge*> adj_edges; 01624 for (jj=close_edges.size(); jj--; ) 01625 { 01626 close_edge = close_edges.get(); 01627 01628 if (close_edge->point(0) == pt || close_edge->point(1) == pt) 01629 { 01630 close_edges.change_to( NULL ); 01631 adj_edges.append( close_edge ); 01632 } 01633 01634 close_edges.step(); 01635 } 01636 close_edges.remove_all_with_value( NULL ); 01637 01638 if( close_edges.size() == 0 && adj_edges.size() > 0 ) 01639 { 01640 //use a coareser tolerance to get some edges 01641 //one tenth the average length of attached edges 01642 double temp_tol = 0; 01643 for( int i=adj_edges.size(); i--; ) 01644 temp_tol += adj_edges.get_and_step()->length(); 01645 01646 temp_tol /= adj_edges.size(); 01647 temp_tol *= 0.1; 01648 01649 //bump up tolerance to get more edges 01650 ptmin.set( coord.x() - temp_tol, coord.y() - temp_tol, coord.z() - temp_tol ); 01651 ptmax.set( coord.x() + temp_tol, coord.y() + temp_tol, coord.z() + temp_tol ); 01652 ptbox.reset( ptmin, ptmax ); 01653 close_edges.clean_out(); 01654 r_tree.find(ptbox, close_edges); 01655 } 01656 01657 01658 // We did find something - go try to merge 01659 01660 CubitBoolean was_merged = CUBIT_FALSE; 01661 for (jj=0; jj<close_edges.size() && !was_merged; jj++) 01662 { 01663 // test the next edge on the list 01664 01665 close_edge = close_edges.get_and_step(); 01666 01667 // make sure the edge does not contain the merge point 01668 01669 if (close_edge->point(0) == pt || close_edge->point(1) == pt) 01670 continue; 01671 01672 // check to see if the edge is within tolerance of the merge point 01673 01674 CubitVector loc_on_edge; 01675 CubitBoolean is_outside_edge; 01676 double dist = close_edge->dist_to_edge(pt->coordinates(), 01677 loc_on_edge, is_outside_edge); 01678 01679 // allow for some surface curvature. permit the point to be close to 01680 // the edge but not on. May want to modify this factor if it not closing 01681 // the facets correctly. If it's too big, it may get edges that aren't 01682 // really adjacent. 01683 double edge_tol = 0.1 * close_edge->length(); 01684 if (is_outside_edge || dist > edge_tol) 01685 continue; 01686 01687 // go merge the point with the edge 01688 was_merged = CUBIT_TRUE; 01689 01690 if (mydebug) 01691 { 01692 DLIList<CubitFacet *> fl; 01693 pt->facets( fl ); 01694 dcolor(CUBIT_YELLOW_INDEX); 01695 dfldraw(fl); 01696 dcolor(CUBIT_BLUE_INDEX); 01697 dpoint(pt->coordinates()); 01698 CubitFacet *f = close_edge->adj_facet(0); 01699 dcolor(CUBIT_RED_INDEX); 01700 dfdraw(f); 01701 dview(); 01702 } 01703 01704 // remove close_edge from the rtree 01705 01706 r_tree.remove( close_edge ); 01707 edge_shell_id = close_edge->marked(); 01708 close_edge->marked(0); 01709 01710 // split the edge 01711 01712 assert(1 == close_edge->num_adj_facets()); // assumes we are splitting a boundary facet 01713 facet = close_edge->adj_facet(0); 01714 CubitFacetData *dfacet = dynamic_cast<CubitFacetData *>(facet); 01715 CubitPoint *new_pt = dfacet->split_edge(close_edge->point(0), 01716 close_edge->point(1), 01717 pt->coordinates()); 01718 int facet_tool_id = facet->tool_id(); 01719 new_pt->marked(edge_shell_id); 01720 01721 // add any new facets to the shell and create missing edges 01722 01723 for (ll=0; ll<edge_shell_id; ll++) 01724 shell_ptr = shell_list.get_and_step(); 01725 DLIList<CubitFacet *>adj_facets; 01726 new_pt->facets( adj_facets ); 01727 for (ll=0; ll<adj_facets.size(); ll++) 01728 { 01729 facet = adj_facets.get_and_step(); 01730 if (!facet->marked()) 01731 { 01732 facet->marked(edge_shell_id); 01733 shell_ptr->append(facet); 01734 for (mm=0; mm<3; mm++) { 01735 if (!(edge = facet->edge(mm))) 01736 { 01737 facet->get_edge_pts(mm, p0, p1); 01738 edge = (CubitFacetEdge *) new CubitFacetEdgeData( p0, p1 ); 01739 edge->marked( 0 ); 01740 } 01741 } 01742 facet->set_tool_id(facet_tool_id); 01743 } 01744 } 01745 01746 // merge the points, 01747 01748 merge_points( pt, new_pt, nemerge, &r_tree ); 01749 npmerge++; 01750 01751 // add any new edges to the rtree 01752 01753 DLIList<CubitFacetEdge *> adj_edges; 01754 pt->edges( adj_edges ); 01755 for (kk=0; kk<adj_edges.size(); kk++) 01756 { 01757 CubitFacetEdge *adj_edge = adj_edges.get_and_step(); 01758 if (!adj_edge->marked() && adj_edge->num_adj_facets() == 1) 01759 { 01760 adj_edge->marked(pt->marked()); 01761 r_tree.add(adj_edge); 01762 } 01763 } 01764 01765 // see if shells need to merge and then merge 01766 01767 pt_shell_id = pt->marked(); 01768 if (pt_shell_id != edge_shell_id) 01769 { 01770 01771 // get the shell containing the close point. Nullify the 01772 // pointer in the shell list and move all of its facets 01773 // to the other shell. 01774 01775 int delete_shell = edge_shell_id; 01776 DLIList<CubitFacet *> *delete_shell_ptr = NULL; 01777 shell_list.reset(); 01778 for (ll=0; ll<delete_shell; ll++) 01779 delete_shell_ptr = shell_list.get_and_step(); 01780 shell_list.back(); 01781 shell_list.change_to(NULL); 01782 01783 if(!delete_shell_ptr) 01784 return CUBIT_FAILURE; 01785 01786 // mark all the points on the delete_shell as now being part of 01787 // the other shell. 01788 01789 for(ll=0; ll<delete_shell_ptr->size(); ll++) 01790 { 01791 facet = delete_shell_ptr->get_and_step(); 01792 facet->marked( pt_shell_id ); 01793 facet->point( 0 )->marked( pt_shell_id ); 01794 facet->point( 1 )->marked( pt_shell_id ); 01795 facet->point( 2 )->marked( pt_shell_id ); 01796 facet->edge( 0 )->marked( pt_shell_id ); 01797 facet->edge( 1 )->marked( pt_shell_id ); 01798 facet->edge( 2 )->marked( pt_shell_id ); 01799 } 01800 01801 // append the two lists together 01802 01803 shell_list.reset(); 01804 for (ll=0; ll<pt_shell_id; ll++) 01805 shell_ptr = shell_list.get_and_step(); 01806 *shell_ptr += (*delete_shell_ptr); 01807 delete delete_shell_ptr; 01808 } 01809 01810 // set the marked flag to negative to indicate that it has been 01811 // merged and it needs to be deleted. 01812 01813 del_points.append(new_pt); 01814 new_pt->marked( -new_pt->marked() ); 01815 pt->marked( -pt->marked() ); 01816 } // close_edges 01817 01818 if (!was_merged) 01819 { 01820 nnomerge++; 01821 if (mydebug) 01822 { 01823 dcolor(CUBIT_BLUE_INDEX); 01824 dpdraw(pt); 01825 dcolor(CUBIT_RED_INDEX); 01826 CubitVector mmin(-1e10, -1e10, -1e10); 01827 CubitVector mmax(1e10, 1e10, 1e10); 01828 ptbox.reset(mmin, mmax); 01829 r_tree.find(ptbox, close_edges); 01830 for(int zz=0; zz<close_edges.size(); zz++) 01831 { 01832 edge = close_edges.get_and_step(); 01833 dedraw(edge); 01834 CubitVector loc_on_edge; 01835 CubitBoolean is_on_edge; 01836 double dist = edge->dist_to_edge(pt->coordinates(), loc_on_edge, is_on_edge); 01837 PRINT_INFO("edge %d dist = %f is_on_edge = %d\n", edge->id(), dist, is_on_edge); 01838 } 01839 dview(); 01840 } 01841 } 01842 } // merge_point_list 01843 01844 // compress the shell list 01845 01846 shell_list.remove_all_with_value(NULL); 01847 01848 // delete points that were merged 01849 01850 for (ii=0; ii<del_points.size(); ii++) 01851 { 01852 pt = del_points.get_and_step(); 01853 if (pt->marked() < 0) 01854 { 01855 assert( pt->num_adj_facets() == 0 ); 01856 delete pt; 01857 } 01858 } 01859 01860 return CUBIT_SUCCESS; 01861 } 01862 01863 //============================================================================= 01864 //Function: merge_points (PRIVATE) 01865 //Description: merge two cubit points where it has been determined that they 01866 // are coincident. Also handle merging their adjacent edges where 01867 // appropriate 01868 //Author: sjowen 01869 //Date: 1/19/2004 01870 //============================================================================= 01871 CubitStatus FacetDataUtil::merge_points( 01872 CubitPoint *pt0, CubitPoint *pt1, 01873 int &nemerge, RTree <CubitFacetEdge*> *r_tree) // number of edges we had to merge top do this 01874 { 01875 int mydebug = 0; 01876 01877 // merge the points 01878 pt0->merge_points( pt1, CUBIT_TRUE ); 01879 //pt0->set_as_feature(); 01880 01881 if (mydebug) 01882 { 01883 DLIList<CubitFacet *>adj_facets; 01884 pt0->facets( adj_facets ); 01885 dcolor(CUBIT_RED_INDEX); 01886 dfldraw(adj_facets); 01887 } 01888 01889 // merge edges 01890 01891 int ll, mm; 01892 bool edge_merged; 01893 do { 01894 edge_merged = false; 01895 CubitFacetEdge *edge, *other_edge; 01896 01897 DLIList<CubitFacetEdge *> adj_edges; 01898 pt0->edges( adj_edges ); 01899 for(ll=0; ll<adj_edges.size() && !edge_merged; ll++) 01900 { 01901 edge = adj_edges.get_and_step(); 01902 for(mm=0; mm<adj_edges.size() && !edge_merged; mm++) 01903 { 01904 other_edge = adj_edges.get_and_step(); 01905 if (other_edge != edge && 01906 edge->other_point(pt0) == other_edge->other_point(pt0)) 01907 { 01908 CubitFacetEdgeData *dedge = dynamic_cast<CubitFacetEdgeData*>(edge); 01909 CubitFacetEdgeData *dother_edge = dynamic_cast<CubitFacetEdgeData*>(other_edge); 01910 // mbrewer (11/16/2005 for Bug 5049) 01911 if(r_tree){ 01912 // r_tree->remove(dother_edge); 01913 CubitBoolean temp_bool = r_tree->remove(dother_edge); 01914 if(!temp_bool){ 01915 PRINT_DEBUG_139("FacetDataUtil: D_OTHER_EDGE did not exist in RTREE.\n"); 01916 } 01917 } 01918 if (dedge->merge_edges( dother_edge ) == CUBIT_SUCCESS) 01919 { 01920 nemerge++; 01921 edge_merged = true; 01922 dedge->set_as_feature(); 01923 } 01924 } 01925 } 01926 } 01927 } while (edge_merged); 01928 return CUBIT_SUCCESS; 01929 } 01930 01931 01932 CubitStatus FacetDataUtil::merge_coincident_vertices( DLIList<CubitPoint*> &points ) 01933 { 01934 points.reset(); 01935 CubitPoint *surviving_point = points.pop(); 01936 while( points.size() ) 01937 { 01938 int nemerge = 0; 01939 merge_points( surviving_point, points.pop(), nemerge ); 01940 } 01941 01942 return CUBIT_SUCCESS; 01943 } 01944 01945 01946 01947 //============================================================================= 01948 //Function: merge_coincident_vertices (PRIVATE) 01949 //Description: merge vertices (and connected facets and edges) if they are 01950 // within tolerance. 01951 //Author: sjowen 01952 //Date: 9/9/03 01953 //============================================================================= 01954 CubitStatus FacetDataUtil::merge_coincident_vertices( 01955 DLIList<DLIList<CubitFacet *> *> &shell_list, 01956 double tol, 01957 int &npmerge, // return number of vertices merged 01958 int &nemerge, // return number of edges merged 01959 DLIList<CubitPoint *> &unmerged_points) // return the vertices on boundary NOT merged 01960 { 01961 int mydebug = 0; 01962 npmerge = 0; 01963 nemerge = 0; 01964 int ii, jj, kk, ll, shell_id; 01965 KDDTree <CubitPoint*> kd_tree(tol, false); 01966 CubitPoint::set_box_tol( tol ); 01967 shell_list.reset(); 01968 DLIList<CubitFacet *> *shell_ptr = NULL; 01969 CubitPoint *pt; 01970 DLIList<CubitPoint *>boundary_points; 01971 DLIList<CubitPoint *> del_points; 01972 for (ii=0; ii<shell_list.size(); ii++) 01973 { 01974 shell_ptr = shell_list.get_and_step(); 01975 01976 // get the boundary points from the shell - these are candidates for merging. 01977 // note that this won't merge internal facets 01978 01979 DLIList<CubitPoint *>shell_boundary_points; 01980 FacetDataUtil::get_boundary_points(*shell_ptr, shell_boundary_points); 01981 01982 // mark each of the points with a shell id so we know when to merge shells 01983 // and add them to the kdtree for fast spatial searching 01984 01985 shell_id = ii+1; 01986 for(jj=0; jj<shell_boundary_points.size(); jj++) 01987 { 01988 pt = shell_boundary_points.get_and_step(); 01989 pt->marked(shell_id); 01990 kd_tree.add(pt); 01991 boundary_points.append(pt); 01992 } 01993 } 01994 kd_tree.balance(); 01995 01996 // find points that are coincident 01997 01998 CubitBox ptbox; 01999 CubitVector ptmin, ptmax, coord; 02000 DLIList<CubitPoint *>close_points; 02001 CubitPoint *close_pt = NULL; 02002 CubitFacet *facet; 02003 DLIList<CubitPoint*>adj_pt_list; 02004 02005 for(ii=0; ii<boundary_points.size(); ii++) 02006 { 02007 pt = boundary_points.get_and_step(); 02008 if (pt->marked() < 0) // has already been merged 02009 continue; 02010 02011 // find the closest points in the kdtree 02012 02013 coord = pt->coordinates(); 02014 ptmin.set( coord.x() - tol, coord.y() - tol, coord.z() - tol ); 02015 ptmax.set( coord.x() + tol, coord.y() + tol, coord.z() + tol ); 02016 ptbox.reset( ptmin, ptmax ); 02017 close_points.clean_out(); 02018 kd_tree.find(ptbox, close_points); 02019 02020 // if it didn't find anything to merge with, then we aren't water-tight 02021 02022 CubitBoolean was_merged = CUBIT_FALSE; 02023 02024 // We did find something - go try to merge 02025 02026 for (jj=0; jj<close_points.size(); jj++) 02027 { 02028 close_pt = close_points.get_and_step(); 02029 if (close_pt == pt) 02030 continue; 02031 if (close_pt->marked() < 0) // has already been merged 02032 continue; 02033 assert(close_points.size() >= 1); 02034 02035 // make sure this point is not already one of its neighbors 02036 // so we don't collapse a triangle 02037 02038 CubitBoolean is_adjacent = CUBIT_FALSE; 02039 adj_pt_list.clean_out(); 02040 close_pt->adjacent_points( adj_pt_list ); 02041 for (kk=0; kk<adj_pt_list.size() && !is_adjacent; kk++) 02042 { 02043 if (adj_pt_list.get_and_step() == pt) 02044 is_adjacent = CUBIT_TRUE; 02045 } 02046 if (!is_adjacent) 02047 { 02048 // merge the points 02049 02050 merge_points( pt, close_pt, nemerge ); 02051 npmerge++; 02052 was_merged = CUBIT_TRUE; 02053 02054 // see if shells need to merge and then merge 02055 02056 shell_id = pt->marked(); 02057 if (shell_id != close_pt->marked()) 02058 { 02059 02060 // get the shell containing the close point. Nullify the 02061 // pointer in the shell list and move all of its facets 02062 // to the other shell. 02063 02064 int delete_shell = close_pt->marked(); 02065 DLIList<CubitFacet *> *delete_shell_ptr = NULL; 02066 shell_list.reset(); 02067 for (ll=0; ll<delete_shell; ll++) 02068 delete_shell_ptr = shell_list.get_and_step(); 02069 shell_list.back(); 02070 shell_list.change_to(NULL); 02071 02072 // mark all the points on the delete_shell as now being part of 02073 // the other shell. 02074 02075 for(ll=0; ll<delete_shell_ptr->size(); ll++) 02076 { 02077 facet = delete_shell_ptr->get_and_step(); 02078 facet->point( 0 )->marked( shell_id ); 02079 facet->point( 1 )->marked( shell_id ); 02080 facet->point( 2 )->marked( shell_id ); 02081 } 02082 02083 // append the two lists together 02084 02085 shell_list.reset(); 02086 for (ll=0; ll<shell_id; ll++) 02087 shell_ptr = shell_list.get_and_step(); 02088 *shell_ptr += (*delete_shell_ptr); 02089 delete delete_shell_ptr; 02090 } 02091 02092 // set the marked flag to negative to indicate that it has been 02093 // merged and it need to be deleted. 02094 02095 if (close_pt->marked() > 0) 02096 close_pt->marked( -close_pt->marked() ); 02097 del_points.append( close_pt ); 02098 } 02099 } 02100 if (was_merged) 02101 { 02102 if (pt->marked() > 0) 02103 pt->marked( -pt->marked() ); 02104 } 02105 else 02106 { 02107 // check to see if it was already merged 02108 if (close_points.size() == 1 && close_pt == pt) 02109 { 02110 CubitFacetEdge *edge_ptr; 02111 DLIList<CubitFacetEdge *>adj_edges; 02112 pt->edges(adj_edges); 02113 CubitBoolean on_boundary = CUBIT_FALSE; 02114 for(kk=0; kk<adj_edges.size() && !on_boundary; kk++) 02115 { 02116 edge_ptr = adj_edges.get_and_step(); 02117 if (edge_ptr->num_adj_facets() == 1) 02118 on_boundary = CUBIT_TRUE; 02119 } 02120 if (on_boundary) 02121 { 02122 //PRINT_INFO("Merging 'boundary' points.\n"); 02123 //if (pt->marked() > 0) pt->marked( -pt->marked() ); 02124 unmerged_points.append(pt); 02125 } 02126 else 02127 { 02128 if (pt->marked() > 0) pt->marked( -pt->marked() ); 02129 } 02130 } 02131 else 02132 { 02133 // otherwise save it as an unmerged point to be handled later 02134 unmerged_points.append(pt); 02135 } 02136 } 02137 } 02138 02139 // compress the shell list 02140 02141 shell_list.remove_all_with_value(NULL); 02142 02143 // delete points that were merged 02144 02145 for (ii=0; ii<del_points.size(); ii++) 02146 { 02147 pt = del_points.get_and_step(); 02148 if (pt->marked() < 0) 02149 { 02150 assert( pt->num_adj_facets() == 0 ); 02151 delete pt; 02152 } 02153 } 02154 02155 //double-check that these are still boundary points. 02156 //found case where two shells were tied together by a single facet point. 02157 //this point was initially deemed an unmerged boundary point but later 02158 //adjacent boundary edges got merged so it should not be a boundary 02159 //point anymore. 02160 for( int k=0; k<unmerged_points.size(); k++ ) 02161 { 02162 DLIList<CubitFacetEdge *>adj_edges; 02163 unmerged_points[k]->edges(adj_edges); 02164 CubitBoolean on_boundary = CUBIT_FALSE; 02165 for(kk=0; kk<adj_edges.size(); kk++) 02166 { 02167 CubitFacetEdge *edge_ptr = adj_edges.get_and_step(); 02168 if (edge_ptr->num_adj_facets() == 1) 02169 { 02170 on_boundary = CUBIT_TRUE; 02171 break; 02172 } 02173 } 02174 if( CUBIT_FALSE == on_boundary ) 02175 unmerged_points[k] = NULL; 02176 } 02177 unmerged_points.remove_all_with_value(NULL); 02178 02179 if (mydebug) 02180 { 02181 CubitFacetEdge *edge; 02182 for (ii=0; ii<shell_list.size(); ii++) 02183 { 02184 shell_ptr = shell_list.get_and_step(); 02185 dcolor(CUBIT_GREEN_INDEX); 02186 dfldraw(*shell_ptr); 02187 dcolor(CUBIT_RED_INDEX); 02188 for(jj=0; jj<shell_ptr->size(); jj++) 02189 { 02190 facet = shell_ptr->get_and_step(); 02191 for(kk=0; kk<3; kk++) 02192 { 02193 edge = facet->edge(kk); 02194 DLIList<FacetEntity *> myfacet_list; 02195 edge->get_parents( myfacet_list ); 02196 assert(myfacet_list.size() == edge->num_adj_facets()); 02197 if (myfacet_list.size() != 2) 02198 { 02199 dedraw( edge ); 02200 } 02201 } 02202 } 02203 } 02204 dcolor(CUBIT_BLUE_INDEX); 02205 dpldraw(unmerged_points); 02206 dview(); 02207 } 02208 02209 return CUBIT_SUCCESS; 02210 02211 } 02212 02213 //============================================================================= 02214 //Function: delete_facets (PUBLIC) 02215 //Description: delete the facets and all associated edges and points from 02216 // a list of lists of facets (shell_list) 02217 //Author: sjowen 02218 //Date: 1/21/2004 02219 //============================================================================= 02220 void FacetDataUtil::delete_facets(DLIList<DLIList<CubitFacet*>*> &shell_list) 02221 { 02222 int ii; 02223 for (ii=0; ii<shell_list.size(); ii++) 02224 { 02225 DLIList<CubitFacet*> *facet_list_ptr = shell_list.get_and_step(); 02226 delete_facets( *facet_list_ptr ); 02227 } 02228 } 02229 02230 //============================================================================= 02231 //Function: delete_facets (PUBLIC) 02232 //Description: delete the facets and all associated edges and points from 02233 // a list of facets 02234 //Author: sjowen 02235 //Date: 1/21/2004 02236 //============================================================================= 02237 void FacetDataUtil::delete_facets(DLIList<CubitFacet*> &facet_list) 02238 { 02239 int ii; 02240 CubitFacet *facet_ptr; 02241 for (ii=0; ii<facet_list.size(); ii++) 02242 { 02243 facet_ptr = facet_list.get_and_step(); 02244 delete_facet( facet_ptr ); 02245 } 02246 } 02247 02248 //============================================================================= 02249 //Function: delete_facet (PUBLIC) 02250 //Description: delete a single facet and its underlying edges and points if 02251 // they are no longer attached to anything 02252 //Author: sjowen 02253 //Date: 1/21/2004 02254 //============================================================================= 02255 void FacetDataUtil::delete_facet(CubitFacet *facet_ptr) 02256 { 02257 DLIList<CubitPoint *>point_list; 02258 DLIList<CubitFacetEdge *>edge_list; 02259 facet_ptr->points(point_list); 02260 facet_ptr->edges(edge_list); 02261 02262 delete facet_ptr; 02263 02264 CubitFacetEdge *edge_ptr; 02265 CubitPoint *point_ptr; 02266 int ii; 02267 02268 for (ii=0; ii<edge_list.size(); ii++) 02269 { 02270 edge_ptr = edge_list.get_and_step(); 02271 if (edge_ptr->num_adj_facets() == 0) 02272 delete edge_ptr; 02273 } 02274 02275 for (ii=0; ii<3; ii++) 02276 { 02277 point_ptr = point_list.get_and_step(); 02278 if (point_ptr->num_adj_facets() == 0) 02279 delete point_ptr; 02280 } 02281 02282 } 02283 02284 02285 void FacetDataUtil::destruct_facet_no_delete(CubitFacet *facet_ptr) 02286 { 02287 CubitFacetData* facet_d_ptr = dynamic_cast<CubitFacetData*>(facet_ptr); 02288 if(!facet_d_ptr){ 02289 PRINT_ERROR("Can't work with Facet pointer that isn't a facet data object.\n"); 02290 return; 02291 } 02292 02293 DLIList<CubitPoint *>point_list; 02294 DLIList<CubitFacetEdge *>edge_list; 02295 facet_ptr->points(point_list); 02296 facet_ptr->edges(edge_list); 02297 02298 facet_d_ptr->destruct_facet_internals(); 02299 02300 CubitFacetEdge *edge_ptr; 02301 CubitPoint *point_ptr; 02302 int ii; 02303 02304 for (ii=0; ii<edge_list.size(); ii++) 02305 { 02306 edge_ptr = edge_list.get_and_step(); 02307 if (edge_ptr->num_adj_facets() == 0) 02308 delete edge_ptr; 02309 } 02310 02311 for (ii=0; ii<3; ii++) 02312 { 02313 point_ptr = point_list.get_and_step(); 02314 if (point_ptr->num_adj_facets() == 0) 02315 delete point_ptr; 02316 } 02317 02318 } 02319 02320 //============================================================================= 02321 //Function: intersect_facet (PUBLIC) 02322 //Description: determine intersection of a segment with a facet 02323 // returns CUBIT_PNT_UNKNOWN: if segment is in plane of facet 02324 // CUBIT_PNT_OUTSIDE: if segment does not intersect 02325 // CUBIT_PNT_INSIDE: if segment intersects inside facet 02326 // CUBIT_PNT_BOUNDARY: if segment intersects a vertex or edge 02327 //Author: sjowen 02328 //Date: 1/30/2004 02329 //============================================================================= 02330 CubitPointContainment FacetDataUtil::intersect_facet( 02331 CubitVector &start, CubitVector &end, // start and end points of vector 02332 CubitFacet *facet_ptr, // the facet to intersect 02333 CubitVector &qq, // return the intersection point 02334 CubitVector &ac, // area coordinates of qq if is in or on facet 02335 CubitBoolean bound) // if true, only check for intersections between the end points. 02336 { 02337 02338 CubitPlane fplane = facet_ptr->plane(); 02339 double dstart = fplane.distance(start); 02340 double dend = fplane.distance(end); 02341 02342 // points are both in the plane of the facet - can't handle this case 02343 02344 if (fabs(dstart) < GEOMETRY_RESABS && 02345 fabs(dend) < GEOMETRY_RESABS) 02346 { 02347 return CUBIT_PNT_UNKNOWN; 02348 } 02349 02350 // one point is on the plane 02351 02352 if (fabs(dstart) < GEOMETRY_RESABS) 02353 { 02354 qq = start; 02355 } 02356 else if (fabs(dend) < GEOMETRY_RESABS) 02357 { 02358 qq = end; 02359 } 02360 02361 // points are both on the same side of the plane 02362 else if(dstart*dend > 0.0 && 02363 (bound || fabs(dstart-dend) < CUBIT_RESABS) ) 02364 { 02365 return CUBIT_PNT_OUTSIDE; 02366 } 02367 // points are on opposite sides of plane: if bound == false then compute intersection with plane 02368 02369 else 02370 { 02371 CubitVector dir = end-start; 02372 dir.normalize(); 02373 qq = fplane.intersect(start, dir); 02374 } 02375 02376 FacetEvalTool::facet_area_coordinate( facet_ptr, qq, ac ); 02377 02378 //mod mbrewer ... the original code would call a point 02379 // on the boundary if any area coordinate was near 02380 // zero, regardless of whether another area coordinate 02381 // was negative... making it outside. 02382 // if (fabs(ac.x()) < GEOMETRY_RESABS || 02383 // fabs(ac.y()) < GEOMETRY_RESABS || 02384 // fabs(ac.z()) < GEOMETRY_RESABS) 02385 // { 02386 // return CUBIT_PNT_BOUNDARY; 02387 // } 02388 if ( (fabs(ac.x()) < GEOMETRY_RESABS && (ac.y() > -GEOMETRY_RESABS && 02389 ac.z() > -GEOMETRY_RESABS) )|| 02390 (fabs(ac.y()) < GEOMETRY_RESABS && (ac.x() > -GEOMETRY_RESABS && 02391 ac.z() > -GEOMETRY_RESABS) )|| 02392 (fabs(ac.z()) < GEOMETRY_RESABS && (ac.x() > -GEOMETRY_RESABS && 02393 ac.y() > -GEOMETRY_RESABS) ) ){ 02394 return CUBIT_PNT_BOUNDARY; 02395 } 02396 else if (ac.x() < 0.0 || ac.y() < 0.0 || ac.z() < 0.0) 02397 { 02398 return CUBIT_PNT_OUTSIDE; 02399 } 02400 02401 return CUBIT_PNT_INSIDE; 02402 } 02403 02404 02405 //============================================================================= 02406 //Function: get_bbox_of_points (PUBLIC) 02407 //Description: Find the bounding box of a list of CubitPoints 02408 //Author: jdfowle 02409 //Date: 12/15/03 02410 //============================================================================= 02411 CubitStatus FacetDataUtil::get_bbox_of_points(DLIList<CubitPoint*>& point_list, CubitBox& bbox) 02412 { 02413 double x, y, z, min[3], max[3]; 02414 int i; 02415 CubitPoint *point; 02416 min[0] = min[1] = min[2] = CUBIT_DBL_MAX; 02417 max[0] = max[1] = max[2] = -CUBIT_DBL_MAX + 1.; 02418 02419 for ( i = 0; i < point_list.size(); i++ ) { 02420 point = point_list.get_and_step(); 02421 x = point->x(); 02422 if ( min[0] > x ) min[0] = x; 02423 if ( max[0] < x ) max[0] = x; 02424 y = point->y(); 02425 if ( min[1] > y ) min[1] = y; 02426 if ( max[1] < y ) max[1] = y; 02427 z = point->z(); 02428 if ( min[2] > z ) min[2] = z; 02429 if ( max[2] < z ) max[2] = z; 02430 } 02431 bbox.reset(min,max); 02432 02433 return CUBIT_SUCCESS; 02434 } 02435 02436 //============================================================================= 02437 //Function: squared_distance_to_segment (PUBLIC) 02438 //Description: get square of distance from point to closest point on a line segment; 02439 // returns closest point. Taken from "Geometric Tools for Computer Graphics", 02440 // by Schneider & Eberly, sec. 6.1. 02441 //Author: jdfowle 02442 //Date: 03/08/03 02443 //============================================================================= 02444 CubitVector FacetDataUtil::squared_distance_to_segment(CubitVector &p, CubitVector &p0, 02445 CubitVector &p1, double &distance2) 02446 { 02447 CubitVector YmPO, D; 02448 double t; 02449 02450 D = p1 - p0; 02451 YmPO = p - p0; 02452 t = D.x()*YmPO.x() + D.y()*YmPO.y() + D.z()*YmPO.z(); 02453 02454 if ( t < 0.0 ) { 02455 distance2 = YmPO.x()*YmPO.x() + YmPO.y()*YmPO.y() + YmPO.z()*YmPO.z(); 02456 return p0; 02457 } 02458 02459 double DdD; 02460 DdD = D.x()*D.x() + D.y()*D.y() + D.z()*D.z(); 02461 if ( t >= DdD ) { 02462 CubitVector YmP1; 02463 YmP1 = p - p1; 02464 distance2 = YmP1.x()*YmP1.x() + YmP1.y()*YmP1.y() + YmP1.z()*YmP1.z(); 02465 return p1; 02466 } 02467 02468 // closest point is interior to segment 02469 distance2 = YmPO.x()*YmPO.x() + YmPO.y()*YmPO.y() + YmPO.z()*YmPO.z() - t*t/DdD; 02470 return p0 + (t/DdD)*(p1 - p0); 02471 } 02472 02473 //============================================================================= 02474 //Function: get_bbox_intersections (PUBLIC) 02475 //Description: Get the intersection of the line defined by point1 and point2 with 02476 //bbox. Returns 0,1 or 2 for the number of intersections. A line 02477 //in one of the planes of the box will return 0. Returns -1 for failure. 02478 //Author mborden 02479 //Date: 04/05/07 02480 //============================================================================= 02481 int FacetDataUtil::get_bbox_intersections(CubitVector& point1, 02482 CubitVector& point2, 02483 const CubitBox& bbox, 02484 CubitVector& intersection_1, 02485 CubitVector& intersection_2) 02486 { 02487 int debug = 0; 02488 if( debug ) 02489 { 02490 GfxDebug::draw_point( point1, CUBIT_RED_INDEX ); 02491 GfxDebug::draw_point( point2, CUBIT_BLUE_INDEX ); 02492 GfxDebug::flush(); 02493 } 02494 02495 double coords[6]; 02496 coords[0] = bbox.min_x(); 02497 coords[1] = bbox.max_x(); 02498 coords[2] = bbox.min_y(); 02499 coords[3] = bbox.max_y(); 02500 coords[4] = bbox.min_z(); 02501 coords[5] = bbox.max_z(); 02502 02503 DLIList<CubitVector*> intersections; 02504 02505 int ii; 02506 for( ii = 0; ii < 3; ii++ ) 02507 { 02508 //Define four points for each plane. 02509 double box_points[4][3]; 02510 02511 //ii = 0 -> x-planes 02512 //ii = 1 -> y_planes 02513 //ii = 2 -> z_planes 02514 02515 //Only the coordinates for the plane we are in 02516 //change. The other two are constant for the 02517 //jj loops below. 02518 box_points[0][(ii + 1) % 3] = coords[((ii*2)+2) % 6]; 02519 box_points[1][(ii + 1) % 3] = coords[((ii*2)+3) % 6]; 02520 box_points[2][(ii + 1) % 3] = coords[((ii*2)+3) % 6]; 02521 box_points[3][(ii + 1) % 3] = coords[((ii*2)+2) % 6]; 02522 02523 box_points[0][(ii + 2) % 3] = coords[((ii*2)+4) % 6]; 02524 box_points[1][(ii + 2) % 3] = coords[((ii*2)+4) % 6]; 02525 box_points[2][(ii + 2) % 3] = coords[((ii*2)+5) % 6]; 02526 box_points[3][(ii + 2) % 3] = coords[((ii*2)+5) % 6]; 02527 02528 int jj; 02529 for( jj = 0; jj < 2; jj++ ) 02530 { 02531 CubitPoint* points[4]; 02532 int kk; 02533 for( kk = 0; kk < 4; kk++ ) 02534 { 02535 box_points[kk][ii] = coords[(ii*2)+jj]; 02536 points[kk] = new CubitPointData( box_points[kk][0], box_points[kk][1], box_points[kk][2] ); 02537 } 02538 02539 //Create two facets for this plane to check for intersections. 02540 CubitFacet* facets[2]; 02541 facets[0] = new CubitFacetData( points[0], points[1], points[3] ); 02542 facets[1] = new CubitFacetData( points[1], points[2], points[3] ); 02543 02544 for( kk = 0; kk < 2; kk++ ) 02545 { 02546 CubitVector intersection; 02547 CubitVector area_coord; 02548 02549 //Make sure the points are not parrellel with the facet. 02550 CubitVector dir = point2 - point1; 02551 CubitVector normal = facets[kk]->normal(); 02552 if( fabs(dir % normal) < CUBIT_RESABS ) 02553 continue; 02554 02555 CubitPointContainment contain = intersect_facet( point1, point2, facets[kk], 02556 intersection, area_coord, CUBIT_FALSE ); 02557 if( CUBIT_PNT_UNKNOWN == contain ) 02558 { 02559 //The points are in a plane. Return 0. 02560 delete facets[0]; 02561 delete facets[1]; 02562 int ll; 02563 for( ll = 0; ll < 4; ll++ ) 02564 delete points[ll]; 02565 for( ll = intersections.size(); ll > 0; ll-- ) 02566 delete intersections.get_and_step(); 02567 02568 return 0; 02569 } 02570 if( CUBIT_PNT_BOUNDARY == contain || 02571 CUBIT_PNT_INSIDE == contain ) 02572 { 02573 //The point intersects the facet so it's inside the box's surface. 02574 CubitVector* new_intersection = new CubitVector; 02575 *new_intersection = intersection; 02576 intersections.append( new_intersection ); 02577 02578 if( debug ) 02579 { 02580 GfxDebug::draw_point( *new_intersection, CUBIT_CYAN_INDEX ); 02581 GfxDebug::flush(); 02582 } 02583 02584 break; 02585 } 02586 } 02587 02588 delete facets[0]; 02589 delete facets[1]; 02590 for( kk = 0; kk < 4; kk++ ) 02591 delete points[kk]; 02592 } 02593 } 02594 02595 //Check for duplicate intersections. 02596 intersections.reset(); 02597 for( ii = 0; ii < intersections.size(); ii++ ) 02598 { 02599 CubitVector* base_vec = intersections.next(ii); 02600 if( NULL == base_vec ) 02601 continue; 02602 02603 int jj; 02604 for( jj = ii+1; jj < intersections.size(); jj++ ) 02605 { 02606 CubitVector* compare_vec = intersections.next(jj); 02607 if( NULL != compare_vec ) 02608 { 02609 if( base_vec->distance_between_squared( *compare_vec ) < GEOMETRY_RESABS * GEOMETRY_RESABS ) 02610 { 02611 intersections.step(jj); 02612 delete intersections.get(); 02613 intersections.change_to( NULL ); 02614 intersections.reset(); 02615 } 02616 } 02617 } 02618 } 02619 intersections.remove_all_with_value( NULL ); 02620 02621 02622 if( intersections.size() > 2 ) 02623 { 02624 assert( intersections.size() <= 2 ); 02625 return -1; 02626 } 02627 else if( intersections.size() > 0 ) 02628 { 02629 intersection_1 = *intersections.get(); 02630 if( intersections.size() > 1 ) 02631 intersection_2 = *intersections.next(); 02632 } 02633 02634 //Delete memory. 02635 for( ii = intersections.size(); ii > 0; ii-- ) 02636 delete intersections.get_and_step(); 02637 02638 return intersections.size(); 02639 } 02640 02641 02642 //============================================================================= 02643 //Function: mark_facets (PUBLIC) 02644 //Description: mark facets and their children. assumes facets have points and edges 02645 //Author sjowen 02646 //Date: 09/18/09 02647 //============================================================================= 02648 void FacetDataUtil::mark_facets( DLIList<FacetEntity *> &facet_list, int mark_value ) 02649 { 02650 int ifacet; 02651 FacetEntity *facet_ptr; 02652 for (ifacet = 0; ifacet<facet_list.size(); ifacet++ ) 02653 { 02654 facet_ptr = facet_list.get_and_step(); 02655 CubitFacet *cfacet_ptr = dynamic_cast<CubitFacet *> (facet_ptr); 02656 if( cfacet_ptr ) 02657 { 02658 cfacet_ptr->marked(mark_value); 02659 for (int ii=0; ii<3; ii++) 02660 { 02661 cfacet_ptr->point(ii)->marked(mark_value); 02662 cfacet_ptr->edge(ii)->marked(mark_value); 02663 } 02664 } 02665 else 02666 { 02667 CubitFacetEdge *edge_ptr = dynamic_cast<CubitFacetEdge*>(facet_ptr); 02668 if( edge_ptr ) 02669 { 02670 edge_ptr->marked(mark_value); 02671 for (int ii=0; ii<2; ii++) 02672 edge_ptr->point(ii)->marked(mark_value); 02673 } 02674 } 02675 } 02676 } 02677 02678 //================================================================================== 02679 // Description: identifies all the facets that contain given two cubit points 02680 // 02681 // 02682 // Notes: 02683 // Author: william roshan quadros 02684 // Date: 3/30/2011 02685 //=================================================================================== 02686 CubitStatus FacetDataUtil::find_facet( DLIList<CubitFacet *> temp_split_facets, CubitPoint *pnt0, CubitPoint *pnt1, DLIList<CubitFacet *> &select_facets ) 02687 { 02688 int i; 02689 CubitFacet *ptr_facet; 02690 for( i = 0; i < temp_split_facets.size(); i++ ) 02691 { 02692 ptr_facet = temp_split_facets.get_and_step(); 02693 02694 if( ptr_facet->contains( pnt0 ) && ptr_facet->contains( pnt1 ) ) 02695 { 02696 select_facets.append( ptr_facet); 02697 } 02698 } 02699 02700 if( select_facets.size() ) 02701 return CUBIT_SUCCESS; 02702 else 02703 return CUBIT_FAILURE; 02704 } 02705 02706 02707