cgma
|
00001 //------------------------------------------------------------------------- 00002 // Filename : GeometryUtil.cc 00003 // 00004 // Purpose : 00005 // 00006 // Special Notes : 00007 // 00008 // Creator : Jason Kraftcheck 00009 // 00010 // Creation Date : 08/03/98 00011 //------------------------------------------------------------------------- 00012 #define COMPSURF_KEEP_CPT_STATS 00013 00014 #include "GeometryUtil.hpp" 00015 #include "GeometryQueryEngine.hpp" 00016 00017 #include "CubitUtil.hpp" 00018 #include "CubitString.hpp" 00019 #include "CubitVector.hpp" 00020 00021 #include "BodySM.hpp" 00022 #include "Lump.hpp" 00023 #include "ShellSM.hpp" 00024 #include "Surface.hpp" 00025 #include "LoopSM.hpp" 00026 #include "CoEdgeSM.hpp" 00027 #include "Curve.hpp" 00028 #include "Point.hpp" 00029 00030 #include "RefVolume.hpp" 00031 #include "RefFace.hpp" 00032 #include "RefEdge.hpp" 00033 #include "RefVertex.hpp" 00034 00035 #include "Body.hpp" 00036 #include "Shell.hpp" 00037 #include "Loop.hpp" 00038 #include "CoFace.hpp" 00039 #include "CoEdge.hpp" 00040 #include "Chain.hpp" 00041 #include "CoVertex.hpp" 00042 00043 #include "DLIList.hpp" 00044 00045 #include "CpuTimer.hpp" 00046 #include "GfxDebug.hpp" 00047 00048 GeometryUtil* GeometryUtil::instance_ = NULL; 00049 00050 00051 00052 //------------------------------------------------------------------------- 00053 // Purpose : Test if a point lies within a loop. 00054 // 00055 // Special Notes : Uses loop angle metric. 00056 // 00057 // Creator : Jason Kraftcheck 00058 // 00059 // Creation Date : 08/04/98 00060 //------------------------------------------------------------------------- 00061 CubitBoolean GeometryUtil::is_position_within_loop( 00062 const CubitVector& position, 00063 Loop* loop_ptr, 00064 CubitVector* closest_on_loop, 00065 CubitVector* passed_normal ) 00066 { 00067 CubitVector surf_point, normal, pt_on_curve; 00068 if( passed_normal ) 00069 { 00070 surf_point = position; 00071 normal = *passed_normal; 00072 } 00073 else 00074 { 00075 loop_ptr->get_ref_face_ptr()->get_surface_ptr()-> 00076 closest_point( position, &surf_point, &normal ); 00077 } 00078 00079 CoEdge* other_coedge = 0; 00080 CoEdge* closest_coedge = 00081 closest_loop_coedge( loop_ptr, position, other_coedge, &pt_on_curve ); 00082 //If we got back NULL, either the loop has no CoEdges, or all Curves 00083 //occur multiple times. 00084 if( !closest_coedge ) return CUBIT_TRUE; 00085 00086 if( closest_on_loop ) *closest_on_loop = pt_on_curve; 00087 00088 CubitVector coe_normal, coe_cross, tangent1, tangent2, junk; 00089 00090 if( ! other_coedge ) 00091 { 00092 Curve* curve_ptr = closest_coedge->get_ref_edge_ptr()->get_curve_ptr(); 00093 double u = curve_ptr->u_from_position( pt_on_curve ); 00094 00095 /**** Special case: closest point on loop at G1 discontinuity ****/ 00096 if( curve_ptr->G1_discontinuous( u, &tangent1, &tangent2 ) ) 00097 { 00098 if( closest_coedge->get_sense() == CUBIT_REVERSED ) 00099 { 00100 tangent1 *= -1.0; 00101 tangent2 *= -1.0; 00102 } 00103 loop_ptr->get_ref_face_ptr()->get_surface_ptr()-> 00104 closest_point( pt_on_curve, NULL, &coe_normal ); 00105 coe_cross = tangent1 * tangent2; 00106 double sum = (coe_cross + coe_normal).length_squared(); 00107 double diff = (coe_cross - coe_normal).length_squared(); 00108 00109 CubitBoolean inside1 = 00110 inside_of_curve( tangent1, pt_on_curve, surf_point, normal ); 00111 CubitBoolean inside2 = 00112 inside_of_curve( tangent2, pt_on_curve, surf_point, normal ); 00113 00114 if( (sum > diff) || (diff < CUBIT_DBL_MIN) ) 00115 //discontinuity is at a convexity 00116 { 00117 //the point must be inside of both sub-edges 00118 return (inside1 && inside2) ? CUBIT_TRUE : CUBIT_FALSE; 00119 } 00120 else //discontinuity is at a concavity 00121 { 00122 //the point must be inside of one of the sub-edges 00123 return (inside1 || inside2) ? CUBIT_TRUE : CUBIT_FALSE; 00124 } 00125 } 00126 00127 else /**** This is the normal, non-special case part ****/ 00128 { 00129 curve_ptr->closest_point( pt_on_curve, junk, &tangent1 ); 00130 if( closest_coedge->get_sense() == CUBIT_REVERSED ) 00131 tangent1 *= -1.0; 00132 00133 return inside_of_curve( tangent1, pt_on_curve, surf_point, normal ); 00134 } 00135 } 00136 /**** Special case: closest point on loop at vertex ****/ 00137 else 00138 { 00139 Curve* curve1_ptr = closest_coedge->get_ref_edge_ptr()->get_curve_ptr(); 00140 Curve* curve2_ptr = other_coedge->get_ref_edge_ptr()->get_curve_ptr(); 00141 curve1_ptr->closest_point( pt_on_curve, junk, &tangent1 ); 00142 curve2_ptr->closest_point( pt_on_curve, junk, &tangent2 ); 00143 00144 if( closest_coedge->get_sense() == CUBIT_REVERSED ) 00145 tangent1 *= -1.0; 00146 if( other_coedge->get_sense() == CUBIT_REVERSED ) 00147 tangent2 *= -1.0; 00148 00149 loop_ptr->get_ref_face_ptr()->get_surface_ptr()-> 00150 closest_point( pt_on_curve, NULL, &coe_normal ); 00151 00152 coe_cross = tangent1 * tangent2; 00153 double sum = (coe_cross + coe_normal).length_squared(); 00154 double diff = (coe_cross - coe_normal).length_squared(); 00155 00156 CubitBoolean inside1 = 00157 inside_of_curve( tangent1, pt_on_curve, surf_point, normal ); 00158 CubitBoolean inside2 = 00159 inside_of_curve( tangent2, pt_on_curve, surf_point, normal ); 00160 00161 if( (sum > diff) || (diff < CUBIT_DBL_MIN) ) 00162 //the common vertex is at a convexity 00163 { 00164 //the point must be inside of both coedges 00165 return (inside1 && inside2) ? CUBIT_TRUE : CUBIT_FALSE; 00166 } 00167 else //the common vertex is at a concavity 00168 { 00169 //the point must be inside of one of the coedges 00170 return (inside1 || inside2) ? CUBIT_TRUE : CUBIT_FALSE; 00171 } 00172 } 00173 } 00174 00175 00176 00177 00178 //------------------------------------------------------------------------- 00179 // Purpose : Attempt to calculate the area of a loop 00180 // 00181 // Special Notes : 00182 // 00183 // Creator : Jason Kraftcheck 00184 // 00185 // Creation Date : 11/19/99 00186 //------------------------------------------------------------------------- 00187 /* 00188 double GeometryUtil::loop_area( Loop* loop_ptr ) 00189 { 00190 int i; 00191 00192 DLIList<CoEdge*> coedges; 00193 loop_ptr->co_edges( coedges ); 00194 00195 RefFace* ref_face_ptr = loop_ptr->get_ref_face_ptr(); 00196 00197 00198 // Get list of segment points around loop 00199 DLIList<CubitVector*> point_list, interior_edge_points; 00200 coedges.reset(); 00201 for( i = coedges.size(); i > 0; i-- ) 00202 { 00203 CoEdge* coedge_ptr = coedges.get_and_step(); 00204 RefEdge* edge_ptr = coedge_ptr->get_ref_edge_ptr(); 00205 CubitSense list_sense; 00206 interior_edge_points.clean_out(); 00207 edge_ptr->get_interior_extrema( interior_edge_points, list_sense ); 00208 if( coedge_ptr->get_sense() == CUBIT_REVERSED ) 00209 { 00210 list_sense = CubitUtil::opposite_sense( list_sense ); 00211 point_list.append( new CubitVector( 00212 edge_ptr->end_vertex()->coordinates() ) ); 00213 } 00214 else point_list.append( new CubitVector( 00215 edge_ptr->start_vertex()->coordinates() ) ); 00216 00217 if( list_sense == CUBIT_REVERSED ) 00218 interior_edge_points.reverse(); 00219 00220 point_list += interior_edge_points; 00221 } 00222 00223 // Pick any point for which the refface has a valid normal 00224 const double STEP = 1e2 * GEOMETRY_RESABS; 00225 const double SMALL = CUBIT_RESABS * CUBIT_RESABS; 00226 CubitVector normal, *point, *prev, *current; 00227 for( i = point_list.size(); i--; ) 00228 { 00229 point = point_list.get_and_step(); 00230 normal = ref_face_ptr->normal_at( *point ); 00231 if( normal.length_squared() > SMALL ) 00232 break; 00233 } 00234 00235 // If we did not find a valid normal at any point (this should 00236 // almost never happen), try stepping a small distance along 00237 // each segment 00238 for( i = point_list.size(); (normal.length_squared() <= SMALL) && (i > 0); i-- ) 00239 { 00240 prev = point; 00241 point = point_list.get_and_step(); 00242 CubitVector direction = *prev - *point; 00243 double length = direction.length(); 00244 if( length < CUBIT_RESABS ) 00245 continue; 00246 double step_fraction = STEP / length; 00247 if( step_fraction >= 1.0 ) 00248 continue; 00249 00250 CubitVector position = *point + step_fraction * direction; 00251 normal = ref_face_ptr->normal_at( position ); 00252 if( normal.length_squared() > SMALL ) 00253 { 00254 point = new CubitVector( position ); 00255 point_list.back(); 00256 point_list.insert( point ); 00257 break; 00258 } 00259 } 00260 00261 // RefFace does not have a valid normal anywhere?? 00262 if( normal.length_squared() <= SMALL ) 00263 return 0.0; 00264 00265 // Do simple 2-D area calculation and hope it isn't too 00266 // inaccurate for the 3-D refface. 00267 double double_area = 0.0; 00268 assert( point_list.prev() == point ); 00269 prev = point_list.get_and_step(); 00270 current = point_list.get_and_step(); 00271 00272 while( current != point ) 00273 { 00274 CubitVector cross = (*prev - *point) * (*current - *point); 00275 double dot_product = cross % normal; 00276 double_area += dot_product >= 0.0 ? cross.length() : -(cross.length()); 00277 prev = current; 00278 current = point_list.get_and_step(); 00279 } 00280 00281 while( point_list.size() > 0 ) delete point_list.pop(); 00282 return double_area / 2.0; 00283 } 00284 */ 00285 00286 struct CoEdgeDataList { 00287 CoEdge* coe_ptr; 00288 Curve* curve_ptr; 00289 double box_dist_sqr; 00290 int mark; 00291 }; 00292 00293 00294 //------------------------------------------------------------------------- 00295 // Purpose : Find the closest point on a loop. 00296 // 00297 // Special Notes : 00298 // 00299 // Creator : Jason Kraftcheck 00300 // 00301 // Creation Date : 08/04/98 00302 //------------------------------------------------------------------------- 00303 CoEdge* GeometryUtil::closest_loop_coedge( Loop* loop_ptr, 00304 const CubitVector& from_pt, 00305 CoEdge*& other_coedge, 00306 CubitVector* closest ) 00307 { 00308 static CoEdgeDataList* coe_array = NULL; 00309 static int coe_array_size = 0; 00310 const double ressqr = CUBIT_RESABS * CUBIT_RESABS; 00311 00312 DLIList<CoEdge*> coedge_list; 00313 coedge_list.clean_out(); 00314 00315 int i; 00316 CubitVector closest_pt, current_pt; 00317 double current_dst, closest_dst; 00318 CoEdge* closest_coedge = 0; 00319 00320 //We need the ordered coedges so that we can make sure that, when 00321 //we pass back other_coedge, it is the coedge following the returned 00322 //coedge in the loop, and not the other way around. 00323 loop_ptr->ordered_co_edges( coedge_list ); 00324 00325 //Make sure we have enough space in the array 00326 int count = coedge_list.size(); 00327 if( coe_array_size < count ) 00328 { 00329 if( coe_array ) delete [] coe_array; 00330 coe_array = new CoEdgeDataList[count]; 00331 coe_array_size = count; 00332 } 00333 00334 //remove from consideration any coedges for which the RefEdge occurs 00335 //more than once on the face. 00336 for( i = coedge_list.size(); i > 0; i-- ) 00337 coedge_list.get_and_step()->get_ref_edge_ptr()->marked( 0 ); 00338 for( i = coedge_list.size(); i > 0; i-- ) 00339 { 00340 RefEdge* edge_ptr = coedge_list.get_and_step()->get_ref_edge_ptr(); 00341 edge_ptr->marked( edge_ptr->marked() + 1 ); 00342 } 00343 00344 //Start at one of the coedges we want to remove. 00345 coedge_list.reset(); 00346 for( i = coedge_list.size(); i > 0; i-- ) 00347 if( coedge_list.get()->get_ref_edge_ptr()->marked() > 1 ) 00348 break; 00349 else 00350 coedge_list.step(); 00351 00352 //Populate the array with the coedges we want to keep. 00353 count = 0; 00354 int last_mark = 0; 00355 for( i = coedge_list.size(); i > 0; i-- ) 00356 { 00357 RefEdge* edge_ptr = coedge_list.get()->get_ref_edge_ptr(); 00358 if( edge_ptr->marked() == 1 ) 00359 { 00360 coe_array[count].coe_ptr = coedge_list.get(); 00361 coe_array[count].curve_ptr = edge_ptr->get_curve_ptr(); 00362 coe_array[count].box_dist_sqr = 00363 coe_array[count].curve_ptr->bounding_box().distance_squared(from_pt); 00364 coe_array[count].mark = 0; 00365 count++; 00366 } 00367 else if( count == 0 ) 00368 last_mark = 1; 00369 else 00370 coe_array[count-1].mark = 1; 00371 00372 edge_ptr->marked(0); 00373 coedge_list.step(); 00374 } 00375 if( last_mark == 0 ) 00376 coe_array[count-1].mark = 1; 00377 00378 //Do we have any coedges left? 00379 if( count == 0 ) 00380 return 0; 00381 00382 //Find the first bounding box that the point is within 00383 int current_coe = -1; 00384 for( i = 0; (i < count) && (current_coe < 0); i++ ) 00385 if( coe_array[i].box_dist_sqr < CUBIT_RESABS ) 00386 current_coe = i; 00387 00388 //If the point wasn't in any bounding box, choose the closest one 00389 closest_dst = CUBIT_DBL_MAX; 00390 if( current_coe < 0 ) 00391 for( i = 0; i < count; i++ ) 00392 if( coe_array[i].box_dist_sqr < closest_dst ) 00393 { 00394 closest_dst = coe_array[i].box_dist_sqr; 00395 current_coe = i; 00396 } 00397 00398 //Start by assuming that the curve we found above is the closest 00399 closest_coedge = coe_array[current_coe].coe_ptr; 00400 coe_array[current_coe].curve_ptr->closest_point_trimmed( from_pt, closest_pt ); 00401 closest_dst = ( from_pt - closest_pt ).length_squared(); 00402 other_coedge = 0; 00403 00404 int start = current_coe; 00405 int closest_index = start; 00406 int other_index = -1; 00407 current_coe = ( current_coe + 1 ) % count; 00408 00409 //Now look for a closer curve 00410 while( start != current_coe ) 00411 { 00412 if( coe_array[current_coe].box_dist_sqr <= (closest_dst+GEOMETRY_RESABS) ) 00413 { 00414 coe_array[current_coe].curve_ptr 00415 ->closest_point_trimmed( from_pt, current_pt ); 00416 current_dst = ( from_pt - current_pt ).length_squared(); 00417 00418 if( (closest_pt - current_pt).length_squared() < ressqr ) 00419 { 00420 if( current_dst < closest_dst ) 00421 { 00422 closest_dst = current_dst; 00423 closest_pt = current_pt; 00424 other_coedge = coe_array[current_coe].coe_ptr; 00425 } 00426 else 00427 { 00428 other_coedge = coe_array[current_coe].coe_ptr; 00429 } 00430 other_index = current_coe; 00431 } 00432 else if( current_dst < closest_dst ) 00433 { 00434 closest_coedge = coe_array[current_coe].coe_ptr; 00435 closest_dst = current_dst; 00436 closest_pt = current_pt; 00437 other_coedge = 0; 00438 closest_index = current_coe; 00439 other_index = -1; 00440 } 00441 } 00442 current_coe = ( current_coe + 1 ) % count; 00443 } 00444 00445 //make sure we have things in the correct order 00446 if( other_coedge ) 00447 { 00448 RefVertex* common = closest_coedge->get_ref_edge_ptr()-> 00449 common_ref_vertex( other_coedge->get_ref_edge_ptr() ); 00450 if( ! common ) 00451 other_coedge = 0; 00452 } 00453 00454 CubitBoolean swap = CUBIT_FALSE; 00455 if( other_coedge ) 00456 { 00457 if( ((closest_index + 1)%count) == other_index ) 00458 swap = CUBIT_FALSE; 00459 else if( ((other_index+1)%count) == closest_index ) 00460 swap = CUBIT_TRUE; 00461 else 00462 { 00463 //locate the start and end of the subsection of the loop 00464 int begin, end; 00465 if( closest_index < other_index ) 00466 { 00467 begin = closest_index; 00468 end = other_index; 00469 } 00470 else 00471 { 00472 begin = other_index; 00473 end = closest_index; 00474 } 00475 00476 while( (begin > 0) && (coe_array[begin-1].mark != 1) ) 00477 begin--; 00478 00479 while( (end < count) && (coe_array[end].mark != 1) ) 00480 end++; 00481 00482 if( (closest_index == begin) && (other_index == end) ) 00483 swap = CUBIT_TRUE; 00484 else 00485 swap = CUBIT_FALSE; 00486 } 00487 } 00488 00489 if( swap ) 00490 { 00491 CoEdge* tmp = other_coedge; 00492 other_coedge = closest_coedge; 00493 closest_coedge = tmp; 00494 } 00495 00496 if( closest ) *closest = closest_pt; 00497 return closest_coedge; 00498 } 00499 CoEdge* GeometryUtil::closest_face_coedge( RefFace* face_ptr, 00500 const CubitVector& from_pt, 00501 CoEdge*& other_coedge, 00502 CubitVector* closest ) 00503 { 00504 static CoEdgeDataList* coe_array = NULL; 00505 static int coe_array_size = 0; 00506 const double ressqr = GEOMETRY_RESABS * GEOMETRY_RESABS; 00507 00508 DLIList<CoEdge*> coedge_list; 00509 coedge_list.clean_out(); 00510 00511 int i; 00512 CubitVector closest_pt, current_pt; 00513 double current_dst, closest_dst; 00514 CoEdge* closest_coedge = 0; 00515 00516 face_ptr->co_edges( coedge_list ); 00517 00518 //Make sure we have enough space in the array 00519 int count = coedge_list.size(); 00520 if( coe_array_size < count ) 00521 { 00522 if( coe_array ) delete [] coe_array; 00523 coe_array = new CoEdgeDataList[count]; 00524 coe_array_size = count; 00525 } 00526 00527 //remove from consideration any coedges for which the RefEdge occurs 00528 //more than once on the face. 00529 for( i = coedge_list.size(); i > 0; i-- ) 00530 coedge_list.get_and_step()->get_ref_edge_ptr()->marked( 0 ); 00531 for( i = coedge_list.size(); i > 0; i-- ) 00532 { 00533 RefEdge* edge_ptr = coedge_list.get_and_step()->get_ref_edge_ptr(); 00534 edge_ptr->marked( edge_ptr->marked() + 1 ); 00535 } 00536 00537 //Start at one of the coedges we want to remove. 00538 coedge_list.reset(); 00539 for( i = coedge_list.size(); i > 0; i-- ) 00540 if( coedge_list.get()->get_ref_edge_ptr()->marked() > 1 ) 00541 break; 00542 else 00543 coedge_list.step(); 00544 00545 //Populate the array with the coedges we want to keep. 00546 count = 0; 00547 int last_mark = 0; 00548 for( i = coedge_list.size(); i > 0; i-- ) 00549 { 00550 RefEdge* edge_ptr = coedge_list.get()->get_ref_edge_ptr(); 00551 if( edge_ptr->marked() == 1 ) 00552 { 00553 coe_array[count].coe_ptr = coedge_list.get(); 00554 coe_array[count].curve_ptr = edge_ptr->get_curve_ptr(); 00555 coe_array[count].box_dist_sqr = 00556 coe_array[count].curve_ptr->bounding_box().distance_squared(from_pt); 00557 coe_array[count].mark = 0; 00558 count++; 00559 } 00560 else if( count == 0 ) 00561 last_mark = 1; 00562 else 00563 coe_array[count-1].mark = 1; 00564 00565 edge_ptr->marked(0); 00566 coedge_list.step(); 00567 } 00568 if( last_mark == 0 ) 00569 coe_array[count-1].mark = 1; 00570 00571 00572 //Find the first bounding box that the point is within 00573 int current_coe = -1; 00574 for( i = 0; (i < count) && (current_coe < 0); i++ ) 00575 if( coe_array[i].box_dist_sqr < ressqr ) 00576 current_coe = i; 00577 00578 //If the point wasn't in any bounding box, choose the closest one 00579 closest_dst = CUBIT_DBL_MAX; 00580 if( current_coe < 0 ) 00581 for( i = 0; i < count; i++ ) 00582 if( coe_array[i].box_dist_sqr < closest_dst ) 00583 { 00584 closest_dst = coe_array[i].box_dist_sqr; 00585 current_coe = i; 00586 } 00587 00588 //Start by assuming that the curve we found above is the closest 00589 closest_coedge = coe_array[current_coe].coe_ptr; 00590 coe_array[current_coe].curve_ptr->closest_point_trimmed( from_pt, closest_pt ); 00591 closest_dst = ( from_pt - closest_pt ).length_squared(); 00592 other_coedge = 0; 00593 00594 int start = current_coe; 00595 current_coe = ( current_coe + 1 ) % count; 00596 00597 //Now look for a closer curve 00598 while( start != current_coe ) 00599 { 00600 if( coe_array[current_coe].box_dist_sqr <= (closest_dst+GEOMETRY_RESABS) ) 00601 { 00602 coe_array[current_coe].curve_ptr 00603 ->closest_point_trimmed( from_pt, current_pt ); 00604 current_dst = ( from_pt - current_pt ).length_squared(); 00605 00606 if( (closest_pt - current_pt).length_squared() < ressqr ) 00607 { 00608 if( current_dst < closest_dst ) 00609 { 00610 closest_dst = current_dst; 00611 closest_pt = current_pt; 00612 other_coedge = coe_array[current_coe].coe_ptr; 00613 } 00614 else 00615 { 00616 other_coedge = coe_array[current_coe].coe_ptr; 00617 } 00618 // other_index = current_coe; 00619 } 00620 else if( current_dst < closest_dst ) 00621 { 00622 closest_coedge = coe_array[current_coe].coe_ptr; 00623 closest_dst = current_dst; 00624 closest_pt = current_pt; 00625 other_coedge = 0; 00626 // closest_index = current_coe; 00627 // other_index = -1; 00628 } 00629 } 00630 current_coe = ( current_coe + 1 ) % count; 00631 } 00632 00633 //make sure we have things in the correct order 00634 if( other_coedge ) 00635 { 00636 RefEdge* closest_edge = closest_coedge->get_ref_edge_ptr(); 00637 RefEdge* other_edge = other_coedge->get_ref_edge_ptr(); 00638 RefVertex* common = closest_edge->common_ref_vertex( other_edge ); 00639 if( ! common ) 00640 other_coedge = 0; 00641 else if( closest_coedge->get_sense() == CUBIT_FORWARD ) 00642 { 00643 if( closest_edge->start_vertex() == common ) 00644 { 00645 CoEdge* tmp = closest_coedge; 00646 closest_coedge = other_coedge; 00647 other_coedge = tmp; 00648 } 00649 } 00650 else if( closest_coedge->get_sense() == CUBIT_REVERSED ) 00651 { 00652 if( closest_edge->end_vertex() == common ) 00653 { 00654 CoEdge* tmp = closest_coedge; 00655 closest_coedge = other_coedge; 00656 other_coedge = tmp; 00657 } 00658 } 00659 } 00660 00661 if( closest ) *closest = closest_pt; 00662 return closest_coedge; 00663 } 00664 00665 //------------------------------------------------------------------------- 00666 // Purpose : recursive method to make a segmented curve on a surface. 00667 // 00668 // Special Notes : This method is was written for use by VirtualCurve, 00669 // which is why virtual curve debug flags (86) appear 00670 // here. 00671 // 00672 // Creator : Jason Kraftcheck 00673 // 00674 // Creation Date : 08/07/98 00675 //------------------------------------------------------------------------- 00676 CubitStatus GeometryUtil::recursive_make_curve( Surface* surface_ptr, 00677 const CubitVector& start_pt, 00678 const CubitVector& end_pt, 00679 DLIList<CubitVector*>& segment_points, 00680 double arc_angle_tol, 00681 double midpoint_dist_tol ) 00682 { 00683 if( midpoint_dist_tol < GEOMETRY_RESABS ) 00684 midpoint_dist_tol = GEOMETRY_RESABS; 00685 00686 CubitVector seg_mid_point, mid_point, mid_pt_norm; 00687 CubitVector start_pt_norm, end_pt_norm, tangent; 00688 double angle = arc_angle_tol; 00689 double midpt_dist = midpoint_dist_tol; 00690 00691 seg_mid_point = (start_pt + end_pt) / 2; 00692 surface_ptr->closest_point_trimmed( seg_mid_point, mid_point ); 00693 surface_ptr->closest_point( mid_point, NULL, &mid_pt_norm ); 00694 surface_ptr->closest_point( start_pt, NULL, &start_pt_norm ); 00695 surface_ptr->closest_point( end_pt, NULL, &end_pt_norm ); 00696 tangent = start_pt - end_pt; 00697 00698 if( tangent.length() < GEOMETRY_RESABS ) 00699 { 00700 PRINT_DEBUG_86( "Solution for polyline on surface not converging.\n" 00701 "GeometryUtil::recursive_make_curve(..) returning " 00702 "FAILURE.\n"); 00703 return CUBIT_FAILURE; 00704 } 00705 00706 CubitBoolean split = CUBIT_FALSE; 00707 00708 if( !split && ( midpoint_dist_tol < CUBIT_DBL_MAX ) ) 00709 { 00710 midpt_dist = (seg_mid_point - mid_point).length(); 00711 if( midpt_dist > midpoint_dist_tol ) 00712 { 00713 split = CUBIT_TRUE; 00714 } 00715 } 00716 00717 if( !split && (arc_angle_tol < (CUBIT_PI / 2)) ) 00718 { 00719 double seg_angle, half1_angle, half2_angle, sum; 00720 seg_angle = fabs( tangent.vector_angle( start_pt_norm, end_pt_norm ) ); 00721 half1_angle = fabs((start_pt-mid_point). 00722 vector_angle( start_pt_norm, mid_pt_norm )); 00723 half2_angle = fabs((end_pt-mid_point). 00724 vector_angle( end_pt_norm, mid_pt_norm )); 00725 sum = half1_angle + half2_angle; 00726 angle = seg_angle > sum ? seg_angle : sum; 00727 00728 if( angle > arc_angle_tol ) 00729 { 00730 split = CUBIT_TRUE; 00731 } 00732 } 00733 00734 if( split ) 00735 { 00736 if( DEBUG_FLAG(86) ) 00737 { 00738 GfxDebug::draw_label( ++linearized_curve_debug_count_, 00739 float(mid_point.x()), float(mid_point.y()), float(mid_point.z()), 00740 CUBIT_WHITE_INDEX ); 00741 GfxDebug::flush(); 00742 } 00743 00744 double start_len = (start_pt - mid_point).length(); 00745 double end_len = (end_pt - mid_point).length(); 00746 double half_tol = 0.5 * midpoint_dist_tol; 00747 if( ((start_len < half_tol) && (end_len < half_tol)) || 00748 (start_len < GEOMETRY_RESABS) || (end_len < GEOMETRY_RESABS) ) 00749 return CUBIT_SUCCESS; 00750 00751 CubitStatus status; 00752 status = recursive_make_curve( surface_ptr, start_pt, mid_point, 00753 segment_points, arc_angle_tol, midpoint_dist_tol ); 00754 segment_points.append( new CubitVector( mid_point ) ); 00755 00756 if( status != CUBIT_SUCCESS ) return status; 00757 00758 status = recursive_make_curve( surface_ptr, mid_point, end_pt, 00759 segment_points, arc_angle_tol, midpoint_dist_tol ); 00760 00761 return status; 00762 } 00763 00764 return CUBIT_SUCCESS; 00765 } 00766 00767 00768 00769 //------------------------------------------------------------------------- 00770 // Purpose : constructor 00771 // 00772 // Special Notes : 00773 // 00774 // Creator : Jason Kraftcheck 00775 // 00776 // Creation Date : 08/03/98 00777 //------------------------------------------------------------------------- 00778 GeometryUtil::GeometryUtil() 00779 { 00780 default_angle_tol = CUBIT_PI / 20; 00781 default_midpoint_tol = CUBIT_DBL_MAX; 00782 surface_cpu_time = 0.0; 00783 other_cpu_time = 0.0; 00784 } 00785 00786 00787 00788 //------------------------------------------------------------------------- 00789 // Purpose : Find the closest coface in a Shell to the passed point 00790 // 00791 // Special Notes : 00792 // 00793 // Creator : Jason Kraftcheck 00794 // 00795 // Creation Date : 11/24/99 00796 //------------------------------------------------------------------------- 00797 CubitStatus GeometryUtil::closest_shell_coface( Shell* shell_ptr, 00798 const CubitVector& from_pt, 00799 DLIList<CoFace*>& result_set, 00800 CubitVector* closest ) 00801 { 00802 static DLIList<CoFace*> coface_list, shell_cofaces; 00803 coface_list.clean_out(); 00804 shell_cofaces.clean_out(); 00805 result_set.clean_out(); 00806 00807 int i; 00808 CubitVector closest_pt, current_pt; 00809 CoFace *current_cof; 00810 double current_dst, closest_dst; 00811 00812 shell_ptr->co_faces( shell_cofaces ); 00813 00814 //remove from consideration any cofaces for which the RefFace occurs 00815 //more than once on the Shell. 00816 for( i = shell_cofaces.size(); i > 0; i-- ) 00817 shell_cofaces.get_and_step()->get_ref_face_ptr()->marked( 0 ); 00818 for( i = shell_cofaces.size(); i > 0; i-- ) 00819 { 00820 RefFace* face_ptr = shell_cofaces.get_and_step()->get_ref_face_ptr(); 00821 face_ptr->marked( face_ptr->marked() + 1 ); 00822 } 00823 for( i = shell_cofaces.size(); i > 0; i-- ) 00824 { 00825 CoFace* cof_ptr = shell_cofaces.get_and_step(); 00826 if( cof_ptr->get_ref_face_ptr()->marked() == 1 ) 00827 coface_list.append( cof_ptr ); 00828 } 00829 for( i = shell_cofaces.size(); i > 0; i-- ) 00830 shell_cofaces.get_and_step()->get_ref_face_ptr()->marked( 0 ); 00831 00832 if( !coface_list.size() ) 00833 return CUBIT_FAILURE; 00834 00835 current_cof = coface_list.get_and_step(); 00836 current_cof->get_ref_face_ptr()-> 00837 find_closest_point_trimmed( from_pt, closest_pt ); 00838 closest_dst = ( from_pt - closest_pt ).length_squared(); 00839 result_set.append( current_cof ); 00840 00841 for( i = coface_list.size(); i > 1; i-- ) 00842 { 00843 current_cof = coface_list.get_and_step(); 00844 current_cof->get_ref_face_ptr()-> 00845 find_closest_point_trimmed( from_pt, current_pt ); 00846 current_dst = ( from_pt - current_pt ).length_squared(); 00847 00848 if( fabs( current_dst - closest_dst ) < CUBIT_RESABS ) 00849 { 00850 result_set.append( current_cof ); 00851 } 00852 else if( current_dst < closest_dst ) 00853 { 00854 result_set.clean_out(); 00855 result_set.append( current_cof ); 00856 closest_dst = current_dst; 00857 closest_pt = current_pt; 00858 } 00859 } 00860 if( closest != NULL ) *closest = closest_pt; 00861 00862 return CUBIT_SUCCESS; 00863 } 00864 00865 00866 //------------------------------------------------------------------------- 00867 // Purpose : Test if a position is within a Shell 00868 // 00869 // Special Notes : 00870 // 00871 // Creator : Jason Kraftcheck 00872 // 00873 // Creation Date : 11/24/99 00874 //------------------------------------------------------------------------- 00875 CubitBoolean GeometryUtil::is_position_within_shell( 00876 const CubitVector& position, 00877 Shell* shell_ptr, 00878 CubitVector* closest_on_shell ) 00879 { 00880 DLIList<CoFace*> result_cofaces; 00881 CubitVector closest_pt; 00882 closest_shell_coface( shell_ptr, position, result_cofaces, &closest_pt ); 00883 if( closest_on_shell ) *closest_on_shell = closest_pt; 00884 00885 //test each resulting coface 00886 CubitVector vector_to_surf = closest_pt - position; 00887 for( int i = result_cofaces.size(); i > 0; i-- ) 00888 { 00889 CoFace* coface_ptr = result_cofaces.get_and_step(); 00890 RefFace* ref_face_ptr = coface_ptr->get_ref_face_ptr(); 00891 CubitVector normal = ref_face_ptr->normal_at( closest_pt ); 00892 if( coface_ptr->get_sense() == CUBIT_REVERSED ) 00893 normal *= -1.0; 00894 00895 double sum = (normal + vector_to_surf).length_squared(); 00896 double diff = (normal - vector_to_surf).length_squared(); 00897 if( diff > sum ) return CUBIT_FALSE; 00898 } 00899 return CUBIT_TRUE; 00900 } 00901 00902 00903 //------------------------------------------------------------------------- 00904 // Purpose : Test if a shell is a void 00905 // 00906 // Special Notes : 00907 // 00908 // Creator : Jason Kraftcheck 00909 // 00910 // Creation Date : 11/27/99 00911 //------------------------------------------------------------------------- 00912 CubitBoolean GeometryUtil::is_shell_a_void( Shell* shell_ptr ) 00913 { 00914 assert( shell_ptr != 0 ); 00915 DLIList<CoFace*> shell_cofaces; 00916 00917 CubitBox box = shell_ptr->bounding_box(); 00918 double box_diag = box.diagonal().length(); 00919 double epsilon = box_diag / 1000; 00920 00921 CubitVector base_point( box.minimum() ); 00922 CubitVector opposite_point; 00923 CubitVector point, normal; 00924 00925 closest_shell_coface( shell_ptr, base_point, shell_cofaces, &point ); 00926 base_point = point; 00927 00928 if( !shell_cofaces.size() ) 00929 return CUBIT_TRUE; 00930 00931 CoFace* coface_ptr = shell_cofaces.get(); 00932 normal = coface_ptr->get_ref_face_ptr()->normal_at( base_point ); 00933 if( coface_ptr->get_sense() == CUBIT_REVERSED ) normal *= -1.0; 00934 normal.length( box_diag ); 00935 00936 opposite_point = base_point + normal; 00937 closest_shell_coface( shell_ptr, opposite_point, shell_cofaces, &point ); 00938 00939 return (base_point - point).length() < epsilon ? CUBIT_FALSE : CUBIT_TRUE; 00940 } 00941 00942 00943 //------------------------------------------------------------------------- 00944 // Purpose : Check if a point is on the inside or outside of a curve, 00945 // given the surface normal, and the sense of the curve on 00946 // the surface. 00947 // 00948 // Special Notes : The passed position is assumed to be on the surface. 00949 // 00950 // Creator : Jason Kraftcheck 00951 // 00952 // Creation Date : 05/02/00 00953 //------------------------------------------------------------------------- 00954 CubitBoolean GeometryUtil::inside_of_curve( const CubitVector& tangent, 00955 const CubitVector& curve_pos, 00956 const CubitVector& surf_pos, 00957 const CubitVector& normal ) 00958 { 00959 CubitVector cross = tangent * ( surf_pos - curve_pos ); 00960 double sum = (cross + normal).length_squared(); 00961 double diff = (cross - normal).length_squared(); 00962 return (sum < diff) ? CUBIT_FALSE : CUBIT_TRUE; 00963 } 00964 00965 //------------------------------------------------------------------------- 00966 // Purpose : Given a coordinate and a list of curves, determine if 00967 // any of the curves has that coordinate as an end point 00968 // and return that curve and whether it is start or end. 00969 // 00970 // Special Notes : The passed position is assumed to be on the surface. 00971 // 00972 // Creator : Steve Storm 00973 // 00974 // Creation Date : 05/30/00 00975 //------------------------------------------------------------------------- 00976 RefEdge* GeometryUtil:: 00977 find_connected_ref_edge_by_coord( CubitVector& coords, 00978 DLIList<RefEdge*>& ref_edge_list, 00979 int& start_flg ) 00980 { 00981 RefEdge* ref_edge; 00982 DLIList<RefEdge*> tmp_list = ref_edge_list; 00983 00984 ref_edge = ref_edge_list.get(); 00985 GeometryQueryEngine* gqe_ptr = ref_edge->get_geometry_query_engine(); 00986 double tol = gqe_ptr->get_sme_resabs_tolerance(); 00987 00988 tmp_list.reset(); 00989 for( int i=0; i<tmp_list.size(); i++ ) 00990 { 00991 ref_edge = tmp_list.get_and_step(); 00992 00993 if( ref_edge->start_coordinates().within_tolerance( coords, tol ) ) 00994 { 00995 start_flg = 1; 00996 return ref_edge; 00997 } 00998 00999 if( ref_edge->end_coordinates().within_tolerance( coords, tol ) ) 01000 { 01001 start_flg = 0; 01002 return ref_edge; 01003 } 01004 } 01005 return NULL; 01006 } 01007 01008 void 01009 GeometryUtil::find_connected_ref_edges_by_coord( CubitVector& coords, 01010 DLIList<RefEdge*>& ref_edge_list, 01011 DLIList<RefEdge*>& connected_edges_list ) 01012 { 01013 RefEdge* ref_edge; 01014 DLIList<RefEdge*> tmp_list = ref_edge_list; 01015 01016 ref_edge = ref_edge_list.get(); 01017 GeometryQueryEngine* gqe_ptr = ref_edge->get_geometry_query_engine(); 01018 double tol = gqe_ptr->get_sme_resabs_tolerance(); 01019 01020 tmp_list.reset(); 01021 for( int i=0; i<tmp_list.size(); i++ ) 01022 { 01023 ref_edge = tmp_list.get_and_step(); 01024 01025 if( ref_edge->start_coordinates().within_tolerance( coords, tol ) ) 01026 connected_edges_list.append_unique( ref_edge ); 01027 01028 if( ref_edge->end_coordinates().within_tolerance( coords, tol ) ) 01029 connected_edges_list.append_unique( ref_edge ); 01030 } 01031 } 01032 01033 CubitStatus 01034 GeometryUtil::form_ref_edge_loop_by_coord( DLIList<RefEdge*>& ref_edge_list ) 01035 { 01036 int i; 01037 01038 if( ref_edge_list.size() == 0 ) 01039 return CUBIT_FAILURE; 01040 01041 if( ref_edge_list.size() == 1 ) 01042 { 01043 double period; 01044 if( ref_edge_list.get()->is_periodic( period ) ) 01045 return CUBIT_SUCCESS; 01046 else 01047 { 01048 // Could be a spline 01049 RefEdge *ref_edge_ptr = ref_edge_list.get(); 01050 GeometryQueryEngine* gqe_ptr = ref_edge_ptr->get_geometry_query_engine(); 01051 double tol = gqe_ptr->get_sme_resabs_tolerance(); 01052 if( ref_edge_ptr->start_coordinates().within_tolerance( 01053 ref_edge_ptr->end_coordinates(), tol ) ) 01054 return CUBIT_SUCCESS; 01055 } 01056 return CUBIT_FAILURE; 01057 } 01058 01059 // First form a chain (which can be a loop) 01060 if( form_ref_edge_chain_by_coord( ref_edge_list ) == CUBIT_FAILURE ) 01061 return CUBIT_FAILURE; 01062 01063 // Now check to make sure a valid loop was formed. For a valid loop 01064 // every vertex must have exactly 2 edges connected to it. The only 01065 // exception is a periodic curve where there is only one vertex, which 01066 // was checked for before. 01067 DLIList<RefEdge*> connected_edges; 01068 RefEdge* ref_edge_ptr; 01069 CubitVector vector; 01070 for( i=0; i<ref_edge_list.size(); i++ ) 01071 { 01072 ref_edge_ptr = ref_edge_list.get_and_step(); 01073 01074 connected_edges.clean_out(); 01075 vector = ref_edge_ptr->start_coordinates(); 01076 find_connected_ref_edges_by_coord( vector , 01077 ref_edge_list, connected_edges ); 01078 if( connected_edges.size() != 2 ) 01079 return CUBIT_FAILURE; 01080 01081 connected_edges.clean_out(); 01082 vector = ref_edge_ptr->end_coordinates(); 01083 find_connected_ref_edges_by_coord( vector , 01084 ref_edge_list, connected_edges ); 01085 if( connected_edges.size() != 2 ) 01086 return CUBIT_FAILURE; 01087 } 01088 01089 return CUBIT_SUCCESS; 01090 } 01091 01092 CubitStatus 01093 GeometryUtil::form_ref_edge_chain_by_coord( DLIList<RefEdge*>& ref_edge_list ) 01094 { 01095 if( ref_edge_list.size() == 1 ) 01096 return CUBIT_SUCCESS; 01097 01098 int i; 01099 int start_flg = 0; 01100 01101 CubitVector vector_start, vector_end; 01102 RefEdge* curr_edge; 01103 RefEdge* next_edge; 01104 01105 DLIList<RefEdge*> temp_list = ref_edge_list; 01106 DLIList<RefEdge*> ordered_list; 01107 01108 // Start vertex must be attached to only one ref_edge in our list. 01109 // Otherwise this is really a loop, which is still okay 01110 01111 // Search to find the starting edge 01112 RefEdge* start_edge = NULL; 01113 for( i=0; i<temp_list.size(); i++ ) 01114 { 01115 curr_edge = temp_list.get(); 01116 01117 // Since DLList doesn't allow a NULL item 01118 DLIList<RefEdge*> temp_list2; 01119 temp_list2 = temp_list; 01120 temp_list2.remove( curr_edge ); // Next item becomes current item 01121 01122 // get the vectors to start and end 01123 vector_start = curr_edge->start_coordinates(); 01124 vector_end = curr_edge->end_coordinates(); 01125 01126 if( !find_connected_ref_edge_by_coord( vector_start , 01127 temp_list2, start_flg ) || 01128 !find_connected_ref_edge_by_coord( vector_end, 01129 temp_list2, start_flg ) ) 01130 01131 { 01132 start_edge = curr_edge; 01133 //temp_list.change_to( curr_edge ); 01134 break; 01135 } 01136 } 01137 01138 temp_list.reset(); 01139 01140 if( start_edge == NULL ) 01141 start_edge = ref_edge_list.get(); 01142 01143 curr_edge = start_edge; 01144 ordered_list.append( curr_edge ); 01145 temp_list.move_to( start_edge ); 01146 temp_list.remove(); 01147 01148 next_edge = temp_list.get(); 01149 01150 // Attempt to use second edge in list as second edge in chain to 01151 // preserve original chain direction. 01152 RefEdge* next_edge_tmp = NULL; 01153 RefEdge* next_edge_tmp2 = NULL; 01154 // Check start first - if this fails check end next so chain order 01155 // will be established properly. 01156 vector_start = curr_edge->start_coordinates(); 01157 next_edge_tmp = find_connected_ref_edge_by_coord( vector_start, 01158 temp_list, start_flg ); 01159 if( next_edge_tmp != next_edge ) 01160 { 01161 vector_end = curr_edge->end_coordinates(); 01162 next_edge_tmp2 = find_connected_ref_edge_by_coord( vector_end, 01163 temp_list, start_flg ); 01164 } 01165 01166 if( next_edge_tmp2 ) 01167 next_edge_tmp = next_edge_tmp2; 01168 01169 if( next_edge_tmp ) 01170 { 01171 curr_edge = next_edge_tmp; 01172 ordered_list.append( next_edge_tmp ); 01173 temp_list.remove( next_edge_tmp ); 01174 } 01175 else 01176 { 01177 return CUBIT_FAILURE; 01178 } 01179 01180 while( temp_list.size() ) 01181 { 01182 if( start_flg ) // Curr edge was found on prev start, so use end 1st 01183 { 01184 vector_end = curr_edge->end_coordinates(); 01185 next_edge = find_connected_ref_edge_by_coord( vector_end , 01186 temp_list, start_flg ); 01187 } 01188 else 01189 { 01190 vector_start = curr_edge->start_coordinates(); 01191 next_edge = find_connected_ref_edge_by_coord( vector_start , 01192 temp_list, start_flg ); 01193 } 01194 01195 if( next_edge ) 01196 { 01197 curr_edge = next_edge; 01198 ordered_list.append( next_edge ); 01199 temp_list.remove( next_edge ); 01200 } 01201 else 01202 { 01203 return CUBIT_FAILURE; 01204 } 01205 } 01206 01207 ref_edge_list.clean_out(); 01208 ref_edge_list = ordered_list; 01209 01210 // Validate the chain 01211 DLIList<RefVertex*> problem_vertices; 01212 return check_valid_chain_by_coord( ref_edge_list, problem_vertices ); 01213 } 01214 01215 CubitStatus 01216 GeometryUtil::check_valid_chain_by_coord( DLIList<RefEdge*>& ref_edge_list, 01217 DLIList<RefVertex*>& problem_vertices ) 01218 { 01219 CubitStatus status = CUBIT_SUCCESS; 01220 01221 DLIList<RefEdge*> connected_edges; 01222 RefEdge* ref_edge_ptr; 01223 CubitVector vector_start, vector_end; 01224 01225 for( int i=0; i<ref_edge_list.size(); i++ ) 01226 { 01227 ref_edge_ptr = ref_edge_list.get_and_step(); 01228 01229 connected_edges.clean_out(); 01230 vector_start = ref_edge_ptr->start_coordinates(); 01231 find_connected_ref_edges_by_coord( vector_start , 01232 ref_edge_list, connected_edges ); 01233 if( connected_edges.size() != 1 && connected_edges.size() != 2 ) 01234 { 01235 status = CUBIT_FAILURE; 01236 problem_vertices.append_unique( ref_edge_ptr->start_vertex() ); 01237 } 01238 01239 connected_edges.clean_out(); 01240 vector_end = ref_edge_ptr->end_coordinates(); 01241 find_connected_ref_edges_by_coord( vector_end , 01242 ref_edge_list, connected_edges ); 01243 if( connected_edges.size() != 1 && connected_edges.size() != 2 ) 01244 { 01245 status = CUBIT_FAILURE; 01246 problem_vertices.append_unique( ref_edge_ptr->end_vertex() ); 01247 } 01248 } 01249 return status; 01250 } 01251 01252 CubitStatus 01253 GeometryUtil::check_valid_loop_by_coord( DLIList<RefEdge*>& ref_edge_list, 01254 DLIList<RefVertex*>& problem_vertices ) 01255 { 01256 CubitStatus status = CUBIT_SUCCESS; 01257 01258 DLIList<RefEdge*> connected_edges; 01259 RefEdge* ref_edge_ptr; 01260 CubitVector vector_start, vector_end; 01261 01262 for( int i=0; i<ref_edge_list.size(); i++ ) 01263 { 01264 ref_edge_ptr = ref_edge_list.get_and_step(); 01265 01266 connected_edges.clean_out(); 01267 vector_start = ref_edge_ptr->start_coordinates(); 01268 find_connected_ref_edges_by_coord( vector_start , 01269 ref_edge_list, connected_edges ); 01270 if( connected_edges.size() != 2 ) 01271 { 01272 status = CUBIT_FAILURE; 01273 problem_vertices.append_unique( ref_edge_ptr->start_vertex() ); 01274 } 01275 01276 connected_edges.clean_out(); 01277 vector_end = ref_edge_ptr->end_coordinates(); 01278 find_connected_ref_edges_by_coord( vector_end , 01279 ref_edge_list, connected_edges ); 01280 if( connected_edges.size() != 2 ) 01281 { 01282 status = CUBIT_FAILURE; 01283 problem_vertices.append_unique( ref_edge_ptr->end_vertex() ); 01284 } 01285 } 01286 return status; 01287 } 01288 01289 // Added by CAT (SRS) 01290 RefEdge* 01291 GeometryUtil::find_connected_ref_edge( RefVertex* ref_vertex_ptr, 01292 DLIList<RefEdge*>& ref_edge_list, 01293 int& start_flg ) 01294 { 01295 RefEdge* ref_edge; 01296 DLIList<RefEdge*> tmp_list = ref_edge_list; 01297 01298 tmp_list.reset(); 01299 for( int i=0; i<tmp_list.size(); i++ ) 01300 { 01301 ref_edge = tmp_list.get_and_step(); 01302 01303 if( ref_edge->start_vertex() == ref_vertex_ptr ) 01304 { 01305 start_flg = 1; 01306 return ref_edge; 01307 } 01308 01309 if( ref_edge->end_vertex() == ref_vertex_ptr ) 01310 { 01311 start_flg = 0; 01312 return ref_edge; 01313 } 01314 } 01315 return NULL; 01316 } 01317 01318 void 01319 GeometryUtil::find_connected_ref_edges( RefVertex* ref_vertex_ptr, 01320 DLIList<RefEdge*>& ref_edge_list, 01321 DLIList<RefEdge*>& connected_edges_list ) 01322 { 01323 RefEdge* ref_edge; 01324 DLIList<RefEdge*> tmp_list = ref_edge_list; 01325 01326 tmp_list.reset(); 01327 for( int i=0; i<tmp_list.size(); i++ ) 01328 { 01329 ref_edge = tmp_list.get_and_step(); 01330 01331 if( ref_edge->start_vertex() == ref_vertex_ptr ) 01332 connected_edges_list.append_unique( ref_edge ); 01333 01334 if( ref_edge->end_vertex() == ref_vertex_ptr ) 01335 connected_edges_list.append_unique( ref_edge ); 01336 } 01337 } 01338 01339 CubitStatus 01340 GeometryUtil::form_ref_edge_loop( DLIList<RefEdge*>& ref_edge_list ) 01341 { 01342 int i; 01343 01344 if( ref_edge_list.size() == 0 ) 01345 return CUBIT_FAILURE; 01346 01347 if( ref_edge_list.size() == 1 ) 01348 { 01349 double period; 01350 if( ref_edge_list.get()->is_periodic( period ) ) 01351 return CUBIT_SUCCESS; 01352 } 01353 01354 // First form a chain (which can be a loop) 01355 if( form_ref_edge_chain( ref_edge_list ) == CUBIT_FAILURE ) 01356 return CUBIT_FAILURE; 01357 01358 // Now check to make sure a valid loop was formed. For a valid loop 01359 // every vertex must have exactly 2 edges connected to it. The only 01360 // exception is a periodic curve where there is only one vertex, which 01361 // was checked for before. 01362 DLIList<RefEdge*> connected_edges; 01363 RefEdge* ref_edge_ptr; 01364 for( i=0; i<ref_edge_list.size(); i++ ) 01365 { 01366 ref_edge_ptr = ref_edge_list.get_and_step(); 01367 01368 connected_edges.clean_out(); 01369 find_connected_ref_edges( ref_edge_ptr->start_vertex(), ref_edge_list, connected_edges ); 01370 if( connected_edges.size() != 2 ) 01371 return CUBIT_FAILURE; 01372 01373 connected_edges.clean_out(); 01374 find_connected_ref_edges( ref_edge_ptr->end_vertex(), ref_edge_list, connected_edges ); 01375 if( connected_edges.size() != 2 ) 01376 return CUBIT_FAILURE; 01377 } 01378 01379 return CUBIT_SUCCESS; 01380 } 01381 01382 CubitStatus 01383 GeometryUtil::form_ref_edge_chain( DLIList<RefEdge*>& ref_edge_list ) 01384 { 01385 if( ref_edge_list.size() == 1 ) 01386 return CUBIT_SUCCESS; 01387 01388 int i; 01389 int start_flg = 0; 01390 01391 RefVertex* ref_vertex_start, *ref_vertex_end; 01392 RefEdge* curr_edge; 01393 RefEdge* next_edge; 01394 01395 DLIList<RefEdge*> temp_list = ref_edge_list; 01396 DLIList<RefEdge*> ordered_list; 01397 01398 // Start vertex must be attached to only one ref_edge in our list. 01399 // Otherwise this is really a loop, which is still okay 01400 01401 // Search to find the starting edge 01402 RefEdge* start_edge = NULL; 01403 for( i=0; i<temp_list.size(); i++ ) 01404 { 01405 curr_edge = temp_list.get(); 01406 01407 // Since DLList doesn't allow a NULL item 01408 DLIList<RefEdge*> temp_list2; 01409 temp_list2 = temp_list; 01410 temp_list2.remove( curr_edge ); // Next item becomes current item 01411 01412 // get the vectors to start and end 01413 ref_vertex_start = curr_edge->start_vertex(); 01414 ref_vertex_end = curr_edge->end_vertex(); 01415 01416 if( !find_connected_ref_edge( ref_vertex_start, 01417 temp_list2, start_flg ) || 01418 !find_connected_ref_edge( ref_vertex_end, 01419 temp_list2, start_flg ) ) 01420 01421 { 01422 start_edge = curr_edge; 01423 //temp_list.change_to( curr_edge ); 01424 break; 01425 } 01426 } 01427 01428 temp_list.reset(); 01429 01430 if( start_edge == NULL ) 01431 start_edge = ref_edge_list.get(); 01432 01433 curr_edge = start_edge; 01434 ordered_list.append( curr_edge ); 01435 temp_list.move_to( start_edge ); 01436 temp_list.remove(); 01437 01438 next_edge = temp_list.get(); 01439 01440 // Attempt to use second edge in list as second edge in chain to 01441 // preserve original chain direction. 01442 RefEdge* next_edge_tmp = NULL; 01443 RefEdge* next_edge_tmp2 = NULL; 01444 // Check start first - if this fails check end next so chain order 01445 // will be established properly. 01446 ref_vertex_start = curr_edge->start_vertex(); 01447 next_edge_tmp = find_connected_ref_edge( ref_vertex_start, 01448 temp_list, start_flg ); 01449 if( next_edge_tmp != next_edge ) 01450 { 01451 ref_vertex_end = curr_edge->end_vertex(); 01452 next_edge_tmp2 = find_connected_ref_edge( ref_vertex_end, 01453 temp_list, start_flg ); 01454 } 01455 01456 if( next_edge_tmp2 ) 01457 next_edge_tmp = next_edge_tmp2; 01458 01459 if( next_edge_tmp ) 01460 { 01461 curr_edge = next_edge_tmp; 01462 ordered_list.append( next_edge_tmp ); 01463 temp_list.remove( next_edge_tmp ); 01464 } 01465 else 01466 { 01467 return CUBIT_FAILURE; 01468 } 01469 01470 while( temp_list.size() ) 01471 { 01472 if( start_flg ) // Curr edge was found on prev start, so use end 1st 01473 { 01474 ref_vertex_end = curr_edge->end_vertex(); 01475 next_edge = find_connected_ref_edge( ref_vertex_end, temp_list, start_flg ); 01476 } 01477 else 01478 { 01479 ref_vertex_start = curr_edge->start_vertex(); 01480 next_edge = find_connected_ref_edge( ref_vertex_start, temp_list, start_flg ); 01481 } 01482 01483 if( next_edge ) 01484 { 01485 curr_edge = next_edge; 01486 ordered_list.append( next_edge ); 01487 temp_list.remove( next_edge ); 01488 } 01489 else 01490 { 01491 return CUBIT_FAILURE; 01492 } 01493 } 01494 01495 ref_edge_list.clean_out(); 01496 ref_edge_list = ordered_list; 01497 01498 // Validate the chain 01499 DLIList<RefVertex*> problem_vertices; 01500 return check_valid_chain( ref_edge_list, problem_vertices ); 01501 } 01502 01503 CubitStatus 01504 GeometryUtil::check_valid_chain( DLIList<RefEdge*>& ref_edge_list, 01505 DLIList<RefVertex*>& problem_vertices ) 01506 { 01507 CubitStatus status = CUBIT_SUCCESS; 01508 01509 DLIList<RefEdge*> connected_edges; 01510 RefEdge* ref_edge_ptr; 01511 RefVertex* vertex_start, *vertex_end; 01512 01513 for( int i=0; i<ref_edge_list.size(); i++ ) 01514 { 01515 ref_edge_ptr = ref_edge_list.get_and_step(); 01516 01517 connected_edges.clean_out(); 01518 vertex_start = ref_edge_ptr->start_vertex(); 01519 find_connected_ref_edges( vertex_start , 01520 ref_edge_list, connected_edges ); 01521 if( connected_edges.size() != 1 && connected_edges.size() != 2 ) 01522 { 01523 status = CUBIT_FAILURE; 01524 problem_vertices.append_unique( ref_edge_ptr->start_vertex() ); 01525 } 01526 01527 connected_edges.clean_out(); 01528 vertex_end = ref_edge_ptr->end_vertex(); 01529 find_connected_ref_edges( vertex_end , 01530 ref_edge_list, connected_edges ); 01531 if( connected_edges.size() != 1 && connected_edges.size() != 2 ) 01532 { 01533 status = CUBIT_FAILURE; 01534 problem_vertices.append_unique( ref_edge_ptr->end_vertex() ); 01535 } 01536 } 01537 return status; 01538 } 01539 01540 CubitStatus 01541 GeometryUtil::check_valid_loop( DLIList<RefEdge*>& ref_edge_list, 01542 DLIList<RefVertex*>& problem_vertices ) 01543 { 01544 CubitStatus status = CUBIT_SUCCESS; 01545 01546 DLIList<RefEdge*> connected_edges; 01547 RefEdge* ref_edge_ptr; 01548 RefVertex* vertex_start; 01549 RefVertex* vertex_end; 01550 01551 for( int i=0; i<ref_edge_list.size(); i++ ) 01552 { 01553 ref_edge_ptr = ref_edge_list.get_and_step(); 01554 01555 connected_edges.clean_out(); 01556 vertex_start = ref_edge_ptr->start_vertex(); 01557 find_connected_ref_edges( vertex_start , 01558 ref_edge_list, connected_edges ); 01559 if( connected_edges.size() != 2 ) 01560 { 01561 status = CUBIT_FAILURE; 01562 problem_vertices.append_unique( ref_edge_ptr->start_vertex() ); 01563 } 01564 01565 connected_edges.clean_out(); 01566 vertex_end = ref_edge_ptr->end_vertex(); 01567 find_connected_ref_edges( vertex_end , 01568 ref_edge_list, connected_edges ); 01569 if( connected_edges.size() != 2 ) 01570 { 01571 status = CUBIT_FAILURE; 01572 problem_vertices.append_unique( ref_edge_ptr->end_vertex() ); 01573 } 01574 } 01575 return status; 01576 } 01577 01578 //------------------------------------------------------------------------- 01579 // Purpose : check vertex order and tangent direction for RefEdge 01580 // 01581 // Special Notes : 01582 // 01583 // Creator : Jason Kraftcheck 01584 // 01585 // Creation Date : 09/07/00 01586 //------------------------------------------------------------------------- 01587 CubitBoolean GeometryUtil::valid_edge( RefEdge* edge_ptr, 01588 CubitBoolean print_error ) 01589 { 01590 RefVertex* start_vertex = edge_ptr->start_vertex(); 01591 RefVertex* end_vertex = edge_ptr->end_vertex(); 01592 CubitBoolean result = CUBIT_TRUE; 01593 01594 if (!edge_ptr->get_curve_ptr()) 01595 { 01596 if (print_error) 01597 PRINT_ERROR("Curve %d does not have a TopologyBridge.\n", edge_ptr->id()); 01598 return CUBIT_FALSE; 01599 } 01600 else if(!start_vertex) 01601 { 01602 if (print_error) 01603 PRINT_ERROR("Curve %d has no start vertex.\n", edge_ptr->id()); 01604 return CUBIT_FALSE; 01605 } 01606 else if(!end_vertex) 01607 { 01608 if (print_error) 01609 PRINT_ERROR("Curve %d has no end vertex.\n", edge_ptr->id()); 01610 return CUBIT_FALSE; 01611 } 01612 else if (!start_vertex->get_point_ptr()) 01613 { 01614 if (print_error) 01615 PRINT_ERROR("Vertex %d has no Point.\n", start_vertex->id()); 01616 return CUBIT_FALSE; 01617 } 01618 else if (!end_vertex->get_point_ptr()) 01619 { 01620 if (print_error) 01621 PRINT_ERROR("Vertex %d has no Point.\n", end_vertex->id()); 01622 return CUBIT_FALSE; 01623 } 01624 else if (edge_ptr->get_curve_ptr()->geometry_type() == POINT_CURVE_TYPE) 01625 { 01626 if (start_vertex != end_vertex) 01627 { 01628 if (print_error) 01629 PRINT_ERROR("Curve %d is a point-curve but has different " 01630 "vertices (%d and %d).\n", edge_ptr->id(), 01631 start_vertex->id(), end_vertex->id()); 01632 result = CUBIT_FALSE; 01633 } 01634 } 01635 else 01636 { 01637 double u_start = edge_ptr->start_param(); 01638 double u_end = edge_ptr->end_param(); 01639 double period; 01640 CubitBoolean periodic = edge_ptr->is_periodic( period ); 01641 if( start_vertex == end_vertex ) 01642 { 01643 if( !periodic && print_error ) 01644 PRINT_WARNING("Curve %d is closed but not periodic.\n",edge_ptr->id()); 01645 } 01646 01647 double u_start_vtx = edge_ptr->u_from_position( start_vertex->coordinates() ); 01648 double u_end_vtx = edge_ptr->u_from_position( end_vertex->coordinates() ); 01649 01650 if (periodic) 01651 { 01652 // For a periodic curve the point perp operation could return u_start or 01653 // u_end for both start_vertex and end_vertex so try to put everything 01654 // in the range from u_start to u_end and recognize cases where u_start_vtx 01655 // equals u_end by accident (and vice versa). 01656 if (period > 0.0) 01657 { 01658 // Logically, if u_start_vtx >= u_end... 01659 while (u_start_vtx > u_end - CUBIT_RESABS) 01660 u_start_vtx -= period; 01661 // Logically, if u_start_vtx < u_start... 01662 while (u_start_vtx < u_start - CUBIT_RESABS) 01663 u_start_vtx += period; 01664 // Logically, if u_end_vtx > u_end... 01665 while (u_end_vtx > u_end + CUBIT_RESABS) 01666 u_end_vtx -= period; 01667 // Logically, if u_end_vtx <= u_start... 01668 while (u_end_vtx < u_start + CUBIT_RESABS) 01669 u_end_vtx += period; 01670 } 01671 else if (period < 0.0) 01672 { 01673 // Logically, if u_start_vtx <= u_end ... 01674 while (u_start_vtx < u_end + CUBIT_RESABS) 01675 u_start_vtx += period; 01676 // Logically, if u_start_vtx > u_start... 01677 while (u_start_vtx > u_start + CUBIT_RESABS) 01678 u_start_vtx -= period; 01679 // Logically, if u_end_vtx < u_end... 01680 while (u_end_vtx < u_end - CUBIT_RESABS) 01681 u_end_vtx += period; 01682 // Logically, if u_end_vtx >= u_start... 01683 while (u_end_vtx > u_start - CUBIT_RESABS) 01684 u_end_vtx -= period; 01685 } 01686 } 01687 01688 01689 01690 if( (fabs( u_start_vtx - u_start ) > CUBIT_RESABS) && print_error ) 01691 PRINT_WARNING("Vertex %d does not appear to be at the start of curve %d.\n", 01692 start_vertex->id(), edge_ptr->id() ); 01693 if( (fabs( u_end_vtx - u_end ) > CUBIT_RESABS) && print_error ) 01694 PRINT_WARNING("Vertex %d does not appear to be at the end of curve %d.\n", 01695 end_vertex->id(), edge_ptr->id() ); 01696 01697 double u_diff = u_start - u_end; 01698 double u_diff_vtx = u_start_vtx - u_end_vtx; 01699 if( (u_diff * u_diff_vtx) < 0 ) 01700 { 01701 if( print_error ) 01702 { 01703 PRINT_ERROR("Vertices on curve %d appear to be in the wrong order.\n", 01704 edge_ptr->id()); 01705 PRINT_INFO("\tstart_param = %f, end_param = %f, u(start_vtx) = %f, " 01706 "u(end_vtx) = %f\n",u_start,u_end,u_start_vtx,u_end_vtx); 01707 } 01708 result = CUBIT_FALSE; 01709 } 01710 01711 double step = (u_end - u_start) / 100.; 01712 if( step > 0.0 ) 01713 { 01714 if( step < CUBIT_RESABS ) step = CUBIT_RESABS; 01715 if( (u_start + step) > u_end ) step = u_end - u_start; 01716 } 01717 else 01718 { 01719 if( step > -CUBIT_RESABS ) step = -CUBIT_RESABS; 01720 if( (u_start + step) < u_end ) step = u_end - u_start; 01721 } 01722 01723 CubitVector closest, tangent, next_pos; 01724 edge_ptr->closest_point( start_vertex->coordinates(), closest, &tangent ); 01725 /* This fails a lot with spline curves, so skip it. 01726 double distance = (start_vertex->coordinates() - closest).length(); 01727 if( (distance > GEOMETRY_RESABS) && print_error ) 01728 { 01729 PRINT_WARNING("Vertex %d of curve %d does not appear to lie on the curve.\n", 01730 start_vertex->id(), edge_ptr->id() ); 01731 } 01732 */ 01733 edge_ptr->position_from_u( u_start + step, next_pos ); 01734 next_pos -= closest; 01735 if( tangent.length_squared() < CUBIT_RESABS ) 01736 { 01737 if( print_error ) 01738 PRINT_ERROR("Zero-length tangent vector returned at start of curve %d\n", edge_ptr->id()); 01739 result = CUBIT_FALSE; 01740 } 01741 else if( next_pos.length_squared() < CUBIT_RESABS ) 01742 { 01743 if( print_error ) 01744 PRINT_WARNING("Distance for delta-u of %f in [%f,%f] near start" 01745 " of curve %d appears to be zero.\n", 01746 step, u_start, u_end, edge_ptr->id()); 01747 } 01748 else if( tangent.interior_angle( next_pos ) > (90. - CUBIT_RESABS) ) 01749 { 01750 if( print_error ) 01751 PRINT_ERROR("The tangent at the start of curve %d appears " 01752 "to be in the wrong direction.\n",edge_ptr->id()); 01753 result = CUBIT_FALSE; 01754 } 01755 01756 edge_ptr->closest_point( end_vertex->coordinates(), closest, &tangent ); 01757 /* This fails a lot with spline curves, so skip it. 01758 distance = (end_vertex->coordinates() - closest).length(); 01759 if( (distance > GEOMETRY_RESABS) && print_error ) 01760 { 01761 PRINT_WARNING("Vertex %d of curve %d does not appear to lie on the curve.\n", 01762 end_vertex->id(), edge_ptr->id() ); 01763 } 01764 */ 01765 edge_ptr->position_from_u( u_end - step, next_pos ); 01766 next_pos = closest - next_pos; 01767 if( tangent.length_squared() < CUBIT_RESABS ) 01768 { 01769 if( print_error ) 01770 PRINT_ERROR("Zero-length tangent vector returned at end of %d\n", edge_ptr->id()); 01771 result = CUBIT_FALSE; 01772 } 01773 else if( next_pos.length_squared() < CUBIT_RESABS ) 01774 { 01775 if( print_error ) 01776 PRINT_WARNING("Distance for delta-u of %f in [%f,%f] near end" 01777 " of curve %d appears to be zero.\n", 01778 step, u_start, u_end, edge_ptr->id()); 01779 } 01780 else if( tangent.interior_angle( next_pos ) > (90. - CUBIT_RESABS) ) 01781 { 01782 if( print_error ) 01783 PRINT_ERROR("The tangent at the end of curve %d appears " 01784 "to be in the wrong direction.\n",edge_ptr->id()); 01785 result = CUBIT_FALSE; 01786 } 01787 } 01788 01789 return result; 01790 } 01791 01792 CubitBoolean GeometryUtil::valid_loop_coedges( Loop* loop_ptr, 01793 CubitBoolean print_error ) 01794 { 01795 CubitBoolean result = CUBIT_TRUE; 01796 RefFace* loop_owner = loop_ptr->get_ref_face_ptr(); 01797 int surf_id = loop_owner ? loop_owner->id() : 0; 01798 01799 if( !loop_ptr->get_loop_sm_ptr() && print_error ) 01800 { 01801 PRINT_WARNING("Loop in Surface %d has no OSME pointer.\n",surf_id); 01802 } 01803 01804 DLIList<CoEdge*> coedge_list; 01805 CubitStatus status = loop_ptr->ordered_co_edges( coedge_list ); 01806 if( ! status ) 01807 { 01808 if( print_error ) 01809 PRINT_ERROR("Query for loop coedges failed!\n"); 01810 return CUBIT_FALSE; 01811 } 01812 01813 if( coedge_list.size() < 2 ) return CUBIT_TRUE; 01814 01815 CoEdge* prev_coedge = coedge_list.get_and_step(); 01816 RefEdge* prev_edge = prev_coedge->get_ref_edge_ptr(); 01817 for( int i = coedge_list.size(); i > 0; i-- ) 01818 { 01819 CoEdge* curr_coedge = coedge_list.get_and_step(); 01820 RefEdge* curr_edge = curr_coedge->get_ref_edge_ptr(); 01821 01822 if (!curr_edge) 01823 { 01824 if (print_error) 01825 PRINT_ERROR("CoEdge in surface %d has no Curve.\n", surf_id); 01826 result = CUBIT_FAILURE; 01827 continue; 01828 } 01829 01830 if( !curr_coedge->get_co_edge_sm_ptr() && print_error ) 01831 { 01832 PRINT_WARNING("CoEdge between surface %d and curve %d has " 01833 "no OSME pointer.\n", surf_id, curr_edge->id() ); 01834 } 01835 01836 RefVertex* common = curr_edge->common_ref_vertex( prev_edge ); 01837 if( !common ) 01838 { 01839 if( print_error ) 01840 PRINT_ERROR("Curves %d and %d are ajacent in a Loop on surface %d, " 01841 "but do not have a common vertex.\n", 01842 prev_edge->id(), curr_edge->id(), surf_id ); 01843 result = CUBIT_FALSE; 01844 } 01845 01846 RefVertex* start_vtx = 0; 01847 CubitSense sense = curr_coedge->get_sense(); 01848 switch( sense ) 01849 { 01850 case CUBIT_FORWARD: 01851 start_vtx = curr_edge->start_vertex(); 01852 break; 01853 case CUBIT_REVERSED: 01854 start_vtx = curr_edge->end_vertex(); 01855 break; 01856 case CUBIT_UNKNOWN: 01857 default: 01858 start_vtx = 0; 01859 break; 01860 } 01861 01862 RefVertex* end_vtx = 0; 01863 switch( prev_coedge->get_sense() ) 01864 { 01865 case CUBIT_FORWARD: 01866 end_vtx = prev_edge->end_vertex(); 01867 break; 01868 case CUBIT_REVERSED: 01869 end_vtx = prev_edge->start_vertex(); 01870 break; 01871 default: 01872 break; 01873 } 01874 01875 if( start_vtx == NULL ) 01876 { 01877 if( print_error ) 01878 PRINT_ERROR("Curve %d has an unknown sense on surface %d.\n", 01879 curr_edge->id(), surf_id ); 01880 result = CUBIT_FALSE; 01881 } 01882 else if( start_vtx != end_vtx ) 01883 { 01884 if( print_error ) 01885 PRINT_ERROR("The sense of curve %d (%s) on surface %d appears " 01886 "to be incorrect with respect to the previous curve " 01887 "in the loop (curve %d).\n", curr_edge->id(), 01888 sense == CUBIT_FORWARD ? "forward" : "reverse", 01889 surf_id, prev_edge->id() ); 01890 result = CUBIT_FALSE; 01891 } 01892 01893 prev_edge = curr_edge; 01894 prev_coedge = curr_coedge; 01895 } 01896 01897 return result; 01898 } 01899 01900 CubitBoolean GeometryUtil::valid_shell_cofaces( Shell* shell_ptr, 01901 CubitBoolean print_error ) 01902 { 01903 DLIList<CoFace*> coface_list, ajacent_cofaces; 01904 DLIList<CoEdge*> coedge_list; 01905 shell_ptr->co_faces( coface_list ); 01906 CubitBoolean result = CUBIT_TRUE; 01907 RefVolume* vol_ptr = shell_ptr->get_ref_volume_ptr(); 01908 int vol_id = vol_ptr ? vol_ptr->id() : 0; 01909 01910 if( ! shell_ptr->get_shell_sm_ptr() && print_error) 01911 { 01912 PRINT_WARNING("Shell in volume %d has no OSME pointer.\n",vol_id); 01913 } 01914 01915 01916 while( coface_list.size() > 0 ) 01917 { 01918 CoFace* coface_ptr = coface_list.pop(); 01919 RefFace* face_ptr = coface_ptr->get_ref_face_ptr(); 01920 if( !face_ptr ) 01921 { 01922 if( print_error ) 01923 PRINT_ERROR("Encountered a CoFace without a RefFace in volume %d.\n",vol_id); 01924 result = CUBIT_FALSE; 01925 continue; 01926 } 01927 if (face_ptr->is_nonmanifold(shell_ptr)) 01928 { 01929 continue; 01930 } 01931 CubitSense sense = coface_ptr->get_sense(); 01932 if( sense == CUBIT_UNKNOWN ) 01933 { 01934 if( print_error ) 01935 PRINT_ERROR("Surface %d has an unknown sense with respect to volume %d.\n", 01936 face_ptr->id(), vol_id ); 01937 result = CUBIT_FALSE; 01938 continue; 01939 } 01940 01941 01942 coedge_list.clean_out(); 01943 face_ptr->co_edges( coedge_list ); 01944 01945 for( int i = coedge_list.size(); i > 0; i-- ) 01946 { 01947 CoEdge* coedge_ptr = coedge_list.get_and_step(); 01948 RefEdge* edge_ptr = coedge_ptr->get_ref_edge_ptr(); 01949 if( !edge_ptr ) 01950 { 01951 result = CUBIT_FALSE; 01952 if( print_error ) 01953 PRINT_ERROR("CoEdge @ %p in Surface %d has no Curve!\n", 01954 (void*)coedge_ptr, face_ptr->id() ); 01955 continue; 01956 } 01957 01958 ajacent_cofaces.clean_out(); 01959 edge_ptr->co_faces( ajacent_cofaces ); 01960 ajacent_cofaces.intersect( coface_list ); 01961 01962 CubitSense coedge_sense = coedge_ptr->get_sense(); 01963 if( coedge_sense == CUBIT_UNKNOWN ) 01964 { 01965 if( print_error ) 01966 PRINT_ERROR("CoEdge connecting Curve %d to surface %d " 01967 "has UNKNOWN sense.\n",edge_ptr->id(), face_ptr->id() ); 01968 result = CUBIT_FALSE; 01969 continue; 01970 } 01971 01972 if( (ajacent_cofaces.size() > 1) && print_error ) 01973 { 01974 PRINT_WARNING("Non-manifold topology at curve %d on volume %d " 01975 "may result in false errors being reported.\n", 01976 edge_ptr->id(), vol_id ); 01977 } 01978 01979 for( int j = ajacent_cofaces.size(); j > 0; j-- ) 01980 { 01981 CoFace* other_coface = ajacent_cofaces.get_and_step(); 01982 RefFace* other_face = other_coface->get_ref_face_ptr(); 01983 if( ! other_face ) 01984 { 01985 if( print_error ) 01986 PRINT_ERROR("Encountered a CoFace on volume %d that does not " 01987 "have a RefFace!\n",vol_id); 01988 result = CUBIT_FALSE; 01989 continue; 01990 } 01991 CubitSense other_coedge_sense = edge_ptr->sense( other_face ); 01992 if( other_coedge_sense == CUBIT_UNKNOWN ) 01993 { 01994 if( print_error ) 01995 PRINT_ERROR("Curve %d has unknown sense with respect to " 01996 "surface %d.\n",edge_ptr->id(), other_face->id() ); 01997 result = CUBIT_FALSE; 01998 continue; 01999 } 02000 CubitSense other_sense = other_coface->get_sense(); 02001 if( other_sense == CUBIT_UNKNOWN ) 02002 { 02003 if( print_error ) 02004 PRINT_ERROR("Surface %d has an unknown sense with respect " 02005 "to volume %d.\n", other_face->id(), vol_id ); 02006 result = CUBIT_FALSE; 02007 continue; 02008 } 02009 02010 if( ((sense == other_sense) && (coedge_sense == other_coedge_sense)) 02011 ||((sense != other_sense) && (coedge_sense != other_coedge_sense)) ) 02012 { 02013 if( print_error ) 02014 PRINT_ERROR("Incompatible CoFace senses found at curve %d in " 02015 "volume %d.\n" 02016 " Surface CoFace Sense CoEdge Sense\n" 02017 " ------- ------------ ------------\n" 02018 " %7d %12s %12s\n %7d %12s %12s\n", 02019 edge_ptr->id(), vol_id, 02020 face_ptr->id(), 02021 sense == CUBIT_FORWARD ? "forward" : "reverse", 02022 coedge_sense == CUBIT_FORWARD ? "forward" : "reverse", 02023 other_face->id(), 02024 other_sense == CUBIT_FORWARD ? "forward" : "reverse", 02025 other_coedge_sense == CUBIT_FORWARD ? 02026 "forward" : "reverse"); 02027 result = CUBIT_FALSE; 02028 } 02029 } // end for( j ) 02030 02031 } // end for( i ) 02032 02033 } // end while( coface_list.size() ) 02034 02035 return result; 02036 } 02037 02038 CubitBoolean GeometryUtil::valid_topology( TopologyEntity* topo_ptr, 02039 CubitBoolean print_error, 02040 DLIList<TopologyEntity*>* invalid_list ) 02041 { 02042 CubitBoolean result = CUBIT_TRUE; 02043 DLIList<Shell*> shell_list; 02044 DLIList<Loop*> loop_list; 02045 DLIList<RefEdge*> edge_list; 02046 Shell* shell_ptr; 02047 Loop* loop_ptr; 02048 RefEdge* edge_ptr; 02049 int i; 02050 02051 if( CAST_TO( topo_ptr, Body ) || 02052 CAST_TO( topo_ptr, CoVolume ) || 02053 CAST_TO( topo_ptr, RefVolume ) ) 02054 { 02055 shell_list.clean_out(); 02056 topo_ptr->shells( shell_list ); 02057 for( i = shell_list.size(); i > 0; i-- ) 02058 { 02059 shell_ptr = shell_list.get_and_step(); 02060 if( ! valid_shell_cofaces( shell_ptr, print_error ) ) 02061 { 02062 if( invalid_list ) invalid_list->append( shell_ptr ); 02063 result = CUBIT_FALSE; 02064 } 02065 } 02066 } 02067 if(CAST_TO( topo_ptr, Body ) || 02068 CAST_TO( topo_ptr, CoVolume ) || 02069 CAST_TO( topo_ptr, RefVolume ) || 02070 CAST_TO( topo_ptr, Shell ) ) 02071 { 02072 shell_ptr = CAST_TO( topo_ptr, Shell ); 02073 if( shell_ptr && !valid_shell_cofaces( shell_ptr, print_error ) ) 02074 { 02075 if( invalid_list ) invalid_list->append( shell_ptr ); 02076 result = CUBIT_FALSE; 02077 } 02078 } 02079 if(CAST_TO( topo_ptr, Body ) || 02080 CAST_TO( topo_ptr, CoVolume ) || 02081 CAST_TO( topo_ptr, RefVolume ) || 02082 CAST_TO( topo_ptr, Shell ) || 02083 CAST_TO( topo_ptr, CoFace ) || 02084 CAST_TO( topo_ptr, RefFace ) ) 02085 { 02086 loop_list.clean_out(); 02087 topo_ptr->loops( loop_list ); 02088 for( i = loop_list.size(); i > 0; i-- ) 02089 { 02090 loop_ptr = loop_list.get_and_step(); 02091 if( ! valid_loop_coedges( loop_ptr, print_error ) ) 02092 { 02093 if( invalid_list ) invalid_list->append( loop_ptr ); 02094 result = CUBIT_FALSE; 02095 } 02096 } 02097 } 02098 if(CAST_TO( topo_ptr, Body ) || 02099 CAST_TO( topo_ptr, CoVolume ) || 02100 CAST_TO( topo_ptr, RefVolume ) || 02101 CAST_TO( topo_ptr, Shell ) || 02102 CAST_TO( topo_ptr, CoFace ) || 02103 CAST_TO( topo_ptr, RefFace ) || 02104 CAST_TO( topo_ptr, Loop ) ) 02105 { 02106 loop_ptr = CAST_TO( topo_ptr, Loop ); 02107 if( loop_ptr && !valid_loop_coedges( loop_ptr, print_error ) ) 02108 { 02109 if( invalid_list ) invalid_list->append( loop_ptr ); 02110 result = CUBIT_FALSE; 02111 } 02112 } 02113 if(CAST_TO( topo_ptr, Body ) || 02114 CAST_TO( topo_ptr, CoVolume ) || 02115 CAST_TO( topo_ptr, RefVolume ) || 02116 CAST_TO( topo_ptr, Shell ) || 02117 CAST_TO( topo_ptr, CoFace ) || 02118 CAST_TO( topo_ptr, RefFace ) || 02119 CAST_TO( topo_ptr, Loop ) || 02120 CAST_TO( topo_ptr, CoEdge ) ) 02121 { 02122 edge_list.clean_out(); 02123 topo_ptr->ref_edges( edge_list ); 02124 for( i = edge_list.size(); i > 0; i-- ) 02125 { 02126 edge_ptr = edge_list.get_and_step(); 02127 if( !valid_edge( edge_ptr, print_error ) ) 02128 { 02129 if( invalid_list ) invalid_list->append( edge_ptr ); 02130 result = CUBIT_FALSE; 02131 } 02132 } 02133 } 02134 if(CAST_TO( topo_ptr, Body ) || 02135 CAST_TO( topo_ptr, CoVolume ) || 02136 CAST_TO( topo_ptr, RefVolume ) || 02137 CAST_TO( topo_ptr, Shell ) || 02138 CAST_TO( topo_ptr, CoFace ) || 02139 CAST_TO( topo_ptr, RefFace ) || 02140 CAST_TO( topo_ptr, Loop ) || 02141 CAST_TO( topo_ptr, CoEdge ) || 02142 CAST_TO( topo_ptr, RefEdge ) ) 02143 { 02144 edge_ptr = CAST_TO( topo_ptr, RefEdge ); 02145 if( edge_ptr && !valid_edge( edge_ptr, print_error ) ) 02146 { 02147 if( invalid_list ) invalid_list->append( edge_ptr ); 02148 result = CUBIT_FALSE; 02149 } 02150 } 02151 else if( CAST_TO( topo_ptr, Chain ) || 02152 CAST_TO( topo_ptr, CoVertex ) || 02153 CAST_TO( topo_ptr, RefVertex ) ) 02154 ;//Do nothing 02155 else 02156 { 02157 if( print_error ) 02158 PRINT_WARNING("Unknown entity type '%s' passed to GeometryUtil::" 02159 "valid_topology(..).\n",topo_ptr->class_name() ); 02160 } 02161 02162 return result; 02163 } 02164 02165 //------------------------------------------------------------------------- 02166 // Purpose : Compare VGI topology to SM topology 02167 // 02168 // Special Notes : 02169 // 02170 // Creator : Jason Kraftcheck 02171 // 02172 // Creation Date : 01/19/01 02173 //------------------------------------------------------------------------- 02174 CubitBoolean GeometryUtil::valid_sm_topology( DLIList<RefEntity*>& entity_list, 02175 CubitBoolean print_error ) 02176 { 02177 CubitBoolean result = CUBIT_TRUE; 02178 02179 DLIList<Body*> body_list; 02180 DLIList<RefVolume*> vol_list, child_vols ; 02181 DLIList<RefFace*> face_list, child_faces; 02182 DLIList<RefEdge*> edge_list, child_edges; 02183 DLIList<RefVertex*> vtx_list, child_vtx; 02184 CAST_LIST( entity_list, body_list, Body ); 02185 CAST_LIST( entity_list, vol_list , RefVolume); 02186 CAST_LIST( entity_list, face_list, RefFace ); 02187 CAST_LIST( entity_list, edge_list, RefEdge ); 02188 CAST_LIST( entity_list, vtx_list , RefVertex); 02189 02190 int i; 02191 for( i = body_list.size(); i--; ) 02192 { 02193 Body* body_ptr = body_list.get_and_step(); 02194 if( !valid_sm_topology( body_ptr, print_error ) ) 02195 result = CUBIT_FALSE; 02196 child_vols.clean_out(); 02197 body_ptr->ref_volumes( child_vols ); 02198 vol_list.merge_unique( child_vols ); 02199 } 02200 for( i = vol_list.size(); i--; ) 02201 { 02202 RefVolume* vol_ptr = vol_list.get_and_step(); 02203 if( !valid_sm_topology( vol_ptr, print_error ) ) 02204 result = CUBIT_FALSE; 02205 child_faces.clean_out(); 02206 vol_ptr->ref_faces( child_faces ); 02207 face_list.merge_unique( child_faces ); 02208 } 02209 for( i = face_list.size(); i--; ) 02210 { 02211 RefFace* face_ptr = face_list.get_and_step(); 02212 if( !valid_sm_topology( face_ptr, print_error ) ) 02213 result = CUBIT_FALSE; 02214 child_edges.clean_out(); 02215 face_ptr->ref_edges( child_edges ); 02216 edge_list.merge_unique( child_edges ); 02217 } 02218 for( i = edge_list.size(); i--; ) 02219 { 02220 RefEdge* edge_ptr = edge_list.get_and_step(); 02221 if( !valid_sm_topology( edge_ptr, print_error ) ) 02222 result = CUBIT_FALSE; 02223 child_vtx.clean_out(); 02224 edge_ptr->ref_vertices( child_vtx ); 02225 vtx_list.merge_unique( child_vtx ); 02226 } 02227 for( i = vtx_list.size(); i--; ) 02228 if( !valid_sm_topology(vtx_list.get_and_step(), print_error ) ) 02229 result = CUBIT_FALSE; 02230 02231 return result; 02232 } 02233 CubitBoolean GeometryUtil::valid_sm_topology( Body* body_ptr, CubitBoolean print ) 02234 { 02235 CubitBoolean result = CUBIT_TRUE; 02236 int i; 02237 02238 // This function checks for extraneous links in the VGI between 02239 // the passed body and its child volumes. To check for missing 02240 // links, use valid_sm_topology(RefVolume*). 02241 02242 DLIList<RefVolume*> vol_list; 02243 body_ptr->ref_volumes( vol_list ); 02244 02245 // Get all child TopologyBridges 02246 DLIList<TopologyBridge*> body_bridges, lump_bridges, temp_list; 02247 body_ptr->bridge_manager()->get_bridge_list( body_bridges ); 02248 02249 if ( body_bridges.size() != 1 ) 02250 { 02251 PRINT_ERROR("%s (Body %d) has %d attached BodySM(s).\n", 02252 body_ptr->entity_name().c_str(), body_ptr->id(), body_bridges.size() ); 02253 result = CUBIT_FALSE; 02254 } 02255 02256 for( i = body_bridges.size(); i > 0; i-- ) 02257 { 02258 TopologyBridge* bodysm = body_bridges.get_and_step(); 02259 temp_list.clean_out(); 02260 bodysm->get_children( temp_list ); 02261 lump_bridges.merge_unique( temp_list ); 02262 } 02263 02264 // Check that each child VGI RefVolume has atleast one 02265 // TopologyBridge in the list we got from the solid modeler. 02266 for( i = vol_list.size(); i > 0; i-- ) 02267 { 02268 RefVolume* vol_ptr = vol_list.get_and_step(); 02269 temp_list.clean_out(); 02270 vol_ptr->bridge_manager()->get_bridge_list( temp_list ); 02271 temp_list.intersect( lump_bridges ); 02272 if( temp_list.size() == 0 ) 02273 { 02274 if( print ) PRINT_ERROR( 02275 "Extraneous VGI link between %s and %s.\n", 02276 body_ptr->entity_name().c_str(), 02277 vol_ptr->entity_name().c_str() ); 02278 result = CUBIT_FALSE; 02279 } 02280 } 02281 02282 for( i = lump_bridges.size(); i--; ) 02283 { 02284 TopologyBridge* lump = lump_bridges.get_and_step(); 02285 TopologyEntity* owner = lump->topology_entity(); 02286 RefVolume* vol_ptr = dynamic_cast<RefVolume*>(owner); 02287 if( ! vol_ptr ) 02288 { 02289 if( print ) PRINT_ERROR( 02290 "No RefVolume for Lump %p in %s\n", 02291 (void*)lump, body_ptr->entity_name().c_str() ); 02292 result = CUBIT_FALSE; 02293 } 02294 } 02295 02296 return result; 02297 } 02298 02299 CubitBoolean GeometryUtil::valid_sm_topology( RefVolume* vol_ptr, CubitBoolean print ) 02300 { 02301 CubitBoolean result = CUBIT_TRUE; 02302 int i; 02303 02304 // This method checks for 02305 // a.) Missing links between the passed RefVolume and its parent Body(s) 02306 // b.) Extraneous links between the RefVolume and its child shell(s) 02307 // c.) Invalid Shells by calling valid_sm_topology(Shell*) 02308 02309 DLIList<Body*> body_list; 02310 vol_ptr->bodies( body_list ); 02311 DLIList<Shell*> shell_list; 02312 vol_ptr->shells( shell_list ); 02313 DLIList<TopologyBridge*> vol_bridges, shell_bridges, temp_list; 02314 vol_ptr->bridge_manager()->get_bridge_list( vol_bridges ); 02315 02316 if ( vol_bridges.size() != 1 ) 02317 { 02318 PRINT_ERROR("%s (RefVolume %d) has %d attached Lump(s).\n", 02319 vol_ptr->entity_name().c_str(), vol_ptr->id(), vol_bridges.size() ); 02320 result = CUBIT_FALSE; 02321 } 02322 02323 for( i = vol_bridges.size(); i > 0; i-- ) 02324 { 02325 TopologyBridge* lump = vol_bridges.get_and_step(); 02326 02327 // Check for missing links between this RefVolume and parent Body(s) 02328 temp_list.clean_out(); 02329 lump->get_parents( temp_list ); 02330 for( int j = temp_list.size(); j > 0; j-- ) 02331 { 02332 TopologyBridge* bodysm = temp_list.get_and_step(); 02333 TopologyEntity* te_ptr = bodysm->topology_entity(); 02334 Body* body_ptr = CAST_TO( te_ptr, Body ); 02335 CubitString body_name; 02336 const char* body_str = "PARENT BODY"; 02337 if( body_ptr ) 02338 { 02339 body_name = body_ptr->entity_name(); 02340 body_str = body_name.c_str(); 02341 } 02342 if( (body_ptr == NULL) || !body_list.is_in_list(body_ptr) ) 02343 { 02344 if( print ) PRINT_ERROR( 02345 "Missing VGI link between %s and %s\n", 02346 body_str, 02347 vol_ptr->entity_name().c_str() ); 02348 result = CUBIT_FALSE; 02349 } 02350 } 02351 02352 // Build ShellSM list for next part 02353 temp_list.clean_out(); 02354 lump->get_children( temp_list ); 02355 shell_bridges.merge_unique( temp_list ); 02356 } 02357 02358 // Check for extraneous VGI links between this RefVolume and child Shell(s) 02359 for( i = shell_list.size(); i > 0; i-- ) 02360 { 02361 Shell* shell_ptr = shell_list.get_and_step(); 02362 temp_list.clean_out(); 02363 shell_ptr->bridge_manager()->get_bridge_list( temp_list ); 02364 temp_list.intersect( shell_bridges ); 02365 if( temp_list.size() == 0 ) 02366 { 02367 DLIList<RefFace*> shell_faces; 02368 shell_ptr->ref_faces( shell_faces ); 02369 CubitString face_name; 02370 const char* face_str = "NO REFFACE"; 02371 if( shell_faces.size() ) 02372 { 02373 face_name = shell_faces.get()->entity_name(); 02374 face_str = face_name.c_str(); 02375 } 02376 if( print ) PRINT_ERROR( 02377 "Extraneous VGI link between %s and Shell with %s.\n", 02378 vol_ptr->entity_name().c_str(), 02379 face_str ); 02380 result = CUBIT_FALSE; 02381 } 02382 } 02383 02384 for( i = shell_bridges.size(); i--; ) 02385 { 02386 TopologyBridge* shell = shell_bridges.get_and_step(); 02387 TopologyEntity* owner = shell->topology_entity(); 02388 Shell* shell_ptr = dynamic_cast<Shell*>(owner); 02389 if( ! shell_ptr ) 02390 { 02391 if( print ) PRINT_ERROR( 02392 "No Shell for ShellSM %p in %s\n", 02393 (void*)shell, vol_ptr->entity_name().c_str() ); 02394 result = CUBIT_FALSE; 02395 } 02396 } 02397 02398 for( i = shell_list.size(); i > 0; i-- ) 02399 if( !valid_sm_topology( shell_list.get_and_step(), print ) ) 02400 result = CUBIT_FALSE; 02401 02402 return result; 02403 } 02404 02405 02406 CubitBoolean GeometryUtil::valid_sm_topology(Shell* shell_ptr, CubitBoolean print ) 02407 { 02408 CubitBoolean result = CUBIT_TRUE; 02409 int i; 02410 02411 // This method checks for 02412 // a.) Missing links between the passed Shell and its parent RefVolume(s) 02413 // b.) Extraneous links between the Shell and its child RefFace(s) 02414 02415 DLIList<RefVolume*> vol_list; 02416 shell_ptr->ref_volumes( vol_list ); 02417 DLIList<RefFace*> face_list; 02418 shell_ptr->ref_faces( face_list ); 02419 DLIList<TopologyBridge*> shell_bridges, face_bridges, temp_list; 02420 shell_ptr->bridge_manager()->get_bridge_list( shell_bridges ); 02421 02422 if ( shell_bridges.size() != 1 ) 02423 { 02424 PRINT_ERROR("Shell %p (in Volume %d) has %d attached ShellSM(s).\n", 02425 (void*)shell_ptr, shell_ptr->get_ref_volume_ptr() ? 02426 shell_ptr->get_ref_volume_ptr()->id() : 0, 02427 shell_bridges.size() ); 02428 result = CUBIT_FALSE; 02429 } 02430 02431 for( i = shell_bridges.size(); i > 0; i-- ) 02432 { 02433 TopologyBridge* shellsm = shell_bridges.get_and_step(); 02434 02435 // Check for missing links between this Shell and parent RefVolume(s) 02436 temp_list.clean_out(); 02437 shellsm->get_parents( temp_list ); 02438 if (temp_list.size() != 1) 02439 { 02440 PRINT_ERROR("Bad SolidModel Topology!\n"); 02441 PRINT_ERROR("ShellSM %p in Shell %p (in Volume %d) has %d parent Lumps.\n", 02442 (void*)shellsm, (void*)shell_ptr, 02443 shell_ptr->get_ref_volume_ptr() ? shell_ptr->get_ref_volume_ptr()->id() : 0, 02444 temp_list.size() ); 02445 } 02446 else 02447 { 02448 TopologyBridge* lump = temp_list.get_and_step(); 02449 TopologyEntity* te_ptr = lump->topology_entity(); 02450 RefVolume* vol_ptr = CAST_TO( te_ptr, RefVolume ); 02451 if( (vol_ptr == NULL) || !vol_list.is_in_list(vol_ptr) ) 02452 { 02453 DLIList<RefFace*> faces; 02454 shell_ptr->ref_faces( faces ); 02455 CubitString vol_name, face_name; 02456 const char* vol_str = "PARENT VOLUME"; 02457 const char* face_str = "NO REFFACES"; 02458 if( vol_ptr ) 02459 { 02460 vol_name = vol_ptr->entity_name(); 02461 vol_str = vol_name.c_str(); 02462 } 02463 if( faces.size() ) 02464 { 02465 face_name = faces.get()->entity_name(); 02466 face_str = face_name.c_str(); 02467 } 02468 if( print ) PRINT_ERROR( 02469 "Missing VGI link between %s and Shell with %s\n", 02470 vol_str, face_str ); 02471 result = CUBIT_FALSE; 02472 } 02473 } 02474 // Build Surface list for next part 02475 temp_list.clean_out(); 02476 shellsm->get_children( temp_list ); 02477 face_bridges.merge_unique( temp_list ); 02478 } 02479 02480 // Check for extraneous VGI links between this Shell and child RefFaces(s) 02481 for( i = face_list.size(); i > 0; i-- ) 02482 { 02483 RefFace* face_ptr = face_list.get_and_step(); 02484 temp_list.clean_out(); 02485 face_ptr->bridge_manager()->get_bridge_list( temp_list ); 02486 temp_list.intersect( face_bridges ); 02487 if( temp_list.size() == 0 ) 02488 { 02489 DLIList<RefFace*> faces; 02490 shell_ptr->ref_faces( faces ); 02491 CubitString face_name; 02492 const char* face_str = "NO REFFACES"; 02493 if( faces.size() ) 02494 { 02495 face_name = faces.get()->entity_name(); 02496 face_str = face_name.c_str(); 02497 } 02498 if( print ) PRINT_ERROR( 02499 "Extraneous VGI link between Shell with %s and %s.\n", 02500 face_str, 02501 face_ptr->entity_name().c_str() ); 02502 result = CUBIT_FALSE; 02503 } 02504 } 02505 02506 for( i = face_bridges.size(); i--; ) 02507 { 02508 TopologyBridge* surface = face_bridges.get_and_step(); 02509 TopologyEntity* owner = surface->topology_entity(); 02510 RefFace* face_ptr = dynamic_cast<RefFace*>(owner); 02511 if( ! face_ptr ) 02512 { 02513 if( print ) PRINT_ERROR( 02514 "No RefFace for Surface %p in Shell %p in %s\n", 02515 (void*)surface, (void*)shell_ptr, 02516 vol_list.size() ? 02517 vol_list.get()->entity_name().c_str() : 02518 "NO REFVOLUME" ); 02519 result = CUBIT_FALSE; 02520 } 02521 } 02522 02523 return result; 02524 } 02525 02526 02527 CubitBoolean GeometryUtil::valid_sm_topology( RefFace* face_ptr, CubitBoolean print ) 02528 { 02529 CubitBoolean result = CUBIT_TRUE; 02530 int i; 02531 02532 // This method checks for 02533 // a.) Missing links between the passed RefFace and its parent Shell(s) 02534 // b.) Extraneous links between the RefFace and its child Loop(s) 02535 // c.) Invalid Loops by calling valid_sm_topology(Loop*) 02536 02537 DLIList<Shell*> shell_list; 02538 face_ptr->shells( shell_list ); 02539 DLIList<Loop*> loop_list; 02540 face_ptr->loops( loop_list ); 02541 DLIList<TopologyBridge*> face_bridges, loop_bridges, temp_list; 02542 face_ptr->bridge_manager()->get_bridge_list( face_bridges ); 02543 02544 if ( face_bridges.size() == 0 ) 02545 { 02546 PRINT_ERROR("%s (RefFace %d) has no attached Surface(s).\n", 02547 face_ptr->entity_name().c_str(), face_ptr->id() ); 02548 result = CUBIT_FALSE; 02549 } 02550 02551 for( i = face_bridges.size(); i > 0; i-- ) 02552 { 02553 TopologyBridge* surf = face_bridges.get_and_step(); 02554 02555 // Check for missing links between this RefFace and parent Shell(s) 02556 temp_list.clean_out(); 02557 surf->get_parents( temp_list ); 02558 for( int j = temp_list.size(); j > 0; j-- ) 02559 { 02560 TopologyBridge* shellsm = temp_list.get_and_step(); 02561 TopologyEntity* te_ptr = shellsm->topology_entity(); 02562 Shell* shell_ptr = CAST_TO( te_ptr, Shell ); 02563 if( (shell_ptr == NULL) || !shell_list.is_in_list(shell_ptr) ) 02564 { 02565 DLIList<RefVolume*> vols; 02566 if( shell_ptr != NULL ) 02567 shell_ptr->ref_volumes( vols ); 02568 CubitString vol_name; 02569 const char* vol_str = "PARENT REFVOLUME"; 02570 if( vols.size() ) 02571 { 02572 vol_name = vols.get()->entity_name(); 02573 vol_str = vol_name.c_str(); 02574 } 02575 if( print ) PRINT_ERROR( 02576 "Missing VGI link between Shell with %s and %s\n", 02577 vol_str, 02578 face_ptr->entity_name().c_str() ); 02579 result = CUBIT_FALSE; 02580 } 02581 } 02582 02583 // Build LoopSM list for next part 02584 temp_list.clean_out(); 02585 surf->get_children( temp_list ); 02586 loop_bridges.merge_unique( temp_list ); 02587 } 02588 02589 // Check for extraneous VGI links between this RefFace and child Loop(s) 02590 for( i = loop_list.size(); i > 0; i-- ) 02591 { 02592 Loop* loop_ptr = loop_list.get_and_step(); 02593 temp_list.clean_out(); 02594 loop_ptr->bridge_manager()->get_bridge_list( temp_list ); 02595 temp_list.intersect( loop_bridges ); 02596 if( temp_list.size() == 0 ) 02597 { 02598 DLIList<RefEdge*> edges; 02599 loop_ptr->ref_edges( edges ); 02600 CubitString edge_name; 02601 const char* edge_str = "NO REFEDGE"; 02602 if( edges.size() ) 02603 { 02604 edge_name = edges.get()->entity_name(); 02605 edge_str = edge_name.c_str(); 02606 } 02607 if( print ) PRINT_ERROR( 02608 "Extraneous VGI link between %s and Loop with %s.\n", 02609 face_ptr->entity_name().c_str(), 02610 edge_str ); 02611 result = CUBIT_FALSE; 02612 } 02613 } 02614 02615 for( i = loop_bridges.size(); i--; ) 02616 { 02617 TopologyBridge* loop = loop_bridges.get_and_step(); 02618 TopologyEntity* owner = loop->topology_entity(); 02619 Loop* loop_ptr = dynamic_cast<Loop*>(owner); 02620 if( ! loop_ptr ) 02621 { 02622 if( print ) PRINT_ERROR( 02623 "No Loop for LoopSM %p in %s\n", 02624 (void*)loop, face_ptr->entity_name().c_str() ); 02625 result = CUBIT_FALSE; 02626 } 02627 } 02628 02629 for( i = loop_list.size(); i > 0; i-- ) 02630 if( !valid_sm_topology( loop_list.get_and_step(), print ) ) 02631 result = CUBIT_FALSE; 02632 02633 return result; 02634 } 02635 02636 02637 CubitBoolean GeometryUtil::valid_sm_topology( Loop* loop_ptr, CubitBoolean print ) 02638 { 02639 CubitBoolean result = CUBIT_TRUE; 02640 CoEdge* coedge_ptr; 02641 int i; 02642 02643 // This method checks for 02644 // a.) Missing links between the passed Loop and its parent RefFace(s) 02645 // b.) Extraneous links between the Loop and its child CoEdge(s) 02646 // c.) Invalid CoEdges by calling valid_sm_topology(CoEdge*) 02647 // d.) CoEdgeSMs w/out CoEdges 02648 // e.) Correct CoEdge order given CoEdgeSM order. 02649 02650 DLIList<RefFace*> face_list; 02651 loop_ptr->ref_faces( face_list ); 02652 DLIList<CoEdge*> coedge_list; 02653 loop_ptr->co_edges( coedge_list ); 02654 DLIList<TopologyBridge*> loop_bridges, coedge_bridges, temp_list; 02655 loop_ptr->bridge_manager()->get_bridge_list( loop_bridges ); 02656 02657 if ( loop_bridges.size() == 0 ) 02658 { 02659 PRINT_ERROR("Loop %p (in surface %d) has no attached LoopSM(s).\n", 02660 (void*)loop_ptr, 02661 loop_ptr->get_ref_face_ptr() ? loop_ptr->get_ref_face_ptr()->id() : 0 ); 02662 result = CUBIT_FALSE; 02663 } 02664 02665 for( i = loop_bridges.size(); i > 0; i-- ) 02666 { 02667 TopologyBridge* loopsm = loop_bridges.get_and_step(); 02668 02669 // Check for missing links between this Loop and parent RefFace(s) 02670 temp_list.clean_out(); 02671 loopsm->get_parents( temp_list ); 02672 for( int j = temp_list.size(); j > 0; j-- ) 02673 { 02674 TopologyBridge* surf = temp_list.get_and_step(); 02675 TopologyEntity* te_ptr = surf->topology_entity(); 02676 RefFace* face_ptr = CAST_TO( te_ptr, RefFace ); 02677 if( (face_ptr == NULL) || !face_list.is_in_list(face_ptr) ) 02678 { 02679 DLIList<RefEdge*> edges; 02680 loop_ptr->ref_edges( edges ); 02681 CubitString face_name; 02682 CubitString edge_name; 02683 const char* face_str = "PARENT REFFACE"; 02684 const char* edge_str = "NO REFEDGES"; 02685 if( face_ptr ) 02686 { 02687 face_name = face_ptr->entity_name(); 02688 face_str = face_name.c_str(); 02689 } 02690 if( edges.size() ) 02691 { 02692 edge_name = edges.get()->entity_name(); 02693 edge_str = edge_name.c_str(); 02694 } 02695 if( print ) PRINT_ERROR( 02696 "Missing VGI link between %s and Loop with %s\n", face_str, edge_str); 02697 result = CUBIT_FALSE; 02698 } 02699 } 02700 02701 // Build CoEdgeSM list for next part 02702 temp_list.clean_out(); 02703 loopsm->get_children( temp_list ); 02704 coedge_bridges.merge_unique( temp_list ); 02705 } 02706 02707 // Check for extraneous VGI links between this Loop and child CoEdge(s) 02708 for( i = coedge_list.size(); i > 0; i-- ) 02709 { 02710 coedge_ptr = coedge_list.get_and_step(); 02711 temp_list.clean_out(); 02712 coedge_ptr->bridge_manager()->get_bridge_list( temp_list ); 02713 temp_list.intersect( coedge_bridges ); 02714 if( temp_list.size() == 0 ) 02715 { 02716 DLIList<RefEdge*> edges; 02717 DLIList<RefFace*> faces; 02718 loop_ptr->ref_faces( faces ); 02719 coedge_ptr->ref_edges( edges ); 02720 CubitString face_name; 02721 CubitString edge_name; 02722 const char* face_str = "NO REFFACE"; 02723 const char* edge_str = "NO REFEDGE"; 02724 if( faces.size() ) 02725 { 02726 face_name = faces.get()->entity_name(); 02727 face_str = face_name.c_str(); 02728 } 02729 if( edges.size() ) 02730 { 02731 edge_name = edges.get()->entity_name(); 02732 edge_str = edge_name.c_str(); 02733 } 02734 if( print ) PRINT_ERROR( 02735 "Extraneous VGI link between Loop in %s and CoEdge with %s.\n", 02736 face_str, edge_str ); 02737 result = CUBIT_FALSE; 02738 } 02739 } 02740 02741 // Check for missing CoedgeSMs 02742 for( i = coedge_bridges.size(); i--; ) 02743 { 02744 TopologyBridge* coedge = coedge_bridges.get_and_step(); 02745 TopologyEntity* owner = coedge->topology_entity(); 02746 coedge_ptr = dynamic_cast<CoEdge*>(owner); 02747 if( ! coedge_ptr ) 02748 { 02749 CubitString face_name = "NO REFFACE"; 02750 if( face_list.size() ) 02751 face_name = face_list.get()->entity_name(); 02752 if( print ) PRINT_ERROR( 02753 "No CoEdge for CoEdgeSM %p in Loop %p in %s\n", 02754 (void*)coedge, (void*)loop_ptr, face_name.c_str() ); 02755 result = CUBIT_FALSE; 02756 } 02757 } 02758 02759 02760 for( i = coedge_list.size(); i > 0; i-- ) 02761 if( !valid_sm_topology( coedge_list.get_and_step(), print ) ) 02762 result = CUBIT_FALSE; 02763 02764 if( !result ) 02765 return result; 02766 02767 02768 RefFace* face_ptr = loop_ptr->get_ref_face_ptr(); 02769 CubitString face_name_str; 02770 const char* face_str_ptr = "NO PARENT REFFACE"; 02771 if( face_ptr ) 02772 { 02773 face_name_str = face_ptr->entity_name(); 02774 face_str_ptr = face_name_str.c_str(); 02775 } 02776 02777 02778 // Check correct order of CoEdges 02779 for( i = loop_bridges.size(); i--; ) 02780 { 02781 TopologyBridge* loopsm_ptr = loop_bridges.get_and_step(); 02782 coedge_bridges.clean_out(); 02783 loopsm_ptr->get_children( coedge_bridges ); 02784 02785 if( coedge_bridges.size() != coedge_list.size() ) 02786 { 02787 if( print ) PRINT_ERROR( 02788 "Loop %p in %s has %d coedges, while LoopSM %p has %d coedgesms.\n", 02789 (void*)loop_ptr, face_str_ptr, coedge_list.size(), 02790 (void*)loopsm_ptr, coedge_bridges.size() ); 02791 result = CUBIT_FAILURE; 02792 continue; 02793 } 02794 02795 // Remaining code checks the order of coedges in the loop. 02796 // There is no wrong order if only one or two coedges. 02797 if( coedge_bridges.size() <= 2 ) 02798 continue; 02799 02800 coedge_bridges.reset(); 02801 coedge_ptr = dynamic_cast<CoEdge*>(coedge_bridges.get()->topology_entity()); 02802 if( !coedge_list.move_to( coedge_ptr ) ) 02803 continue; 02804 02805 coedge_ptr = dynamic_cast<CoEdge*>(coedge_bridges.next()->topology_entity()); 02806 if( coedge_list.next() != coedge_ptr && 02807 coedge_list.prev() != coedge_ptr ) 02808 { 02809 if( print ) PRINT_ERROR( 02810 "Order of CoEdges in Loop %p in %s is incorrect w.r.t. LoopSM %p.\n", 02811 (void*)loop_ptr, face_str_ptr, (void*)loopsm_ptr); 02812 result = CUBIT_FAILURE; 02813 continue; 02814 } 02815 02816 bool loop_reversed = false; 02817 TopologyBridge* coedge_bridge; 02818 if( coedge_list.prev() == coedge_ptr ) 02819 { 02820 coedge_bridge = coedge_bridges.get(); 02821 coedge_bridges.reverse(); 02822 coedge_bridges.move_to(coedge_bridge); 02823 loop_reversed = true; 02824 } 02825 02826 for( int j = coedge_bridges.size(); j--; ) 02827 { 02828 coedge_bridge = coedge_bridges.get_and_step(); 02829 coedge_ptr = coedge_list.get_and_step(); 02830 if( coedge_bridge->topology_entity() != coedge_ptr ) 02831 { 02832 if( print ) PRINT_ERROR( 02833 "Order of CoEdges in Loop %p in %s is incorrect w.r.t. loopsm %p.\n", 02834 (void*)loop_ptr, face_str_ptr, (void*)loopsm_ptr); 02835 result = CUBIT_FAILURE; 02836 break; 02837 } 02838 } 02839 02840 temp_list.clean_out(); 02841 loopsm_ptr->get_parents(temp_list); 02842 if (temp_list.size() != 1) 02843 continue; 02844 02845 bool surf_reversed = (temp_list.get()->bridge_sense() == CUBIT_REVERSED); 02846 if (surf_reversed != loop_reversed) 02847 { 02848 result = CUBIT_FAILURE; 02849 if (print) PRINT_ERROR( 02850 "Loop %p in %s is reversed w.r.t. loopsm %p.\n", 02851 (void*)loop_ptr, face_str_ptr, (void*)loopsm_ptr); 02852 } 02853 02854 } 02855 02856 return result; 02857 } 02858 02859 02860 CubitBoolean GeometryUtil::valid_sm_topology(CoEdge* coedge_ptr, CubitBoolean print ) 02861 { 02862 CubitBoolean result = CUBIT_TRUE; 02863 int i; 02864 02865 // This method checks for 02866 // a.) Missing links between the passed CoEdge and its parent Loop(s) 02867 // b.) Extraneous links between the Loop and its child RefEdge(s) 02868 02869 DLIList<Loop*> loop_list; 02870 coedge_ptr->loops( loop_list ); 02871 DLIList<RefEdge*> edge_list; 02872 coedge_ptr->ref_edges( edge_list ); 02873 DLIList<TopologyBridge*> coedge_bridges, edge_bridges, temp_list; 02874 coedge_ptr->bridge_manager()->get_bridge_list( coedge_bridges ); 02875 02876 if ( coedge_bridges.size() == 0 ) 02877 { 02878 if (print) PRINT_ERROR( 02879 "CoEdge %p (curve %d %s in surface %d) has no attached CoEdgeSM(s).\n", 02880 (void*)coedge_ptr, 02881 coedge_ptr->get_ref_edge_ptr() ? coedge_ptr->get_ref_edge_ptr()->id() : 0, 02882 coedge_ptr->get_sense() == CUBIT_FORWARD ? "FORWARD" : 02883 coedge_ptr->get_sense() == CUBIT_REVERSED ? "REVERSED" : "UNKNOWN", 02884 coedge_ptr->get_ref_face() ? coedge_ptr->get_ref_face()->id() : 0 ); 02885 result = CUBIT_FALSE; 02886 } 02887 02888 for( i = coedge_bridges.size(); i > 0; i-- ) 02889 { 02890 CoEdgeSM* coedgesm = dynamic_cast<CoEdgeSM*>(coedge_bridges.get_and_step()); 02891 02892 // Check for missing links between this CoEdge and parent Loop(s) 02893 temp_list.clean_out(); 02894 coedgesm->get_parents( temp_list ); 02895 if (temp_list.size() != 1) 02896 { 02897 PRINT_ERROR( 02898 "Bad SolidModel topology. CoEdgeSM %p in CoEdge %p " 02899 "(curve %d %s in surface %d) has %d parent LoopSMs.\n", 02900 (void*)coedgesm, (void*)coedge_ptr, 02901 coedge_ptr->get_ref_edge_ptr() ? coedge_ptr->get_ref_edge_ptr()->id() : 0, 02902 coedge_ptr->get_sense() == CUBIT_FORWARD ? "FORWARD" : 02903 coedge_ptr->get_sense() == CUBIT_REVERSED ? "REVERSED" : "UNKNOWN", 02904 coedge_ptr->get_ref_face() ? coedge_ptr->get_ref_face()->id() : 0, 02905 temp_list.size() ); 02906 continue; 02907 } 02908 02909 TopologyBridge* loopsm = temp_list.get_and_step(); 02910 TopologyEntity* te_ptr = loopsm->topology_entity(); 02911 Loop* loop_ptr = CAST_TO( te_ptr, Loop ); 02912 if( !loop_ptr ) 02913 { 02914 const char* edge_str = "NO REFEDGE"; 02915 CubitString edge_name; 02916 DLIList<RefEdge*> edges; 02917 coedge_ptr->ref_edges( edges ); 02918 if( edges.size() ) 02919 { 02920 edge_name = edges.get()->entity_name(); 02921 edge_str = edge_name.c_str(); 02922 } 02923 if( print ) PRINT_ERROR( 02924 "Missing VGI Entity for LoopSM %p. Discovered on CoEdge with %s\n", 02925 (void*)loopsm, edge_str ); 02926 result = CUBIT_FALSE; 02927 } 02928 else if( !loop_list.is_in_list(loop_ptr) ) 02929 { 02930 DLIList<RefFace*> faces; 02931 DLIList<RefEdge*> edges; 02932 loop_ptr->ref_faces( faces ); 02933 coedge_ptr->ref_edges( edges ); 02934 CubitString face_name, edge_name; 02935 const char* face_str = "NO REFFACE"; 02936 const char* edge_str = "NO REFEDGE"; 02937 if( faces.size() ) 02938 { 02939 face_name = faces.get()->entity_name(); 02940 face_str = face_name.c_str(); 02941 } 02942 if( edges.size() ) 02943 { 02944 edge_name = edges.get()->entity_name(); 02945 edge_str = edge_name.c_str(); 02946 } 02947 if( print ) PRINT_ERROR( 02948 "Missing VGI link between Loop in %s and CoEdge with %s\n", 02949 face_str, edge_str ); 02950 result = CUBIT_FALSE; 02951 } 02952 02953 02954 // Build curve list for next part 02955 temp_list.clean_out(); 02956 coedgesm->get_children( temp_list ); 02957 edge_bridges.merge_unique( temp_list ); 02958 02959 // Get curve and surface connected by this CoEdgeSM 02960 if (temp_list.size() != 1) // should never happen! 02961 continue; 02962 TopologyBridge* curv_bridge = temp_list.get(); 02963 temp_list.clean_out(); 02964 loopsm->get_parents(temp_list); 02965 if (temp_list.size() != 1) // should never happen! 02966 continue; 02967 TopologyBridge* surf_bridge = temp_list.get(); 02968 02969 bool curv_reversed = curv_bridge->bridge_sense() == CUBIT_REVERSED; 02970 bool surf_reversed = surf_bridge->bridge_sense() == CUBIT_REVERSED; 02971 bool want_reversed = curv_reversed != surf_reversed; 02972 bool are_reversed = coedgesm->sense() != coedge_ptr->get_sense(); 02973 if (want_reversed != are_reversed) 02974 { 02975 result = CUBIT_FAILURE; 02976 if (print) PRINT_ERROR( 02977 "CoEdge %p (curve %d %s in surface %d) has wrong sense w.r.t CoEdgeSM.\n", 02978 (void*)coedge_ptr, 02979 coedge_ptr->get_ref_edge_ptr() ? coedge_ptr->get_ref_edge_ptr()->id() : 0, 02980 coedge_ptr->get_sense() == CUBIT_FORWARD ? "FORWARD" : 02981 coedge_ptr->get_sense() == CUBIT_REVERSED ? "REVERSED" : "UNKNOWN", 02982 coedge_ptr->get_ref_face() ? coedge_ptr->get_ref_face()->id() : 0 ); 02983 } 02984 } 02985 02986 // Check for extraneous VGI links between this CoEdge and child RefEdge(s) 02987 for( i = edge_list.size(); i > 0; i-- ) 02988 { 02989 RefEdge* edge_ptr = edge_list.get_and_step(); 02990 temp_list.clean_out(); 02991 edge_ptr->bridge_manager()->get_bridge_list( temp_list ); 02992 temp_list.intersect( edge_bridges ); 02993 if( temp_list.size() == 0 ) 02994 { 02995 DLIList<RefEdge*> edges; 02996 coedge_ptr->ref_edges( edges ); 02997 CubitString edge_name; 02998 const char* edge_str = "NO REFEDGE"; 02999 if( edges.size() ) 03000 { 03001 edge_name = edges.get()->entity_name(); 03002 edge_str = edge_name.c_str(); 03003 } 03004 if( print ) PRINT_ERROR( 03005 "Extraneous VGI link between CoEdge with %s and %s.\n", 03006 edge_str, 03007 edge_ptr->entity_name().c_str() ); 03008 result = CUBIT_FALSE; 03009 } 03010 } 03011 03012 for( i = edge_bridges.size(); i--; ) 03013 { 03014 TopologyBridge* curve = edge_bridges.get_and_step(); 03015 TopologyEntity* owner = curve->topology_entity(); 03016 RefEdge* edge_ptr = dynamic_cast<RefEdge*>(owner); 03017 if( ! edge_ptr ) 03018 { 03019 DLIList<RefFace*> faces; 03020 coedge_ptr->ref_faces( faces ); 03021 CubitString face_name = "NO REFFACE"; 03022 if( faces.size() ) 03023 face_name = faces.get()->entity_name(); 03024 if( print ) PRINT_ERROR( 03025 "No RefEdge for Curve %p in CoEdge %p in %s\n", 03026 (void*)curve, (void*)coedge_ptr, face_name.c_str() ); 03027 result = CUBIT_FALSE; 03028 } 03029 } 03030 03031 return result; 03032 } 03033 03034 03035 CubitBoolean GeometryUtil::valid_sm_topology( RefEdge* edge_ptr, CubitBoolean print ) 03036 { 03037 CubitBoolean result = CUBIT_TRUE; 03038 int i; 03039 03040 // This method checks for 03041 // a.) Missing links between the passed RefEdge and its parent CoEdge(s) 03042 // b.) Extraneous links between the RefEdge and its child vert(ex/ices) 03043 03044 DLIList<CoEdge*> coedge_list; 03045 edge_ptr->co_edges( coedge_list ); 03046 DLIList<RefVertex*> vtx_list; 03047 edge_ptr->ref_vertices( vtx_list ); 03048 DLIList<TopologyBridge*> edge_bridges, vtx_bridges, temp_list; 03049 edge_ptr->bridge_manager()->get_bridge_list( edge_bridges ); 03050 03051 if ( edge_bridges.size() == 0 ) 03052 { 03053 PRINT_ERROR("%s (RefEdge %d) has no attached Curve(s).\n", 03054 edge_ptr->entity_name().c_str(), edge_ptr->id()); 03055 result = CUBIT_FALSE; 03056 } 03057 03058 for( i = edge_bridges.size(); i > 0; i-- ) 03059 { 03060 TopologyBridge* curve = edge_bridges.get_and_step(); 03061 03062 // Check for missing links between this RefEdge and parent CoEdge(s) 03063 temp_list.clean_out(); 03064 curve->get_parents( temp_list ); 03065 for( int j = temp_list.size(); j > 0; j-- ) 03066 { 03067 TopologyBridge* coedgesm = temp_list.get_and_step(); 03068 TopologyEntity* te_ptr = coedgesm->topology_entity(); 03069 CoEdge* coedge_ptr = CAST_TO( te_ptr, CoEdge ); 03070 if( (coedge_ptr == NULL) || !coedge_list.is_in_list(coedge_ptr) ) 03071 { 03072 DLIList<RefFace*> faces; 03073 if( coedge_ptr ) 03074 coedge_ptr->ref_faces( faces ); 03075 CubitString face_name; 03076 const char* face_str = "NO REFFACE"; 03077 if( faces.size() ) 03078 { 03079 face_name = faces.get()->entity_name(); 03080 face_str = face_name.c_str(); 03081 } 03082 03083 if( print ) PRINT_ERROR( 03084 "Missing VGI link between CoEdge with %s and %s\n", 03085 face_str, 03086 edge_ptr->entity_name().c_str() ); 03087 result = CUBIT_FALSE; 03088 } 03089 } 03090 03091 // Build Point list for next part 03092 temp_list.clean_out(); 03093 curve->get_children( temp_list ); 03094 vtx_bridges.merge_unique( temp_list ); 03095 } 03096 03097 // Check for extraneous VGI links between this RefEdge and child RefVert(s) 03098 for( i = vtx_list.size(); i > 0; i-- ) 03099 { 03100 RefVertex* vtx_ptr = vtx_list.get_and_step(); 03101 temp_list.clean_out(); 03102 vtx_ptr->bridge_manager()->get_bridge_list( temp_list ); 03103 temp_list.intersect( vtx_bridges ); 03104 if( temp_list.size() == 0 ) 03105 { 03106 if( print ) PRINT_ERROR( 03107 "Extraneous VGI link between %s and %s.\n", 03108 edge_ptr->entity_name().c_str(), 03109 vtx_ptr->entity_name().c_str() ); 03110 result = CUBIT_FALSE; 03111 } 03112 } 03113 03114 for( i = vtx_bridges.size(); i--; ) 03115 { 03116 TopologyBridge* point = vtx_bridges.get_and_step(); 03117 TopologyEntity* owner = point->topology_entity(); 03118 RefVertex* vtx_ptr = dynamic_cast<RefVertex*>(owner); 03119 if( ! vtx_ptr ) 03120 { 03121 if( print ) PRINT_ERROR( 03122 "No RefVertex for Point %p in %s\n", 03123 (void*)point, edge_ptr->entity_name().c_str() ); 03124 result = CUBIT_FALSE; 03125 } 03126 } 03127 03128 return result; 03129 } 03130 03131 03132 CubitBoolean GeometryUtil::valid_sm_topology( RefVertex* vtx_ptr, CubitBoolean print ) 03133 { 03134 CubitBoolean result = CUBIT_TRUE; 03135 int i; 03136 03137 // This method checks for 03138 // a.) Missing links between the RefVertex and its parent RefEdge(s) 03139 03140 DLIList<RefEdge*> edge_list; 03141 vtx_ptr->ref_edges( edge_list ); 03142 DLIList<TopologyBridge*> vtx_bridges, temp_list; 03143 vtx_ptr->bridge_manager()->get_bridge_list( vtx_bridges ); 03144 03145 if ( vtx_bridges.size() == 0 ) 03146 { 03147 PRINT_ERROR("%s (RefVertex %d) has no attached Point(s).\n", 03148 vtx_ptr->entity_name().c_str(), vtx_ptr->id()); 03149 result = CUBIT_FALSE; 03150 } 03151 03152 for( i = vtx_bridges.size(); i > 0; i-- ) 03153 { 03154 TopologyBridge* point = vtx_bridges.get_and_step(); 03155 03156 // Check for missing links between this RefVertex and parent RefEdge(s) 03157 temp_list.clean_out(); 03158 point->get_parents( temp_list ); 03159 for( int j = temp_list.size(); j > 0; j-- ) 03160 { 03161 TopologyBridge* curve = temp_list.get_and_step(); 03162 TopologyEntity* te_ptr = curve->topology_entity(); 03163 RefEdge* edge_ptr = CAST_TO( te_ptr, RefEdge ); 03164 if( !edge_ptr ) 03165 { 03166 if( print ) PRINT_ERROR( 03167 "Missing VGI Entity for Curve %p. Discovered as parent of %s\n", 03168 (void*)curve, vtx_ptr->entity_name().c_str() ); 03169 result = CUBIT_FAILURE; 03170 } 03171 else if( !edge_list.is_in_list(edge_ptr) ) 03172 { 03173 if( print ) PRINT_ERROR( 03174 "Missing VGI link between %s and %s\n", 03175 edge_ptr->entity_name().c_str(), 03176 vtx_ptr->entity_name().c_str() ); 03177 result = CUBIT_FALSE; 03178 } 03179 } 03180 } 03181 03182 return result; 03183 } 03184 03185 void GeometryUtil::list_SM_topology( TopologyBridge* bridge, int depth ) 03186 { 03187 int counts[8] = {0,0,0,0,0,0,0,0}; 03188 const char* names[8] = {"BodySM","Lump","ShellSM", "Surface", "LoopSM", 03189 "CoEdgeSM", "Curve", "Point"}; 03190 list_SM_topology( bridge, depth, 0, counts ); 03191 03192 for( int i = 0; i < 8; i++ ) 03193 if( counts[i] == 1 ) 03194 PRINT_INFO("%d %s, ", counts[i], names[i] ); 03195 else if( counts[i] > 1 ) 03196 PRINT_INFO("%d %ss, ", counts[i], names[i] ); 03197 PRINT_INFO("\n"); 03198 } 03199 03200 void GeometryUtil::list_SM_topology( TopologyBridge* bridge, int depth, 03201 int indent, int counts[8] ) 03202 { 03203 DLIList<TopologyBridge*> relatives; 03204 03205 if( depth < 0 ) 03206 { 03207 bridge->get_parents( relatives ); 03208 relatives.reset(); 03209 for( int i = relatives.size(); i--; ) 03210 list_SM_topology( relatives.get_and_step(), depth+1, indent+1, counts ); 03211 } 03212 03213 int index = print_topo_bridge( bridge, indent ); 03214 if( index >= 0 && index <= 8 ) 03215 counts[index]++; 03216 03217 if( depth > 0 ) 03218 { 03219 bridge->get_children( relatives ); 03220 relatives.reset(); 03221 for( int i = relatives.size(); i--; ) 03222 list_SM_topology( relatives.get_and_step(), depth-1, indent+1, counts ); 03223 } 03224 } 03225 03226 int GeometryUtil::print_topo_bridge( TopologyBridge* bridge, int indent ) 03227 { 03228 const char* label = bridge ? typeid(*bridge).name() : "(null)"; 03229 #ifdef __GNUC__ 03230 while( isdigit(*label) ) label++; 03231 #endif 03232 03233 int index = -1; 03234 if( dynamic_cast<BodySM*>(bridge) ) 03235 index = 0; 03236 else if( dynamic_cast<Lump*>(bridge) ) 03237 index = 1; 03238 else if( dynamic_cast<ShellSM*>(bridge) ) 03239 index = 2; 03240 else if( dynamic_cast<Surface*>(bridge) ) 03241 index = 3; 03242 else if( dynamic_cast<LoopSM*>(bridge) ) 03243 index = 4; 03244 else if( dynamic_cast<CoEdgeSM*>(bridge) ) 03245 index = 5; 03246 else if( dynamic_cast<Curve*>(bridge) ) 03247 index = 6; 03248 else if( dynamic_cast<TBPoint*>(bridge) ) 03249 index = 7; 03250 03251 CubitString name(""); 03252 RefEntity* re = 0; 03253 if( bridge && (re = dynamic_cast<RefEntity*>(bridge->topology_entity())) ) 03254 name = re->entity_name(); 03255 PRINT_INFO("%*s%s 0x%lx (%s)\n", indent*3, "", label, (long)bridge, name.c_str()); 03256 03257 return index; 03258 }