cgma
|
00001 //======================================================================= 00002 // 00003 // File: CubitFacetEdge 00004 // Description: used for edges of CubitFacets. These are optional 00005 // and used only if specific information must be stored at 00006 // the edge common to two facets. 00007 // Notes: See notes in CubitFacetEdge.hpp 00008 // Owner: sjowen 00009 // 00010 //======================================================================= 00011 00012 #include "CubitFacetEdge.hpp" 00013 #include "CubitFacet.hpp" 00014 #include "CubitPoint.hpp" 00015 #include "CubitVector.hpp" 00016 #include "GeometryDefines.h" 00017 #include "FacetEvalTool.hpp" 00018 #include "GfxDebug.hpp" 00019 #include "IntersectionTool.hpp" 00020 #include "CubitMessage.hpp" 00021 00022 00023 //====================================================================== 00024 // Function: CubitFacetEdge (PUBLIC) 00025 // Description: constructor 00026 // Author: sjowen 00027 // Date: 8/00 00028 //====================================================================== 00029 CubitFacetEdge::CubitFacetEdge( ) 00030 : bezierOrder(0), markedFlag(0), isFeature(0), isFlipped(CUBIT_FALSE) 00031 { 00032 } 00033 00034 00035 //====================================================================== 00036 // Function: ~CubitFacetEdge (PUBLIC) 00037 // Description: destructor 00038 // Author: sjowen 00039 // Date: 8/00 00040 //====================================================================== 00041 CubitFacetEdge::~CubitFacetEdge() 00042 { 00043 } 00044 00045 //====================================================================== 00046 // Function: set_control_points (PUBLIC) 00047 // Description: set the control points from an array of doubles 00048 // Author: sjowen 00049 // Date: 8/00 00050 //====================================================================== 00051 void CubitFacetEdge::set_control_points( const double *ctrl_pt_array ) 00052 { 00053 int ii; 00054 for (ii=0; ii<3; ii++) 00055 { 00056 controlPoints[ii].x( ctrl_pt_array[ii*3] ); 00057 controlPoints[ii].y( ctrl_pt_array[ii*3+1] ); 00058 controlPoints[ii].z( ctrl_pt_array[ii*3+2] ); 00059 } 00060 } 00061 00062 //====================================================================== 00063 // Function: control_points (PUBLIC) 00064 // Description: return the Bezier control points (including the end points) 00065 // The order of the bezier is returned. 00066 // Author: sjowen 00067 // Date: 8/00 00068 //====================================================================== 00069 int CubitFacetEdge::control_points( CubitVector *ctrl_pts ) 00070 { 00071 DLIList<CubitPoint*> my_points; 00072 points(my_points); 00073 00074 ctrl_pts[0] = my_points.get()->coordinates(); 00075 for(int i=0; i<bezierOrder-1; i++) { 00076 ctrl_pts[i+1] = controlPoints[i]; 00077 } 00078 ctrl_pts[bezierOrder] = my_points.next()->coordinates(); 00079 return bezierOrder; 00080 } 00081 00082 //====================================================================== 00083 // Function: control_points (PUBLIC) 00084 // Description: return the control points on the edge of a facet based 00085 // on its edge use direction 00086 // Author: sjowen 00087 // Date: 8/00 00088 //====================================================================== 00089 CubitStatus CubitFacetEdge::control_points( 00090 CubitFacet *facet, CubitVector *ctrl_pts ) 00091 { 00092 int index = -1; 00093 CubitBoolean found = CUBIT_FALSE; 00094 for (int i=0; i<3 && !found; i++) { 00095 if (this == facet->edge(i)) { 00096 index = i; 00097 found = CUBIT_TRUE; 00098 } 00099 } 00100 if (!found) { 00101 return CUBIT_FAILURE; 00102 } 00103 00104 DLIList<CubitPoint*> my_points; 00105 points(my_points); 00106 00107 switch (facet->edge_use(index)) { 00108 case 1: 00109 ctrl_pts[0] = my_points.get()->coordinates(); 00110 ctrl_pts[1] = controlPoints[0]; 00111 ctrl_pts[2] = controlPoints[1]; 00112 ctrl_pts[3] = controlPoints[2]; 00113 ctrl_pts[4] = my_points.next()->coordinates(); 00114 break; 00115 case -1: 00116 ctrl_pts[0] = my_points.next()->coordinates(); 00117 ctrl_pts[1] = controlPoints[2]; 00118 ctrl_pts[2] = controlPoints[1]; 00119 ctrl_pts[3] = controlPoints[0]; 00120 ctrl_pts[4] = my_points.get()->coordinates(); 00121 break; 00122 default: 00123 return CUBIT_FAILURE; 00124 } 00125 return CUBIT_SUCCESS; 00126 } 00127 00128 //=========================================================================== 00129 //Function Name: evaluate_position 00130 // 00131 //Member Type: PUBLIC 00132 //Description: evaluate the facet edge at a position 00133 // eval_tangent is NULL if tangent not needed 00134 //=========================================================================== 00135 CubitStatus CubitFacetEdge::evaluate_position( const CubitVector &start_position, 00136 CubitVector *eval_point, 00137 CubitVector *eval_tangent) 00138 { 00139 CubitStatus stat = CUBIT_SUCCESS; 00140 00141 // find the adjacent facet 00142 00143 CubitFacet *facet_ptr = this->adj_facet( 0 ); 00144 00145 // If there is none or this is a linear representation - 00146 // then project to the linear edge 00147 00148 if (!facet_ptr || facet_ptr->eval_order() == 0 || facet_ptr->is_flat()) 00149 { 00150 if (eval_point) 00151 { 00152 closest_point(start_position, *eval_point); 00153 } 00154 if (eval_tangent) 00155 { 00156 *eval_tangent = point(1)->coordinates() - point(0)->coordinates(); 00157 (*eval_tangent).normalize(); 00158 } 00159 } 00160 else 00161 { 00162 int vert0 = facet_ptr->point_index( point(0) ); 00163 int vert1 = facet_ptr->point_index( point(1) ); 00164 CubitVector pt_on_plane, close_point; 00165 CubitVector start = start_position; 00166 double dist_to_plane; 00167 CubitBoolean outside_facet; 00168 FacetEvalTool::project_to_facet_plane( facet_ptr, start, 00169 pt_on_plane, dist_to_plane ); 00170 stat = FacetEvalTool::project_to_facetedge( facet_ptr, 00171 vert0, vert1, 00172 start, 00173 pt_on_plane, 00174 close_point, 00175 outside_facet ); 00176 if (eval_point) 00177 { 00178 *eval_point = close_point; 00179 } 00180 if (eval_tangent) 00181 { 00182 CubitVector edvec = point(1)->coordinates() - point(0)->coordinates(); 00183 edvec.normalize(); 00184 CubitVector areacoord; 00185 FacetEvalTool::facet_area_coordinate( facet_ptr, close_point, areacoord ); 00186 FacetEvalTool::eval_facet_normal(facet_ptr, areacoord, *eval_tangent); 00187 CubitVector cross = edvec * *eval_tangent; 00188 *eval_tangent = *eval_tangent * cross; 00189 (*eval_tangent).normalize(); 00190 } 00191 } 00192 00193 return stat; 00194 } 00195 00196 //=========================================================================== 00197 //Function Name: evaluate 00198 // 00199 //Member Type: PUBLIC 00200 //Description: evaluate the facet at area coordinates 00201 // eval_normal is NULL if normal not needed 00202 //Note: t is a value from -1 to 1. t=0 is the midpoint 00203 //=========================================================================== 00204 CubitStatus CubitFacetEdge::evaluate( double &t, 00205 CubitVector *eval_point, 00206 CubitVector *eval_tangent ) 00207 { 00208 CubitStatus stat = CUBIT_SUCCESS; 00209 00210 // project the position to the linear edge 00211 00212 double tt = (t + 1) * 0.5; 00213 if (tt <= 0.0) tt = 0.0; 00214 if (tt >= 1.0) tt = 1.0; 00215 *eval_point = point(0)->coordinates() + 00216 tt * (point(1)->coordinates() - point(0)->coordinates()); 00217 00218 // evaluate the point on the facet (if the order is higher than 0) 00219 00220 CubitFacet *facet_ptr = this->adj_facet( 0 ); 00221 if (!facet_ptr || facet_ptr->is_flat()) 00222 { 00223 if (eval_tangent) 00224 { 00225 *eval_tangent = point(1)->coordinates() - point(0)->coordinates(); 00226 (*eval_tangent).normalize(); 00227 } 00228 } 00229 else 00230 { 00231 CubitVector areacoord; 00232 FacetEvalTool::facet_area_coordinate( facet_ptr, *eval_point, areacoord ); 00233 stat = facet_ptr->evaluate( areacoord, eval_point, eval_tangent ); 00234 if (stat != CUBIT_SUCCESS) 00235 return stat; 00236 if (eval_tangent) 00237 { 00238 CubitVector edvec = point(1)->coordinates() - point(0)->coordinates(); 00239 edvec.normalize(); 00240 CubitVector cross = edvec * *eval_tangent; 00241 *eval_tangent = *eval_tangent * cross; 00242 (*eval_tangent).normalize(); 00243 } 00244 } 00245 return stat; 00246 } 00247 00248 //=========================================================================== 00249 //Function Name: evaluate_single 00250 // 00251 //Member Type: PUBLIC 00252 //Description: evaluate edge not associated with a facet. 00253 //Note: t is a value from -1 to 1. 00254 //=========================================================================== 00255 CubitStatus CubitFacetEdge::evaluate_single(double &t, 00256 CubitVector *outv) 00257 { 00258 CubitVector P0, P1; 00259 double t4, t3, t2, one_minus_t, one_minus_t2, one_minus_t3, one_minus_t4; 00260 DLIList<CubitPoint*> my_points; 00261 // project the position to the linear edge 00262 00263 double tt = (t + 1) * 0.5; 00264 if (tt <= 0.0) tt = 0.0; 00265 if (tt >= 1.0) tt = 1.0; 00266 00267 points(my_points); 00268 00269 P0 = my_points.get()->coordinates(); 00270 P1 = my_points.next()->coordinates(); 00271 00272 t2 = tt*tt; 00273 t3 = t2*tt; 00274 t4 = t3*tt; 00275 one_minus_t = 1.-tt; 00276 one_minus_t2 = one_minus_t*one_minus_t; 00277 one_minus_t3 = one_minus_t2*one_minus_t; 00278 one_minus_t4 = one_minus_t3*one_minus_t; 00279 00280 *outv = one_minus_t4*P0 + 00281 4.*one_minus_t3*tt* controlPoints[0] + 00282 6.*one_minus_t2*t2*controlPoints[1] + 00283 4.*one_minus_t* t3*controlPoints[2] + 00284 t4*P1; 00285 00286 return CUBIT_SUCCESS; 00287 } 00288 00289 //=========================================================================== 00290 //Function Name: evaluate_single_tangent 00291 // 00292 //Member Type: PUBLIC 00293 //Description: evaluate tangent to edge not associated with a facet. 00294 //Note: t is a value from -1 to 1. 00295 //=========================================================================== 00296 CubitStatus CubitFacetEdge::evaluate_single_tangent(double &t, 00297 CubitVector *outv) 00298 { 00299 CubitVector P0, P1; 00300 double t3, t2, one_minus_t, one_minus_t2, one_minus_t3; 00301 DLIList<CubitPoint*> my_points; 00302 // project the position to the linear edge 00303 00304 double tt = (t + 1) * 0.5; 00305 if (tt <= 0.0) tt = 0.0; 00306 if (tt >= 1.0) tt = 1.0; 00307 00308 points(my_points); 00309 00310 P0 = my_points.get()->coordinates(); 00311 P1 = my_points.next()->coordinates(); 00312 00313 t2 = tt*tt; 00314 t3 = t2*tt; 00315 one_minus_t = 1.-tt; 00316 one_minus_t2 = one_minus_t*one_minus_t; 00317 one_minus_t3 = one_minus_t2*one_minus_t; 00318 00319 *outv = -4.*one_minus_t3*P0 + 00320 4.*(one_minus_t3 -3.*tt*one_minus_t2)*controlPoints[0] + 00321 12.*(tt*one_minus_t2 - t2*one_minus_t)*controlPoints[1] + 00322 4.*(3.*t2*one_minus_t - t3)*controlPoints[2] + 00323 4.*t3*P1; 00324 00325 return CUBIT_SUCCESS; 00326 } 00327 00328 //=========================================================================== 00329 //Function Name: evaluate_2nd_derivative 00330 // 00331 //Member Type: PUBLIC 00332 //Description: evaluate tangent to edge not associated with a facet. 00333 //Note: t is a value from -1 to 1. 00334 //=========================================================================== 00335 CubitStatus CubitFacetEdge::evaluate_2nd_derivative(double &t, 00336 CubitVector *outv) 00337 { 00338 CubitVector P0, P1, second_d; 00339 DLIList<CubitPoint*> my_points; 00340 double val; 00341 // project the position to the linear edge 00342 00343 double tt = (t + 1) * 0.5; 00344 if (tt <= 0.0) tt = 0.0; 00345 if (tt >= 1.0) tt = 1.0; 00346 00347 points(my_points); 00348 00349 P0 = my_points.get()->coordinates(); 00350 P1 = my_points.next()->coordinates(); 00351 00352 val = 12.*(1.-tt)*(1.-tt)*P0.x() - 00353 24.*(2.*tt*tt - 3.*tt + 1.)*controlPoints[0].x() + 00354 12.*(6.*tt*tt - 6.*tt + 1.)*controlPoints[1].x() + 00355 24.*(tt - 2.*tt*tt)*controlPoints[2].x() + 00356 12.*tt*tt*P1.x(); 00357 second_d.x(val); 00358 val = 12.*(1.-tt)*(1.-tt)*P0.y() - 00359 24.*(2.*tt*tt - 3.*tt + 1.)*controlPoints[0].y() + 00360 12.*(6.*tt*tt - 6.*tt + 1.)*controlPoints[1].y() + 00361 24.*(tt - 2.*tt*tt)*controlPoints[2].y() + 00362 12.*tt*tt*P1.y(); 00363 second_d.y(val); 00364 val = 12.*(1.-tt)*(1.-tt)*P0.z() - 00365 24.*(2.*tt*tt - 3.*tt + 1.)*controlPoints[0].z() + 00366 12.*(6.*tt*tt - 6.*tt + 1.)*controlPoints[1].z() + 00367 24.*(tt - 2.*tt*tt)*controlPoints[2].z() + 00368 12.*tt*tt*P1.z(); 00369 second_d.z(val); 00370 *outv = second_d; 00371 00372 return CUBIT_SUCCESS; 00373 } 00374 00375 //=========================================================================== 00376 //Function Name: closest_point 00377 // 00378 //Member Type: PUBLIC 00379 //Description: return the closest point on segment defined by the edge 00380 //=========================================================================== 00381 CubitStatus CubitFacetEdge::closest_point(const CubitVector &point, 00382 CubitVector &closest_point ) 00383 { 00384 //CubitStatus rv = CUBIT_SUCCESS; 00385 CubitPoint *pt0 = this->point(0); 00386 CubitPoint *pt1 = this->point(1); 00387 00388 // the edge vector 00389 00390 CubitVector e0 ( pt1->x() - pt0->x(), 00391 pt1->y() - pt0->y(), 00392 pt1->z() - pt0->z() ); 00393 double elen = e0.normalize(); 00394 00395 // vector from vert0 to point 00396 00397 CubitVector v0 ( point.x() - pt0->x(), 00398 point.y() - pt0->y(), 00399 point.z() - pt0->z() ); 00400 00401 // project to edge 00402 00403 double len = v0%e0; 00404 if (len <= 0.0) 00405 { 00406 closest_point = pt0->coordinates(); 00407 } 00408 else if( len >= elen ) 00409 { 00410 closest_point = pt1->coordinates(); 00411 } 00412 else 00413 { 00414 closest_point.x ( pt0->x() + e0.x() * len ); 00415 closest_point.y ( pt0->y() + e0.y() * len ); 00416 closest_point.z ( pt0->z() + e0.z() * len ); 00417 } 00418 00419 return CUBIT_SUCCESS; 00420 } 00421 00422 //=========================================================================== 00423 //Function Name: intersect 00424 // 00425 //Member Type: PUBLIC 00426 //Description: intersect the edge with a segment. Assumes segment and edge 00427 // are on the same plane (project to facet plane first) 00428 //=========================================================================== 00429 CubitStatus CubitFacetEdge::intersect( 00430 CubitVector &aa, CubitVector &bb, // end point of segment 00431 CubitVector &norm, // normal of the common plane 00432 CubitVector &qq, // return the intersection point 00433 CubitBoolean &does_intersect ) // return status of intersection 00434 { 00435 00436 CubitPoint *pt0 = this->point(0); 00437 CubitPoint *pt1 = this->point(1); 00438 00439 double P0[2], P1[2], AA[2], BB[2]; 00440 CubitVector absnorm(fabs(norm.x()), fabs(norm.y()), fabs(norm.z())); 00441 if (absnorm.x() >= absnorm.y() && absnorm.x() >= absnorm.z()) 00442 { 00443 P0[0] = pt0->coordinates().y(); P0[1] = pt0->coordinates().z(); 00444 P1[0] = pt1->coordinates().y(); P1[1] = pt1->coordinates().z(); 00445 AA[0] = aa.y(); AA[1] = aa.z(); 00446 BB[0] = bb.y(); BB[1] = bb.z(); 00447 } 00448 else if (absnorm.y() >= absnorm.x() && absnorm.y() >= absnorm.z()) 00449 { 00450 P0[0] = pt0->coordinates().z(); P0[1] = pt0->coordinates().x(); 00451 P1[0] = pt1->coordinates().z(); P1[1] = pt1->coordinates().x(); 00452 AA[0] = aa.z(); AA[1] = aa.x(); 00453 BB[0] = bb.z(); BB[1] = bb.x(); 00454 } 00455 else 00456 { 00457 P0[0] = pt0->coordinates().x(); P0[1] = pt0->coordinates().y(); 00458 P1[0] = pt1->coordinates().x(); P1[1] = pt1->coordinates().y(); 00459 AA[0] = aa.x(); AA[1] = aa.y(); 00460 BB[0] = bb.x(); BB[1] = bb.y(); 00461 } 00462 00463 double QQ[4], s; 00464 int ninter = intersect_2D_segments(P0, P1, AA, BB, QQ); 00465 00466 if (ninter != 1) 00467 { 00468 does_intersect = CUBIT_FALSE; 00469 return CUBIT_SUCCESS; 00470 } 00471 does_intersect = CUBIT_TRUE; 00472 00473 double dx = P1[0] - P0[0]; 00474 double dy = P1[1] - P0[1]; 00475 if (fabs(dx) > fabs(dy)) 00476 s = (QQ[0] - P0[0]) / dx; 00477 else 00478 s = (QQ[1] - P0[1]) / dy; 00479 00480 qq = pt0->coordinates() + s * (pt1->coordinates() - pt0->coordinates()); 00481 00482 return CUBIT_SUCCESS; 00483 } 00484 00485 //====================================================================== 00486 // Function: boundary_edge_points (PUBLIC) 00487 // Description: return the oriented endpoints of a facet edge assuming 00488 // the edge is at the frontier of the facets (only one adjacency) 00489 // Author: sjowen 00490 // Date: 8/00 00491 //====================================================================== 00492 void CubitFacetEdge::boundary_edge_points( CubitPoint * &pt0, 00493 CubitPoint * &pt1, 00494 int tool_id ) 00495 { 00496 if(num_adj_facets() == 0) 00497 { 00498 pt0 = point(0); 00499 pt1 = point(1); 00500 return; 00501 } 00502 CubitFacet *facet = NULL; 00503 if (tool_id != 0) 00504 { 00505 int ii; 00506 int found = 0; 00507 DLIList <CubitFacet *> adj_facets; 00508 facets(adj_facets); 00509 for (ii=0; ii<adj_facets.size() && !found; ii++) 00510 { 00511 facet = adj_facets.get_and_step(); 00512 if (facet->tool_id() == tool_id) 00513 found = 1; 00514 } 00515 assert(found); 00516 } 00517 else 00518 { 00519 facet = adj_facet(0); 00520 if (!facet) facet = adj_facet(1); 00521 assert(facet != 0); 00522 } 00523 00524 int index = facet->edge_index( this ); 00525 int use = facet->edge_use( index ); 00526 if (use == 1) { 00527 pt0 = point(0); 00528 pt1 = point(1); 00529 } 00530 else { 00531 pt0 = point(1); 00532 pt1 = point(0); 00533 } 00534 } 00535 00536 //====================================================================== 00537 // Function: dist_to_edge 00538 // Description: return the distance from the point to this edge 00539 // Author: sjowen 00540 // Date: 2/01 00541 // Corrected by JFowler 5/03 00542 //====================================================================== 00543 double CubitFacetEdge::dist_to_edge( 00544 const CubitVector &this_point, 00545 CubitVector &close_point, 00546 CubitBoolean &outside_edge ) 00547 { 00548 double dist = 0.0; 00549 CubitVector p0 = point(0)->coordinates(); 00550 CubitVector p1 = point(1)->coordinates(); 00551 CubitVector edge_vec( p1, p0 ); 00552 CubitVector point_vec( this_point, p0 ); 00553 double edge_length; 00554 edge_length = edge_vec.normalize(); 00555 double dist_on_edge = edge_vec % point_vec; 00556 if (dist_on_edge < 0.0e0) 00557 { 00558 close_point = p0; 00559 outside_edge = CUBIT_TRUE; 00560 } 00561 else if (dist_on_edge > edge_length) 00562 { 00563 close_point = p1; 00564 outside_edge = CUBIT_TRUE; 00565 } 00566 else 00567 { 00568 close_point = p0 - edge_vec * dist_on_edge; 00569 outside_edge = CUBIT_FALSE; 00570 } 00571 dist = close_point.distance_between( this_point ); 00572 return dist; 00573 } 00574 00575 /*//====================================================================== 00576 // Function: dist_to_edge 00577 // Description: return the distance from the point to this edge 00578 // Author: sjowen 00579 // Date: 2/01 00580 //====================================================================== 00581 double CubitFacetEdge::dist_to_edge( 00582 CubitVector &this_point, 00583 CubitVector &close_point, 00584 CubitBoolean &outside_edge ) 00585 { 00586 double dist = 0.0; 00587 CubitVector p0 = point(0)->coordinates(); 00588 CubitVector p1 = point(1)->coordinates(); 00589 CubitVector edge_vec( p1, p0 ); 00590 CubitVector point_vec( this_point, p0 ); 00591 point_vec.normalize(); 00592 double dist_on_edge = edge_vec % point_vec; 00593 double edge_length; 00594 edge_length = edge_vec.normalize(); 00595 if (dist_on_edge < 0.0e0) 00596 { 00597 close_point = p0; 00598 outside_edge = CUBIT_TRUE; 00599 } 00600 else if (dist_on_edge > edge_length) 00601 { 00602 close_point = p1; 00603 outside_edge = CUBIT_TRUE; 00604 } 00605 else 00606 { 00607 close_point = p0 + edge_vec * dist_on_edge; 00608 outside_edge = CUBIT_FALSE; 00609 } 00610 dist = close_point.distance_between( this_point ); 00611 return dist; 00612 } 00613 */ 00614 //====================================================================== 00615 // Function: proj_to_line 00616 // Description: project the point to a line defined by the edge 00617 // Author: sjowen 00618 // Date: 2/01 00619 //====================================================================== 00620 CubitStatus CubitFacetEdge::proj_to_line( 00621 const CubitVector &this_point, 00622 CubitVector &proj_point ) 00623 { 00624 CubitStatus stat = CUBIT_SUCCESS; 00625 CubitVector p0 = point(0)->coordinates(); 00626 CubitVector p1 = point(1)->coordinates(); 00627 CubitVector edge_vec( p0,p1 ); 00628 CubitVector point_vec( p0, this_point ); 00629 edge_vec.normalize(); 00630 double dist_on_edge = edge_vec % point_vec; 00631 proj_point = p0 + (edge_vec * dist_on_edge); 00632 00633 return stat; 00634 } 00635 00636 //====================================================================== 00637 // Function: edge_tangent 00638 // Description: return tangent at a point on the edge 00639 // Author: sjowen 00640 // Date: 2/01 00641 //====================================================================== 00642 CubitStatus CubitFacetEdge::edge_tangent( 00643 const CubitVector &/*point_on_edge*/, 00644 CubitVector &tangent ) 00645 { 00646 CubitStatus stat = CUBIT_SUCCESS; 00647 tangent = point(1)->coordinates() - 00648 point(0)->coordinates(); 00649 tangent.normalize(); 00650 return stat; 00651 } 00652 00653 //====================================================================== 00654 // Function: edge_tangent 00655 // Description: return curvature at a point on the edge 00656 // Author: sjowen 00657 // Date: 2/01 00658 //====================================================================== 00659 CubitStatus CubitFacetEdge::edge_curvature( 00660 const CubitVector &/*point_on_edge*/, 00661 CubitVector &curvature, 00662 CubitFacetEdge *closest_edge ) 00663 { 00664 CubitVector vec_ba, vec_ca, center_point; 00665 00666 //if point(0) is middle point 00667 if( closest_edge->other_point( point(0) ) ) 00668 { 00669 center_point = point(0)->coordinates(); 00670 vec_ba = closest_edge->point(0)->coordinates() - center_point; 00671 vec_ca = point(1)->coordinates() - center_point; 00672 } 00673 //if point(1) is middle point 00674 else if( closest_edge->other_point( point(1) ) ) 00675 { 00676 center_point = point(1)->coordinates(); 00677 vec_ba = point(0)->coordinates() - center_point; 00678 vec_ca = closest_edge->point(1)->coordinates() - center_point; 00679 } 00680 else 00681 assert(0); 00682 00683 // Squares of lengths of the edges incident to `a'. 00684 double ba_length = vec_ba.length_squared(); 00685 double ca_length = vec_ca.length_squared(); 00686 00687 // Cross product of these edges. 00688 // (Take your chances with floating-point roundoff.) 00689 CubitVector cross_bc = vec_ba * vec_ca; 00690 00691 // Calculate the denominator of the formulae. 00692 double temp_dbl = cross_bc % cross_bc; 00693 CubitVector circle_center(0.0,0.0,0.0); 00694 if(fabs(temp_dbl) > CUBIT_DBL_MIN){ 00695 double denominator = 0.5 / (temp_dbl); 00696 assert(denominator != 0.0); 00697 00698 // Calculate offset (from `a') of circumcenter. 00699 circle_center = (ba_length * vec_ca - ca_length * vec_ba) * cross_bc; 00700 circle_center *= denominator; 00701 00702 //store radius 00703 double radius = circle_center.length(); 00704 circle_center.normalize(); 00705 circle_center /= radius; 00706 } 00707 curvature = circle_center; 00708 00709 return CUBIT_SUCCESS; 00710 } 00711 00712 //====================================================================== 00713 // Function: length 00714 // Description: return length of an edge 00715 // Author: sjowen 00716 // Date: 2/01 00717 //====================================================================== 00718 double CubitFacetEdge::length() 00719 { 00720 CubitVector start = point(0)->coordinates(); 00721 CubitVector end = point(1)->coordinates(); 00722 return start.distance_between( end ); 00723 } 00724 00725 //====================================================================== 00726 // Function: length 00727 // Description: return length of an edge 00728 // Author: jakraft 00729 // Date: 3/04 00730 //====================================================================== 00731 CubitVector CubitFacetEdge::position_from_fraction( double f ) 00732 { 00733 return (1.0 - f) * point(0)->coordinates() + 00734 f * point(1)->coordinates(); 00735 } 00736 00737 //====================================================================== 00738 // Function: other_point 00739 // Description: return the other point on the edge 00740 // Author: sjowen 00741 // Date: 4/01 00742 //====================================================================== 00743 CubitPoint* CubitFacetEdge::other_point( CubitPoint *point_ptr ) 00744 { 00745 if (point(0) == point_ptr) 00746 return point(1); 00747 if(point(1) == point_ptr) 00748 return point(0); 00749 return NULL; 00750 } 00751 00752 //====================================================================== 00753 // Function: get_parents 00754 // Description: return entities attached to this edge 00755 // Author: sjowen 00756 // Date: 4/01 00757 //====================================================================== 00758 void CubitFacetEdge::get_parents(DLIList<FacetEntity *> &facet_list) 00759 { 00760 DLIList<CubitFacet *> cf_list; 00761 facets( cf_list ); 00762 for (int ii=0; ii<cf_list.size(); ii++) 00763 facet_list.append(cf_list.get_and_step()); 00764 } 00765 00766 //====================================================================== 00767 // Function: other_facet 00768 // Description: return the other facet on the edge (assumes 00769 // max two facets per edge) 00770 // Author: sjowen 00771 // Date: 5/01 00772 //====================================================================== 00773 CubitFacet *CubitFacetEdge::other_facet( CubitFacet *facet_ptr ) 00774 { 00775 DLIList<CubitFacet *> cf_list; 00776 facets( cf_list ); 00777 assert(cf_list.size() < 3); 00778 CubitFacet *adj_facet = NULL; 00779 if (cf_list.size() > 0) 00780 { 00781 adj_facet = cf_list.get_and_step(); 00782 if (adj_facet == facet_ptr) 00783 { 00784 if (cf_list.size() == 2) 00785 { 00786 adj_facet = cf_list.get(); 00787 } 00788 } 00789 } 00790 return adj_facet; 00791 } 00792 00793 //====================================================================== 00794 // Function: other_facet_on_surf 00795 // Description: return the other facet on the edge that has the 00796 // same tool id. (finds the first occurrence 00797 // of the same tool id of the adjacent facets 00798 // to this edge that is not facet_ptr) 00799 // Author: sjowen 00800 // Date: 5/01 00801 //====================================================================== 00802 CubitFacet *CubitFacetEdge::other_facet_on_surf( CubitFacet *facet_ptr ) 00803 { 00804 assert(facet_ptr != 0); 00805 int tool_id = facet_ptr->tool_id(); 00806 DLIList<CubitFacet *> cf_list; 00807 facets( cf_list ); 00808 CubitFacet *adj_facet = NULL; 00809 int found = 0; 00810 for (int ii=0; ii<cf_list.size() && !found; ii++) 00811 { 00812 adj_facet = cf_list.get_and_step(); 00813 if (adj_facet != facet_ptr) 00814 { 00815 if (adj_facet->tool_id() == tool_id) 00816 found = 1; 00817 } 00818 } 00819 if (!found) 00820 adj_facet = NULL; 00821 return adj_facet; 00822 } 00823 00824 //====================================================================== 00825 // Function: num_adj_facets_on_surf 00826 // Description: count the number of adjacent facets to this edge that 00827 // have the specified tool id 00828 // Author: sjowen 00829 // Date: 5/01 00830 //====================================================================== 00831 int CubitFacetEdge::num_adj_facets_on_surf( int tool_id ) 00832 { 00833 00834 DLIList<CubitFacet *> cf_list; 00835 facets( cf_list ); 00836 CubitFacet *adj_facet = NULL; 00837 int nfacets = 0; 00838 for (int ii=0; ii<cf_list.size(); ii++) 00839 { 00840 adj_facet = cf_list.get_and_step(); 00841 if (adj_facet->tool_id() == tool_id) 00842 nfacets++; 00843 } 00844 return nfacets; 00845 } 00846 00847 //====================================================================== 00848 // Function: adj_facet_on_surf 00849 // Description: return the first facet on the adjacent facet list with 00850 // the indicated tool id 00851 // Author: sjowen 00852 // Date: 5/01 00853 //====================================================================== 00854 CubitFacet *CubitFacetEdge::adj_facet_on_surf( int tool_id ) 00855 { 00856 DLIList<CubitFacet *> cf_list; 00857 facets( cf_list ); 00858 CubitFacet *adj_facet = NULL; 00859 int found = 0; 00860 for (int ii=0; ii<cf_list.size() && !found; ii++) 00861 { 00862 adj_facet = cf_list.get_and_step(); 00863 if (adj_facet->tool_id() == tool_id) 00864 { 00865 found = 1; 00866 } 00867 } 00868 if (!found) 00869 adj_facet = NULL; 00870 return adj_facet; 00871 } 00872 00873 //====================================================================== 00874 // Function: contains 00875 // Description: determines if point is contained in edge 00876 // Author: sjowen 00877 // Date: 5/01 00878 //====================================================================== 00879 CubitBoolean CubitFacetEdge::contains( CubitPoint *point_ptr ) 00880 { 00881 if (point(0) == point_ptr || point(1) == point_ptr) 00882 return CUBIT_TRUE; 00883 return CUBIT_FALSE; 00884 } 00885 00886 //====================================================================== 00887 // Function: draw 00888 // Description: draw the edge 00889 // Author: sjowen 00890 // Date: 5/01 00891 //====================================================================== 00892 void CubitFacetEdge::debug_draw(int color, int flush, int /*draw_uv*/) 00893 { 00894 if ( color == -1 ) 00895 color = CUBIT_RED_INDEX; 00896 GfxDebug::draw_facet_edge(this, color); 00897 GfxDebug::draw_point( point(0)->coordinates(), color ); 00898 GfxDebug::draw_point( point(1)->coordinates(), color ); 00899 if ( flush ) 00900 GfxDebug::flush(); 00901 } 00902 00903 //====================================================================== 00904 // Function: shared_point (PUBLIC) 00905 // Description: find the common point 00906 // Author: sjowen 00907 // Date: 10/02 00908 //====================================================================== 00909 CubitPoint *CubitFacetEdge::shared_point( CubitFacetEdge *edge_ptr ) 00910 { 00911 CubitPoint *pA = this->point(0); 00912 CubitPoint *pB = this->point(1); 00913 CubitPoint *pC = edge_ptr->point(0); 00914 CubitPoint *pD = edge_ptr->point(1); 00915 CubitPoint *pShared = NULL; 00916 if (pA == pC || pA == pD) 00917 { 00918 pShared = pA; 00919 } 00920 else if (pB == pC || pB == pD) 00921 { 00922 pShared = pB; 00923 } 00924 return pShared; 00925 } 00926 00927 00928 //====================================================================== 00929 // Function: bounding_box (PUBLIC) 00930 // Description: return the bounding box of the edge 00931 // Author: sjowen 00932 // Date: 10/02 00933 //====================================================================== 00934 CubitBox CubitFacetEdge::bounding_box( ) 00935 { 00936 CubitPoint *p1 = point (0); 00937 CubitPoint *p2 = point (1); 00938 00939 CubitVector bbox_min, bbox_max; 00940 bbox_min.x(CUBIT_MIN(p1->x(),p2->x())); 00941 bbox_min.y(CUBIT_MIN(p1->y(),p2->y())); 00942 bbox_min.z(CUBIT_MIN(p1->z(),p2->z())); 00943 bbox_max.x(CUBIT_MAX(p1->x(),p2->x())); 00944 bbox_max.y(CUBIT_MAX(p1->y(),p2->y())); 00945 bbox_max.z(CUBIT_MAX(p1->z(),p2->z())); 00946 CubitBox edge_box(bbox_min,bbox_max); 00947 return edge_box; 00948 } 00949 00950 //====================================================================== 00951 // 00952 // The following 2 function really belong in IntersectionTool in the util 00953 // directory. Because of the current distribution policy it was not easy 00954 // to get it into there without breaking the build. These should be 00955 // removed at a later time and integrated with the IntersectionTool 00956 // 00957 //======================================================================= 00958 // Intersection of two line segments in 2D. Intersect [P0,P1] with [P2,P3] 00959 // Return value is zero if there is no intersection, 1 if there is a unique 00960 // intersection, and 2 if the 2 segments overlap and the intersection set is 00961 // a segment itself. The return value is the number of valid entries*2 in 00962 // the array qq. 00963 int CubitFacetEdge::intersect_2D_segments( double P0[2], double P1[2], 00964 double P2[2], double P3[2], 00965 double qq[4] ) 00966 { 00967 00968 double D0[2], D1[2]; 00969 D0[0] = P1[0] - P0[0]; D0[1] = P1[1] - P0[1]; 00970 D1[0] = P3[0] - P2[0]; D1[1] = P3[1] - P2[1]; 00971 00972 // segments P0 + s * D0 for s in [0,1], 00973 // P2 + t * D1 for t in [0,1] 00974 00975 double sqr_epsilon = DBL_EPSILON * DBL_EPSILON; 00976 double E[2]; 00977 E[0] = P2[0] - P0[0]; 00978 E[1] = P2[1] - P0[1]; 00979 00980 double kross = D0[0] * D1[1] - D0[1] * D1[0]; 00981 double sqr_kross = kross * kross; 00982 double sqr_len0 = D0[0] * D0[0] + D0[1] * D0[1]; 00983 double sqr_len1 = D1[0] * D1[0] + D1[1] * D1[1]; 00984 if (sqr_kross > sqr_epsilon * sqr_len0 * sqr_len1) 00985 { 00986 // lines of the segment are not parallel 00987 00988 double s = (E[0] * D1[1] - E[1] * D1[0]) / kross; 00989 if (s < 0.0 || s > 1.0) 00990 { 00991 // intersection of lines is not a point on segment P0 + s * D0 00992 return 0; 00993 } 00994 00995 double t = (E[0] * D0[1] - E[1] * D0[0]) / kross; 00996 if (t < 0.0 || t > 1.0) 00997 { 00998 // intersection of lines is not a point on segment P1 + t * D1 00999 return 0; 01000 } 01001 01002 // intersection of lines is a point on each segment 01003 01004 qq[0] = P0[0] + s * D0[0]; 01005 qq[1] = P0[1] + s * D0[1]; 01006 return 1; 01007 } 01008 01009 // lines of the segments are parallel 01010 01011 double sqr_lenE = E[0] * E[0] + E[1] * E[1]; 01012 kross = E[0] * D0[1] - E[1] * D0[1]; 01013 sqr_kross = kross * kross; 01014 if (sqr_kross > sqr_epsilon * sqr_len0 * sqr_lenE) 01015 { 01016 // lines of the segments are different 01017 return 0; 01018 } 01019 01020 // lines of the segment are the same. Need to test for overlap of segments 01021 01022 double s0 = (D0[0] * E[0] + D0[1] * E[1]) / sqr_len0; 01023 double s1 = s0 + (D0[0] * D1[0] + D0[1] * D1[1]) / sqr_len0; 01024 double smin = CUBIT_MIN(s0, s1); 01025 double smax = CUBIT_MAX(s0, s1); 01026 01027 double w[2]; 01028 int imax = intersect_intervals(0.0, 1.0, smin, smax, w); 01029 for (int i=0; i<imax; i++) 01030 { 01031 qq[i*2] = P0[0] + w[i] * D0[0]; 01032 qq[i*2+1] = P0[1] + w[i] * D0[1]; 01033 } 01034 return imax; 01035 } 01036 01037 // The intersection of two intervals [u0,u1] and [v0,v1], where u0<u1 and v0<v1. 01038 // Return value is zero if intervals do not intersect; 1 if they intersect at 01039 // a single point, in which case w[0] contains that point; or 2 if they intersect 01040 // in an interval whose endpoints are stored in w[0] and w[1] 01041 int CubitFacetEdge::intersect_intervals( double u0, double u1, 01042 double v0, double v1, 01043 double w[2] ) 01044 { 01045 if (u1 < v0 || u0 > v1) 01046 return 0; 01047 01048 if (u1 > v0) 01049 { 01050 if (u0 < v1) 01051 { 01052 if (u0 < v0) 01053 w[0] = v0; 01054 else 01055 w[0] = u0; 01056 if (u1 > v1) 01057 w[1] = v1; 01058 else 01059 w[1] = u1; 01060 return 2; 01061 } 01062 else 01063 { 01064 w[0] = u0; 01065 return 1; 01066 } 01067 } 01068 else 01069 { 01070 w[0] = u1; 01071 return 1; 01072 } 01073 return 0; 01074 } 01075 01076 //====================================================================== 01077 // Function: add_facets (PUBLIC) 01078 // Description: add this edge to its adjacent facets 01079 // Author: sjowen 01080 // Date: 04/04 01081 //====================================================================== 01082 void CubitFacetEdge::add_facets( ) 01083 { 01084 CubitPoint *p0 = point (0); 01085 CubitPoint *p1 = point (1); 01086 01087 DLIList<CubitFacet *> adj_facets; 01088 p0->shared_facets(p1, adj_facets ); 01089 01090 CubitFacet *facet; 01091 int ii; 01092 for(ii=0; ii<adj_facets.size(); ii++) 01093 { 01094 facet = adj_facets.get_and_step(); 01095 facet->add_edge( this ); 01096 } 01097 } 01098 01099 double CubitFacetEdge::angle_between_facets() 01100 { 01101 CubitFacet *facet0 = adj_facet(0); 01102 CubitFacet *facet1 = adj_facet(1); 01103 01104 // assumes facets are always oriented with outwards pointing normal 01105 01106 CubitVector n0 = facet0->normal(); 01107 CubitVector n1 = facet1->normal(); 01108 01109 // get orientation of edge with respect to facet0 01110 01111 CubitPoint *p0 = point(0); 01112 CubitPoint *p1 = point(1); 01113 CubitPoint *pnext = facet0->next_node(p0); 01114 if (pnext != p1) 01115 { 01116 pnext = p0; 01117 p0 = p1; 01118 p1 = pnext; 01119 } 01120 CubitVector evec = p1->coordinates() - p0->coordinates(); 01121 evec.normalize(); 01122 CubitVector cross = n0 * n1; cross.normalize(); 01123 double angle; 01124 double edot = evec % cross; 01125 double ndot = n0 % n1; 01126 if (ndot >= 1.0) 01127 angle = 0.0; 01128 else if (ndot <= -1.0) 01129 angle = CUBIT_PI; 01130 else 01131 angle = acos(ndot); 01132 if (edot <= 0.0) 01133 { 01134 angle = 2.0 * CUBIT_PI - angle; 01135 } 01136 return angle; 01137 } 01138 01139 // order edges in list beginning at start_point 01140 // report the endpoint 01141 // return CUBIT_SUCCESS if all edges are connected and ordered successfully 01142 // otherwise return CUBIT_FAILURE, in which case no changes are made 01143 CubitStatus CubitFacetEdge::order_edge_list(DLIList<CubitFacetEdge*> &edge_list, 01144 CubitPoint *start_point, 01145 CubitPoint *&end_point) 01146 { 01147 int i; 01148 assert(start_point); 01149 01150 end_point = NULL; 01151 01152 // invalid input 01153 if (0 == edge_list.size()) 01154 return CUBIT_FAILURE; 01155 01156 // simple case of a single edge - endpoitn 01157 if (1 == edge_list.size()) 01158 { 01159 end_point = edge_list.get()->other_point(start_point); 01160 return end_point ? CUBIT_SUCCESS : CUBIT_FAILURE; 01161 } 01162 01163 edge_list.reset(); 01164 01165 // note that a periodic/closed curve will fail 01166 // we could handle that case here if needed, but we may need more information 01167 // to know where to start and end the curve 01168 if (NULL == start_point) 01169 return CUBIT_FAILURE; 01170 01171 // put edges in a set for faster searching 01172 std::set<CubitFacetEdge *> edge_set; 01173 for (i=0; i<edge_list.size(); i++) 01174 edge_set.insert(dynamic_cast<CubitFacetEdge*> (edge_list.step_and_get())); 01175 01176 // a vector for the ordered list 01177 std::vector<CubitFacetEdge*> ordered_edges; 01178 01179 // find connected edges from the start point 01180 CubitPoint *cur_pt = start_point; 01181 do 01182 { 01183 // get edges connected to the current point and find the next edge 01184 DLIList<CubitFacetEdge *> pt_edges; 01185 cur_pt->edges(pt_edges); 01186 01187 std::set<CubitFacetEdge *>::iterator iter_found; 01188 CubitFacetEdge *cur_edge = NULL; 01189 for (i=0; i<pt_edges.size() && !cur_edge; i++) 01190 { 01191 CubitFacetEdge *tmp_edge = pt_edges.get_and_step(); 01192 iter_found = edge_set.find(tmp_edge); 01193 if ( iter_found != edge_set.end() ) 01194 cur_edge = tmp_edge; 01195 } 01196 01197 // if we don't find a connection before we empty the set 01198 // then not all the edges are connected -- return failure 01199 if (NULL == cur_edge) 01200 return CUBIT_FAILURE; 01201 01202 // add the edge to the ordered list 01203 ordered_edges.push_back( cur_edge ); 01204 edge_set.erase(iter_found); 01205 01206 cur_pt = cur_edge->other_point(cur_pt); 01207 } 01208 while ( edge_set.size()); 01209 01210 if (ordered_edges.size() != (size_t)edge_list.size()) 01211 return CUBIT_FAILURE; 01212 01213 // store the edges in the correct order 01214 edge_list.clean_out(); 01215 01216 std::vector<CubitFacetEdge*>::iterator iter; 01217 for (iter=ordered_edges.begin(); iter!=ordered_edges.end(); iter++) 01218 edge_list.append(*iter); 01219 01220 // get the end point 01221 CubitFacetEdge *edge1 = edge_list[edge_list.size() - 1]; 01222 CubitFacetEdge *edge2 = edge_list[edge_list.size() - 2]; 01223 01224 end_point = edge1->other_point( edge1->shared_point(edge2) ); 01225 01226 return CUBIT_SUCCESS; 01227 } 01228 01229 CubitPoint *CubitFacetEdge::find_start_point_for_edge_list(DLIList<CubitFacetEdge*> edge_list) 01230 { 01231 // look for an edge with a point only connected to the one edge in the set 01232 // 01233 // TODO - this algorithm could be made more efficient by only checking one endpoint 01234 // per edge. The current implementation should match the order points were 01235 // checked in previous functionality. 01236 // If speed becomes an issue it could be reimplemented 01237 // 01238 01239 if (1 == edge_list.size()) 01240 { 01241 return edge_list[0]->point(0); 01242 } 01243 01244 int i; 01245 CubitPoint *start_point = NULL; 01246 for (i=0; i<edge_list.size() && (start_point == NULL); i++) 01247 { 01248 CubitFacetEdge *tmp_edge = edge_list.get_and_step(); 01249 DLIList<CubitFacetEdge*> pt_edges; 01250 tmp_edge->point(0)->edges(pt_edges); 01251 01252 pt_edges.intersect_unordered(edge_list); 01253 if (pt_edges.size() == 1) 01254 { 01255 start_point = tmp_edge->point(0); 01256 } 01257 else 01258 { 01259 pt_edges.clean_out(); 01260 tmp_edge->point(1)->edges(pt_edges); 01261 pt_edges.intersect_unordered(edge_list); 01262 if (pt_edges.size() == 1) 01263 { 01264 start_point = tmp_edge->point(1); 01265 } 01266 } 01267 } 01268 return start_point; 01269 } 01270 01271 //EOF