cgma
|
00001 00002 #include "VGLoopTool.hpp" 00003 #include "GMem.hpp" 00004 #include "GeometryQueryEngine.hpp" 00005 #include "CubitVector.hpp" 00006 /* 00007 //------------------------------------------------------------------------- 00008 // Purpose : Remove a curve from a loop 00009 // 00010 // Special Notes : 00011 // 00012 // Creator : Jason Kraftcheck 00013 // 00014 // Creation Date : 08/14/02 00015 //------------------------------------------------------------------------- 00016 template <class SURFACE, class LOOP, class COEDGE,class CURVE, class POINT> 00017 CubitStatus VGLoopTool<SURFACE,LOOP,COEDGE,CURVE,POINT>:: 00018 remove_curve( COEDGE* coedge1, COEDGE* coedge2, 00019 DLIList<COEDGE*>& new_loop_coedges ) 00020 { 00021 new_loop_coedges.clean_out(); 00022 00023 if( !coedge1->get_loop() || !coedge2->get_loop() ) 00024 return CUBIT_FAILURE; 00025 00026 // remove sipe or split loop? 00027 if( coedge1->get_loop() == coedge2->get_loop() ) 00028 { 00029 // split loop? 00030 if( coedge1->next() != coedge2 && coedge1->prev() != coedge2 ) 00031 { 00032 COEDGE* coedge = coedge1->next(); 00033 while( coedge != coedge2 ) 00034 { 00035 COEDGE* next = coedge; 00036 coedge->get_loop()->remove( coedge ); 00037 new_loop_coedges.append( coedge ); 00038 coedge = next; 00039 } 00040 } 00041 00042 coedge1->get_loop()->remove( coedge1 ); 00043 coedge2->get_loop()->remove( coedge2 ); 00044 } 00045 00046 // stitch/combine loops 00047 else 00048 { 00049 COEDGE* coedge; 00050 00051 // insert coedges 00052 while( coedge2->next() != coedge2 ) // loop has more than 1 coedge 00053 { 00054 coedge = coedge2->next(); 00055 coedge2->get_loop()->remove( coedge ); 00056 coedge1->insert_before( coedge, coedge1 ); 00057 } 00058 coedge1->get_loop()->remove( coedge1 ); 00059 coedge2->get_loop()->remove( coedge2 ); 00060 } 00061 00062 return CUBIT_SUCCESS; 00063 } 00064 00065 //------------------------------------------------------------------------- 00066 // Purpose : Insert a curve in a loop 00067 // 00068 // Special Notes : 00069 // 00070 // Creator : Jason Kraftcheck 00071 // 00072 // Creation Date : 08/14/02 00073 //------------------------------------------------------------------------- 00074 template <class SURFACE, class LOOP, class COEDGE,class CURVE, class POINT> 00075 CubitStatus VGLoopTool<SURFACE,LOOP,COEDGE,CURVE,POINT>:: 00076 insert_curve( COEDGE* coedge1, COEDGE* coedge2, 00077 SURFACE* surface, LOOP*& new_loop1, LOOP*& new_loop2 ) 00078 { 00079 assert( coedge1 && coedge2 && 00080 coedge1->get_curve() == coedge2->get_curve() && 00081 coedge1->sense() != coedge2->sense() ); 00082 new_loop1 = new_loop2 = 0; 00083 00084 if( coedge1->sense() == CUBIT_REVERSED ) 00085 { 00086 COEDGE* tmp = coedge1; 00087 coedge2 = coedge2; 00088 coedge2 = tmp; 00089 } 00090 00091 // Find loop insertion locations. 00092 COEDGE *start_prev = 0, *end_prev = 0; 00093 if( ! previous_coedge( coedge2, surface, start_prev ) || 00094 ! previous_coedge( coedge1, surface, end_prev ) ) 00095 return CUBIT_FAILURE; 00096 00097 // If no loop was passed, just pass back the coedges 00098 // so that the caller can create new loop(s) 00099 if( !(start_prev || end_prev) ) 00100 { 00101 new_loop1 = new LOOP; 00102 new_loop1->insert_after( coedge1, 0 ); 00103 if( coedge1->start_point() == coedge1->end_point() ) 00104 { 00105 new_loop2 = new LOOP; 00106 new_loop2->insert_after( coedge2, 0 ); 00107 } 00108 else 00109 { 00110 new_loop1->insert_after( coedge2, coedge1 ); 00111 } 00112 00113 return CUBIT_SUCCESS; 00114 } 00115 00116 00117 // sipe? 00118 if( !loop1_prev || !loop2_prev ) 00119 { 00120 COEDGE *prev = loop1_prev ? loop1_prev : loop2_prev; 00121 if( coedge1->start_point() == prev->end_point() ) 00122 { 00123 prev->get_loop()->insert_after( coedge1, prev ); 00124 prev->get_loop()->insert_after( coedge2, coedge1 ); 00125 } 00126 else if( coedge1->end_point() == prev->end_point() ) 00127 { 00128 prev->get_loop()->insert_after( coedge2, prev ); 00129 prev->get_loop()->insert_after( coedge1, coedge2 ); 00130 } 00131 else 00132 { 00133 assert(0); 00134 return CUBIT_FAILURE; 00135 } 00136 } 00137 00138 // combine loops? 00139 else if( loop1_prev->get_loop() != loop2_prev->get_loop() ) 00140 { 00141 COEDGE* prev = 0; 00142 00143 // Which of the two coedges for the curve are 00144 // inserting do we want to begin with? 00145 if( coedge1->start_point() == loop1_prev->end_point() ) 00146 { 00147 loop1_prev->get_loop()->insert_after( coedge1, loop1_prev ); 00148 loop1_prev->get_loop()->insert_after( coedge2, coedge1 ); 00149 prev = coedge1; 00150 } 00151 else if( coedge2->start_point() == loop1_prev->end_point() ) 00152 { 00153 loop1_prev->get_loop()->insert_after( coedge2, loop1_prev ); 00154 loop1_prev->get_loop()->insert_after( coedge1, coedge2 ); 00155 prev = coedge2; 00156 } 00157 else 00158 { 00159 assert(0); 00160 return CUBIT_FAILURE; 00161 } 00162 00163 COEDGE* coedge = loop2_prev->next(); 00164 COEDGE* next = 0; 00165 while( loop2_prev->get_loop() != loop1_prev->get_loop() ) 00166 { 00167 next = coedge->next(); 00168 coedge->get_loop()->remove( coedge ); 00169 loop1_prev->get_loop()->insert_after( coedge, prev ); 00170 prev = coedge; 00171 coedge = next; 00172 } 00173 00174 } 00175 00176 // split the loop 00177 else 00178 { 00179 assert( loop1_prev->get_loop() == loop2_prev->get_loop() ); 00180 00181 // check for and handle a hole insersecting the original 00182 // loop at just one vertex 00183 if( coedge1->start_point() == coedge1->end_point() ) 00184 { 00185 assert( loop1_prev == loop2_prev ); 00186 00187 CubitVector prev_tan, coe1_tan, coe2_tan, norm, junk; 00188 CubitVector point = coedge1->start_point()->coordinates(); 00189 loop1_prev->get_curve()->closest_point( point, junk, &prev_tan ); 00190 if( loop1_prev->sense() == CUBIT_FORWARD ) // yes, I mean forward here!! 00191 prev_tan *= -1.0; 00192 coedge1->get_curve()->closest_point( point, junk, &coe1_tan ); 00193 coe2_tan = coe1_tan; 00194 if( coedge1->sense() == CUBIT_REVERSED ) 00195 coe1_tan *= -1.0; 00196 if( coedge2->sense() == CUBIT_REVERSED ) 00197 coe2_tan *= -1.0; 00198 loop1_prev->get_loop()->get_surface()->closest_point( point, 0, &norm ); 00199 00200 double angle1 = norm.vector_angle( prev_tan, coe1_tan ); 00201 double angle2 = norm.vector_angle( prev_tan, coe2_tan ); 00202 00203 if( angle2 < angle1 ) 00204 { 00205 COEDGE* temp = coedge2; 00206 coedge2 = coedge1; 00207 coedge1 = temp; 00208 } 00209 } 00210 00211 else if( coedge1->end_point() == loop2_prev->end_point() ) 00212 { 00213 COEDGE* temp = coedge2; 00214 coedge2 = coedge1; 00215 coedge1 = temp; 00216 } 00217 00218 00219 new_loop1 = new LOOP; 00220 loop1_prev->insert_after( coedge1, loop2_prev ); 00221 new_loop1->insert_after( coedge2, 0 ); 00222 COEDGE* prev = coedge2; 00223 00224 COEDGE* coedge = loop2_prev->next(); 00225 COEDGE* stop = loop1_prev->next(); 00226 while( coedge != stop ) 00227 { 00228 COEDGE* next = coedge->next(); 00229 coedge->get_loop()->remove( coedge ); 00230 new_loop1->insert_after( coedge, prev ); 00231 prev = coedge; 00232 coedge = next; 00233 } 00234 00235 } 00236 00237 return CUBIT_SUCCESS; 00238 } 00239 */ 00240 /* 00241 template <class SURFACE, class LOOP, class COEDGE, class CURVE, class POINT> 00242 CubitStatus VGLoopTool<SURFACE,LOOP,COEDGE,CURVE,POINT>:: 00243 VGLoopTool::curves_in_loop( LOOP* loop, POINT* point, DLIList<CURVE*>& results ) 00244 { 00245 CURVE* curve = 0; 00246 while ( (curve = point->next_curve(curve)) ) 00247 { 00248 COEDGE* coedge = 0; 00249 while ( (coedge = curve->next_coedge(coedge)) ) 00250 { 00251 if (coedge->get_loop() == loop) 00252 { 00253 results.append(curve); 00254 break; 00255 } 00256 } 00257 } 00258 return CUBIT_SUCCESS; 00259 } 00260 00261 template <class SURFACE, class LOOP, class COEDGE, class CURVE, class POINT> 00262 CubitStatus VGLoopTool<SURFACE,LOOP,COEDGE,CURVE,POINT>:: 00263 VGLoopTool::traverse_coedges( LOOP* loop, COEDGE* coedge, DLIList<COEDGE*>& results ) 00264 { 00265 // Traverse coedges, appending them to the list until 00266 // the end point is reached. 00267 POINT* loop_point = coedge->start_point(); 00268 results.append(coedge); 00269 DLIList<CURVE*> loop_curves; 00270 while ( coedge->end_point() != loop_point ) 00271 { 00272 POINT* point = coedge->end_point(); 00273 loop_curves.clean_out(); 00274 curves_in_loop( loop, point, loop_curves ); 00275 00276 COEDGE *boundary_coedge = 0, *split_coedge = 0; 00277 while( loop_curves.size() ) 00278 { 00279 CURVE* curve = loop_curves.pop(); 00280 if ( curve == coedge->get_curve() ) 00281 continue; 00282 00283 COEDGE* curve_coedge = 0; 00284 while ( (curve_coedge = curve->next_coedge(curve_coedge)) ) 00285 { 00286 if ((curve_coedge->get_loop() != loop_to_split()) || 00287 (curve_coedge->start_point() != point)) 00288 continue; 00289 00290 if (curve_coedge->get_curve()->mark == 2) 00291 { 00292 if (split_coedge) 00293 { assert(0); return CUBIT_FAILURE; } 00294 split_coedge = curve_coedge; 00295 } 00296 else if(curve_coedge->get_curve()->mark == 0) 00297 { 00298 if (boundary_coedge) 00299 { assert(0); return CUBIT_FAILURE; } 00300 boundary_coedge = curve_coedge; 00301 } 00302 } 00303 } 00304 00305 if (split_coedge) 00306 coedge = split_coedge; 00307 else if(boundary_coedge) 00308 coedge = boundary_coedge; 00309 else 00310 { assert(0); return CUBIT_FAILURE; } 00311 00312 results.append(coedge); 00313 } 00314 00315 return CUBIT_SUCCESS; 00316 } 00317 00318 00319 template <class SURFACE, class LOOP, class COEDGE, class CURVE, class POINT> 00320 LOOP* VGLoopTool<SURFACE,LOOP,COEDGE,CURVE,POINT>:: 00321 VGLoopTool::split_loop( LOOP* loop_to_split ) 00322 { 00323 // Make sure all coedge curve marks are cleared, 00324 // and count coedges (use the count to make sure 00325 // things are going okay later) 00326 int coedge_count = 0; 00327 COEDGE* coedge = loop_to_split->first_coedge(); 00328 do { 00329 coedge->mark = 0; 00330 coedge->get_curve()->mark = 0; 00331 coedge_count++; 00332 coedge = loop_to_split->next_coedge(coedge); 00333 } while ( coedge != loop_to_split->first_coedge() ); 00334 00335 // Identify non-manifold curves, marking them either 00336 // with a 2 if they can be used to split the surface 00337 // (if they are part of a connected patch for which the 00338 // bounadary of that patch intersects the surface boundary 00339 // at all points) or a 3 if they are other non-manifold 00340 // curves. This will get a bit tricky if there are 00341 // non-manifold curves hanging off of the patch of 00342 // split curves. 00343 00344 // First for all non-manifold curves, if the curve has 00345 // a point that is not shared with any other curve, mark 00346 // it with a 3. Otherwise mark it with a 2. 00347 DLIList<CURVE*> curve_stack, loop_curves, nonman_curves; 00348 coedge = loop_to_split->first_coedge(); 00349 do { 00350 CURVE* curve = coedge->get_curve(); 00351 // If we haven't done this curve yet and it is non-manifold 00352 if ( !curve->mark && curve->find_next(coedge) ) 00353 { 00354 curve->mark = 2; 00355 00356 for ( int i = 2; i--; ) 00357 { 00358 POINT* point = i ? curve->start_point() : curve->end_point(); 00359 loop_curves.clean_out(); 00360 curves_in_loop( loop_to_split, curve->start_point(), loop_curves ); 00361 if ( loop_curves.size() == 1 ) 00362 { 00363 curve->mark = 3; 00364 curve_stack.append(curve); 00365 nonman_curves.append(curve); 00366 break; 00367 } 00368 } 00369 } 00370 00371 coedge = loop_to_split->next_coedge(coedge); 00372 } while( coedge != loop_to_split->first_coedge() ); 00373 00374 // Now for each curve we marked with a three, traverse 00375 // and mark adjacent curve until we come to a point 00376 // connected to more that two curves. 00377 while( curve_stack.size() ) 00378 { 00379 CURVE* curve = curve_stack.pop(); 00380 00381 for ( int i = 2; i--; ) 00382 { 00383 POINT* point = i ? curve->start_point() : curve->end_point(); 00384 loop_curves.clean_out(); 00385 curves_in_loop( loop_to_split, curve->start_point(), loop_curves ); 00386 if ( loop_curves.size() != 2 ) 00387 continue; 00388 00389 loop_curves.move_to(curve); 00390 CURVE* other = loop_curves.next(); 00391 assert(other && other != curve ); 00392 00393 if ( other->mark != 3 ) 00394 { 00395 other->mark = 3; 00396 curve_stack.append(other); 00397 nonman_curves.append(other); 00398 } 00399 } 00400 } 00401 00402 // Find a split curve to begin at. 00403 coedge = loop_to_split->first_coedge(); 00404 do 00405 { 00406 if ( coedge->get_curve()->mark == 2 ) 00407 break; 00408 coedge = loop_to_split->next_coedge(coedge); 00409 } while( coedge != loop_to_split->first_coedge() ); 00410 00411 if ( coedge->get_curve()->mark != 2 ) 00412 { assert(0); return 0; } 00413 00414 // Get two coedges for split curve 00415 COEDGE *coedge1 = coedge, *coedge2 = 0; 00416 coedge = 0; 00417 while ( (coedge = coedge1->get_curve()->next_coedge(coedge)) ) 00418 if (coedge != coedge1) 00419 { coedge2 = coedge; break; } 00420 assert( coedge2 && coedge2->sense() != coedge1->sense() ); 00421 00422 // Get coedges for each loop by traversing from 00423 // split curve coedges 00424 DLIList<COEDGE*> old_loop_coedges, new_loop_coedges; 00425 if ( !traverse_loop(loop_to_split, coedge1, old_loop_coedges) ) 00426 return 0; 00427 if ( !traverse_loop(loop_to_split, coedge2, new_loop_coedges) ) 00428 return 0; 00429 00430 // Make sure everything adds up 00431 if ( old_loop_coedges.size() + new_loop_coedges.size() 00432 + 2*nonman_curves.size() != coedge_count) 00433 { assert(0); return 0; } 00434 00435 // Leave the larger list on the existing loop, as this 00436 // is more likely to result in the expected behavior 00437 if (new_loop_coedges.size() > old_loop_coedges.size()) 00438 { 00439 DLIList<COEDGE*> tmp_list(old_loop_coedges); 00440 old_loop_coedges = new_loop_coedges; 00441 new_loop_coedges = tmp_list; 00442 } 00443 00444 // Remove all coedges from old loop (faster this way) 00445 while( loop_to_split->first_coedge() ) 00446 loop_to_split->remove( loop_to_split->first_coedge() ); 00447 00448 // Put old_loop_coedges in loop_to_split 00449 COEDGE* next = 0; 00450 while ( old_loop_coedges.size() ) 00451 { 00452 coedge = old_loop_coedges.pop(); 00453 coedge->get_curve()->mark = 0; 00454 loop_to_split->insert_before( coedge, next ); 00455 next = coedge; 00456 } 00457 00458 // Put new_loop_coedges in new_loop 00459 LOOP* new_loop = new LOOP; 00460 next = 0; 00461 while ( new_loop_coedges.size() ) 00462 { 00463 coedge = new_loop_coedges.pop(); 00464 coedge->get_curve()->mark = 0; 00465 new_loop->insert_before( coedge, next ); 00466 next = coedge; 00467 } 00468 00469 // Now sort out other non-manifold curves 00470 00471 // Clear marks 00472 for ( int j = nonman_curves.size(); j--; ) 00473 nonman_curves->step_and_get()->mark = 0; 00474 00475 if( nonman_curves.size() ) 00476 insert_nonmanifold_curves( nonman_curves, loop_to_split, new_loop ); 00477 return new_shell; 00478 } 00479 00480 template <class SURFACE, class LOOP, class COEDGE, class CURVE, class POINT> 00481 CubitStatus VGLoopTool<SURFACE,LOOP,COEDGE,CURVE,POINT>:: 00482 VGLoopTool::insert_nonmanifold_curves( DLIList<CURVE*>& curve_stack, 00483 LOOP* loop1, LOOP* loop2 ) 00484 { 00485 return CUBIT_FAILURE; 00486 } 00487 00488 */ 00489 00490 /* 00491 //------------------------------------------------------------------------- 00492 // Purpose : Check if a curve occurs an odd number of times in a loop 00493 // 00494 // Special Notes : Input is the coedge connecting the relevent curve & loop 00495 // 00496 // Creator : Jason Kraftcheck 00497 // 00498 // Creation Date : 08/14/02 00499 //------------------------------------------------------------------------- 00500 template <class SURFACE, class LOOP, class COEDGE,class CURVE, class POINT> 00501 bool VGLoopTool<SURFACE,LOOP,COEDGE,CURVE,POINT>:: 00502 odd_coedge_count( COEDGE* coedge ) 00503 { 00504 COEDGE* curve_coedge = 0; 00505 int count = 0; 00506 while( curve_coedge = coedge->get_curve()->next_coedge( curve_coedge ) ) 00507 if( curve_coedge->get_loop() == coedge->get_loop() ) 00508 count++; 00509 00510 return (bool)(count % 2); 00511 } 00512 00513 //------------------------------------------------------------------------- 00514 // Purpose : Find the previous coedge in loop 00515 // 00516 // Special Notes : 00517 // 00518 // Creator : Jason Kraftcheck 00519 // 00520 // Creation Date : 10/28/02 00521 //------------------------------------------------------------------------- 00522 template <class SURFACE, class LOOP, class COEDGE,class CURVE, class POINT> 00523 CubitStatus VGLoopTool<SURFACE,LOOP,COEDGE,CURVE,POINT>:: 00524 previous_coedge( COEDGE* coedge, SURFACE* surface, COEDGE*& result ) 00525 { 00526 result = 0; 00527 00528 POINT* point = coedge->end_point(); 00529 CubitVector normal, tanget, closest; 00530 surface->closest_point( point->coordinates(), &closest, &normal ); 00531 00532 coedge->get_curve()->closest_point( point->coordinates(), closest, &tangent ); 00533 if( coedge->sense() == CUBIT_REVERSED ) 00534 tangent *= -1.0; 00535 00536 CURVE* curve = 0; 00537 while( curve = point->next_curve( curve ) ) 00538 { 00539 COEDGE* coedge = 0; 00540 while( coedge = curve->next_coedge( coedge ) ) 00541 { 00542 if( coedge->end_point() != point ) 00543 continue; 00544 00545 if( !coedge->get_loop() || coedge->get_loop()->get_surface() != surface ) 00546 continue; 00547 00548 if( ! result ) 00549 { 00550 result = coedge; 00551 } 00552 else if( result->get_loop() != coedge->get_loop() ) 00553 { 00554 result = 0; 00555 return CUBIT_FAILURE; 00556 } 00557 else 00558 { 00559 CubitVector result_tan, coedge_tan, closest; 00560 result->get_curve()->closest_point( point->coordinates(), closest, &result_tan ); 00561 coedge->get_curve()->closest_point( point->coordinates(), closest, &coedge_tan ); 00562 if( result->sense() == CUBIT_FORWARD ) 00563 result_tan *= -1.0; 00564 if( coedge->sense() == CUBIT_FORWARD ) 00565 result_tan *= -1.0; 00566 00567 double result_angle = normal.vector_angle( result_tan, tangent ); 00568 double coedge_angle = normal.vector_angle( coedge_tan, tangent ); 00569 if( result_angle < 0.0 ) result_angle += 2.0*CUBIT_PI; 00570 if( coedge_angle < 0.0 ) coedge_angle += 2.0*CUBIT_PI; 00571 if( coedge_angle < result_angle ) 00572 result = coedge; 00573 } 00574 } 00575 } 00576 00577 return CUBIT_SUCCESS; 00578 } 00579 00580 */ 00581 00582 00583 //------------------------------------------------------------------------- 00584 // Purpose : Get a polygon representation of a loop as a point list 00585 // 00586 // Special Notes : 00587 // 00588 // Creator : Jason Kraftcheck 00589 // 00590 // Creation Date : 08/14/02 00591 //------------------------------------------------------------------------- 00592 template <class SURFACE, class LOOP, class COEDGE,class CURVE, class POINT> 00593 CubitStatus VGLoopTool<SURFACE,LOOP,COEDGE,CURVE,POINT>:: 00594 get_loop_polygon( COEDGE* first_coedge, DLIList<CubitVector*>& polygon ) 00595 { 00596 if( !first_coedge ) 00597 return CUBIT_FAILURE; 00598 00599 DLIList<CubitVector*> interior; 00600 CubitSense sense; 00601 polygon.clean_out(); 00602 00603 COEDGE* coedge = first_coedge; 00604 do 00605 { 00606 polygon.append( new CubitVector( coedge->start_point()->coordinates() ) ); 00607 00608 interior.clean_out(); 00609 if( !coedge->get_curve()->get_interior_extrema( interior, sense ) ) 00610 { 00611 while( polygon.size() ) delete polygon.pop(); 00612 return CUBIT_FAILURE; 00613 } 00614 00615 if( sense != coedge->sense() ) 00616 interior.reverse(); 00617 polygon += interior; 00618 00619 coedge = coedge->next(); 00620 } while( coedge != first_coedge ); 00621 00622 return CUBIT_SUCCESS; 00623 } 00624 00625 00626 //------------------------------------------------------------------------- 00627 // Purpose : Calculate loop angle metric 00628 // 00629 // Special Notes : 00630 // 00631 // Creator : Jason Kraftcheck 00632 // 00633 // Creation Date : 08/14/02 00634 //------------------------------------------------------------------------- 00635 template <class SURFACE, class LOOP, class COEDGE,class CURVE, class POINT> 00636 double VGLoopTool<SURFACE,LOOP,COEDGE,CURVE,POINT>:: 00637 loop_angle_metric( COEDGE* first_coedge ) 00638 { 00639 if( !first_coedge ) 00640 return 0.0; 00641 00642 assert( first_coedge 00643 && first_coedge->get_loop() 00644 && first_coedge->get_loop()->get_surface() ); 00645 00646 DLIList<CubitVector*> polygon; 00647 get_loop_polygon( first_coedge, polygon ); 00648 00649 double result = 0.0; 00650 CubitVector *point[3], segment[2], normal; 00651 point[0] = polygon.step_and_get(); 00652 point[1] = polygon.step_and_get(); 00653 segment[0] = *point[1] - *point[0]; 00654 for( int i = polygon.size(); i--; ) 00655 { 00656 point[2] = polygon.step_and_get(); 00657 segment[1] = *point[1] - *point[2]; 00658 first_coedge->get_loop()->get_surface()->closest_point( *point[1], 0, &normal ); 00659 result += normal.vector_angle( segment[1], segment[0] ); 00660 00661 point[1] = point[2]; 00662 segment[0] = -segment[1]; 00663 } 00664 00665 result /= CUBIT_PI; 00666 result -= polygon.size(); 00667 00668 while( polygon.size() ) 00669 delete polygon.pop(); 00670 00671 return result; 00672 } 00673 00674 template <class SURFACE, class LOOP, class COEDGE,class CURVE, class POINT> 00675 void VGLoopTool<SURFACE,LOOP,COEDGE,CURVE,POINT>:: 00676 get_loop_polyline( COEDGE* first_coedge, std::vector<CubitVector>& list ) 00677 { 00678 COEDGE* coedge = first_coedge; 00679 GMem gmem; 00680 list.resize(0); 00681 00682 do { 00683 coedge->get_curve()->get_geometry_query_engine()-> 00684 get_graphics( coedge->get_curve(), &gmem ); 00685 int num_pts = gmem.pointListCount; 00686 if ( num_pts > 1 ) { 00687 00688 int start = list.size(); 00689 list.resize( start + num_pts - 1 ); 00690 std::vector<CubitVector>::iterator itor = list.begin() + start; 00691 if ( coedge->sense() == CUBIT_FORWARD ) { 00692 GPoint* pitor = gmem.point_list(); 00693 GPoint* pend = pitor + num_pts - 1; 00694 for ( ; pitor != pend; ++pitor ) { 00695 itor->set( pitor->x, pitor->y, pitor->z ); 00696 ++itor; 00697 } 00698 } else { 00699 GPoint* pend = gmem.point_list(); 00700 GPoint* pitor = pend + num_pts - 1; 00701 for ( ; pitor != pend; --pitor ) { 00702 itor->set( pitor->x, pitor->y, pitor->z ); 00703 ++itor; 00704 } 00705 } 00706 } 00707 00708 coedge = coedge->next(); 00709 } while ( coedge != first_coedge ); 00710 } 00711 00712 00713 /* 00714 //------------------------------------------------------------------------- 00715 // Purpose : Check if a position is to the "left" of a coedge 00716 // 00717 // Special Notes : 00718 // 00719 // Creator : Jason Kraftcheck 00720 // 00721 // Creation Date : 08/14/02 00722 //------------------------------------------------------------------------- 00723 template <class SURFACE, class LOOP, class COEDGE,class CURVE, class POINT> 00724 bool VGLoopTool<SURFACE,LOOP,COEDGE,CURVE,POINT>:: 00725 inside_of_curve( const CubitVector& tangent, 00726 const CubitVector& curve_pos, 00727 const CubitVector& surf_pos, 00728 const CubitVector& normal ) 00729 { 00730 CubitVector cross = tangent * ( surf_pos - curve_pos ); 00731 return cross % normal > -CUBIT_RESABS; 00732 } 00733 00734 //------------------------------------------------------------------------- 00735 // Purpose : Find the coedge in a loop that is closest to the passed 00736 // point 00737 // 00738 // Special Notes : 00739 // 00740 // Creator : Jason Kraftcheck 00741 // 00742 // Creation Date : 08/14/02 00743 //------------------------------------------------------------------------- 00744 template <class SURFACE, class LOOP, class COEDGE,class CURVE, class POINT> 00745 COEDGE* VGLoopTool<SURFACE,LOOP,COEDGE,CURVE,POINT>:: 00746 closest_loop_coedge( const CubitVector& from_pt, 00747 COEDGE* first_coedge, 00748 COEDGE*& other_coedge, 00749 CubitVector* closest ) 00750 { 00751 CubitVector closest_pt, current_pt; 00752 double current_dst, closest_dst; 00753 COEDGE* closest_coedge = 0; 00754 other_coedge = 0; 00755 00756 // Skip coedges for curves that occur twice in the loop (sipes, etc) 00757 COEDGE* coedge = first_coedge; 00758 while( !odd_coedge_count(coedge) ) 00759 { 00760 coedge = coedge->next(); 00761 if( coedge == first_coedge ) 00762 return false; 00763 } 00764 00765 // Search for a) a curve who's bounding box contains the point 00766 // or b) the curve who's box is closest to the point 00767 closest_coedge = coedge; 00768 closest_dst = coedge->get_curve()->bounding_box().distance_squared(from_pt); 00769 coedge = coedge->next(); 00770 while( (coedge != first_coedge) && (closest_dst > CUBIT_RESABS) ) 00771 { 00772 if( odd_coedge_count(coedge) ) 00773 { 00774 current_dst = coedge->get_curve()->bounding_box().distance_squared(from_pt); 00775 if( current_dst < closest_dst ) 00776 { 00777 closest_coedge = coedge; 00778 closest_dst = current_dst; 00779 } 00780 } 00781 coedge = coedge->next(); 00782 } 00783 00784 // Now find actual distance from the curve 00785 closest_coedge->get_curve()->closest_point_trimmed( from_pt, closest_pt ); 00786 closest_dst = (from_pt - closest_pt).length_squared(); 00787 00788 // Look for any curves that are closer 00789 first_coedge = closest_coedge; 00790 coedge = first_coedge.next(); 00791 while( coedge != first_coedge ) 00792 { 00793 if( odd_coedge_count(coedge) ) 00794 { 00795 if( coedge->get_curve()->bounding_box().distance_squared(from_pt) < closest_dst ) 00796 { 00797 coedge->get_curve()->closest_point_trimmed( from_pt, current_pt ); 00798 current_dst = (from_pt - current_pt).length_squared(); 00799 00800 if( (closest_pt - current_pt).length_squared() < RESSQR ) 00801 { 00802 if( current_dst < closest_dst ) 00803 { 00804 closest_dst = current_dst; 00805 closest_pt = current_pt; 00806 } 00807 other_coedge = coedge; 00808 } 00809 else if( current_dst < closest_dst ) 00810 { 00811 closest_coedge = coedge; 00812 closest_dst = current_dst; 00813 closest_pt = current_pt; 00814 other_coedge = 0; 00815 } 00816 } 00817 } 00818 coedge = coedge->next(); 00819 } 00820 00821 //make sure we have things in the correct order 00822 if( other_coedge ) 00823 { 00824 if( closest_coedge->start_point() == other_coedge->end_point() ) 00825 { 00826 COEDGE* tmp = closest_coedge; 00827 closest_coedge = other_coedge; 00828 other_coedge = tmp; 00829 } 00830 else if( closest_coedge->end_point() != other_coedge->start_point() ) 00831 { 00832 other_coedge = 0; 00833 } 00834 } 00835 00836 if( closest ) *closest = closest_pt; 00837 return closest_coedge; 00838 } 00839 00840 00841 //------------------------------------------------------------------------- 00842 // Purpose : Test if a position is on the surface side of a loop. 00843 // 00844 // Special Notes : 00845 // 00846 // Creator : Jason Kraftcheck 00847 // 00848 // Creation Date : 08/14/02 00849 //------------------------------------------------------------------------- 00850 template <class SURFACE, class LOOP, class COEDGE,class CURVE, class POINT> 00851 bool VGLoopTool<SURFACE,LOOP,COEDGE,CURVE,POINT>:: 00852 is_position_within_loop( const CubitVector& position, 00853 COEDGE* first_coedge, 00854 CubitVector* closest_on_loop, 00855 CubitVector* passed_normal ) 00856 { 00857 CubitVector surf_point, normal, pt_on_curve; 00858 if( passed_normal ) 00859 { 00860 surf_point = position; 00861 normal = *pased_normal; 00862 } 00863 else 00864 { 00865 first_coedge->get_loop()->get_surface() 00866 ->closest_point( position, &surf_point, &normal ); 00867 } 00868 00869 COEDGE* other_coedge = 0; 00870 COEDGE* closest_coedge = 00871 closest_loop_coedge( first_coedge, position, other_coedge, &pt_on_curve ); 00872 if( !closest_coedge ) 00873 return true; 00874 00875 if( closest_on_loop ) 00876 *closest_on_loop = pt_on_curve; 00877 00878 CubitVector coe_normal, coe_cross, tangent1, tangent2, junk; 00879 00880 if( ! other_coedge ) 00881 { 00882 double u = closest_coedge->get_curve()->u_from_position( pt_on_curve ); 00883 00884 // Special case: closest point on loop at G1 discontinuity 00885 if( closest_coedge->get_curve()->G1_discontinuous( u, &tangent1, &tangent2 ) ) 00886 { 00887 if( closest_coedge->sense() == CUBIT_REVERSED ) 00888 { 00889 tangent1 *= -1.0; 00890 tangent2 *= -1.0; 00891 } 00892 00893 closest_coedge->get_loop()->get_surface()-> 00894 closest_point( pt_on_curve, 0, &coe_normal ); 00895 coe_cross = tangent1 * tangent2; 00896 bool inside1 = inside_of_curve( tangent1, pt_on_curve, surf_point, normal ); 00897 bool inside2 = inside_of_curve( tangent2, pt_on_curve, surf_point, normal ); 00898 if( cross % coe_normal > -CUBIT_RESABS ) 00899 return inside1 && inside2; 00900 else 00901 return inside1 || inside2; 00902 } 00903 00904 else // **** This is the normal, non-special case part **** 00905 { 00906 closest_coedge->closest_point( pt_on_curve, junk, &tangent1 ); 00907 if( closest_coedge->sense() == CUBIT_REVERSED ) 00908 tangent1 *= -1.0; 00909 00910 return inside_of_curve( tangent1, pt_on_curve, surf_point, normal ); 00911 } 00912 } 00913 // Special case: closest point on loop at vertex 00914 else 00915 { 00916 closest_coedge->get_curve()->closest_point( pt_on_curve, junk, &tangent1 ); 00917 other_coedge->get_curve()->closest_point( pt_on_curve, junk, &tangent2 ); 00918 if( closest_coedge->sense() == CUBIT_REVERSED ) 00919 tangent1 *= -1.0; 00920 if( other_coedge->sense() == CUBIT_REVERSED ) 00921 tangent2 *= -1.0; 00922 00923 closest_coedge->get_loop()->get_surface()-> 00924 closest_point( pt_on_curve, 0, &coe_normal ); 00925 00926 coe_cross = tangent1 * tangent2; 00927 bool inside1 = inside_of_curve( tangent1, pt_on_curve, surf_point, normal ); 00928 bool inside2 = inside_of_curve( tangent2, pt_on_curve, surf_point, normal ); 00929 00930 if( coe_cross % coe_normal > -CUBIT_RESABS ) 00931 return inside1 && inside2; 00932 else 00933 return inside1 || inside2; 00934 } 00935 } 00936 00937 00938 //------------------------------------------------------------------------- 00939 // Purpose : Very rough approximation of the area bounded by a loop 00940 // 00941 // Special Notes : 00942 // 00943 // Creator : Jason Kraftcheck 00944 // 00945 // Creation Date : 08/14/02 00946 //------------------------------------------------------------------------- 00947 template <class SURFACE, class LOOP, class COEDGE,class CURVE, class POINT> 00948 double VGLoopTool<SURFACE,LOOP,COEDGE,CURVE,POINT>:: 00949 loop_area( COEDGE* first_coedge ) 00950 { 00951 int i; 00952 00953 DLIList<CubitVector*> polygon; 00954 get_loop_polygon( first_coedge ); 00955 00956 // Get surface normal at each polygon point 00957 DLIList<CubitVector*> normals; 00958 polygon.reset(); 00959 for( i = polygon.size(); i--; ) 00960 { 00961 CubitVector norm, *pt = polygon.get_and_step(); 00962 first_coedge->get_loop()->get_surface()->closest_point(*pt,0,&norm); 00963 normals.append( new CubitVector(norm) ); 00964 } 00965 00966 // Average surface normals 00967 normal_list.reset(); 00968 CubitVector mean_normal(0.,0.,0.); 00969 for( i = normals.size(); i--; ) 00970 mean_normal += *normals.get_and_step(); 00971 mean_normal /= normals.size(); 00972 00973 // Choose base point at which the surface normal 00974 // is closest to the mean normal from above 00975 point_list.reset(); 00976 normal_list.reset(); 00977 CubitVector* base_point = polygon.get_and_step(); 00978 CubitVector* base_normal = normals.get_and_step(); 00979 double largest_dot = mean_normal % *base_normal; 00980 00981 for( i = polygon.size(); i > 1; i-- ) 00982 { 00983 CubitVector* normal = normals.get_and_step(); 00984 double dot = mean_normal % *normal; 00985 if( dot > largest_dot ) 00986 { 00987 base_point = polygon.get(); 00988 base_normal = normal; 00989 } 00990 polygon.step(); 00991 } 00992 00993 polygon.move_to( base_point ); 00994 normals.move_to( base_normal ); 00995 polygon.step(); 00996 normals.step(); 00997 00998 // Do simple 2-D area calculation and hope it isn't too 00999 // inaccurate for the 3-D refface. 01000 double double_area = 0.0; 01001 CubitVector *prev_point = polygon.get_and_step(), 01002 *curr_point = polygon.get_and_step(); 01003 CubitVector *prev_normal = normals.get_and_step(), 01004 *curr_normal = normals.get_and_step(); 01005 01006 while( curr_point != base_point ) 01007 { 01008 CubitVector cross = (*prev_point - *base_point)*(*curr_point - *base_point); 01009 CubitVector normal = *base_normal + *prev_normal + *curr_normal; 01010 double dot_product = cross % normal; 01011 double_area += dot_product >= 0.0 ? cross.length() : -(cross.length()); 01012 01013 prev_point = curr_point; 01014 prev_normal = curr_normal; 01015 curr_point = polygon.get_and_step(); 01016 curr_normal = normals.get_and_step(); 01017 } 01018 01019 while( polygon.size() > 0 ) delete polygon.pop(); 01020 while( normals.size() > 0 ) delete normals.pop(); 01021 return double_area / 2.0; 01022 } 01023 01024 template <class SURFACE, class LOOP, class COEDGE,class CURVE, class POINT> 01025 CubitStatus VGLoopTool<SURFACE,LOOP,COEDGE,CURVE,POINT>:: 01026 closest_point_trimmed( DLIList<COEDGE*>& surface_coedges, const CubitVector& from_pt, 01027 CubitVector& result_pt, CubitPointContainment* containment ) 01028 { 01029 CubitVector pt_on_surf, normal; 01030 if( ! surface->closest_point( from_pt, &pt_on_surf, &normal ) ) 01031 return CUBIT_FAILURE; 01032 01033 01034 CubitVector pt_on_curve; 01035 COEDGE *closest_coedge = 0, *other_coedge = 0; 01036 if( ! closest_surface_coedge( surface, from_pt, closest_coedge, 01037 other_coedge, &pt_on_curve ) ) 01038 return CUBIT_FAILURE; 01039 01040 CubitVector coe_normal, coe_cross, tangent1, tangent2, junk; 01041 bool inside; 01042 if( ! other_coedge ) 01043 { 01044 CURVE* curve_ptr = closest_coedge->get_curve(); 01045 double u = curve_ptr->u_from_position( pt_on_curve ); 01046 01047 // **** Special case: closest point on loop at G1 discontinuity **** 01048 if( curve_ptr->G1_discontinuous( u, &tangent1, &tangent2 ) ) 01049 { 01050 if( closest_coedge->sense() == CUBIT_REVERSED ) 01051 { 01052 tangent1 *= -1.0; 01053 tangent2 *= -1.0; 01054 } 01055 surface->closest_point( pt_on_curve, NULL, &coe_normal ); 01056 coe_cross = tangent1 * tangent2; 01057 double sum = (coe_cross + coe_normal).length_squared(); 01058 double diff = (coe_cross - coe_normal).length_squared(); 01059 01060 CubitBoolean inside1 = 01061 inside_of_curve( tangent1, pt_on_curve, pt_on_surf, normal ); 01062 CubitBoolean inside2 = 01063 inside_of_curve( tangent2, pt_on_curve, pt_on_surf, normal ); 01064 01065 if( (sum > diff) || (diff < CUBIT_DBL_MIN) ) 01066 //discontinuity is at a convexity 01067 { 01068 //the point must be inside of both sub-edges 01069 inside = inside1 && inside2; 01070 } 01071 else //discontinuity is at a concavity 01072 { 01073 //the point must be inside of one of the sub-edges 01074 inside = inside1 || inside2; 01075 } 01076 } 01077 01078 else // **** This is the normal, non-special case part **** 01079 { 01080 curve_ptr->closest_point( pt_on_curve, junk, &tangent1 ); 01081 if( closest_coedge->sense() == CUBIT_REVERSED ) 01082 tangent1 *= -1.0; 01083 01084 inside = (inside_of_curve(tangent1, pt_on_curve, pt_on_surf, normal) == CUBIT_TRUE); 01085 } 01086 } 01087 // **** Special case: closest point on loop at vertex **** 01088 else 01089 { 01090 CURVE* curve1_ptr = closest_coedge->get_curve(); 01091 CURVE* curve2_ptr = other_coedge->get_curve(); 01092 curve1_ptr->closest_point( pt_on_curve, junk, &tangent1 ); 01093 curve2_ptr->closest_point( pt_on_curve, junk, &tangent2 ); 01094 01095 if( closest_coedge->sense() == CUBIT_REVERSED ) 01096 tangent1 *= -1.0; 01097 if( other_coedge->sense() == CUBIT_REVERSED ) 01098 tangent2 *= -1.0; 01099 01100 surface->closest_point( pt_on_curve, NULL, &coe_normal ); 01101 01102 coe_cross = tangent1 * tangent2; 01103 double sum = (coe_cross + coe_normal).length_squared(); 01104 double diff = (coe_cross - coe_normal).length_squared(); 01105 01106 CubitBoolean inside1 = 01107 inside_of_curve( tangent1, pt_on_curve, pt_on_surf, normal ); 01108 CubitBoolean inside2 = 01109 inside_of_curve( tangent2, pt_on_curve, pt_on_surf, normal ); 01110 01111 if( (sum > diff) || (diff < CUBIT_DBL_MIN) ) 01112 //the common vertex is at a convexity 01113 { 01114 //the point must be inside of both coedges 01115 inside = inside1 && inside2; 01116 } 01117 else //the common vertex is at a concavity 01118 { 01119 //the point must be inside of one of the coedges 01120 inside = inside1 || inside2; 01121 } 01122 } 01123 01124 result_pt = inside ? pt_on_surf : pt_on_curve; 01125 if( containment ) 01126 { 01127 if( (pt_on_surf-pt_on_curve).length_squared() < (GEOMETRY_RESABS*GEOMETRY_RESABS) ) 01128 *containment = CUBIT_PNT_BOUNDARY; 01129 else 01130 *containment = inside ? CUBIT_PNT_INSIDE : CUBIT_PNT_OUTSIDE; 01131 } 01132 01133 return CUBIT_SUCCESS; 01134 } 01135 01136 template <class SURFACE, class LOOP, class COEDGE,class CURVE, class POINT> 01137 CubitStatus VGLoopTool<SURFACE,LOOP,COEDGE,CURVE,POINT>:: 01138 closest_surface_coedge( SURFACE* surface, const CubitVector& from_pt, 01139 COEDGE*& coedge1, COEDGE*& coedge2, 01140 CubitVector* pt_on_curve ) 01141 { 01142 coedge1 = coedge2 = 0; 01143 LOOP* loop = 0; 01144 COEDGE* coedge; 01145 const double ressqr = CUBIT_RESABS * CUBIT_RESABS; 01146 01147 01148 01149 //Find the first bounding box that the point is within, or if the 01150 // point isn't in any bounding box, the closest one 01151 closest_dst = CUBIT_DBL_MAX; 01152 while( loop = surface->next_loop( loop ) ) 01153 { 01154 coedge = loop->first_coedge(); 01155 do 01156 { 01157 if( odd_coedge_count( coedge ) ) 01158 { 01159 double dist_sqr = 01160 coedge->get_curve()->bounding_box().distance_squared(from_pt); 01161 if( dist_sqr < closest_dst ) 01162 { 01163 coedge1 = coedge; 01164 closest_dst = dist_sqr; 01165 if( dist_sqr < ressqr ) 01166 break; 01167 } 01168 } 01169 01170 coedge = coedge->next(); 01171 } while( coedge != loop->first_coedge() ); 01172 01173 if( closest_dst < ressqr ) 01174 break; 01175 } 01176 01177 if( !coedge1 ) 01178 return CUBIT_FAILURE; 01179 01180 //Start by assuming that the curve we found above is the closest 01181 CubitVector closest_pt; 01182 coedge1->get_curve()->closest_point_trimmed( from_pt, closest_pt ); 01183 closest_dst = ( from_pt - closest_pt ).length_squared(); 01184 01185 //Now look for a closer curve 01186 while( loop = surface->next_loop( loop ) ) 01187 { 01188 coedge = loop->first_coedge(); 01189 do 01190 { 01191 if( odd_coedge_count( coedge ) ) 01192 { 01193 if( coedge->get_curve()->bounding_box().distance_squared(from_pt) <= 01194 closest_dst+GEOMETRY_RESABS ) 01195 { 01196 CubitVector current_pt; 01197 coedge->get_curve()->closest_point_trimmed( from_pt, current_pt ); 01198 double current_dst = (from_pt - current_pt).length_squared(); 01199 01200 if( (closest_pt = current_pt).length_squared() < ressqr ) 01201 { 01202 if( current_dst < closest_dst ) 01203 { 01204 closest_dst = current_dst; 01205 closest_pt = current_pt; 01206 coedge2 = coedge; 01207 } 01208 else 01209 { 01210 coedge2 = coedge; 01211 } 01212 } 01213 else if( current_dst < closest_dst ) 01214 { 01215 coedge1 = coedge; 01216 closest_dst = current_dst; 01217 closest_pt = current_pt; 01218 coedge2 = 0; 01219 } 01220 } 01221 } 01222 coedge = coedge->next(); 01223 } while( coedge != loop->first_coedge() ); 01224 } 01225 01226 01227 //make sure we have things in the correct order 01228 if( coedge2 ) 01229 { 01230 POINT* common = coedge1->get_curve()->common( coedge2->get_curve() ); 01231 if( ! common ) 01232 coedge2 = 0; 01233 else if( coedge1->start_point() == coedge2->end_point() ) 01234 { 01235 COEDGE* tmp = coedge1; 01236 coedge1 = coedge2; 01237 coedge2 = tmp; 01238 } 01239 } 01240 01241 if( pt_on_curve ) *pt_on_curve = closest_pt; 01242 return CUBIT_SUCCESS; 01243 } 01244 */