cgma
|
00001 //------------------------------------------------------------------------- 00002 // Filename : SegmentedCurve.cc 00003 // 00004 // Purpose : 00005 // 00006 // Special Notes : The parameterization of this is defined such that the 00007 // parameter range between two adjacent nodes is one. 00008 // 00009 // Creator : Jason Kraftcheck 00010 // 00011 // Creation Date : 06/10/98 00012 //------------------------------------------------------------------------- 00013 00014 #include "SegmentedCurve.hpp" 00015 00016 #include "PartitionPoint.hpp" 00017 #include "PartitionCoEdge.hpp" 00018 #include "PartitionSurface.hpp" 00019 #include "PartitionLump.hpp" 00020 #include "GMem.hpp" 00021 #include "PartitionEngine.hpp" 00022 #include "CubitTransformMatrix.hpp" 00023 #include "CubitMessage.hpp" 00024 00025 int SegmentedCurve::segment_from_u( double& param ) 00026 { 00027 if( is_periodic() ) 00028 normalize_periodic_parameter( param ); 00029 00030 int num_segments = point_count() - 1; 00031 if( param < -CUBIT_RESABS || 00032 param > (num_segments + CUBIT_RESABS) ) 00033 return -1; 00034 00035 // Could call trunc() here, but why? Need to cast to an 00036 // int anyway. Also, the cast to int should be save 00037 // because the magnitude of param is tested above. 00038 int segment_index = (int)param; 00039 if( segment_index == num_segments ) 00040 --segment_index; 00041 00042 param -= segment_index; 00043 return segment_index; 00044 } 00045 00046 PartitionCurve* SegmentedCurve::split( double param ) 00047 { 00048 int seg = segment_from_u(param); 00049 if( seg < 0 ) 00050 return 0; 00051 00052 CubitVector beg = position(seg); 00053 CubitVector end = position(seg+1); 00054 CubitVector pos = beg + param * (end - beg); 00055 00056 if( (pos - end).length_squared() < GEOMETRY_RESABS*GEOMETRY_RESABS ) 00057 { 00058 seg++; 00059 param = 0; 00060 beg = pos = end; 00061 00062 if( seg == point_count() - 1 ) 00063 return 0; 00064 } 00065 else if( (pos - beg).length_squared() < GEOMETRY_RESABS*GEOMETRY_RESABS ) 00066 { 00067 if( seg == 0 ) 00068 return 0; 00069 00070 pos = beg; 00071 param = 0; 00072 } 00073 00074 SegmentedCurve* new_curve = new SegmentedCurve( this, point_count() - seg ); 00075 00076 new_curve->point_list[0] = pos; 00077 for( int i = 1; i < new_curve->point_list.size(); i++ ) 00078 new_curve->point_list[i] = point_list[seg + i]; 00079 if( param == 0 ) 00080 { 00081 point_list.size( seg + 1 ); 00082 } 00083 else 00084 { 00085 point_list.size( seg + 2 ); 00086 point_list[seg+1] = pos; 00087 } 00088 00089 return new_curve; 00090 } 00091 00092 CubitStatus SegmentedCurve::combine( PartitionCurve* dead_curve ) 00093 { 00094 SegmentedCurve* dead = dynamic_cast<SegmentedCurve*>(dead_curve); 00095 if( !dead || dead->partitioned_entity() != this->partitioned_entity() ) 00096 return CUBIT_FAILURE; 00097 00098 CubitVector this_start = this->position(0); 00099 CubitVector dead_start = dead->position(0); 00100 CubitVector this_end = this->position( this->point_count() - 1 ); 00101 CubitVector dead_end = dead->position( dead->point_count() - 1 ); 00102 00103 int i; 00104 bool append, reverse; 00105 const double tol_sqr = GEOMETRY_RESABS * GEOMETRY_RESABS; 00106 if( (this_end - dead_start).length_squared() < tol_sqr ) 00107 { 00108 append = true; 00109 reverse = false; 00110 } 00111 else if( (this_end - dead_end).length_squared() < tol_sqr ) 00112 { 00113 append = true; 00114 reverse = true; 00115 } 00116 else if( (this_start - dead_end).length_squared() < tol_sqr ) 00117 { 00118 append = false; 00119 reverse = false; 00120 } 00121 else if( (this_start - dead_start).length_squared() < tol_sqr ) 00122 { 00123 append = false; 00124 reverse = true; 00125 } 00126 else 00127 { 00128 assert(0); 00129 return CUBIT_FAILURE; 00130 } 00131 00132 if( reverse ) 00133 dead->point_list.reverse(); 00134 00135 int this_point_count = this->point_list.size(); 00136 int dead_point_count = dead->point_list.size(); 00137 int new_point_count = this_point_count + dead_point_count - 1; 00138 this->point_list.size(new_point_count); 00139 00140 if( append ) 00141 { 00142 for( i = 1; i < dead_point_count; i++ ) 00143 point_list[this_point_count + i - 1] = dead->point_list[i]; 00144 } 00145 else 00146 { 00147 for( i = 1; i <= this_point_count; i++ ) 00148 point_list[new_point_count-i] = point_list[this_point_count-1]; 00149 00150 for( i = 0; i < dead_point_count; i++ ) 00151 this->point_list[i] = dead->point_list[i]; 00152 } 00153 00154 return CUBIT_SUCCESS; 00155 } 00156 00157 00158 00159 CubitBoolean SegmentedCurve::is_linear() 00160 { 00161 int i, count = point_count(); 00162 if( count == 2 ) return CUBIT_TRUE; 00163 if( is_periodic() ) return CUBIT_FALSE; 00164 00165 CubitVector mean(0.0,0.0,0.0); 00166 for( i = 1; i < count; i++ ) mean += (position(i)-position(i-1)); 00167 mean.normalize(); 00168 for( i = 1; i < count; i++ ) 00169 { 00170 if( (1-(mean % ~(position(i)-position(i-1)))) > CUBIT_RESABS ) 00171 return CUBIT_FALSE; 00172 } 00173 return CUBIT_TRUE; 00174 } 00175 00176 CubitStatus SegmentedCurve::get_point_direction( 00177 CubitVector& origin, CubitVector& direction ) 00178 { 00179 if( ! is_linear() ) return CUBIT_FAILURE; 00180 origin = position(0); 00181 direction = ~(position(point_count()-1) - origin); 00182 return CUBIT_SUCCESS; 00183 } 00184 00185 double SegmentedCurve::length_from_u( double param1, double param2 ) 00186 { 00187 if( param1 > param2 ) 00188 { 00189 double temp = param1; 00190 param1 = param2; 00191 param2 = temp; 00192 } 00193 00194 if( is_periodic() ) 00195 { 00196 normalize_periodic_parameter( param1 ); 00197 normalize_periodic_parameter( param2 ); 00198 } 00199 00200 int first = (int)floor( param1 ); 00201 int last = (int)floor( param2 ); 00202 int seg_count = point_count() - 1; 00203 00204 //check for errors, round a little 00205 if( first < 0 ) 00206 { 00207 if( param1 > -CUBIT_RESABS ) first = 0; 00208 else return -1.0; 00209 } 00210 if( last < 0 ) 00211 { 00212 if( param2 > -CUBIT_RESABS ) last = 0; 00213 else return -1.0; 00214 } 00215 if( last >= seg_count ) 00216 { 00217 if( param2 < (CUBIT_RESABS + seg_count) ) 00218 last--; 00219 else return -1.0; 00220 } 00221 if( first >= seg_count ) 00222 { 00223 if( param1 < (CUBIT_RESABS + seg_count) ) 00224 first--; 00225 else return -1.0; 00226 } 00227 00228 //calculate the remaining length on the first segment 00229 00230 double length_sum = segment_length( first ) * (1 - (param1 - first) ); 00231 00232 //add up the remaining segments upto and including last 00233 00234 for( int i = first + 1; i <= last; i++ ) 00235 length_sum += segment_length( i ); 00236 00237 // by including the last segment, we (may have) gone too far, 00238 // so subtract back off the extra on the last segment 00239 00240 length_sum -= segment_length(last) * (1 - (param2 - last) ); 00241 00242 return length_sum; 00243 00244 } 00245 00246 CubitBoolean SegmentedCurve::get_param_range( double& lower, double& upper ) 00247 { 00248 lower = 0.0; 00249 upper = double(point_count() - 1); 00250 return CUBIT_TRUE; 00251 } 00252 00253 CubitStatus SegmentedCurve::closest_point( 00254 CubitVector const& location, 00255 CubitVector& closest_location, 00256 CubitVector* tangent_ptr, 00257 CubitVector* curvature_ptr, 00258 double* param) 00259 { 00260 double seg_param; 00261 int segment_no = closest_segment( location, &seg_param, &closest_location ); 00262 00263 if ( Surface* surf = dynamic_cast<Surface*>(partitioned_entity()) ) 00264 { 00265 CubitVector seg_point(closest_location); 00266 surf->closest_point( seg_point, &closest_location ); 00267 } 00268 00269 if( tangent_ptr != NULL ) 00270 { 00271 //First check if the closest point is at the join of 00272 //two segments. If so, return the average of the two 00273 //tangets. 00274 if( (seg_param < CUBIT_RESABS) && (segment_no > 0) ) 00275 { 00276 CubitVector seg1_start = position( segment_no - 1 ); 00277 CubitVector seg2_end = position( segment_no + 1 ); 00278 *tangent_ptr = seg2_end - seg1_start; 00279 } 00280 00281 //ditto 00282 else if( ( (1.0 - seg_param) < CUBIT_RESABS ) && 00283 ( segment_no < (point_count() - 2) ) ) 00284 { 00285 CubitVector seg1_start = position( segment_no ); 00286 CubitVector seg2_end = position( segment_no + 2 ); 00287 *tangent_ptr = seg2_end - seg1_start; 00288 } 00289 00290 //The segment_no is the index of the point beginning the segment. 00291 //A segment_no equal to point_count() - 1, the last point is 00292 //possible. So, for any segment point but the last, return the 00293 //tangent of the segment beginning with the point at segment_no. 00294 else if( segment_no < point_count() - 1 ) 00295 { 00296 *tangent_ptr = this->position( segment_no + 1 ) 00297 - this->position( segment_no ); 00298 } 00299 00300 else if( segment_no == 0 ) 00301 { 00302 *tangent_ptr = this->position( segment_no + 1 ) 00303 - this->position( segment_no ); 00304 } 00305 00306 //If the point is the last one, return the direction of 00307 //the last segment (this point and the previous one.) 00308 else 00309 { 00310 *tangent_ptr = this->position( segment_no ) 00311 - this->position( segment_no - 1 ); 00312 } 00313 00314 tangent_ptr->normalize(); 00315 } 00316 00317 //There is never a valid curvature for a segmented curve. 00318 //The curvature is either infinity in the interior of segments, 00319 //or zero at the points between segments. Just return zero. 00320 if( curvature_ptr != NULL ) 00321 { 00322 curvature_ptr->set( 0., 0., 0. ); 00323 } 00324 00325 if (param) 00326 { 00327 *param = double(segment_no) + seg_param; 00328 } 00329 00330 return CUBIT_SUCCESS; 00331 } 00332 00333 CubitStatus SegmentedCurve::closest_point_trimmed( 00334 CubitVector const& from_pt, CubitVector& result_pt ) 00335 { 00336 return closest_point( from_pt, result_pt ); 00337 } 00338 00339 int SegmentedCurve::closest_segment( CubitVector const& location, 00340 double* seg_fraction, 00341 CubitVector* closest_pt ) 00342 { 00343 int length_ = point_count(); 00344 00345 int segment_no = 0; 00346 CubitVector start = position( 0 ); 00347 CubitVector end = position( 1 ); 00348 CubitVector dir = end - start; 00349 double seg_param = closest_point_on_segment( start, dir, location ); 00350 CubitVector point = start + seg_param * dir; 00351 if( closest_pt ) *closest_pt = point; 00352 double shortest = (point - location ).length_squared(); 00353 00354 for( int i = 2; i < length_; i++ ) 00355 { 00356 start = end; 00357 end = position( i ); 00358 dir = end - start; 00359 double param = closest_point_on_segment( start, dir, location ); 00360 point = start + param * dir; 00361 double dist = (point - location).length_squared(); 00362 if( dist < shortest ) 00363 { 00364 shortest = dist; 00365 if( closest_pt ) *closest_pt = point; 00366 segment_no = i - 1; 00367 seg_param = param; 00368 } 00369 } 00370 00371 if( seg_fraction ) *seg_fraction = seg_param; 00372 return segment_no; 00373 } 00374 00375 double SegmentedCurve::u_from_position( const CubitVector& position ) 00376 { 00377 double seg_param; 00378 int segment = closest_segment( position, &seg_param ); 00379 return double(segment) + seg_param; 00380 } 00381 00382 CubitStatus SegmentedCurve::position_from_u( double u, CubitVector& p) 00383 { 00384 double fraction = u; 00385 int segment_no = segment_from_u(fraction); 00386 if( segment_no < 0 ) 00387 return CUBIT_FAILURE; 00388 00389 CubitVector s = position( segment_no ); 00390 CubitVector e = position( segment_no+1 ); 00391 p = s + fraction * ( e - s ); 00392 00393 if ( Surface* surf = dynamic_cast<Surface*>(partitioned_entity()) ) 00394 { 00395 CubitVector seg_pos(p); 00396 surf->closest_point( seg_pos, &p ); 00397 } 00398 00399 return CUBIT_SUCCESS; 00400 } 00401 00402 double SegmentedCurve::u_from_arc_length( double param, double length ) 00403 { 00404 if( fabs(length) < CUBIT_RESABS ) 00405 return param; 00406 00407 double fraction = param; 00408 int segment = segment_from_u( fraction ); 00409 if( segment < 0 ) 00410 return param; 00411 00412 //Find the length of the remaining portion of the first 00413 //segment (after the base param.) 00414 double seg_len = segment_length( segment ); 00415 // BWC double len_sum = seg_len * ( 1.0 - param + segment ); 00416 double len_sum; 00417 00418 if(length < 0.0) 00419 len_sum = seg_len*(param-segment); 00420 else 00421 len_sum = seg_len * ( 1.0 - param + segment ); 00422 00423 //If the passed base param and length correspond to a 00424 //portion of the curve which lies entirely on a single 00425 //segment, return the passed base param plus the 00426 //fraction of the segment (the parameter range for a 00427 //segment is one.) 00428 //BWC if( len_sum >= length ) 00429 if(length < 0.0) 00430 { 00431 if(-len_sum < length) 00432 return param + ((seg_len > CUBIT_DBL_MIN ) ? length / seg_len : 0.0); 00433 } 00434 else 00435 { 00436 if( len_sum >= length ) 00437 return param + ((seg_len > CUBIT_DBL_MIN ) ? length / seg_len : 0.0); 00438 } 00439 00440 //Increment the total length until we have passed up 00441 //the specified arc length. 00442 /* 00443 BWC 00444 while( length > len_sum) 00445 { 00446 segment++; 00447 if( segment >= point_count() - 1 ) return -1.0; 00448 seg_len = segment_length( segment ); 00449 len_sum += seg_len; 00450 if(fabs(len_sum-length) < GEOMETRY_RESABS) 00451 len_sum = length; 00452 } 00453 */ 00454 if(length < 0.0) 00455 { 00456 while( fabs(length) > len_sum ) 00457 { 00458 segment--; 00459 if( segment < 0 ) return -1.0; 00460 seg_len = segment_length( segment ); 00461 len_sum += seg_len; 00462 if(fabs(len_sum+length) < GEOMETRY_RESABS) 00463 len_sum = -length; 00464 } 00465 } 00466 else 00467 { 00468 while( length > len_sum ) 00469 { 00470 segment++; 00471 if( segment >= point_count() - 1 ) return -1.0; 00472 seg_len = segment_length( segment ); 00473 len_sum += seg_len; 00474 if(fabs(len_sum-length) < GEOMETRY_RESABS) 00475 len_sum = length; 00476 } 00477 } 00478 00479 //Now subtract off the extra length on the last segment, 00480 //the amount passed the specified arc length. The ratio 00481 //of this length to the total length of the last segment 00482 //is the about we overshot the desired parameter value. 00483 if(length < 0.0) 00484 { 00485 if( seg_len > CUBIT_DBL_MIN ) 00486 return (double)(segment) + (len_sum + length)/seg_len; 00487 else 00488 return (double)(segment); 00489 } 00490 else 00491 { 00492 if( seg_len > CUBIT_DBL_MIN ) 00493 return (double)(segment + 1) - (len_sum - length)/seg_len; 00494 else 00495 return (double)(segment + 1); 00496 } 00497 } 00498 00499 CubitBoolean SegmentedCurve::is_position_on( const CubitVector& pos ) 00500 { 00501 //Get the segment to test on 00502 CubitVector v; 00503 closest_segment( pos, NULL, &v); 00504 00505 return (pos - v).length() <= GEOMETRY_RESABS ? CUBIT_TRUE : CUBIT_FALSE; 00506 } 00507 00508 CubitBox SegmentedCurve::bounding_box() const 00509 { 00510 CubitBox b( position( 0 ) ); 00511 for( int i = 1; i < point_count(); i++ ) 00512 b |= position( i ); 00513 00514 return b; 00515 } 00516 00517 double SegmentedCurve::measure() 00518 { 00519 double len = 0; 00520 for( int i = 0; i < point_count() - 1; i++ ) 00521 { 00522 len += segment_length( i ); 00523 } 00524 return len; 00525 } 00526 00527 CubitStatus SegmentedCurve::get_interior_extrema( 00528 DLIList<CubitVector*>& interior_points, 00529 CubitSense& return_sense ) 00530 { 00531 return_sense = CUBIT_FORWARD; 00532 00533 //For each point, check the segments to either side. If any of deltaX, 00534 //deltaY or deltaZ have opposite signs for the two segments, then the 00535 //point is an extrema in x, y, or z, respectively. 00536 int count = point_count() - 1; //stop with second-to-last point 00537 int prev_index = 0; 00538 00539 for( int i = 1; i < count; i++ ) 00540 { 00541 CubitVector curr = position(i+1) - position(i); 00542 CubitVector prev = position( i ) - position( prev_index ); 00543 if( (prev.x()*curr.x() < 0.0) || (prev.y()*curr.y()<0.0) || (prev.z()*curr.z()<0.0) ) 00544 { 00545 interior_points.append( new CubitVector( position(i) ) ); 00546 prev_index = i; 00547 } 00548 } 00549 return CUBIT_SUCCESS; 00550 } 00551 00552 CubitStatus SegmentedCurve::get_center_radius( CubitVector&, double& ) 00553 { return CUBIT_FAILURE; } 00554 00555 00556 double SegmentedCurve::closest_point_on_segment( 00557 const CubitVector& base, 00558 const CubitVector& dir, 00559 const CubitVector& location ) 00560 { 00561 if( dir.length_squared() < CUBIT_DBL_MIN ) return 0.0; 00562 00563 //Find closest location to infinite line 00564 double param = dir % ( location - base ) / dir.length_squared(); 00565 00566 //Trim to segment 00567 if( param < 0.0 ) param = 0.0; 00568 else if( param > 1.0 ) param = 1.0; 00569 00570 return param; 00571 } 00572 00573 //------------------------------------------------------------------------- 00574 // Purpose : Check for G1 discontinuities 00575 // 00576 // Special Notes : 00577 // 00578 // Creator : Jason Kraftcheck 00579 // 00580 // Creation Date : 05/03/00 00581 //------------------------------------------------------------------------- 00582 CubitBoolean SegmentedCurve::G1_discontinuous( double param, 00583 CubitVector* minus_tangent, 00584 CubitVector* plus_tangent ) 00585 { 00586 if( is_periodic() ) normalize_periodic_parameter( param ); 00587 00588 double lower = floor( param ); 00589 double upper = ceil( param ); 00590 int first_point = -1; 00591 int last = point_count() - 1; 00592 if( last < 2 ) return CUBIT_FALSE; 00593 00594 //If the parameter value corresponds to the start of a segment, 00595 //and that segment is not the first one 00596 if( ((param - lower) < CUBIT_RESABS) && (int(lower) != 0) ) 00597 first_point = int(lower) - 1; 00598 //If the parameter value corresponds to the end of a segment, 00599 //and that segment is not the last one 00600 else if( ((upper - param) < CUBIT_RESABS) && (int(upper) < last ) ) 00601 first_point = int(upper); 00602 //If the parameter value corresponds to the start or end of the 00603 //curve, and the curve is a closed, periodic curve. 00604 else if( is_periodic() && (fabs(start_param() - end_param()) < CUBIT_RESABS) && 00605 ((((param - lower) < CUBIT_RESABS) && (int(lower) == 0)) || 00606 (((upper - param) < CUBIT_RESABS) && (int(upper) == last)) ) ) 00607 first_point = last - 1; 00608 //Otherwise the point is in the interior of a segment 00609 else return CUBIT_FALSE; 00610 00611 int third_point = first_point + 2; 00612 if( third_point > last ) 00613 { 00614 if( is_periodic() ) 00615 { 00616 third_point = (third_point + 1) % point_count(); 00617 } 00618 else 00619 { 00620 return CUBIT_FALSE; 00621 } 00622 } 00623 00624 CubitVector tan1, tan2; 00625 tan1 = position( first_point + 1 ) - position( first_point ); 00626 tan2 = position( third_point ) - position( first_point + 1 ); 00627 if( (tan1 * tan2).length_squared() < CUBIT_RESABS ) 00628 return CUBIT_FALSE; 00629 00630 if( minus_tangent ) *minus_tangent = tan1; 00631 if( plus_tangent ) *plus_tangent = tan2; 00632 return CUBIT_TRUE; 00633 } 00634 00635 00636 //------------------------------------------------------------------------- 00637 // Purpose : If the curve is periodic, adjust the param value to 00638 // be in the base range. 00639 // 00640 // Special Notes : 00641 // 00642 // Creator : Jason Kraftcheck 00643 // 00644 // Creation Date : 05/15/00 00645 //------------------------------------------------------------------------- 00646 void SegmentedCurve::normalize_periodic_parameter( double& u ) 00647 { 00648 //The parameter range for a segmented curve is always (by my implementation) 00649 //from zero to some positive n. And the period is equal to that n. This 00650 //simplifies the following a lot. -jk 00651 double period; 00652 if( is_periodic( period ) ) 00653 { 00654 if( u > period ) 00655 u = fmod( u, period ); 00656 else if( u < -period ) 00657 u = fmod( u, period ) + period; 00658 else if( u < 0.0 ) 00659 u += period; //fmod() seems to be expensive, so avoid it here. 00660 } 00661 } 00662 00663 //------------------------------------------------------------------------- 00664 // Purpose : Constructor 00665 // 00666 // Special Notes : 00667 // 00668 // Creator : Jason Kraftcheck 00669 // 00670 // Creation Date : 05/15/00 00671 //------------------------------------------------------------------------- 00672 SegmentedCurve::SegmentedCurve( PartitionSurface* surf, 00673 DLIList<CubitVector*>& points ) 00674 : point_list( points.size() ) 00675 { 00676 points.reset(); 00677 for( int i = 0; i < points.size(); i++ ) 00678 point_list[i] = *points.get_and_step(); 00679 00680 surf->sub_entity_set().add_lower_order( this ); 00681 } 00682 SegmentedCurve::SegmentedCurve( PartitionLump* vol, 00683 DLIList<CubitVector*>& points ) 00684 : point_list( points.size() ) 00685 { 00686 points.reset(); 00687 for( int i = 0; i < points.size(); i++ ) 00688 point_list[i] = *points.get_and_step(); 00689 00690 vol->sub_entity_set().add_lower_order( this ); 00691 } 00692 00693 00694 SegmentedCurve::SegmentedCurve( SegmentedCurve* curve, int ptcount ) 00695 : point_list(ptcount) 00696 { 00697 curve->sub_entity_set().add_lower_order(this); 00698 } 00699 00700 00701 SegmentedCurve::~SegmentedCurve() 00702 { 00703 } 00704 00705 int SegmentedCurve::point_count() const 00706 { 00707 return point_list.size(); 00708 } 00709 00710 double SegmentedCurve::segment_length( int segment_no ) const 00711 { 00712 return (point_list[segment_no+1] - point_list[segment_no]).length(); 00713 } 00714 00715 CubitVector SegmentedCurve::position( int index ) const 00716 { 00717 return point_list[index]; 00718 } 00719 00720 00721 CubitStatus SegmentedCurve::get_graphics( GMem& result, 00722 double /*angle_tolerance*/, 00723 double /*distance_tolerance*/, 00724 double /*max_edge_length*/) 00725 { 00726 result.allocate_polylines( point_count()-1 ); 00727 for( int i = 0; i < point_count(); i++ ) 00728 { 00729 CubitVector v = position(i); 00730 result.point_list()[i].x = (float)(v.x()); 00731 result.point_list()[i].y = (float)(v.y()); 00732 result.point_list()[i].z = (float)(v.z()); 00733 } 00734 result.pointListCount = point_count(); 00735 return CUBIT_SUCCESS; 00736 } 00737 00738 CubitBoolean SegmentedCurve::is_periodic( double& period ) 00739 { 00740 if( is_periodic() ) 00741 { 00742 period = end_param() - start_param(); 00743 return CUBIT_TRUE; 00744 } 00745 return CUBIT_FALSE; 00746 } 00747 00748 CubitBoolean SegmentedCurve::is_periodic() const 00749 { 00750 return start_point() == end_point(); 00751 } 00752 00753 CubitPointContainment SegmentedCurve::point_containment( const CubitVector& pos ) 00754 { 00755 const double tol_sqr = GEOMETRY_RESABS * GEOMETRY_RESABS; 00756 if( (start_point()->coordinates() - pos).length_squared() < tol_sqr ) 00757 return CUBIT_PNT_BOUNDARY; 00758 else if( (end_point()->coordinates() - pos).length_squared() < tol_sqr ) 00759 return CUBIT_PNT_BOUNDARY; 00760 else if( is_position_on( pos ) ) 00761 return CUBIT_PNT_ON; 00762 else 00763 return CUBIT_PNT_OFF; 00764 } 00765 00766 00767 CubitStatus SegmentedCurve::get_segments( DLIList<CubitVector*>& list ) 00768 { 00769 for( int i = 0; i < point_count(); i++ ) 00770 list.append( new CubitVector( position(i) ) ); 00771 return CUBIT_SUCCESS; 00772 } 00773 00774 void SegmentedCurve::reverse_sense() 00775 { 00776 point_list.reverse(); 00777 reverse_point_order(); 00778 if( owner() ) 00779 owner()->notify_reversed(this); 00780 } 00781 00782 CubitStatus SegmentedCurve::save( CubitSimpleAttrib& attrib ) 00783 { 00784 DLIList<CubitVector*> segments; 00785 get_segments(segments); 00786 00787 DLIList<int> topo; 00788 get_save_topology( topo ); 00789 00790 int id = sub_entity_set().get_id(this); 00791 00792 return sub_entity_set().save_geometry( id, 1, &segments, 0, &topo, 0, attrib ); 00793 } 00794 00795 SegmentedCurve* SegmentedCurve::construct( const CubitSimpleAttrib& attrib, 00796 PartitionEntity* parent ) 00797 { 00798 PartitionSurface* owning_surf = dynamic_cast<PartitionSurface*>(parent); 00799 PartitionLump* owning_lump = dynamic_cast<PartitionLump*>(parent); 00800 if( !owning_surf && !owning_lump ) 00801 return 0; 00802 00803 DLIList<int> vertex_conn; 00804 SegmentedCurve* result = new SegmentedCurve( parent, attrib, vertex_conn ); 00805 00806 if( vertex_conn.size() != 4 ) 00807 { 00808 delete result; 00809 return 0; 00810 } 00811 00812 PartitionPoint *start = 0, *end = 0; 00813 PartitionEntity* ent; 00814 vertex_conn.reset(); 00815 int set_id = vertex_conn.get_and_step(); 00816 int ent_id = vertex_conn.get_and_step(); 00817 ent = PartitionEngine::instance().entity_from_id(set_id,ent_id,parent->sub_entity_set()); 00818 start = dynamic_cast<PartitionPoint*>(ent); 00819 set_id = vertex_conn.get_and_step(); 00820 ent_id = vertex_conn.get_and_step(); 00821 ent = PartitionEngine::instance().entity_from_id(set_id,ent_id,parent->sub_entity_set()); 00822 end = dynamic_cast<PartitionPoint*>(ent); 00823 if( !start || !end ) 00824 { 00825 delete result; 00826 return 0; 00827 } 00828 00829 result->start_point(start); 00830 result->end_point(end); 00831 return result; 00832 } 00833 00834 00835 SegmentedCurve::SegmentedCurve( PartitionEntity* vol, 00836 const CubitSimpleAttrib& attrib, 00837 DLIList<int>& vertex_conn ) 00838 { 00839 DLIList<CubitVector*> points; 00840 DLIList<int> junk; 00841 vol->sub_entity_set().add_lower_order( this, attrib, 1, points, junk, vertex_conn, junk ); 00842 00843 points.reset(); 00844 point_list.size(points.size()); 00845 for( int i = 0; i < points.size(); i++ ) 00846 { 00847 CubitVector* pt = points.get_and_step(); 00848 point_list[i] = *pt; 00849 delete pt; 00850 } 00851 } 00852 00853 void SegmentedCurve::transform( const CubitTransformMatrix& xform ) 00854 { 00855 PartitionCurve::transform(xform); 00856 for( int i = 0; i < point_list.size(); i++ ) 00857 point_list[i] = xform * point_list[i]; 00858 } 00859 00860 void SegmentedCurve::print_debug_info( const char* prefix, bool pss ) const 00861 { 00862 if( prefix == 0 ) prefix = ""; 00863 PartitionCurve::print_debug_info( prefix, pss ); 00864 PRINT_INFO("%sSegmentedCurve %p\n", prefix, (void*)this); 00865 PRINT_INFO("%s%d segment points:\n", prefix, point_list.size()); 00866 int i; 00867 for( i = 0; i < point_list.size() - 1; i+= 2 ) 00868 { 00869 PRINT_INFO("%s (%f, %f, %f), (%f, %f, %f),\n", 00870 prefix, point_list[i ].x(), point_list[i ].y(), point_list[i ].z(), 00871 point_list[i+1].x(), point_list[i+1].y(), point_list[i+1].z()); 00872 } 00873 if( i == point_list.size() - 1 ) 00874 { 00875 PRINT_INFO("%s (%f, %f, %f)\n", prefix, point_list[i].x(), 00876 point_list[i].y(), point_list[i].z()); 00877 } 00878 } 00879 00880 CubitStatus SegmentedCurve::get_spline_params 00881 ( 00882 bool &rational, // return true/false 00883 int °ree, // the degree of this spline 00884 DLIList<CubitVector> &cntrl_pts, // xyz position of controlpoints 00885 DLIList<double> &cntrl_pt_weights, // if rational, a weight for each cntrl point. 00886 DLIList<double> &knots, // There should be order+cntrl_pts.size()-2 knots 00887 bool &spline_is_reversed 00888 ) const 00889 { 00890 PRINT_ERROR("Currently, Cubit is unable to determine spline parameters for SegmentedCurves.\n"); 00891 return CUBIT_FAILURE; 00892 } 00893 00894 CubitStatus SegmentedCurve::get_ellipse_params 00895 ( 00896 CubitVector ¢er_vec, 00897 CubitVector &normal, 00898 CubitVector &major_axis, 00899 double &radius_ratio 00900 ) const 00901 { 00902 PRINT_ERROR("Currently, Cubit is unable to determine ellipse parameters for SegmentedCurves.\n"); 00903 return CUBIT_FAILURE; 00904 }