cgma
|
00001 //------------------------------------------------------------------------- 00002 // Filename : Curve.cc 00003 // 00004 // Purpose : 00005 // 00006 // Special Notes : 00007 // 00008 // Creator : Xuechen Liu 00009 // 00010 // Creation Date : 08/02/96 00011 // 00012 // Owner : Malcolm J. Panthaki 00013 //------------------------------------------------------------------------- 00014 00015 // ********** BEGIN STANDARD INCLUDES ********** 00016 // ********** END STANDARD INCLUDES ********** 00017 00018 // ********** BEGIN CUBIT INCLUDES ********** 00019 #include "Curve.hpp" 00020 #include "Point.hpp" 00021 #include "GeometryQueryTool.hpp" 00022 00023 #include "CastTo.hpp" 00024 #include "CubitMessage.hpp" 00025 // ********** END CUBIT INCLUDES ********** 00026 00027 // ********** BEGIN STATIC DECLARATIONS ********** 00028 // ********** END STATIC DECLARATIONS ********** 00029 00030 // ********** BEGIN PUBLIC FUNCTIONS ********** 00031 00032 //------------------------------------------------------------------------- 00033 // Purpose : The default constructor. Does not do anything right now. 00034 // 00035 // Special Notes : 00036 // 00037 // Creator : Xuechen Liu 00038 // 00039 // Creation Date : 08/02/96 00040 //------------------------------------------------------------------------- 00041 00042 Curve::Curve() 00043 {} 00044 00045 //------------------------------------------------------------------------- 00046 // Purpose : The destructor. Does not do anything right now. 00047 // 00048 // Special Notes : 00049 // 00050 // Creator : Raikanta Sahu 00051 // 00052 // Creation Date : 09/06/96 00053 //------------------------------------------------------------------------- 00054 00055 Curve::~Curve() 00056 {} 00057 00058 CubitSense Curve::relative_sense(Curve *other_curve) 00059 { 00060 CubitVector center, junk, this_tangent, other_tangent; 00061 double start, end; 00062 00063 if (!get_param_range(start,end) || 00064 !position_from_u(0.5*(start+end), center) || 00065 !closest_point(center, junk, &this_tangent) || 00066 !other_curve->closest_point(center, junk, &other_tangent)) 00067 return CUBIT_UNKNOWN; 00068 00069 double dot = this_tangent % other_tangent; 00070 return dot == 0.0 ? CUBIT_UNKNOWN : dot > 0. ? CUBIT_FORWARD : CUBIT_REVERSED; 00071 } 00072 00073 //- When this is implemented in VirtualGeometryEngine it should be a pure vitual 00074 CubitStatus Curve::get_point_direction( CubitVector& , CubitVector& ) 00075 { 00076 return CUBIT_FAILURE; 00077 } 00078 00079 //- default implementation 00080 CubitStatus Curve::get_center_radius( CubitVector& c, double& r) 00081 { 00082 CubitVector start_pos, closest_pos; 00083 if ( position_from_u(start_param(), start_pos) && 00084 closest_point(start_pos, closest_pos, 0, &c) ) 00085 { 00086 r = c.length(); 00087 if (r > CUBIT_RESABS) 00088 { 00089 r = 1.0 / r; 00090 c *= r * r; 00091 c += closest_pos; 00092 return CUBIT_SUCCESS; 00093 } 00094 } 00095 return CUBIT_FAILURE; 00096 } 00097 00098 //------------------------------------------------------------------------- 00099 // Purpose : This function returns the point that is a distance 00100 // arc length from the root_point. 00101 // 00102 // Special Notes : If the root point is on a periodic curve, it may 00103 // accidentaly get the wrong parameter. There is 00104 // a special test here to make sure root point does 00105 // not get set as the end parameter... 00106 // If root point is at the end, we will assert later on.. 00107 // 00108 // Creator : David White 00109 // 00110 // Creation Date : 03/24/97 00111 //------------------------------------------------------------------------- 00112 CubitStatus Curve::point_from_arc_length ( const CubitVector &root_point, 00113 double const arc_length, 00114 CubitVector& new_point ) 00115 { 00116 // Get the parameter value of the root point 00117 double root_param = u_from_position( root_point ); 00118 return point_from_arc_length(root_param, arc_length, new_point); 00119 } 00120 00121 //------------------------------------------------------------------------- 00122 // Purpose : This function returns the point that is a distance 00123 // arc length from the point corresponding to root_param 00124 // 00125 // Special Notes : The original point_from_arc_length was split up 00126 // to allow the starting parameter to be specified directly. 00127 // This helps with periodic curves, where the start_param of the 00128 // curve can be passed in so we're sure its starting from the 00129 // start vertex. 00130 // 00131 // Creator : David White (modified by Ved Vyas) 00132 // 00133 // Creation Date : 5/21/2006 00134 //------------------------------------------------------------------------- 00135 00136 CubitStatus Curve::point_from_arc_length( double root_param, 00137 const double arc_length, 00138 CubitVector &new_point ) 00139 { 00140 double low_param = start_param(); 00141 double high_param = end_param(); 00142 00143 if (high_param < low_param) 00144 { 00145 double temp = high_param; 00146 high_param = low_param; 00147 low_param = temp; 00148 } 00149 00150 // Comment: The way we handle points not on the bounded curve is 00151 // different for periodic and non-periodic curves! 00152 // Periodic curves leave the parameter off of the curve, 00153 // while non-periodic curves move the point to the closest 00154 // endpoint. Just an observation! 00155 00156 00157 // Adjust the parameter for periodic curves 00158 double periodic_param; 00159 00160 if ( is_periodic( periodic_param )) 00161 { 00162 while (root_param < low_param) 00163 root_param += periodic_param; 00164 while (root_param > high_param) 00165 root_param -= periodic_param; 00166 // If you're moving in the positive direction and 00167 // you're almost at the start point... 00168 if (fabs( this->end_param() - root_param ) <= CUBIT_RESABS && 00169 arc_length > 0.0 ) 00170 { 00171 //the root param should be switched with the start param. 00172 root_param = this->start_param(); 00173 } 00174 // If you're moving in the negative direction and 00175 // you're almost at the end point... 00176 else if (fabs( this->start_param() - root_param ) <= CUBIT_RESABS && 00177 arc_length < 0.0 ) 00178 { 00179 root_param = this->end_param(); 00180 } 00181 } 00182 else if ( root_param < (low_param + CUBIT_RESABS) ) 00183 root_param = low_param; 00184 else if ( root_param > (high_param - CUBIT_RESABS) ) 00185 root_param = high_param; 00186 00187 // Get the parameter value of the new point 00188 double new_param = this->u_from_arc_length( root_param, 00189 arc_length ); 00190 00191 // Now get the coordinates (in world space) representing this parameter 00192 // value 00193 return this->position_from_u(new_param, new_point); 00194 } 00195 00196 //------------------------------------------------------------------------- 00197 // Purpose : Find the closest point on a BOUNDED curve. 00198 // 00199 // Creator : Jason Kraftcheck 00200 // 00201 // Creation Date : 07/17/98 00202 //------------------------------------------------------------------------- 00203 CubitStatus Curve::closest_point_trimmed( CubitVector const& from_pt, 00204 CubitVector& result ) 00205 { 00206 // Get the untrimmed point 00207 double param; 00208 if ( !closest_point(from_pt, result, NULL, NULL, ¶m) ) 00209 return CUBIT_FAILURE; 00210 00211 double param_range = 0.0; 00212 double period, start_param, end_param; 00213 00214 // Get whether periodic 00215 CubitBoolean is_per = this->is_periodic(period); 00216 // Get the parameter range 00217 get_param_range( start_param, end_param ); 00218 00219 // Make sure the start_param is lower than end_param. 00220 if (start_param > end_param) 00221 { 00222 // use param_range as temp 00223 param_range = start_param; 00224 start_param = end_param; 00225 end_param = param_range; 00226 } 00227 param_range = end_param - start_param; 00228 00229 // If the Curve does not loop onto itself... 00230 if( is_per == CUBIT_FALSE || 00231 param_range < period) 00232 { 00233 // If not within parameter range, return 00234 // the the closest endpoint 00235 CubitVector start, end; 00236 position_from_u( start_param, start ); 00237 position_from_u( end_param, end ); 00238 00239 if( (param < start_param) || (param > end_param) ) 00240 { 00241 result = ( (start - result).length_squared() < 00242 (end - result).length_squared() ) ? start : end ; 00243 } 00244 else 00245 { 00246 double tmp_dist_sq = (from_pt - result).length_squared(); 00247 if( (start-from_pt).length_squared() < tmp_dist_sq ) 00248 result = start; 00249 else if( (end-from_pt).length_squared() < tmp_dist_sq ) 00250 result = end; 00251 } 00252 } 00253 00254 00255 return CUBIT_SUCCESS; 00256 } 00257 00258 //------------------------------------------------------------------------- 00259 // Purpose : Check for discontinuity in the tangents of a curve 00260 // 00261 // Special Notes : 00262 // 00263 // Creator : Jason Kraftcheck 00264 // 00265 // Creation Date : 05/01/00 00266 //------------------------------------------------------------------------- 00267 CubitBoolean Curve::G1_discontinuous( double u, 00268 CubitVector* minus_tangent_r, CubitVector* plus_tangent_r ) 00269 { 00270 double start_param, end_param; 00271 if( ! get_param_range( start_param, end_param ) ) return CUBIT_FALSE; 00272 //if the curve is not parametric, just return false. 00273 if( start_param > end_param ) 00274 { 00275 double tmp = start_param; 00276 start_param = end_param; 00277 end_param = tmp; 00278 } 00279 00280 double u_minus = (2 * CUBIT_RESABS); 00281 double u_plus = u_minus; 00282 00283 //can't be C1 discontinous at an end point! 00284 if( ((u - u_minus) < start_param) || ((u + u_plus) > end_param) ) 00285 return CUBIT_FALSE; 00286 00287 CubitVector position; 00288 position_from_u( u, position ); 00289 const double res_abs_sqr = CUBIT_RESABS * CUBIT_RESABS; 00290 00291 CubitVector minus_position, minus_tangent; 00292 position_from_u( u - u_minus, minus_position ); 00293 double u_minus2 = u_from_position( minus_position ); 00294 minus_tangent = position - minus_position; 00295 00296 while( ((u - u_minus2) > (u - CUBIT_RESABS)) || 00297 (minus_tangent.length_squared() < res_abs_sqr) ) 00298 { 00299 u_minus *= 10.; 00300 //can't be C1 discontinous at an end point! 00301 if( (u - u_minus) < start_param ) return CUBIT_FALSE; 00302 position_from_u( u - u_minus, minus_position ); 00303 u_minus2 = u_from_position( minus_position ); 00304 minus_tangent = position - minus_position; 00305 } 00306 00307 CubitVector plus_position, plus_tangent; 00308 position_from_u( u + u_plus, plus_position ); 00309 double u_plus2 = u_from_position( plus_position ); 00310 plus_tangent = plus_position - position; 00311 00312 while( ((u + u_plus2) < (u + CUBIT_RESABS)) || 00313 ((position - plus_position).length_squared() < res_abs_sqr) ) 00314 { 00315 u_plus *= 10.; 00316 //can't be C1 discontinous at an end point! 00317 if( (u + u_plus) > end_param ) return CUBIT_FALSE; 00318 position_from_u( u + u_plus, plus_position ); 00319 u_plus2 = u_from_position( plus_position ); 00320 plus_tangent = plus_position - position; 00321 } 00322 00323 plus_tangent.normalize(); 00324 minus_tangent.normalize(); 00325 if( (plus_tangent * minus_tangent).length_squared() > (2 * res_abs_sqr) ) 00326 { 00327 if( plus_tangent_r ) *plus_tangent_r = plus_tangent; 00328 if( minus_tangent_r ) * minus_tangent_r = minus_tangent; 00329 return CUBIT_TRUE; 00330 } 00331 00332 return CUBIT_FALSE; 00333 } 00334 00335 // ********** END PUBLIC FUNCTIONS ********** 00336 00337 // ********** BEGIN PROTECTED FUNCTIONS ********** 00338 // ********** END PROTECTED FUNCTIONS ********** 00339 00340 // ********** BEGIN PRIVATE FUNCTIONS ********** 00341 // ********** END PRIVATE FUNCTIONS ********** 00342 00343 // ********** BEGIN HELPER CLASSES ********** 00344 // ********** END HELPER CLASSES ********** 00345 00346 // ********** BEGIN EXTERN FUNCTIONS ********** 00347 // ********** END EXTERN FUNCTIONS ********** 00348 00349 // ********** BEGIN STATIC FUNCTIONS ********** 00350 // ********** END STATIC FUNCTIONS ********** 00351