cgma
|
00001 #include "PartSurfFacetTool.hpp" 00002 #include "CubitMessage.hpp" 00003 #include "DLIList.hpp" 00004 #include "GeometryQueryEngine.hpp" 00005 00006 #include "PartitionSurface.hpp" 00007 #include "PartitionCurve.hpp" 00008 #include "PartitionPoint.hpp" 00009 #include "TDVGFacetOwner.hpp" 00010 00011 #include "CubitFacetData.hpp" 00012 #include "CubitFacetEdgeData.hpp" 00013 #include "CubitPointData.hpp" 00014 00015 #include "RefVertex.hpp" 00016 #include "RefEdge.hpp" 00017 #include "GfxDebug.hpp" 00018 #include "GMem.hpp" 00019 00020 #undef PART_SURF_REFACET 00021 00022 void PartSurfFacetTool::validate_facets( PartitionSurface* mySurface ) 00023 { 00024 int i, j, k; 00025 DLIList<CubitFacetData*> facets; 00026 DLIList<CubitFacet*> pt_facets, edge_facets; 00027 DLIList<CubitFacetEdge*> pt_edges; 00028 mySurface->get_facet_data(facets); 00029 for( i = facets.size(); i--; ) 00030 { 00031 CubitFacetData* facet = facets.get_and_step(); 00032 for ( j = 0; j < 3; j++ ) 00033 { 00034 CubitFacetEdge* edge = facet->edge(j); 00035 if ( !edge ) 00036 { 00037 PRINT_ERROR("Facet with NULL edge.\n"); 00038 continue; 00039 } 00040 00041 if ( PartitionEntity* ent = TDVGFacetOwner::get(edge) ) 00042 { 00043 PartitionCurve* curve = dynamic_cast<PartitionCurve*>(ent); 00044 if (!curve) 00045 { 00046 PRINT_ERROR("Facet edge owned by non-curve %s %p\n", 00047 typeid(*ent).name(), (void*)ent); 00048 GfxDebug::draw_line( edge->point(0)->coordinates(), 00049 edge->point(1)->coordinates(), 00050 CUBIT_RED_INDEX ); 00051 continue; 00052 } 00053 00054 int edge_use_count = 0; 00055 for ( k = 0; k < edge->num_adj_facets(); k++ ) 00056 if ( (const PartitionEntity*)TDVGFacetOwner::get(edge->adj_facet(k)) == mySurface ) 00057 edge_use_count++; 00058 assert(edge_use_count); 00059 00060 int curve_use_count = 0; 00061 int coedge_count = 0; 00062 PartitionCoEdge* coedge = 0; 00063 while (( coedge = curve->next_coedge(coedge) )) 00064 { 00065 if (coedge->get_loop()) 00066 { 00067 coedge_count++; 00068 if (coedge->get_loop()->get_surface() == mySurface) 00069 curve_use_count++; 00070 } 00071 } 00072 00073 RefEdge* curve_owner = dynamic_cast<RefEdge*>(curve->topology_entity()); 00074 if ( coedge_count != edge->num_adj_facets() ) 00075 { 00076 PRINT_ERROR("Curve %p (RefEdge %d): Curve in %d partition surfaces " 00077 "has facet edge in %d facets.\n", (void*)curve, 00078 curve_owner ? curve_owner->id() : 0, 00079 coedge_count, edge->num_adj_facets() ); 00080 GfxDebug::draw_line( edge->point(0)->coordinates(), 00081 edge->point(1)->coordinates(), 00082 CUBIT_RED_INDEX ); 00083 } 00084 00085 if ( curve_use_count != edge_use_count ) 00086 { 00087 PRINT_ERROR("Curve %p (RefEdge %d): Curve used in %d coedges of " 00088 "this surface exists in %d facets of this surface.\n", 00089 (void*)curve, 00090 curve_owner ? curve_owner->id() : 0, 00091 curve_use_count, edge_use_count ); 00092 GfxDebug::draw_line( edge->point(0)->coordinates(), 00093 edge->point(1)->coordinates(), 00094 CUBIT_RED_INDEX ); 00095 } 00096 } 00097 else // FacetEdge has no owner 00098 { 00099 if (edge->num_adj_facets() != 2) 00100 { 00101 PRINT_ERROR("Interior facet edge is %d-valent.\n", edge->num_adj_facets()); 00102 GfxDebug::draw_line( edge->point(0)->coordinates(), 00103 edge->point(1)->coordinates(), 00104 CUBIT_RED_INDEX ); 00105 } 00106 } 00107 00108 bool found = false; 00109 for ( k = 0; k < edge->num_adj_facets(); k++ ) 00110 { 00111 CubitFacet* edge_facet = edge->adj_facet(k); 00112 if( edge_facet == facet ) 00113 found = true; 00114 00115 int index = edge_facet->edge_index(edge); 00116 if( index < 0 ) 00117 { 00118 PRINT_ERROR("edge->facet link missing facet->edge link.\n"); 00119 continue; 00120 } 00121 CubitPoint* fp1 = edge_facet->point((index+1)%3); 00122 CubitPoint* fp2 = edge_facet->point((index+2)%3); 00123 int sense = 1; 00124 if( fp1 == edge->point(1) && fp2 == edge->point(0) ) 00125 sense = -1; 00126 else if( fp1 != edge->point(0) || fp2 != edge->point(1) ) 00127 { 00128 PRINT_ERROR("Facet adjacent to edge does not contain edge end points.\n"); 00129 GfxDebug::draw_line( edge->point(0)->coordinates(), 00130 edge->point(1)->coordinates(), 00131 CUBIT_RED_INDEX ); 00132 continue; 00133 } 00134 if ( sense != edge_facet->edge_use(index) ) 00135 { 00136 //PRINT_ERROR("Facet has incorrect edge use\n"); 00137 } 00138 } 00139 00140 if( !found ) 00141 PRINT_ERROR("facet->edge link missing edge->facet link.\n"); 00142 } 00143 00144 for ( j = 0; j < 3; j++ ) 00145 { 00146 CubitPoint* point = facet->point(j); 00147 pt_facets.clean_out(); 00148 point->facets(pt_facets); 00149 bool found = false; 00150 for ( k = pt_facets.size(); k--; ) 00151 { 00152 CubitFacet* pt_facet = pt_facets.get_and_step(); 00153 if ( pt_facet == facet ) 00154 found = true; 00155 else if( pt_facet->point_index(point) < 0 ) 00156 PRINT_ERROR("point->facet link missing facet->point link.\n"); 00157 } 00158 if( ! found ) 00159 PRINT_ERROR("facet->point link missing point->facet link.\n"); 00160 00161 point->edges(pt_edges); 00162 while (pt_edges.size()) 00163 { 00164 CubitFacetEdge* edge = pt_edges.pop(); 00165 edge_facets.clean_out(); 00166 edge->facets(edge_facets); 00167 int count = 0; 00168 while (edge_facets.size()) 00169 if (TDVGFacetOwner::get(edge_facets.pop()) == mySurface) 00170 count++; 00171 00172 bool draw = false; 00173 if (count == 0) // not in this face 00174 ; 00175 else if (PartitionEntity* ent = TDVGFacetOwner::get(edge)) 00176 { 00177 PartitionCurve* curve = dynamic_cast<PartitionCurve*>(ent); 00178 if (curve->is_nonmanifold(mySurface)) 00179 { 00180 if (count != 2) 00181 { 00182 draw = true; 00183 PRINT_ERROR("Edge on non-manifold curve contained in %d facets.\n", count); 00184 } 00185 } 00186 else if (count != 1) 00187 { 00188 draw = true; 00189 PRINT_ERROR("Boundary edge contained in %d facets.\n", count); 00190 } 00191 } 00192 else if (count != 2) 00193 { 00194 draw = true; 00195 PRINT_ERROR("Interior edge contained in %d facets.\n", count); 00196 } 00197 00198 if (draw) { 00199 CubitVector start = edge->point(0)->coordinates(); 00200 CubitVector step = 0.05 * (edge->point(1)->coordinates() - start); 00201 for (int k = 0; k < 20; k++) 00202 GfxDebug::draw_point( start + k * step, CUBIT_RED_INDEX ); 00203 GfxDebug::flush(); 00204 } 00205 } 00206 } 00207 } 00208 00209 00210 // Check loops for contiguous chains of facet edges. 00211 DLIList<CubitFacetEdgeData*> curve_edges, loop_edges; 00212 PartitionLoop* loop = 0; 00213 while ((loop = mySurface->next_loop(loop))) 00214 { 00215 loop_edges.clean_out(); 00216 PartitionCoEdge* coedge = loop->first_coedge(); 00217 do { 00218 PartitionCurve* curve = coedge->get_curve(); 00219 if (!curve->is_nonmanifold(mySurface)) 00220 { 00221 curve_edges.clean_out(); 00222 curve->get_facet_data(curve_edges); 00223 if (coedge->sense() == CUBIT_REVERSED) 00224 curve_edges.reverse(); 00225 loop_edges += curve_edges; 00226 } 00227 coedge = loop->next_coedge(coedge); 00228 } while (coedge != loop->first_coedge()); 00229 00230 loop_edges.last(); 00231 CubitFacetEdgeData* prev = loop_edges.get_and_step(); 00232 PartitionCurve* prev_curve = dynamic_cast<PartitionCurve*>(TDVGFacetOwner::get(prev)); 00233 for (int i = 0; i < loop_edges.size(); i++) 00234 { 00235 CubitFacetEdgeData* edge = loop_edges.get_and_step(); 00236 CubitPoint* shared = edge->shared_point(prev); 00237 PartitionCurve* curve = dynamic_cast<PartitionCurve*>(TDVGFacetOwner::get(edge)); 00238 00239 if (!prev_curve || !curve) 00240 { 00241 PRINT_ERROR("Missing facet owner on boundary curve.\n"); 00242 prev_curve = curve; 00243 prev = edge; 00244 continue; 00245 } 00246 00247 if (!shared) 00248 { 00249 PRINT_ERROR("Broken facet-edge chain at curve %p (RefEdge %d):\n" 00250 " start of segment (%f,%f,%f)->(%f,%f,%f)\n", 00251 (void*)curve, curve && dynamic_cast<RefEdge*>(curve->topology_entity())? 00252 dynamic_cast<RefEdge*>(curve->topology_entity())->id() : 0, 00253 edge->point(0)->coordinates().x(), 00254 edge->point(0)->coordinates().y(), 00255 edge->point(0)->coordinates().z(), 00256 edge->point(1)->coordinates().x(), 00257 edge->point(1)->coordinates().y(), 00258 edge->point(1)->coordinates().z()); 00259 } 00260 else if(PartitionPoint *pt = dynamic_cast<PartitionPoint*>(TDVGFacetOwner::get(shared))) 00261 { 00262 if( (prev_curve == curve) && 00263 !(pt == curve->start_point() && pt == curve->end_point()) ) 00264 { 00265 PRINT_ERROR("Edges at point %p (vertex %d) (%f,%f,%f) owned\n" 00266 " by the same curve: %p (RefEdge %d)\n", 00267 (void*)pt, dynamic_cast<RefVertex*>(pt->topology_entity()) ? 00268 dynamic_cast<RefVertex*>(pt->topology_entity())->id() : 0, 00269 pt->coordinates().x(), pt->coordinates().y(), pt->coordinates().z(), 00270 (void*)curve, curve && dynamic_cast<RefEdge*>(curve->topology_entity())? 00271 dynamic_cast<RefEdge*>(curve->topology_entity())->id() : 0); 00272 } 00273 else if (!curve->other_point(pt)) 00274 { 00275 PRINT_ERROR("Edge owner curve %p (RefEdge %d) at point %p \n" 00276 " (vertex %d) (%f,%f,%f) doesn't match topology\n", 00277 (void*)curve, curve && dynamic_cast<RefEdge*>(curve->topology_entity())? 00278 dynamic_cast<RefEdge*>(curve->topology_entity())->id() : 0, 00279 (void*)pt, dynamic_cast<RefVertex*>(pt->topology_entity()) ? 00280 dynamic_cast<RefVertex*>(pt->topology_entity())->id() : 0, 00281 pt->coordinates().x(), pt->coordinates().y(), pt->coordinates().z()); 00282 } 00283 else if(!prev_curve->other_point(pt)) 00284 { 00285 PRINT_ERROR("Edge owner curve %p (RefEdge %d) at point %p \n" 00286 " (vertex %d) (%f,%f,%f) doesn't match topology\n", 00287 (void*)prev_curve, prev_curve && dynamic_cast<RefEdge*>(prev_curve->topology_entity())? 00288 dynamic_cast<RefEdge*>(prev_curve->topology_entity())->id() : 0, 00289 (void*)pt, dynamic_cast<RefVertex*>(pt->topology_entity()) ? 00290 dynamic_cast<RefVertex*>(pt->topology_entity())->id() : 0, 00291 pt->coordinates().x(), pt->coordinates().y(), pt->coordinates().z()); 00292 } 00293 } 00294 else if (prev_curve != curve) 00295 { 00296 PRINT_ERROR("Missing point-owner at transition between\n" 00297 " curve %p (RefEdge %d) and curve %p (RefEdge %d):\n" 00298 " at location (%f,%f,%f)\n", 00299 (void*)curve, curve && dynamic_cast<RefEdge*>(curve->topology_entity())? 00300 dynamic_cast<RefEdge*>(curve->topology_entity())->id() : 0, 00301 (void*)prev_curve, prev_curve && dynamic_cast<RefEdge*>(prev_curve->topology_entity())? 00302 dynamic_cast<RefEdge*>(prev_curve->topology_entity())->id() : 0, 00303 shared->coordinates().x(), 00304 shared->coordinates().y(), 00305 shared->coordinates().z() ); 00306 } 00307 00308 prev = edge; 00309 prev_curve = curve; 00310 } 00311 } 00312 } 00313 00314 00315 //------------------------------------------------------------------------- 00316 // Purpose : Find closest point on passed facet 00317 // 00318 // Special Notes : static 00319 // 00320 // Creator : Jason Kraftcheck 00321 // 00322 // Creation Date : 03/28/03 00323 //------------------------------------------------------------------------- 00324 void PartSurfFacetTool::closest_pt_on_facet( CubitFacet* facet, 00325 const CubitVector& p, 00326 CubitVector& result ) 00327 { 00328 // Get triangle vertices 00329 CubitVector p0(facet->point(0)->coordinates()); 00330 CubitVector p1(facet->point(1)->coordinates()); 00331 CubitVector p2(facet->point(2)->coordinates()); 00332 00333 /* 00334 Algorithm from: 00335 "Distance Between Point and Triangle in 3D" 00336 David Eberly 00337 Magic Software, Inc. 00338 Sept. 28, 1999 00339 00340 Use barycentric coordinates. Coordinates are 00341 calculated in the range [0,det] rather than [0,1] 00342 to avoid the fp division entirely where it can 00343 be avoided. 00344 00345 ^v*t 00346 \R2| 00347 \ | 00348 \| 00349 *p2 00350 |\ 00351 | \ R1 00352 R3 | \ 00353 | \ 00354 | R0 \ 00355 | \p1 00356 ---*------*--->u*s 00357 |p0 \ R6 00358 R4 | R5 \ 00359 | \u+v=det 00360 */ 00361 00362 00363 CubitVector s(p1 - p0); // the u (or s) axis in parameterized space 00364 CubitVector t(p2 - p0); // the v (or t) axis in parameterized space 00365 CubitVector d(p0 - p); // vector from input position to corner at (u,v) = (0,0) 00366 // Pre-calculate all the dot products we need 00367 // Name the dot product of vectors 'a' and 'b' as 'ab' 00368 double ss = s.length_squared(); 00369 double st = s % t; 00370 double tt = t.length_squared(); 00371 double sd = s % d; 00372 double td = t % d; 00373 // Calculate barycentric coordinates in the range [0,det] 00374 double det = ss*tt - st*st; 00375 double u = st*td - tt*sd; 00376 double v = st*sd - ss*td; 00377 00378 // Big tree of conditionals to determine which of the 00379 // regions in the above diagram the projection of 00380 // the point into the plane lies in. 00381 if ( u+v < det ) 00382 { 00383 if ( u < 0 ) 00384 { 00385 if( v < 0 ) // Region 4 00386 { 00387 if ( sd < 0 ) 00388 { 00389 if ( -sd > ss ) 00390 result = p1; 00391 else 00392 result = p0 + (-sd/ss) * s; 00393 } 00394 else if ( td < 0 ) 00395 { 00396 if ( -td > tt ) 00397 result = p2; 00398 else 00399 result = p0 + (-td/tt) * t; 00400 } 00401 else 00402 { 00403 result = p0; 00404 } 00405 } 00406 else // Region 3 (Edge p2-p0, u->0) 00407 { 00408 if ( td > 0 ) 00409 result = p0; 00410 else if ( -td > tt ) 00411 result = p2; 00412 else 00413 result = p0 + (-td/tt) * t; 00414 } 00415 } 00416 else if ( v < 0) // Region 5 (Edge p0-p1, v->0) 00417 { 00418 if ( sd > 0 ) 00419 result = p0; 00420 else if ( -sd > ss ) 00421 result = p1; 00422 else 00423 result = p0 + (-sd/ss) * s; 00424 } 00425 else // Region 0 (Interior) 00426 { 00427 result = p0 + (1.0/det) * (u*s + v*t); 00428 } 00429 } 00430 else if ( u < 0 ) // Region 2 00431 { 00432 double num = tt + td - st - sd; 00433 if ( num > 0.0 ) 00434 { 00435 double den = ss - 2*st + tt; 00436 if ( num >= den ) // (Point p1) 00437 result = p1; 00438 else // (Edge p1-p2) 00439 { 00440 u = num / den; 00441 result = p0 + u*s + (1-u)*t; 00442 } 00443 } 00444 else if ( td >= 0 ) // (Point p0) 00445 result = p0; 00446 else if ( tt+td <= 0 ) // (Point p2) 00447 result = p2; 00448 else // (Edge p2-p0) 00449 result = p0 + (-td/tt)*t; 00450 } 00451 else if ( v < 0 ) // Region 6 00452 { 00453 double num = tt + td - st - sd; 00454 double den = ss - 2*st + tt; 00455 if (num < den) 00456 { 00457 if ( num < 0 ) // (Point p1) 00458 result = p2; 00459 else // (Edge p1-p2) 00460 { 00461 u = num / den; 00462 result = p0 + u*s + (1-u)*t; 00463 } 00464 } 00465 else if ( sd >= 0 ) // (Point p0) 00466 result = p0; 00467 else if ( ss+sd <= 0 ) // (Point p1) 00468 result = p1; 00469 else // (Edge p0-p1) 00470 result = p0 + (-sd/ss)*s; 00471 } 00472 else // Region 1 (Edge p1-p2, u+v->1) 00473 { 00474 double num = tt + td - st - sd; 00475 if ( num <= 0 ) 00476 result = p2; 00477 else 00478 { 00479 double den = ss - 2*st + tt; 00480 if ( num >= den ) 00481 result = p1; 00482 else 00483 { 00484 u = num/den; 00485 result = p0 + u*s + (1-u)*t; 00486 } 00487 } 00488 } 00489 } 00490 00491 //------------------------------------------------------------------------- 00492 // Purpose : Local method for debug output 00493 // 00494 // Special Notes : 00495 // 00496 // Creator : Jason Kraftcheck 00497 // 00498 // Creation Date : 12/02/03 00499 //------------------------------------------------------------------------- 00500 static void draw_edges( DLIList<CubitFacetEdge*>& edges, int edge_color = 0, 00501 bool label_edges = false, bool draw_points = false, 00502 int point_color = 0, bool label_points = false ) 00503 { 00504 char buffer[2*sizeof(void*)+3]; 00505 00506 if (edge_color == 0) 00507 edge_color = CUBIT_WHITE_INDEX; 00508 if (point_color == 0) 00509 point_color = CUBIT_WHITE_INDEX; 00510 00511 for (int i = edges.size(); i--; ) 00512 { 00513 CubitFacetEdge* edge = edges.get_and_step(); 00514 CubitVector start = edge->point(0)->coordinates(); 00515 CubitVector end = edge->point(1)->coordinates(); 00516 GfxDebug::draw_line(start, end, edge_color ); 00517 00518 if (label_edges) 00519 { 00520 CubitVector mid = 0.5 * (start + end); 00521 sprintf(buffer, "%p", (void*)edge); 00522 float x = (float)mid.x(); 00523 float y = (float)mid.y(); 00524 float z = (float)mid.z(); 00525 GfxDebug::draw_label( buffer, x, y, z, edge_color ); 00526 } 00527 00528 for ( int j = 0; j < 2; j++ ) 00529 { 00530 CubitPoint* point = edge->point(j); 00531 float x = (float)point->coordinates().x(); 00532 float y = (float)point->coordinates().y(); 00533 float z = (float)point->coordinates().z(); 00534 00535 if (draw_points) 00536 { 00537 GfxDebug::draw_point( x, y, z, point_color ); 00538 } 00539 if (label_points) 00540 { 00541 sprintf(buffer, "%p", (void*)point); 00542 GfxDebug::draw_label( buffer, x, y, z, point_color ); 00543 } 00544 } 00545 } 00546 GfxDebug::flush(); 00547 } 00548 00549 00550 CubitStatus PartSurfFacetTool::init_facet_data( 00551 DLIList<CubitFacetData*>& facets ) 00552 { 00553 assert(!mySurface->has_facets()); 00554 00555 int i; 00556 CubitStatus rval; 00557 DLIList<CubitPoint*> boundary_points, interior_points; 00558 DLIList<CubitFacetEdge*> boundary_edges, interior_edges; 00559 DLIList<PartitionPoint*> geom_points, interior_geom_points; 00560 00561 // Get facet data 00562 rval = get_facet_points_and_edges( facets, boundary_points, 00563 interior_points, boundary_edges, interior_edges ); 00564 if (!rval) 00565 { 00566 PRINT_ERROR("Internal error at %s:%d\n", __FILE__, __LINE__ ); 00567 return CUBIT_FAILURE; 00568 } 00569 00570 // Get real points on surface boundary 00571 mySurface->get_points(geom_points); 00572 for (i = 0; i < geom_points.size(); i++ ) 00573 { 00574 if (!geom_points[i]->real_point()) 00575 geom_points[i] = 0; 00576 // also process for hardpoints 00577 if (geom_points[i]) 00578 { 00579 PartitionCurve* curve = geom_points[i]->next_curve(); 00580 if ( curve->measure() < GEOMETRY_RESABS && 00581 curve->start_point() == curve->end_point() ) 00582 { 00583 geom_points[i] = 0; 00584 } 00585 } 00586 } 00587 geom_points.remove_all_with_value(0); 00588 00589 // Group geometric points into boundary and interior sets 00590 for (i = geom_points.size(); i--; ) 00591 { 00592 PartitionPoint* point = geom_points.step_and_get(); 00593 bool boundary = false; 00594 PartitionCurve* curve = 0; 00595 while ( (curve = point->next_curve(curve)) ) 00596 if (curve->is_in_surface(mySurface,true)) 00597 boundary = true; 00598 if (!boundary) 00599 { 00600 geom_points.change_to(0); 00601 interior_geom_points.append(point); 00602 } 00603 } 00604 geom_points.remove_all_with_value(0); 00605 00606 // Associate each boundary geometry point with the closest 00607 // boundary facet point. 00608 if(boundary_points.size() == 0 && geom_points.size() != 0) 00609 rval = CUBIT_FAILURE; 00610 else 00611 rval = associate_points( boundary_points, geom_points ); 00612 00613 if (!rval) 00614 return CUBIT_FAILURE; 00615 00616 // Associate each interior geometry point with the closest 00617 // interior facet point. 00618 rval = associate_points( interior_points, interior_geom_points ); 00619 if (!rval) 00620 return CUBIT_FAILURE; 00621 00622 if (DEBUG_FLAG(145)) 00623 { 00624 draw_edges( boundary_edges, CUBIT_ORANGE_INDEX, true, false, CUBIT_WHITE_INDEX, true ); 00625 draw_edges( interior_edges, CUBIT_WHITE_INDEX ); 00626 } 00627 00628 00629 // Populate sets 00630 boundary_set.clear(); 00631 interior_set.clear(); 00632 for (i = boundary_edges.size(); i--; ) 00633 boundary_set.insert(boundary_edges.step_and_get()); 00634 for (i = interior_edges.size(); i--; ) 00635 interior_set.insert(interior_edges.step_and_get()); 00636 00637 // For each loop on the surface... 00638 PartitionLoop* loop = 0; 00639 DLIList<PartitionCurve*> curve_set; 00640 DLIList<CubitFacetEdge*> point_edges, edge_set_1, edge_set_2; 00641 DLIList<PartitionCurve*> nonmanifold_stack; 00642 while ( (loop = mySurface->next_loop(loop)) ) 00643 { 00644 // Find coedge beginning at real vertex (must be at least one) 00645 PartitionCoEdge* coedge = loop->first_coedge(); 00646 while (!coedge->start_point()->real_point()) 00647 { 00648 coedge = coedge->next(); 00649 assert(coedge != loop->first_coedge()); 00650 } 00651 00652 PartitionCoEdge* first_coedge = coedge; // so we know when to stop 00653 00654 00655 do // Loop until all curves in loop have been handled (back to first_coedge) 00656 { 00657 // Keep track of start and end 00658 PartitionCurve* first_curve = coedge->get_curve(); 00659 PartitionPoint* start_point = coedge->start_point(); 00660 PartitionPoint* end_point = coedge->end_point(); 00661 00662 // Hardpoints (meeting all cases below) are a special 00663 // case loop that should not be handled in the partitioning. 00664 if (loop->num_coedges() == 1 && 00665 first_curve->measure() < GEOMETRY_RESABS && 00666 start_point == end_point) 00667 break; 00668 00669 // Get list of curves until next real vertex 00670 curve_set.clean_out(); 00671 curve_set.append(first_curve); 00672 while (!coedge->end_point()->real_point()) 00673 { 00674 coedge = coedge->next(); 00675 curve_set.append(coedge->get_curve()); 00676 end_point = coedge->end_point(); 00677 assert(&first_curve->sub_entity_set() == &coedge->get_curve()->sub_entity_set()); 00678 } 00679 00680 if (DEBUG_FLAG(145)) 00681 { 00682 curve_set.reset(); 00683 for (i = curve_set.size(); i--; ) 00684 { 00685 GMem gmem; 00686 PartitionCurve* c = curve_set.get_and_step(); 00687 c->get_geometry_query_engine()->get_graphics( c, &gmem ); 00688 GfxDebug::draw_polyline(gmem.point_list(), gmem.pointListCount, CUBIT_RED_INDEX ); 00689 } 00690 GfxDebug::flush(); 00691 } 00692 00693 // Special case for non-manifold curves 00694 if (first_curve->is_nonmanifold(mySurface)) 00695 { 00696 // Don't do the same non-manifold curve twice 00697 curve_set.reset(); 00698 nonmanifold_stack.last(); 00699 if (nonmanifold_stack.size() && 00700 curve_set.get() == nonmanifold_stack.get()) 00701 { 00702 for (i = curve_set.size(); i--; ) 00703 { 00704 PartitionCurve* curv1 = curve_set.get_and_step(); 00705 PartitionCurve* curv2 = nonmanifold_stack.pop(); 00706 assert(curv1 == curv2); 00707 if (curv1 != curv2) { 00708 PRINT_ERROR("Internal error at %s:%d\n", __FILE__, __LINE__); 00709 return CUBIT_FAILURE; 00710 } 00711 } 00712 } 00713 else 00714 { 00715 for (i = curve_set.size(); i--; ) 00716 nonmanifold_stack.append(curve_set.get_and_step()); 00717 00718 if (!seam_nonmanifold_curves(curve_set, facets)) 00719 { 00720 return CUBIT_FAILURE; 00721 } 00722 } 00723 coedge = coedge->next(); 00724 if (coedge != first_coedge) 00725 continue; 00726 else 00727 break; 00728 } 00729 00730 // Get facet edges adjacent to first point 00731 point_edges.clean_out(); 00732 start_point->facet_point()->edges(point_edges); 00733 00734 // For each boundary edge on the point, look for a chain 00735 // of connected boundary edges. 00736 edge_set_1.clean_out(); 00737 edge_set_2.clean_out(); 00738 while(point_edges.size()) 00739 { 00740 CubitFacetEdge* edge = point_edges.pop(); 00741 if (boundary_set.count(edge) == 0) // skip non-boundary edges 00742 continue; 00743 00744 edge_set_2.clean_out(); 00745 if (!get_boundary_chain(start_point->facet_point(), edge, 00746 end_point->facet_point(), edge_set_2)) 00747 continue; // skip edges that don't begin a chain that reaches the end vertex 00748 00749 // If only one chain found so far, store the chain and 00750 // continue to the next edge around the point 00751 if (!edge_set_1.size()) 00752 { 00753 edge_set_1 = edge_set_2; 00754 edge_set_2.clean_out(); 00755 continue; 00756 } 00757 00758 // If we reached this point, handle special case where 00759 // loop is composed of two real curves and we need a 00760 // geometric check to determine which half of the facet edge 00761 // loop goes with which curve. 00762 edge_set_1.reset(); 00763 edge_set_2.reset(); 00764 CubitVector set_1_mid = edge_set_1.get()->center(); 00765 CubitVector set_2_mid = edge_set_2.get()->center(); 00766 CubitVector set_1_closest, set_2_closest; 00767 first_curve->closest_point_trimmed(set_1_mid, set_1_closest); 00768 first_curve->closest_point_trimmed(set_2_mid, set_2_closest); 00769 00770 set_1_closest -= set_1_mid; 00771 set_2_closest -= set_2_mid; 00772 if (set_2_closest.length_squared() < set_1_closest.length_squared()) 00773 edge_set_1 = edge_set_2; 00774 } // while(point_edges.size()) 00775 00776 // We have the chain of edges to associate with the curve 00777 // set. Seam with adjacent surface facettings (if any) 00778 if (DEBUG_FLAG(145)) 00779 draw_edges( edge_set_1, CUBIT_RED_INDEX, true ); 00780 00781 if (!seam_curves( curve_set, edge_set_1, facets )) 00782 return CUBIT_FAILURE; 00783 00784 coedge = coedge->next(); 00785 } while (coedge != first_coedge); 00786 00787 } // while (loop) 00788 00789 // attach facets to surface 00790 mySurface->set_facet_data(facets); 00791 00792 return CUBIT_SUCCESS; 00793 } 00794 00795 //------------------------------------------------------------------------- 00796 // Purpose : Helper function for curve seaming functions. 00797 // Check that input curve list are partitions of the 00798 // same real curve and are all the partitions of that curve. 00799 // Returns the real curve and the PartitionPoints that 00800 // are the start and end of the real curve. 00801 // 00802 // Special Notes : Assumes the passed curves are either in order or in 00803 // the reverse order. If the reverse order, the passed 00804 // list will be reversed. 00805 // 00806 // Creator : Jason Kraftcheck 00807 // 00808 // Creation Date : 09/08/03 00809 //------------------------------------------------------------------------- 00810 Curve* PartSurfFacetTool::get_real_curve( DLIList<PartitionCurve*>& curve_list, 00811 PartitionPoint*& start_point, 00812 PartitionPoint*& end_point ) 00813 { 00814 SubEntitySet* set = &(curve_list.get()->sub_entity_set()); 00815 DLIList<PartitionEntity*> tmp_set(curve_list.size()); 00816 set->get_sub_entities(tmp_set); 00817 if (tmp_set.size() != curve_list.size()) 00818 return 0; 00819 00820 tmp_set.reset(); 00821 curve_list.reset(); 00822 if (tmp_set.get() != curve_list.get()) 00823 { 00824 curve_list.reverse(); 00825 curve_list.reset(); 00826 } 00827 00828 for (int i = curve_list.size(); i--; ) 00829 if (curve_list.get_and_step() != tmp_set.get_and_step()) 00830 return 0; 00831 00832 // Get real curve 00833 Curve* real_curve = dynamic_cast<Curve*>(set->get_entity()); 00834 assert(!!real_curve); 00835 00836 DLIList<TopologyBridge*> point_bridges(2); 00837 real_curve->get_children(point_bridges, false, set->get_owner_layer()); 00838 point_bridges.reset(); 00839 start_point = dynamic_cast<PartitionPoint*>(point_bridges.get()); 00840 end_point = dynamic_cast<PartitionPoint*>(point_bridges.next()); 00841 assert(start_point && end_point); 00842 00843 return real_curve; 00844 } 00845 00846 CubitStatus PartSurfFacetTool::get_boundary_chain( 00847 CubitPoint* start_point, 00848 CubitFacetEdge* start_edge, 00849 CubitPoint* end_point, 00850 DLIList<CubitFacetEdge*>& result_list ) 00851 { 00852 DLIList<CubitFacetEdge*> point_edges; 00853 00854 //assert(start_edge->marked()); 00855 assert(result_list.size() == 0); 00856 CubitPoint* point = start_point; 00857 CubitFacetEdge* edge = start_edge; 00858 while (true) 00859 { 00860 result_list.append(edge); 00861 point = edge->other_point(point); 00862 if (TDVGFacetOwner::get(point)) 00863 return point == end_point ? CUBIT_SUCCESS : CUBIT_FAILURE; 00864 00865 point->edges(point_edges); 00866 for (int i = point_edges.size(); i--; ) 00867 { 00868 CubitFacetEdge* point_edge = point_edges.step_and_get(); 00869 //if (point_edge->marked() != 1 || point_edge == edge) 00870 if (boundary_set.count(point_edge) == 0 || point_edge == edge) 00871 point_edges.change_to(0); 00872 } 00873 point_edges.remove_all_with_value(0); 00874 00875 if (point_edges.size() != 1) 00876 return CUBIT_FAILURE; 00877 00878 edge = point_edges.remove(); 00879 } 00880 00881 // unreachable 00882 return CUBIT_SUCCESS; 00883 } 00884 00885 //------------------------------------------------------------------------- 00886 // Purpose : Associate facet edges in the interior of a surface 00887 // facetting with the set of curve partitions of some 00888 // real, non-manifold curve in the surface. 00889 // 00890 // Special Notes : Assumes edges internal to the surface facetting 00891 // have been marked with a '2' by the caller. Clears 00892 // marks on consumed edges. 00893 // 00894 // Creator : Jason Kraftcheck 00895 // 00896 // Creation Date : 09/08/03 00897 //------------------------------------------------------------------------- 00898 CubitStatus PartSurfFacetTool::seam_nonmanifold_curves( 00899 DLIList<PartitionCurve*>& curve_list, 00900 DLIList<CubitFacetData*>& facet_list ) 00901 { 00902 // All the curves in the attached coedge_list should belong 00903 // to the same real curve and thus have a single continuous 00904 // parameterization over the entire set of curves. Verify 00905 // this now. 00906 PartitionPoint *start_point, *end_point; 00907 Curve* real_curve = get_real_curve(curve_list, start_point, end_point); 00908 if (!real_curve) 00909 { 00910 PRINT_ERROR("Internal error at %s:%d\n", __FILE__, __LINE__ ); 00911 assert(false); 00912 return CUBIT_FAILURE; 00913 } 00914 00915 // Assume caller has marked all interior edges with a '2'. 00916 // Clear marks as we go to ensure we don't loop forever. 00917 // Find chain of curves closest to real curve and ending 00918 // at the end facet point. 00919 CubitPoint* const start_vtx = start_point->facet_point(); 00920 CubitPoint* const end_vtx = end_point->facet_point(); 00921 assert(start_vtx&&end_vtx); 00922 DLIList<CubitFacetEdge*> vtx_edges, seam_list; 00923 CubitPoint* vtx = start_vtx; 00924 do 00925 { 00926 vtx->edges(vtx_edges); 00927 CubitFacetEdge* edge = 0; 00928 double shortest_dist_sqr = CUBIT_DBL_MAX; 00929 while( vtx_edges.size() ) 00930 { 00931 CubitFacetEdge* curr = vtx_edges.pop(); 00932 //if (curr->marked() != 2 ) 00933 if (interior_set.count(curr) == 0) 00934 continue; 00935 00936 if (curr->other_point(vtx) == end_vtx) 00937 { 00938 edge = curr; 00939 break; 00940 } 00941 00942 CubitVector closest, tangent; 00943 CubitVector start(vtx->coordinates()); 00944 CubitVector end(curr->other_point(vtx)->coordinates()); 00945 real_curve->closest_point(0.5*(start+end), closest, &tangent); 00946 if (tangent % (end-start) < 0.0) 00947 continue; 00948 00949 real_curve->closest_point(end, closest); 00950 closest -= end; 00951 double dist_sqr = closest.length_squared(); 00952 if (dist_sqr < shortest_dist_sqr) 00953 { 00954 edge = curr; 00955 shortest_dist_sqr = dist_sqr; 00956 } 00957 } 00958 00959 if (!edge) 00960 { 00961 PRINT_ERROR("Internal error at %s:%d:\n" 00962 "Failed to associate facet edges with non-manofold curves.\n", 00963 __FILE__, __LINE__ ); 00964 return CUBIT_FAILURE; 00965 } 00966 if (DEBUG_FLAG(145)) 00967 { 00968 GfxDebug::draw_facet_edge( edge, CUBIT_MAGENTA_INDEX ); 00969 GfxDebug::flush(); 00970 } 00971 00972 seam_list.append(edge); 00973 //edge->marked(0); 00974 vtx = edge->other_point(vtx); 00975 } while (vtx != end_vtx); 00976 00977 return seam_curves( curve_list, seam_list, facet_list ); 00978 } 00979 00980 00981 CubitStatus PartSurfFacetTool::split_edge( CubitFacetEdge* old_edge, 00982 const CubitVector& position, 00983 CubitFacet* edge_facet, 00984 CubitPoint*& new_point, 00985 CubitFacetEdge*& new_edge, 00986 CubitFacet*& new_facet ) 00987 { 00988 CubitVector v1, v2; 00989 int i = 0, junk; 00990 new_point = 0; 00991 new_edge = 0; 00992 new_facet = 0; 00993 00994 CubitFacet* split_facet = edge_facet; 00995 if( !split_facet ) 00996 split_facet = old_edge->adj_facet(0); 00997 else if( edge_facet->edge_index(old_edge) < 0 ) 00998 { assert(0); return CUBIT_FAILURE; } 00999 01000 CubitPoint* pt1 = old_edge->point(0); 01001 CubitPoint* pt2 = old_edge->point(1); 01002 01003 v1 = position - pt1->coordinates(); 01004 v2 = pt2->coordinates() - position; 01005 assert( v1.length_squared() > GEOMETRY_RESABS*GEOMETRY_RESABS ); 01006 assert( v2.length_squared() > GEOMETRY_RESABS*GEOMETRY_RESABS ); 01007 #ifndef NDEBUG 01008 double dot = v1 % v2; 01009 assert( dot > 0 ); // projection of new point onto line lies outside edge. 01010 // double cos_sqr = (dot * dot) / (v1.length_squared() * v2.length_squared()); 01011 // assert( cos_sqr > 0.99240387650610407 ); // angle less than 5 degrees 01012 #endif 01013 01014 01015 CubitPoint* new_pt = split_facet->split_edge( pt1, pt2, position ); 01016 new_edge = new_pt->shared_edge(pt2); 01017 if( !new_edge ) { assert(0); return CUBIT_FAILURE; } 01018 01019 // find new facet and update for other split facets 01020 CubitFacet *facet, *other_facet; 01021 PartitionEntity* facet_owner; 01022 while ( (facet = old_edge->adj_facet(i++)) ) { 01023 CubitPoint* pt3 = facet->point( facet->edge_index(pt1,new_pt,junk) ); 01024 if( !pt3->shared_edge( new_pt ) ) 01025 new CubitFacetEdgeData( pt3, new_pt ); 01026 01027 other_facet = facet->shared_facet( new_pt, pt3 ); 01028 if( !other_facet ) { assert(0); continue; } 01029 if ( facet == edge_facet ) 01030 new_facet = other_facet; 01031 else if( (facet_owner = TDVGFacetOwner::get(facet)) ) 01032 facet_owner->notify_split( facet, other_facet ); 01033 } 01034 if( (facet_owner = TDVGFacetOwner::get( old_edge )) ) 01035 facet_owner->notify_split( old_edge, new_edge ); 01036 01037 if( edge_facet ) 01038 assert(!!new_facet); 01039 else 01040 new_facet = 0; 01041 01042 new_point = new_pt; 01043 return CUBIT_SUCCESS; 01044 } 01045 01046 CubitStatus PartSurfFacetTool::collapse_edge( CubitPoint* keep, 01047 CubitPoint* dead, 01048 DLIList<CubitFacetData*>* unowned ) 01049 { 01050 int i; 01051 01052 CubitPointData* keep_pt = dynamic_cast<CubitPointData*>(keep); 01053 CubitPointData* dead_pt = dynamic_cast<CubitPointData*>(dead); 01054 CubitFacetEdge* dead_edge; 01055 assert(keep_pt&&dead_pt); 01056 01057 // Cannot proceed if dead_pt is owned by a PartitionPoint. 01058 if ( TDVGFacetOwner::get(dead_pt) ) 01059 return CUBIT_FAILURE; 01060 01061 // Get list of facets to be destroyed when edge is collapsed 01062 DLIList<CubitFacet*> dead_facets; 01063 keep->shared_facets(dead_pt,dead_facets); 01064 DLIList<PartitionSurface*> dead_facet_owners(dead_facets.size()); 01065 DLIList<CubitFacetData*> dead_facet_ds(dead_facets.size()); 01066 CAST_LIST(dead_facets, dead_facet_ds, CubitFacetData); 01067 01068 // Find other edges to be destroyed when edge is collapsed. 01069 // cannot proceed if any of them belong to a PartitionCurve. 01070 // Also, find owners of each facet to be destroyed. 01071 dead_facets.reset(); 01072 for ( i = dead_facets.size(); i--; ) 01073 { 01074 CubitFacet* facet = dead_facets.get_and_step(); 01075 int keep_index = facet->point_index(keep); 01076 int dead_index = facet->point_index(dead); 01077 int othr_index = (keep_index + 1) % 3; 01078 if ( othr_index == dead_index ) 01079 othr_index = (keep_index + 2) % 3; 01080 assert( keep_index >= 0 && dead_index >= 0 ); 01081 dead_edge = dead_pt->shared_edge(facet->point(othr_index)); 01082 if ( TDVGFacetOwner::get(dead_edge) ) 01083 return CUBIT_FAILURE; 01084 01085 PartitionSurface* surf = dynamic_cast<PartitionSurface*>(TDVGFacetOwner::get(facet)); 01086 dead_facet_owners.append( surf ); 01087 } 01088 01089 PRINT_INFO("Collapsing edge (%f,%f,%f)->(%f,%f,%f) (%f)\n", 01090 keep_pt->coordinates().x(), keep_pt->coordinates().y(), keep_pt->coordinates().z(), 01091 dead_pt->coordinates().x(), dead_pt->coordinates().y(), dead_pt->coordinates().z(), 01092 (keep_pt->coordinates()-dead_pt->coordinates()).length()); 01093 01094 // Get PartitionCurve to update for collapsed edge. 01095 PartitionCurve* dead_edge_owner = 0; 01096 dead_edge = dead_pt->shared_edge(keep_pt); 01097 if (dead_edge) 01098 dead_edge_owner = dynamic_cast<PartitionCurve*>(TDVGFacetOwner::get(dead_edge)); 01099 01100 // Collapse the edge 01101 if ( !keep_pt->collapse_edge(dead_pt) ) 01102 return CUBIT_FAILURE; 01103 01104 // Update owning curve 01105 if (dead_edge_owner) 01106 dead_edge_owner->remove_dead_facet( (CubitFacetEdgeData*)dead_edge ); 01107 01108 // Update facet owners for dead facets. 01109 dead_facet_ds.reset(); 01110 dead_facet_owners.reset(); 01111 for ( i = dead_facet_ds.size(); i--; ) 01112 { 01113 CubitFacetData* facet = dead_facet_ds.get_and_step(); 01114 PartitionSurface* facet_owner = dead_facet_owners.get_and_step(); 01115 if (!facet_owner) 01116 unowned->append(facet); 01117 else 01118 facet_owner->notify_destroyed(facet); 01119 } 01120 01121 return CUBIT_SUCCESS; 01122 } 01123 01124 01125 01126 01127 //------------------------------------------------------------------------- 01128 // Purpose : Seam a list of facet edges from the boundary of a 01129 // surface facetting with all the curves that are 01130 // partitions of the same real curve on the boundary of 01131 // that surface. 01132 // 01133 // Special Notes : 01134 // 01135 // Creator : Jason Kraftcheck 01136 // 01137 // Creation Date : 09/08/03 01138 //------------------------------------------------------------------------- 01139 CubitStatus PartSurfFacetTool::seam_curves( DLIList<PartitionCurve*>& curve_list, 01140 DLIList<CubitFacetEdge*>& edge_list, 01141 DLIList<CubitFacetData*>& facets ) 01142 { 01143 int i; 01144 if (!curve_list.size() || !edge_list.size()) 01145 return CUBIT_FAILURE; 01146 01147 if (DEBUG_FLAG(145)) 01148 draw_edges( edge_list, CUBIT_WHITE_INDEX, true, true, CUBIT_WHITE_INDEX, false ); 01149 01150 DLIList<CubitFacetData*> old_facets, new_facets; 01151 DLIList<CubitFacetEdgeData*> dead_edge_ptrs; 01152 PartitionCurve* curve = 0; 01153 01154 // All the curves in the attached coedge_list should belong 01155 // to the same real curve and thus have a single continuous 01156 // parameterization over the entire set of curves. Verify 01157 // this now. 01158 PartitionPoint *start_point, *end_point; 01159 Curve* real_curve = get_real_curve(curve_list, start_point, end_point); 01160 if (!real_curve) 01161 { 01162 PRINT_ERROR("Internal error at %s:%d\n", __FILE__, __LINE__ ); 01163 assert(false); 01164 return CUBIT_FAILURE; 01165 } 01166 01167 double period; 01168 const bool periodic = real_curve->is_periodic(period); 01169 const bool fwdparam = (periodic ? period > 0.0 : real_curve->start_param() < real_curve->end_param()); 01170 01171 edge_list.reset(); 01172 CubitPoint *next_vtx, *curr_vtx; 01173 if (edge_list.size() == 1) 01174 { 01175 next_vtx = edge_list.get()->point(1); 01176 curr_vtx = edge_list.get()->point(0); 01177 } 01178 else 01179 { 01180 next_vtx = edge_list.get()->shared_point(edge_list.next()); 01181 curr_vtx = edge_list.get()->other_point(next_vtx); 01182 } 01183 assert(curr_vtx&&next_vtx); 01184 // Special case: If curve_list is a closed loop of curves, 01185 // a geometric check is required to determine if the passed 01186 // list of facet edges is reversed wrt the curve list. 01187 if (start_point == end_point) 01188 { 01189 CubitVector tangent, closest, start(curr_vtx->coordinates()), end(next_vtx->coordinates()); 01190 real_curve->closest_point( 0.5*(start+end), closest, &tangent ); 01191 if ((end - start) % tangent < 0.0) 01192 edge_list.reverse(); 01193 } 01194 // Otherwise just compare end coordinates 01195 else 01196 { 01197 if ((start_point->coordinates() - curr_vtx->coordinates()).length_squared() > 01198 (end_point->coordinates() - curr_vtx->coordinates()).length_squared()) 01199 { 01200 if (edge_list.size() == 1) 01201 { 01202 next_vtx = curr_vtx; 01203 curr_vtx = edge_list.get()->other_point(next_vtx); 01204 } 01205 else 01206 { 01207 edge_list.reverse(); 01208 edge_list.reset(); 01209 next_vtx = edge_list.get()->shared_point(edge_list.next()); 01210 curr_vtx = edge_list.get()->other_point(next_vtx); 01211 } 01212 assert(next_vtx&&curr_vtx); 01213 } 01214 } 01215 01216 DLIList<CubitFacetEdgeData*> edge_data_list; 01217 CAST_LIST(edge_list, edge_data_list, CubitFacetEdgeData); 01218 assert(edge_list.size() == edge_data_list.size()); 01219 01220 // Find the subset of edges which belong on each curve. 01221 // Begin with the first edge in the list, and the point 01222 // at the end (opposite the curve start point) of the edge. 01223 DLIList<CubitFacetEdgeData*> curve_edge_list; // edges for current curve 01224 PartitionPoint* vertex = start_point; // end point of current curve 01225 curve_list.reset(); 01226 edge_data_list.reset(); 01227 edge_data_list.reverse(); 01228 CubitFacetEdgeData* edge = edge_data_list.pop(); 01229 CubitPoint* point = start_point->facet_point(); // edge end point 01230 point = edge->other_point(point); 01231 if (!point) 01232 { 01233 PRINT_ERROR("Internal error at %s:%d\n", __FILE__, __LINE__); 01234 assert(0); 01235 return CUBIT_FAILURE; 01236 } 01237 01238 // Iterate over all but the last curve 01239 double prev_vtx_param = real_curve->start_param(); 01240 double prev_pt_param = real_curve->start_param(); 01241 for (i = curve_list.size() - 1; i--; ) 01242 { 01243 curve_edge_list.clean_out(); 01244 01245 curve = curve_list.get_and_step(); 01246 vertex = curve->other_point(vertex); 01247 const CubitVector vtx_pos(vertex->coordinates()); 01248 double vtx_param = real_curve->u_from_position(vtx_pos); 01249 double point_param = real_curve->u_from_position(point->coordinates()); 01250 if (periodic) 01251 { 01252 if ((vtx_param < prev_vtx_param) == fwdparam) 01253 vtx_param += period; 01254 if ((point_param < prev_pt_param) == fwdparam) 01255 point_param += period; 01256 prev_vtx_param = vtx_param; 01257 prev_pt_param = point_param; 01258 } 01259 01260 // Iterate until the edge "containing" the vertex 01261 while ((vtx_param > point_param) == fwdparam) 01262 { 01263 // decrement edge count each time we add one of the 01264 // original, input edges to the cuve edge list. 01265 curve_edge_list.append(edge); 01266 01267 if (!edge_data_list.size()) { assert(0); return CUBIT_FAILURE; } 01268 01269 // Get the next edge and facet point 01270 edge = edge_data_list.pop(); 01271 point = edge->other_point(point); 01272 point_param = real_curve->u_from_position(point->coordinates()); 01273 if (periodic) 01274 { 01275 if ((point_param < prev_pt_param) == fwdparam) 01276 point_param += period; 01277 prev_pt_param = point_param; 01278 } 01279 } 01280 01281 CubitVector edge_pos; 01282 edge->closest_point(vtx_pos, edge_pos); 01283 01284 CubitFacetEdgeData* new_edge; 01285 CubitPoint* new_point = split_edge_closest( edge, edge_pos, 0.1*edge->length(), new_edge, facets ); 01286 if (!new_point) 01287 return CUBIT_FAILURE; 01288 01289 // If the edge was split... 01290 if (new_edge) 01291 { 01292 // If new_edge ends at the "end" point 01293 // swap the edges. 01294 if (new_edge->other_point(point)) 01295 std::swap(edge, new_edge); 01296 // Put the earlier peice of the edge in the curve 01297 // list. Keep the latter peice for the next curve 01298 // iteration. 01299 curve_edge_list.append(new_edge); 01300 } 01301 // If the input position was the same as the edge end point... 01302 else if (new_point == point) 01303 { 01304 // Add edge to list for current curve and decrement count. 01305 curve_edge_list.append(edge); 01306 if (!edge_data_list.size()) { assert(0); return CUBIT_FAILURE; } 01307 01308 // Get the next edge and facet point for the next iteration. 01309 edge = edge_data_list.pop(); 01310 point = edge->other_point(point); 01311 } 01312 01313 // Move edge split point to location of vertex 01314 #ifdef PART_SURF_REFACET 01315 double d_sqr = (vtx_pos - edge_pos).length_squared(); 01316 bool close = d_sqr < (GEOMETRY_RESABS*GEOMETRY_RESABS); 01317 old_facets.clean_out(); 01318 new_facets.clean_out(); 01319 if (close) 01320 dynamic_cast<CubitPointData*>(new_point)->set(vtx_pos); 01321 else if (!fix_move_point( new_point, vtx_pos, facets, old_facets, new_facets )) 01322 return CUBIT_FAILURE; 01323 assert(!old_facets.size() == !new_facets.size()); 01324 facets -= old_facets; 01325 facets += new_facets; 01326 #else 01327 dynamic_cast<CubitPointData*>(new_point)->set(vtx_pos); 01328 #endif 01329 // Merge the points 01330 CubitPointData* vtx_pointd = vertex->facet_point(); 01331 CubitPointData* new_pointd = dynamic_cast<CubitPointData*>(new_point); 01332 if (vtx_pointd) 01333 vtx_pointd->merge_points(new_pointd); 01334 else 01335 vertex->facet_point(new_pointd); 01336 01337 if (!curve->has_facet_data()) 01338 curve->set_facet_data(curve_edge_list); 01339 else if(!seam_curve( curve_edge_list, curve, facets, &dead_edge_ptrs )) 01340 return CUBIT_FAILURE; 01341 01342 while (dead_edge_ptrs.size()) 01343 { 01344 CubitFacetEdgeData* edge = dead_edge_ptrs.pop(); 01345 boundary_set.erase(edge); 01346 interior_set.erase(edge); 01347 } 01348 01349 } // for(curve_list) 01350 01351 // Do last curve 01352 01353 curve = curve_list.get(); 01354 curve_edge_list.clean_out(); 01355 if (edge) 01356 curve_edge_list.append(edge); 01357 while (edge_data_list.size()) 01358 curve_edge_list.append(edge_data_list.pop()); 01359 01360 if(!curve_edge_list.size()) { assert(0); return CUBIT_FAILURE; } 01361 01362 if (!curve->has_facet_data()) 01363 curve->set_facet_data(curve_edge_list); 01364 else if(!seam_curve( curve_edge_list, curve, facets, &dead_edge_ptrs )) 01365 return CUBIT_FAILURE; 01366 01367 while (dead_edge_ptrs.size()) 01368 { 01369 CubitFacetEdgeData* edge = dead_edge_ptrs.pop(); 01370 boundary_set.erase(edge); 01371 interior_set.erase(edge); 01372 } 01373 01374 return CUBIT_SUCCESS; 01375 } 01376 01377 //------------------------------------------------------------------------- 01378 // Purpose : Seam a new list of facet edges with the list of facet 01379 // edges on a curve. 01380 // 01381 // Special Notes : 01382 // 01383 // Creator : Jason Kraftcheck 01384 // 01385 // Creation Date : 12/02/03 01386 //------------------------------------------------------------------------- 01387 CubitStatus PartSurfFacetTool::seam_curve( DLIList<CubitFacetEdgeData*>& edge_list, 01388 PartitionCurve* curve, 01389 DLIList<CubitFacetData*>& facets, 01390 DLIList<CubitFacetEdgeData*>* dead_ptrs ) 01391 { 01392 DLIList<CubitFacetData*> old_facets, new_facets; 01393 const double FRACT_TOL = 0.1; 01394 01395 int curve_color = CUBIT_GREEN_INDEX; 01396 if (DEBUG_FLAG(145)) 01397 { 01398 RefEntity* ent = dynamic_cast<RefEntity*>(curve->topology_entity()); 01399 while (ent && ent->color() < 0) 01400 { 01401 DLIList<RefEntity*> list; 01402 ent->get_parent_ref_entities(list); 01403 list.reset(); 01404 if (!list.size()) break; 01405 ent = list.get(); 01406 } 01407 if (ent) 01408 curve_color = ent->color(); 01409 } 01410 01411 // Vertices should already be "seamed". Verify... 01412 01413 PartitionPoint* start_vtx = curve->start_point(); 01414 PartitionPoint* end_vtx = curve->end_point(); 01415 CubitPointData* start_point = start_vtx->facet_point(); 01416 CubitPointData* end_point = end_vtx->facet_point(); 01417 01418 edge_list.last(); 01419 CubitFacetEdgeData* last_edge = edge_list.get(); 01420 edge_list.reset(); 01421 CubitFacetEdgeData* first_edge = edge_list.get(); 01422 if (!first_edge->other_point(start_point) || 01423 !last_edge->other_point(end_point)) 01424 { 01425 PRINT_ERROR("Internal error at %s:%d\n", __FILE__, __LINE__); 01426 assert(0); 01427 return CUBIT_FAILURE; 01428 } 01429 01430 // Get direction of parameter (probably always increasing...) 01431 double period; 01432 const bool fwdparam = curve->is_periodic(period) ? period > 0.0 : 01433 curve->start_param() < curve->end_param(); 01434 01435 // Get list of facet edges on curve. 01436 DLIList<CubitFacetEdgeData*> curve_edges; 01437 curve->get_facet_data(curve_edges); 01438 if (!curve_edges.size()) 01439 { 01440 curve->set_facet_data( edge_list ); 01441 return CUBIT_SUCCESS; 01442 } 01443 01444 // Seam edge lists 01445 double curve_param = curve->start_param(); 01446 double new_param = curve->start_param(); 01447 curve_edges.reset(); 01448 edge_list.reset(); 01449 CubitFacetEdgeData* curve_edge = curve_edges.get_and_step(); 01450 CubitFacetEdgeData* new_edge = edge_list.get_and_step(); 01451 CubitPoint* prev_point = start_point; 01452 double orig_crv_len = curve_edge->length(); 01453 double orig_new_len = new_edge->length(); 01454 double split_tol = FRACT_TOL * CUBIT_MIN(orig_crv_len, orig_new_len); 01455 while (curve_edge || new_edge) 01456 { 01457 if (!curve_edge || !new_edge) 01458 { 01459 PRINT_ERROR("Internal error at %s:%d\n", __FILE__, __LINE__ ); 01460 assert(0); 01461 return CUBIT_FAILURE; 01462 } 01463 01464 CubitPoint* curve_point = curve_edge->other_point(prev_point); 01465 CubitPoint* new_point = new_edge->other_point(prev_point); 01466 if (DEBUG_FLAG(145)) { 01467 GfxDebug::draw_point(curve_point->coordinates(), curve_color); 01468 GfxDebug::draw_facet_edge(curve_edge, curve_color); 01469 GfxDebug::draw_point(new_point->coordinates(), curve_color + 1); 01470 GfxDebug::draw_facet_edge(new_edge, curve_color + 1); 01471 GfxDebug::flush(); 01472 } 01473 01474 double prev_curve_param = curve_param; 01475 double prev_new_param = new_param; 01476 curve_param = curve->u_from_position(curve_point->coordinates()); 01477 new_param = curve->u_from_position(new_point->coordinates()); 01478 if (curve->is_periodic(period)) 01479 { 01480 if ((prev_curve_param > curve_param) == fwdparam) 01481 curve_param += period; 01482 if ((prev_new_param > new_param) == fwdparam) 01483 new_param += period; 01484 } 01485 01486 if ((curve_param > new_param) == fwdparam) 01487 { 01488 CubitFacetEdgeData* split_edge = 0; 01489 CubitVector edge_pos; 01490 curve_edge->closest_point( new_point->coordinates(), edge_pos ); 01491 CubitPoint* split = split_edge_closest( curve_edge, 01492 edge_pos, 01493 split_tol, 01494 split_edge, 01495 facets ); 01496 if(!split) 01497 return CUBIT_FAILURE; 01498 01499 if (split == prev_point) 01500 { 01501 // new_edge is very small compared to split_edge 01502 assert(!split_edge); 01503 old_facets.clean_out(); 01504 if (!collapse_edge(prev_point, new_point, &old_facets)) 01505 { 01506 if (!collapse_edge(new_point, prev_point, &old_facets)) 01507 { 01508 return CUBIT_FAILURE; 01509 } 01510 std::swap(prev_point, new_point); 01511 } 01512 if (dead_ptrs) 01513 dead_ptrs->append( new_edge ); 01514 facets -= old_facets; 01515 01516 if (edge_list.is_at_beginning()) 01517 new_edge = 0; 01518 else 01519 { 01520 new_edge = edge_list.get_and_step(); 01521 orig_new_len = new_edge->length(); 01522 split_tol = FRACT_TOL * CUBIT_MIN(orig_crv_len, orig_new_len); 01523 } 01524 01525 continue; 01526 } 01527 01528 if (split_edge) 01529 { 01530 if (curve_edge->other_point(prev_point)) 01531 std::swap(split_edge, curve_edge); 01532 } 01533 else 01534 { 01535 assert(split == curve_point); 01536 split_edge = curve_edge; 01537 if (curve_edges.is_at_beginning()) 01538 curve_edge = 0; 01539 else 01540 { 01541 curve_edge = curve_edges.get_and_step(); 01542 orig_crv_len = curve_edge->length(); 01543 split_tol = FRACT_TOL * CUBIT_MIN(orig_crv_len, orig_new_len); 01544 } 01545 } 01546 01547 // Move split point to position of other point (safely) 01548 #ifdef PART_SURF_REFACET 01549 double d_sqr = (edge_pos - new_point->coordinates()).length_squared(); 01550 bool close = d_sqr < (GEOMETRY_RESABS*GEOMETRY_RESABS); 01551 old_facets.clean_out(); 01552 new_facets.clean_out(); 01553 if (close) 01554 dynamic_cast<CubitPointData*>(split)->set(new_point->coordinates()); 01555 else if (!fix_move_point( split, new_point->coordinates(), facets, old_facets, new_facets )) 01556 return CUBIT_FAILURE; 01557 facets -= old_facets; 01558 facets += new_facets; 01559 #else 01560 dynamic_cast<CubitPointData*>(split)->set(new_point->coordinates()); 01561 #endif 01562 01563 CubitStatus s1 = split->merge_points(new_point); 01564 CubitStatus s2 = split_edge->merge_edges(new_edge); 01565 if (dead_ptrs) 01566 dead_ptrs->append(new_edge); 01567 assert(s1 && s2); 01568 prev_point = split; 01569 01570 if (edge_list.is_at_beginning()) 01571 new_edge = 0; 01572 else 01573 { 01574 new_edge = edge_list.get_and_step(); 01575 orig_new_len = new_edge->length(); 01576 split_tol = FRACT_TOL * CUBIT_MIN(orig_crv_len, orig_new_len); 01577 } 01578 } 01579 else 01580 { 01581 CubitFacetEdgeData* split_edge = 0; 01582 CubitVector edge_pos; 01583 new_edge->closest_point( curve_point->coordinates(), edge_pos ); 01584 CubitPoint* split = split_edge_closest( new_edge, 01585 edge_pos, 01586 split_tol, 01587 split_edge, 01588 facets ); 01589 if(!split) 01590 return CUBIT_FAILURE; 01591 01592 if (split == prev_point) 01593 { 01594 // curve_edge is very small compared to split_edge 01595 assert(!split_edge); 01596 old_facets.clean_out(); 01597 if (!collapse_edge(prev_point,curve_point,&old_facets)) 01598 { 01599 if (!collapse_edge(curve_point, prev_point, &old_facets)) 01600 { 01601 return CUBIT_FAILURE; 01602 } 01603 std::swap(curve_point, prev_point); 01604 } 01605 facets -= old_facets; 01606 if (dead_ptrs) 01607 dead_ptrs->append(curve_edge); 01608 01609 if (curve_edges.is_at_beginning()) 01610 curve_edge = 0; 01611 else 01612 { 01613 curve_edge = curve_edges.get_and_step(); 01614 orig_crv_len = curve_edge->length(); 01615 split_tol = FRACT_TOL * CUBIT_MIN(orig_crv_len, orig_new_len); 01616 } 01617 continue; 01618 } 01619 01620 if (split_edge) 01621 { 01622 if (new_edge->other_point(prev_point)) 01623 std::swap(split_edge, new_edge); 01624 } 01625 else 01626 { 01627 assert(split == new_point); 01628 split_edge = new_edge; 01629 if (edge_list.is_at_beginning()) 01630 new_edge = 0; 01631 else 01632 { 01633 new_edge = edge_list.get_and_step(); 01634 orig_new_len = new_edge->length(); 01635 split_tol = FRACT_TOL * CUBIT_MIN(orig_crv_len, orig_new_len); 01636 } 01637 } 01638 01639 // Move split point to position of other point (safely) 01640 #ifdef PART_SURF_REFACET 01641 double d_sqr = (edge_pos - curve_point->coordinates()).length_squared(); 01642 bool close = d_sqr < (GEOMETRY_RESABS*GEOMETRY_RESABS); 01643 old_facets.clean_out(); 01644 new_facets.clean_out(); 01645 if (close) 01646 dynamic_cast<CubitPointData*>(split)->set(curve_point->coordinates()); 01647 else if (!fix_move_point( split, curve_point->coordinates(), facets, old_facets, new_facets )) 01648 return CUBIT_FAILURE; 01649 facets -= old_facets; 01650 facets += new_facets; 01651 #else 01652 dynamic_cast<CubitPointData*>(split)->set(curve_point->coordinates()); 01653 #endif 01654 01655 CubitStatus s2, s1 = CUBIT_SUCCESS; 01656 if (curve_point != split) 01657 s1 = curve_point->merge_points(split); 01658 s2 = curve_edge->merge_edges(split_edge); 01659 assert(s1 && s2); 01660 if (CUBIT_SUCCESS != s1 || CUBIT_SUCCESS != s2) { 01661 PRINT_ERROR("Internal error at %s:%d\n", __FILE__, __LINE__); 01662 return CUBIT_FAILURE; 01663 } 01664 if (dead_ptrs) 01665 dead_ptrs->append(split_edge); 01666 prev_point = curve_point; 01667 01668 if (curve_edges.is_at_beginning()) 01669 curve_edge = 0; 01670 else 01671 { 01672 curve_edge = curve_edges.get_and_step(); 01673 orig_crv_len = curve_edge->length(); 01674 split_tol = FRACT_TOL * CUBIT_MIN(orig_crv_len, orig_new_len); 01675 } 01676 } 01677 } 01678 01679 return CUBIT_SUCCESS; 01680 } 01681 01682 01683 //------------------------------------------------------------------------- 01684 // Purpose : Retriangulate if necessary for moving a boundary point 01685 // into the interior of a facet patch. 01686 // 01687 // Special Notes : 01688 // 01689 // Creator : Jason Kraftcheck 01690 // 01691 // Creation Date : 12/07/03 01692 //------------------------------------------------------------------------- 01693 CubitStatus PartSurfFacetTool::fix_move_point( 01694 CubitPoint* point, 01695 const CubitVector& new_pos, 01696 const DLIList<CubitFacetData*>& facetds, 01697 DLIList<CubitFacetData*>& old_facets, 01698 DLIList<CubitFacetData*>& new_facets, 01699 PartitionSurface* surface ) 01700 { 01701 int i; 01702 DLIList<CubitFacet*> facets(facetds.size()); 01703 for (i = 0; i < facetds.size(); i++) 01704 facets.append(facetds.next(i)); 01705 01706 // Look for a triangle containing the passed point. 01707 CubitVector closest_pos, vect; 01708 CubitFacet* facet = closest_facet(new_pos, facetds, closest_pos ); 01709 if ( facet == NULL) 01710 return CUBIT_FAILURE; 01711 01712 if (facet->point_index(point) >= 0) 01713 { 01714 dynamic_cast<CubitPointData*>(point)->set(new_pos); 01715 return CUBIT_SUCCESS; 01716 } 01717 01718 PRINT_WARNING("Refacetting surface near (%f,%f,%f)\n", 01719 new_pos.x(), new_pos.y(), new_pos.z()); 01720 01721 // Line direction 01722 const CubitVector dir(point->coordinates() - new_pos); 01723 01724 if (DEBUG_FLAG(145)) 01725 { 01726 GfxDebug::draw_facet(facet, CUBIT_BLUE_INDEX); 01727 GfxDebug::draw_point(point->coordinates(), CUBIT_BLUE_INDEX); 01728 GfxDebug::draw_point(new_pos, CUBIT_CYAN_INDEX); 01729 GfxDebug::draw_line(point->coordinates(), new_pos, CUBIT_BLUE_INDEX); 01730 GfxDebug::flush(); 01731 } 01732 01733 // Find where line exits first triangle 01734 CubitFacetEdge* edge = 0; 01735 bool leftofpoint[3]; 01736 for ( i = 0; i < 3; i++) 01737 { 01738 CubitVector vect = facet->point(i)->coordinates() - new_pos; 01739 vect *= dir; 01740 leftofpoint[i] = (vect % facet->normal()) >= 0.0; 01741 } 01742 01743 for ( i = 0; i < 3; ++i) 01744 if (leftofpoint[i] && !leftofpoint[(i+1)%3]) 01745 { 01746 edge = facet->edge((i+2)%3); 01747 break; 01748 } 01749 01750 if (!edge) 01751 return CUBIT_FAILURE; 01752 01753 // Find the set of triangles the line from the old 01754 // position to the new position crosses. 01755 DLIList<CubitFacet*> intersect_list, edge_facets; 01756 while (facet->point_index(point) < 0) 01757 { 01758 intersect_list.append(facet); 01759 01760 if (DEBUG_FLAG(145)) 01761 { 01762 GfxDebug::draw_facet_edge(edge, CUBIT_WHITE_INDEX); 01763 GfxDebug::draw_facet(facet, CUBIT_BLUE_INDEX); 01764 GfxDebug::flush(); 01765 } 01766 01767 // Find the facet on the other side of the edge 01768 edge_facets.clean_out(); 01769 if (surface) 01770 PartSurfFacetTool::edge_facets(surface, edge, edge_facets); 01771 else 01772 PartSurfFacetTool::edge_facets( edge, facets, edge_facets ); 01773 edge_facets.move_to(facet); 01774 assert(edge_facets.get() == facet); 01775 01776 if(edge_facets.size() != 2) 01777 break; 01778 01779 facet = edge_facets.step_and_get(); 01780 01781 // Find the edge that the line intersects exiting the facet 01782 i = facet->edge_index(edge); 01783 vect = facet->point(i)->coordinates() - new_pos; 01784 vect *= dir; 01785 if (vect % facet->normal() >= 0.0) 01786 edge = facet->edge((i+1)%3); 01787 else 01788 edge = facet->edge((i+2)%3); 01789 } 01790 01791 if (facet) 01792 { 01793 if (DEBUG_FLAG(145)) 01794 { 01795 GfxDebug::draw_facet_edge(edge, CUBIT_WHITE_INDEX); 01796 GfxDebug::flush(); 01797 } 01798 intersect_list.append_unique(facet); 01799 } 01800 01801 // Get ordered boundary 01802 DLIList<CubitPoint*> boundary_list; 01803 DLIList<CubitFacetEdge*> point_edges; 01804 CubitFacetEdge* prev_edge = 0; 01805 CubitFacet* prev_facet = 0; 01806 // Find one boundary edge to start with 01807 for (i = intersect_list.size(); !prev_edge && i--; ) 01808 { 01809 CubitFacet* facet = intersect_list.get_and_step(); 01810 for (int j = 0; j < 3; j++) 01811 { 01812 CubitFacetEdge* edge = facet->edge(j); 01813 edge_facets.clean_out(); 01814 if (surface) 01815 PartSurfFacetTool::edge_facets( surface, edge, edge_facets); 01816 else 01817 PartSurfFacetTool::edge_facets( edge, facets, edge_facets ); 01818 edge_facets.intersect(intersect_list); 01819 if (edge_facets.size() == 1) 01820 { 01821 prev_edge = edge; 01822 prev_facet = facet; 01823 break; 01824 } 01825 } 01826 } 01827 CubitFacetEdge* first_edge = prev_edge; 01828 // Traverse boundary edges in order 01829 do 01830 { 01831 int direction = prev_facet->edge_use( prev_facet->edge_index(prev_edge) ); 01832 CubitPoint* pt = prev_edge->point( direction == -1 ? 0 : 1 ); 01833 point_edges.clean_out(); 01834 pt->edges( point_edges ); 01835 01836 if (DEBUG_FLAG(145)) 01837 { 01838 GfxDebug::draw_facet_edge( prev_edge, CUBIT_LIGHTBLUE_INDEX ); 01839 GfxDebug::flush(); 01840 } 01841 boundary_list.append(pt); 01842 01843 point_edges.move_to(prev_edge); 01844 assert(point_edges.get() == prev_edge); 01845 point_edges.extract(); 01846 prev_edge = 0; 01847 01848 while (point_edges.size()) 01849 { 01850 CubitFacetEdge* edge = point_edges.pop(); 01851 edge_facets.clean_out(); 01852 if (surface) 01853 PartSurfFacetTool::edge_facets( surface, edge, edge_facets); 01854 else 01855 PartSurfFacetTool::edge_facets( edge, facets, edge_facets ); 01856 edge_facets.intersect(intersect_list); 01857 if (edge_facets.size() == 1) 01858 { 01859 if (prev_edge) { 01860 prev_edge = 0; 01861 break; 01862 } 01863 prev_edge = edge; 01864 prev_facet = edge_facets.get(); 01865 } 01866 } 01867 01868 if (!prev_edge) 01869 { 01870 PRINT_ERROR("Problems finding boundary to re-facet around split point.\n"); 01871 return CUBIT_FAILURE; 01872 } 01873 } while (prev_edge != first_edge); 01874 01875 01876 // Construct new facets in affected region by connecting 01877 // the split point to each boundary point 01878 int junk = 0; 01879 //DLIList<CubitFacetData*> new_facets, old_facets(intersect_list.size()); 01880 if (!boundary_list.move_to(point)) 01881 { 01882 PRINT_ERROR("Problems finding region around split point for re-facetting.\n"); 01883 return CUBIT_FAILURE; 01884 } 01885 boundary_list.step(); 01886 CubitPoint* prev_pt = boundary_list.get_and_step(); 01887 for (i = boundary_list.size(); i > 2; i--) 01888 { 01889 CubitPoint* next_pt = boundary_list.get_and_step(); 01890 CubitFacetData* new_facet = new CubitFacetData( point, prev_pt, next_pt, &junk); 01891 new_facets.append(new_facet); 01892 prev_pt = next_pt; 01893 01894 if (DEBUG_FLAG(145)) 01895 { 01896 GfxDebug::draw_facet( new_facet, CUBIT_YELLOW_INDEX ); 01897 GfxDebug::flush(); 01898 } 01899 } 01900 01901 CAST_LIST( intersect_list, old_facets, CubitFacetData ); 01902 assert(intersect_list.size() == old_facets.size()); 01903 dynamic_cast<CubitPointData*>(point)->set(new_pos); 01904 //replace_facets( old_facets, new_facets ); 01905 return CUBIT_SUCCESS; 01906 } 01907 01908 //------------------------------------------------------------------------- 01909 // Purpose : Find closest facet and point on facet 01910 // 01911 // Special Notes : 01912 // 01913 // Creator : Jason Kraftcheck 01914 // 01915 // Creation Date : 03/28/03 01916 //------------------------------------------------------------------------- 01917 CubitFacet* PartSurfFacetTool::closest_facet( 01918 const CubitVector& input_position, 01919 const DLIList<CubitFacetData*>& facet_list, 01920 CubitVector& result_position ) 01921 { 01922 CubitFacet* return_val = 0; 01923 double closest_dist_sqr = CUBIT_DBL_MAX; 01924 CubitVector facet_position; 01925 01926 const int size = facet_list.size(); 01927 for ( int i = 0; i < size; i++ ) { 01928 CubitFacet* facet = facet_list.next(i); 01929 closest_pt_on_facet( facet, input_position, facet_position ); 01930 double dist_sqr = (input_position - facet_position).length_squared(); 01931 if ( dist_sqr < closest_dist_sqr ) { 01932 closest_dist_sqr = dist_sqr; 01933 result_position = facet_position; 01934 return_val = facet; 01935 } 01936 } 01937 01938 return return_val; 01939 } 01940 01941 //------------------------------------------------------------------------- 01942 // Purpose : Return edge start/end if input position is sufficiently 01943 // close. Otherwise split the edge and return the new 01944 // point. 01945 // 01946 // Special Notes : For all facets modified by this operation, owning surfaces 01947 // will be notified of the change. For any un-owned facets, 01948 // new facets will be appended to the passed list. 01949 // 01950 // Creator : Jason Kraftcheck 01951 // 01952 // Creation Date : 12/01/03 01953 //------------------------------------------------------------------------- 01954 CubitPoint* PartSurfFacetTool::split_edge_closest( 01955 CubitFacetEdgeData* old_edge, 01956 const CubitVector& pos, 01957 double tolerance, 01958 CubitFacetEdgeData*& new_edge, 01959 DLIList<CubitFacetData*>& new_facets ) 01960 { 01961 // square of absolute tolerance 01962 const double GEOM_TOL_SQR = GEOMETRY_RESABS*GEOMETRY_RESABS; 01963 // tolerance as fraction of edge length. 01964 const double TOL_SQR = tolerance < GEOM_TOL_SQR ? GEOM_TOL_SQR : tolerance * tolerance; 01965 01966 new_edge = 0; 01967 01968 const CubitVector start(old_edge->point(0)->coordinates()); 01969 const CubitVector end(old_edge->point(1)->coordinates()); 01970 // const CubitVector dir(end - start); 01971 //const double fract = (dir % (pos - start)) / dir.length_squared(); 01972 01973 // If near the start/end of the edge and start/end point is 01974 // not already owned by some other vertex 01975 const double start_sqr = (start - pos).length_squared(); 01976 const double end_sqr = (end - pos).length_squared(); 01977 if (start_sqr < TOL_SQR && !TDVGFacetOwner::get(old_edge->point(0))) 01978 return old_edge->point(0); 01979 else if (end_sqr < TOL_SQR && !TDVGFacetOwner::get(old_edge->point(1))) 01980 return old_edge->point(1); 01981 01982 // Else if start/end of edge are same position as vertex 01983 else if(start_sqr < GEOM_TOL_SQR) 01984 return old_edge->point(0); 01985 else if(end_sqr < GEOM_TOL_SQR) 01986 return old_edge->point(1); 01987 01988 // Otherwise split the edge 01989 CubitFacet* a_face = old_edge->adj_facet(0); 01990 CubitFacetData* facet = dynamic_cast<CubitFacetData*>(a_face); 01991 if (!facet) 01992 return 0; 01993 01994 //CubitVector edge_pos((1.0-edge_param)*edge_start + edge_param*edge_end); 01995 CubitPoint* start_pt = old_edge->point(0); 01996 CubitPoint* end_pt = old_edge->point(1); 01997 CubitPoint* new_pt = facet->split_edge( start_pt, end_pt, pos ); 01998 CubitFacetEdge* temp_edge = new_pt->shared_edge(end_pt); 01999 new_edge = dynamic_cast<CubitFacetEdgeData*>(temp_edge); 02000 if (!new_edge) 02001 return 0; 02002 02003 // Update partition curve facetting 02004 PartitionCurve* edge_owner = dynamic_cast<PartitionCurve*>(TDVGFacetOwner::get(old_edge)); 02005 if (edge_owner) 02006 edge_owner->notify_split(old_edge, new_edge); 02007 02008 // Update partition surfaces for split of adjacent facets 02009 int i, junk = -1; 02010 DLIList<CubitFacet*> facets(old_edge->num_adj_facets()); 02011 old_edge->facets(facets); 02012 02013 for ( i = facets.size(); i--; ) 02014 { 02015 a_face = facets.get_and_step(); 02016 facet = dynamic_cast<CubitFacetData*>(a_face); 02017 assert(!!facet); 02018 int edge_index = facet->edge_index( start_pt, new_pt, junk ); 02019 CubitPoint* other_pt = facet->point( edge_index ); 02020 if (!other_pt->shared_edge( new_pt )) 02021 new CubitFacetEdgeData( other_pt, new_pt ); 02022 02023 CubitFacet* a_face = facet->shared_facet( new_pt, other_pt ); 02024 CubitFacetData* other_facet = dynamic_cast<CubitFacetData*>(a_face); 02025 if (!other_facet) { assert(0); continue; } 02026 02027 PartitionEntity* owner = TDVGFacetOwner::get(facet); 02028 #ifndef NDEBUG 02029 PartitionSurface* surf = dynamic_cast<PartitionSurface*>(owner); 02030 assert(!owner || surf); 02031 #endif 02032 02033 if (owner) 02034 owner->notify_split( facet, other_facet ); 02035 else 02036 new_facets.append(other_facet); 02037 } 02038 02039 return new_pt; 02040 } 02041 02042 //------------------------------------------------------------------------- 02043 // Purpose : Spatially match a set of geometric points one-to-one 02044 // with a subset of a set of facet vertices. 02045 // 02046 // Special Notes : If the geometric point already has an attached facet 02047 // point, the points will be merged such that the facet 02048 // point originally on the geometric point survives the 02049 // merge. If the geometric point does not already have 02050 // a facet point, the input facet point will be attached 02051 // to the geometric point. 02052 // 02053 // Creator : Jason Kraftcheck 02054 // 02055 // Creation Date : 09/08/03 02056 //------------------------------------------------------------------------- 02057 CubitStatus PartSurfFacetTool::associate_points( 02058 DLIList<CubitPoint*>& facet_points, 02059 DLIList<PartitionPoint*>& geom_points ) 02060 { 02061 int i; 02062 DLIList<int> geom_indices(geom_points.size()); 02063 02064 for (i = 0; i < geom_points.size(); i++ ) 02065 geom_indices.append(i); 02066 02067 for (i = facet_points.size(); i--; ) 02068 facet_points.step_and_get()->marked(-1); 02069 02070 geom_points.reset(); 02071 facet_points.reset(); 02072 while (geom_indices.size()) 02073 { 02074 int index = geom_indices.pop(); 02075 PartitionPoint* geom_pt = geom_points.next(index); 02076 const CubitVector pos(geom_pt->coordinates()); 02077 double shortest_dist_sqr = CUBIT_DBL_MAX; 02078 int closest_index = -1; 02079 for (i = 0; i < facet_points.size(); i++ ) 02080 { 02081 CubitPoint* facet_pt = facet_points.next(i); 02082 double dist_sqr = (pos - facet_pt->coordinates()).length_squared(); 02083 if (dist_sqr < shortest_dist_sqr) 02084 { 02085 if (facet_pt->marked() == -1) 02086 { 02087 shortest_dist_sqr = dist_sqr; 02088 closest_index = i; 02089 } 02090 else 02091 { 02092 int j = facet_pt->marked(); 02093 CubitPoint* other_point = facet_points.next(j); 02094 double other_dist_sqr = (pos - other_point->coordinates()).length_squared(); 02095 if (other_dist_sqr > dist_sqr) 02096 { 02097 shortest_dist_sqr = dist_sqr; 02098 closest_index = i; 02099 facet_pt->marked(-1); 02100 geom_indices.append(j); 02101 } 02102 } 02103 } 02104 } 02105 02106 if (closest_index < 0) 02107 { 02108 assert(false); 02109 for (i = facet_points.size(); i--; ) 02110 facet_points.step_and_get()->marked(0); 02111 for (i = geom_points.size(); i--; ) 02112 geom_points.step_and_get()->mark = 0; 02113 return CUBIT_FAILURE; 02114 } 02115 geom_pt->mark = closest_index; 02116 facet_points.next(closest_index)->marked(index); 02117 } 02118 02119 for (i = facet_points.size(); i--; ) 02120 facet_points.step_and_get()->marked(0); 02121 02122 facet_points.reset(); 02123 for (i = geom_points.size(); i--; ) 02124 { 02125 PartitionPoint* geom_pt = geom_points.step_and_get(); 02126 CubitPoint* facet_pt = facet_points.next(geom_pt->mark); 02127 geom_pt->mark = 0; 02128 02129 assert(!TDVGFacetOwner::get(facet_pt)); 02130 facet_pt->set(geom_pt->coordinates()); 02131 02132 CubitPointData* point_data = dynamic_cast<CubitPointData*>(facet_pt); 02133 assert(!!point_data); 02134 02135 if (geom_pt->facet_point()) 02136 geom_pt->facet_point()->merge_points( point_data ); 02137 else 02138 geom_pt->facet_point(point_data); 02139 } 02140 02141 return CUBIT_SUCCESS; 02142 } 02143 02144 //------------------------------------------------------------------------- 02145 // Purpose : Get points and edges in facet patch, separated into 02146 // boundary and internal sets where a boundary point is 02147 // a point for which one or more adjacent edges is on the 02148 // boundary of the patch. 02149 // 02150 // Special Notes : Aborts and returns failure if the input facets are not 02151 // a manifold patch. 02152 // 02153 // Creator : Jason Kraftcheck 02154 // 02155 // Creation Date : 09/08/03 02156 //------------------------------------------------------------------------- 02157 CubitStatus PartSurfFacetTool::get_facet_points_and_edges( 02158 const DLIList<CubitFacetData*>& facets, 02159 DLIList<CubitPoint*>& boundary_points, 02160 DLIList<CubitPoint*>& interior_points, 02161 DLIList<CubitFacetEdge*>& boundary_edges, 02162 DLIList<CubitFacetEdge*>& interior_edges ) 02163 { 02164 int i, j; 02165 CubitStatus result = CUBIT_SUCCESS; 02166 CubitFacetData* facet; 02167 DLIList<CubitFacetEdge*> edge_list; 02168 const int count = facets.size(); 02169 02170 // Initialize marks 02171 for (i = 0; i < count; i++ ) 02172 { 02173 facet = facets.next(i); 02174 for (j = 0; j < 3; j++) 02175 { 02176 facet->edge(j)->marked(0); 02177 facet->point(j)->marked(1); 02178 } 02179 } 02180 02181 // Mark each edge with a count of the number of 02182 // adjcent facets. 02183 for (i = 0; i < count; i++ ) 02184 { 02185 facet = facets.next(i); 02186 for (j = 0; j < 3; j++) 02187 facet->edge(j)->marked(facet->edge(j)->marked() + 1); 02188 } 02189 02190 // Collect points and clear point marks 02191 for (i = 0; i < count; i++ ) 02192 { 02193 facet = facets.next(i); 02194 for (j = 0; j < 3; j++) 02195 { 02196 CubitPoint* point = facet->point(j); 02197 if (!point->marked()) 02198 continue; 02199 point->marked(0); 02200 02201 point->edges(edge_list); 02202 bool boundary = false; 02203 while (edge_list.size()) 02204 if (edge_list.pop()->marked() == 1) 02205 boundary = true; 02206 if (boundary) 02207 boundary_points.append(point); 02208 else 02209 interior_points.append(point); 02210 } 02211 } 02212 02213 // Collect edges and clear edge marks 02214 for (i = 0; i < count; i++ ) 02215 { 02216 facet = facets.next(i); 02217 for (j = 0; j < 3; j++) 02218 { 02219 CubitFacetEdge* edge = facet->edge(j); 02220 switch (edge->marked()) 02221 { 02222 case 0: 02223 continue; 02224 case 1: 02225 boundary_edges.append(edge); 02226 break; 02227 case 2: 02228 interior_edges.append(edge); 02229 break; 02230 default: 02231 result = CUBIT_FAILURE; 02232 assert(false); 02233 } 02234 edge->marked(0); 02235 } 02236 } 02237 02238 return result; 02239 } 02240 02241 02242 //------------------------------------------------------------------------- 02243 // Purpose : Get facets adjacent to edge and owned by this surface. 02244 // 02245 // Special Notes : 02246 // 02247 // Creator : Jason Kraftcheck 02248 // 02249 // Creation Date : 12/07/03 02250 //------------------------------------------------------------------------- 02251 void PartSurfFacetTool::edge_facets( PartitionSurface* surf, 02252 CubitFacetEdge* edge, 02253 DLIList<CubitFacet*>& facets ) 02254 { 02255 edge->facets(facets); 02256 02257 for (int i = facets.size(); i--; ) 02258 if (TDVGFacetOwner::get(facets.step_and_get()) != surf) 02259 facets.change_to(0); 02260 02261 facets.remove_all_with_value(0); 02262 } 02263 02264 02265 02266 //------------------------------------------------------------------------- 02267 // Purpose : Get facets in passed list adjacent to passed edge 02268 // 02269 // Special Notes : 02270 // 02271 // Creator : Jason Kraftcheck 02272 // 02273 // Creation Date : 12/07/03 02274 //------------------------------------------------------------------------- 02275 void PartSurfFacetTool::edge_facets( CubitFacetEdge* edge, 02276 const DLIList<CubitFacet*>& input_facets, 02277 DLIList<CubitFacet*>& output_facets ) 02278 { 02279 edge->facets(output_facets); 02280 output_facets.intersect( input_facets ); 02281 }