cgma
|
00001 #include "SubCurve.hpp" 00002 #include "GMem.hpp" 00003 #include "GeometryQueryEngine.hpp" 00004 00005 PartitionCurve* SubCurve::split( double param ) 00006 { 00007 if( startParam <= endParam ) 00008 { 00009 if( (param <= startParam) || (param >= endParam) ) 00010 return 0; 00011 } 00012 else if( (param >= startParam) || (param <= endParam) ) 00013 return 0; 00014 00015 return new SubCurve( this, param ); 00016 } 00017 00018 CubitStatus SubCurve::combine( PartitionCurve* dead_curve ) 00019 { 00020 SubCurve* curve = dynamic_cast<SubCurve*>(dead_curve); 00021 if( !curve || curve->real_curve() != this->real_curve() ) 00022 return CUBIT_FAILURE; 00023 00024 double dse = fabs(start_param() - dead_curve->end_param()); 00025 double des = fabs(end_param() - dead_curve->start_param()); 00026 00027 if( des <= dse ) 00028 endParam = curve->endParam; 00029 else 00030 startParam = curve->startParam; 00031 00032 return CUBIT_SUCCESS; 00033 } 00034 00035 00036 00037 00038 SubCurve::SubCurve( Curve* curve_ptr ) 00039 { 00040 assert( dynamic_cast<SubEntitySet*>(curve_ptr->owner()) == 0 ); 00041 new SubEntitySet( curve_ptr, this ); 00042 00043 00044 startParam = curve_ptr->start_param(); 00045 endParam = curve_ptr->end_param(); 00046 00047 double period; 00048 if( fabs( startParam - endParam ) < CUBIT_RESABS ) 00049 { 00050 if( ! curve_ptr->is_periodic( period ) ) 00051 { 00052 assert( 0 ); 00053 } 00054 endParam = startParam + period ; 00055 } 00056 00057 if( curve_ptr->bridge_sense() != this->bridge_sense() ) 00058 reverse_bridge_sense(); 00059 } 00060 00061 SubCurve::SubCurve( SubCurve* split_from, double start ) 00062 { 00063 split_from->sub_entity_set().add_partition( this, split_from ); 00064 00065 endParam = split_from->endParam; 00066 startParam = split_from->endParam = start; 00067 00068 if( CUBIT_REVERSED == split_from->bridge_sense() ) 00069 this->reverse_bridge_sense(); 00070 } 00071 00072 SubCurve::~SubCurve() 00073 { 00074 } 00075 00076 int SubCurve::num_partitions() const 00077 { 00078 DLIList<TopologyBridge*> tmp; 00079 get_all_partitions( tmp ); 00080 return tmp.size(); 00081 } 00082 00083 void SubCurve::get_all_partitions( DLIList<TopologyBridge*>& curves ) const 00084 { 00085 sub_entity_set().get_owners(curves); 00086 } 00087 00088 CubitBox SubCurve::bounding_box() const 00089 { 00090 /* 00091 CubitVector start, end; 00092 SubCurve* me = (SubCurve*)this; 00093 me->position_from_u( me->start_param(), start ); 00094 me->position_from_u( me-> end_param(), end ); 00095 CubitBox box( start, end ); 00096 00097 DLIList<CubitVector*> extrema; 00098 CubitSense sense; 00099 me->get_interior_extrema( extrema, sense ); 00100 if( sense == CUBIT_REVERSED ) 00101 extrema.reverse(); 00102 while( extrema.size() ) 00103 { 00104 CubitVector* v = extrema.pop(); 00105 box |= *v; 00106 delete v; 00107 } 00108 */ 00109 return dynamic_cast<Curve*>(partitioned_entity())->bounding_box(); 00110 } 00111 00112 double SubCurve::measure() 00113 { 00114 return fabs(real_curve()->length_from_u( startParam, endParam )); 00115 } 00116 00117 GeometryType SubCurve::geometry_type() 00118 { 00119 return real_curve()->geometry_type(); 00120 } 00121 00122 CubitStatus SubCurve::closest_point( const CubitVector& from, 00123 CubitVector& closest, 00124 CubitVector* tangent, 00125 CubitVector* curvature, 00126 double* param ) 00127 { 00128 double u; 00129 CubitStatus result = 00130 real_curve()->closest_point( from, closest, tangent, curvature, &u ); 00131 if( param ) 00132 *param = u; 00133 00134 // Snap position to the ends of the SubCurve if 00135 // necessary. 00136 if(result) 00137 { 00138 double lower, upper; 00139 double period; 00140 00141 // If curve is periodic we first need to see if our location 00142 // can be mapped to the subcurve range just by adding or 00143 // subtracting multiples of the period. If no then we 00144 // will snap it to one of the ends. 00145 int is_per = is_periodic(period); 00146 00147 // Get the param range of the SubCurve (will probably 00148 // be different from that of the underlying real curve). 00149 get_ordered_param_range(lower, upper); 00150 00151 // If we are past the low end... 00152 if(u < lower) 00153 { 00154 // Adjust for periodic curve. 00155 if(is_per) 00156 { 00157 double tmp_u = u; 00158 while(tmp_u < upper + GEOMETRY_RESABS) 00159 { 00160 tmp_u += period; 00161 if(tmp_u > lower - GEOMETRY_RESABS && 00162 tmp_u < upper + GEOMETRY_RESABS) 00163 { 00164 u = tmp_u; 00165 } 00166 } 00167 } 00168 // If the value of u was not adjusted because 00169 // of a periodic curve go ahead and snap to 00170 // the lower bound. 00171 if(u < lower) 00172 { 00173 u = lower; 00174 } 00175 // Update the position we will return. 00176 position_from_u(u, closest); 00177 } 00178 // If we are past the high end... 00179 else if(u > upper) 00180 { 00181 // Adjust for periodic curve. 00182 if(is_per) 00183 { 00184 double tmp_u = u; 00185 while(tmp_u > upper - GEOMETRY_RESABS) 00186 { 00187 tmp_u -= period; 00188 if(tmp_u > lower - GEOMETRY_RESABS && 00189 tmp_u < upper + GEOMETRY_RESABS) 00190 { 00191 u = tmp_u; 00192 } 00193 } 00194 } 00195 // If the value of u was not adjusted because 00196 // of a periodic curve go ahead and snap to 00197 // the upper bound. 00198 if(u > upper) 00199 { 00200 u = upper; 00201 } 00202 // Update the position we will return. 00203 position_from_u(u, closest); 00204 } 00205 } 00206 00207 if( result && tangent ) 00208 { 00209 CubitVector start, end; 00210 if( !position_from_u( start_param(), start ) || 00211 !position_from_u( end_param(), end ) ) 00212 return CUBIT_FAILURE; 00213 00214 double ds = (start - from).length_squared(); 00215 double de = (end - from).length_squared(); 00216 const double rsq = GEOMETRY_RESABS * GEOMETRY_RESABS; 00217 if( ds < rsq && G1_discontinuous( u, &end, &start ) ) 00218 *tangent = start; 00219 else if( de < rsq && G1_discontinuous( u, &end, &start ) ) 00220 *tangent = end; 00221 } 00222 00223 return result; 00224 } 00225 00226 CubitPointContainment SubCurve::point_containment( const CubitVector& point ) 00227 { 00228 CubitPointContainment cpc = real_curve()->point_containment( point ); 00229 if( (cpc == CUBIT_PNT_INSIDE) || (cpc == CUBIT_PNT_ON) || 00230 (cpc == CUBIT_PNT_BOUNDARY) ) 00231 { 00232 double u = real_curve()->u_from_position( point ); 00233 double lower, upper; 00234 get_ordered_param_range( lower, upper ); 00235 if( u < lower || u > upper ) 00236 cpc = CUBIT_PNT_OFF; 00237 } 00238 00239 if( (cpc == CUBIT_PNT_INSIDE) || (cpc == CUBIT_PNT_ON) ) 00240 { 00241 CubitVector start, end; 00242 position_from_u( start_param(), start ); 00243 position_from_u( end_param(), end ); 00244 if( (point-start).length_squared() < GEOMETRY_RESABS*GEOMETRY_RESABS || 00245 (point-end ).length_squared() < GEOMETRY_RESABS*GEOMETRY_RESABS ) 00246 { 00247 cpc = CUBIT_PNT_BOUNDARY; 00248 } 00249 } 00250 00251 return cpc; 00252 } 00253 00254 CubitBoolean SubCurve::is_position_on( const CubitVector& position ) 00255 { 00256 return real_curve()->is_position_on( position ); 00257 } 00258 00259 CubitBoolean SubCurve::G1_discontinuous( double param, 00260 CubitVector* minus_tan, 00261 CubitVector* plus_tan ) 00262 { 00263 double lower, upper; 00264 get_ordered_param_range( lower, upper ); 00265 if( param <= lower || param >= upper ) 00266 return CUBIT_FALSE; 00267 00268 CubitVector pos, start, end; 00269 if( !position_from_u( lower, start ) || 00270 !position_from_u( upper, end ) || 00271 !position_from_u( param, pos ) ) 00272 assert(0); 00273 00274 double ds = (pos - start).length_squared(); 00275 double de = (pos - end ).length_squared(); 00276 const double grs = GEOMETRY_RESABS * GEOMETRY_RESABS; 00277 if( ds < grs || de < grs ) 00278 return CUBIT_FALSE; 00279 00280 return real_curve()->G1_discontinuous( param, minus_tan, plus_tan ); 00281 } 00282 00283 CubitStatus SubCurve::get_interior_extrema( DLIList<CubitVector*>& points, 00284 CubitSense& sense ) 00285 { 00286 assert( !points.size() ); 00287 00288 double lower, upper; 00289 get_ordered_param_range( lower, upper ); 00290 00291 CubitVector start, end; 00292 if( ! real_curve()->position_from_u( lower, start ) || 00293 ! real_curve()->position_from_u( upper, end ) ) 00294 return CUBIT_FAILURE; 00295 00296 DLIList<CubitVector*> list; 00297 if( ! real_curve()->get_interior_extrema( list, sense ) ) 00298 return CUBIT_FAILURE; 00299 if( list.size() == 0 ) 00300 return CUBIT_SUCCESS; 00301 00302 list.last(); 00303 double param = real_curve()->u_from_position( *list.get() ); 00304 while( (param <= lower) || (param >= upper) ) 00305 { 00306 delete list.pop(); 00307 if( list.size() == 0 ) 00308 return CUBIT_SUCCESS; 00309 list.last(); 00310 param = real_curve()->u_from_position( *list.get() ); 00311 } 00312 00313 double ds = (*list.get() - start).length_squared(); 00314 double de = (*list.get() = end ).length_squared(); 00315 const double grs = GEOMETRY_RESABS * GEOMETRY_RESABS; 00316 if( ds < grs || de < grs ) 00317 { 00318 delete list.pop(); 00319 if( list.size() == 0 ) 00320 return CUBIT_SUCCESS; 00321 list.last(); 00322 param = real_curve()->u_from_position( *list.get() ); 00323 } 00324 00325 while( (param > lower) && (param < upper) ) 00326 { 00327 points.append( list.pop() ); 00328 if( list.size() == 0 ) 00329 break; 00330 list.last(); 00331 param = real_curve()->u_from_position( *list.get() ); 00332 } 00333 00334 while( list.size() ) 00335 delete list.pop(); 00336 00337 if( sense == CUBIT_FORWARD ) 00338 sense = CUBIT_REVERSED; 00339 else if( sense == CUBIT_REVERSED ) 00340 sense = CUBIT_FORWARD; 00341 00342 return CUBIT_SUCCESS; 00343 } 00344 00345 CubitStatus SubCurve::get_center_radius( CubitVector& center, double& radius ) 00346 { return real_curve()->get_center_radius(center,radius); } 00347 00348 00349 CubitBoolean SubCurve::get_param_range( double& lower, double& upper ) 00350 { 00351 lower = startParam; 00352 upper = endParam; 00353 return CUBIT_TRUE; 00354 } 00355 00356 CubitBoolean SubCurve::get_ordered_param_range( double& lower, double& upper ) 00357 { 00358 if( startParam < endParam ) 00359 { 00360 lower = startParam; 00361 upper = endParam; 00362 } 00363 else 00364 { 00365 lower = endParam; 00366 upper = startParam; 00367 } 00368 return CUBIT_TRUE; 00369 } 00370 00371 double SubCurve::start_param() 00372 { return startParam; } 00373 double SubCurve::end_param() 00374 { return endParam; } 00375 00376 CubitBoolean SubCurve::is_periodic( double& period ) 00377 { 00378 return real_curve()->is_periodic( period ); 00379 } 00380 00381 double SubCurve::length_from_u( double u1, double u2 ) 00382 { 00383 return real_curve()->length_from_u( u1, u2 ); 00384 } 00385 00386 double SubCurve::u_from_position( const CubitVector& p ) 00387 { 00388 double result = real_curve()->u_from_position( p ); 00389 fixup_periodic_param(result); 00390 return result; 00391 } 00392 00393 CubitStatus SubCurve::position_from_u( double u, CubitVector& p ) 00394 { 00395 return real_curve()->position_from_u( u, p ); 00396 } 00397 00398 double SubCurve::u_from_arc_length( double root, double length ) 00399 { 00400 return real_curve()->u_from_arc_length( root, length ); 00401 } 00402 00403 void SubCurve::fixup_periodic_param( double& param ) const 00404 { 00405 double period; 00406 if( ! real_curve()->is_periodic(period) ) 00407 return; 00408 00409 assert(period > GEOMETRY_RESABS); 00410 double start, end; 00411 if ( startParam < endParam ) { 00412 start = startParam; 00413 end = endParam; 00414 } else { 00415 start = endParam; 00416 end = startParam; 00417 } 00418 00419 if( fabs( start-param ) < GEOMETRY_RESABS ) 00420 param = start; 00421 if( fabs( end-param ) < GEOMETRY_RESABS ) 00422 param = end; 00423 00424 while ( param > end ) 00425 param -= period; 00426 while ( param < start ) 00427 param += period; 00428 } 00429 00430 CubitStatus SubCurve::get_graphics( GMem& result, 00431 double angle_tolerance, 00432 double distance_tolerance, 00433 double max_edge_length ) 00434 { 00435 if (POINT_CURVE_TYPE == this->geometry_type()) 00436 { 00437 result.pointListCount = 0; 00438 return CUBIT_SUCCESS; 00439 } 00440 00441 int i; 00442 if( !real_curve()->get_geometry_query_engine()-> 00443 get_graphics( real_curve(), &result, angle_tolerance, distance_tolerance, max_edge_length ) ) 00444 return CUBIT_FAILURE; 00445 00446 if (0 == result.pointListCount) 00447 return CUBIT_FAILURE; 00448 00449 double lo, hi, start_param, end_param; 00450 get_ordered_param_range( lo, hi ); 00451 get_param_range(start_param, end_param); 00452 DLIList<double> param_list( result.pointListCount ); 00453 00454 // don't use first and last points -- this avoids projection 00455 // close to a seam on a periodic curve. The projection can 00456 // jump the seam and cause endpoints of the curve to incorrectly 00457 // fall inside the parameter range causing extra segments to be drawn 00458 for( i = 1; i < result.pointListCount-1; i++ ) 00459 { 00460 CubitVector v( result.point_list()[i].x, 00461 result.point_list()[i].y, 00462 result.point_list()[i].z ); 00463 double u = real_curve()->u_from_position( v ); 00464 if( (u >= lo) && (u <= hi) ) 00465 param_list.append( u ); 00466 } 00467 00468 CubitVector start_pt, end_pt; 00469 position_from_u( start_param, start_pt ); 00470 position_from_u( end_param, end_pt ); 00471 00472 bool append_start = true, append_end = true; 00473 if( param_list.size() > 0 ) 00474 { 00475 CubitVector first_pt, last_pt; 00476 param_list.last(); 00477 position_from_u( param_list.get(), last_pt ); 00478 param_list.reset(); 00479 position_from_u( param_list.get(), first_pt ); 00480 00481 double d1 = (start_pt - first_pt).length_squared(); 00482 double d2 = (start_pt - last_pt ).length_squared(); 00483 double d4 = ( end_pt - first_pt).length_squared(); 00484 double d3 = ( end_pt - last_pt ).length_squared(); 00485 double forward = d1 + d3; 00486 double reverse = d2 + d4; 00487 if( reverse < forward ) 00488 { 00489 CubitVector tmp( start_pt ); 00490 start_pt = end_pt; 00491 end_pt = tmp; 00492 d1 = d2; 00493 d3 = d4; 00494 } 00495 00496 if( d1 < (GEOMETRY_RESABS*GEOMETRY_RESABS) ) 00497 append_start = false; 00498 if( d3 < (GEOMETRY_RESABS*GEOMETRY_RESABS) ) 00499 append_end = false; 00500 } 00501 00502 int index = 0; 00503 result.allocate_polylines( param_list.size() + 1 ); 00504 00505 if( append_start ) 00506 { 00507 result.point_list()[index].x = (float)(start_pt.x()); 00508 result.point_list()[index].y = (float)(start_pt.y()); 00509 result.point_list()[index].z = (float)(start_pt.z()); 00510 index++; 00511 } 00512 00513 param_list.reset(); 00514 CubitVector position; 00515 for( i = param_list.size(); i--; ) 00516 { 00517 position_from_u( param_list.get_and_step(), position ); 00518 result.point_list()[index].x = (float)(position.x()); 00519 result.point_list()[index].y = (float)(position.y()); 00520 result.point_list()[index].z = (float)(position.z()); 00521 index++; 00522 } 00523 00524 if( append_end ) 00525 { 00526 result.point_list()[index].x = (float)(end_pt.x()); 00527 result.point_list()[index].y = (float)(end_pt.y()); 00528 result.point_list()[index].z = (float)(end_pt.z()); 00529 index++; 00530 } 00531 00532 result.pointListCount = index; 00533 return CUBIT_SUCCESS; 00534 } 00535 00536 00537 void SubCurve::reverse_sense() 00538 { 00539 reverse_point_order(); 00540 if( owner() ) 00541 owner()->notify_reversed(this); 00542 } 00543 00544 CubitStatus SubCurve::save( CubitSimpleAttrib& attrib ) 00545 { 00546 int id = sub_entity_set().get_id(this); 00547 if( id <= 0 ) return CUBIT_FAILURE; 00548 00549 DLIList<int> end_points(4); 00550 get_save_topology(end_points); 00551 00552 return sub_entity_set().save_geometry( id, 1, 0, 0, &end_points, 0, attrib ); 00553 } 00554 00555 CubitStatus SubCurve::get_spline_params 00556 ( 00557 bool &rational, // return true/false 00558 int °ree, // the degree of this spline 00559 DLIList<CubitVector> &cntrl_pts, // xyz position of controlpoints 00560 DLIList<double> &cntrl_pt_weights, // if rational, a weight for each cntrl point. 00561 DLIList<double> &knots, // There should be order+cntrl_pts.size()-2 knots 00562 bool &spline_is_reversed 00563 ) const 00564 { 00565 PRINT_ERROR("Currently, Cubit is unable to determine spline parameters for SubCurves.\n"); 00566 return CUBIT_FAILURE; 00567 } 00568 00569 CubitStatus SubCurve::get_ellipse_params 00570 ( 00571 CubitVector ¢er_vec, 00572 CubitVector &normal, 00573 CubitVector &major_axis, 00574 double &radius_ratio 00575 ) const 00576 { 00577 PRINT_ERROR("Currently, Cubit is unable to determine ellipse parameters for SubCurves.\n"); 00578 return CUBIT_FAILURE; 00579 }