Branch data Line data Source code
1 : : //-------------------------------------------------------------------------
2 : : // Filename : SegmentedCurve.cc
3 : : //
4 : : // Purpose :
5 : : //
6 : : // Special Notes : The parameterization of this is defined such that the
7 : : // parameter range between two adjacent nodes is one.
8 : : //
9 : : // Creator : Jason Kraftcheck
10 : : //
11 : : // Creation Date : 06/10/98
12 : : //-------------------------------------------------------------------------
13 : :
14 : : #include "SegmentedCurve.hpp"
15 : :
16 : : #include "PartitionPoint.hpp"
17 : : #include "PartitionCoEdge.hpp"
18 : : #include "PartitionSurface.hpp"
19 : : #include "PartitionLump.hpp"
20 : : #include "GMem.hpp"
21 : : #include "PartitionEngine.hpp"
22 : : #include "CubitTransformMatrix.hpp"
23 : : #include "CubitMessage.hpp"
24 : :
25 : 0 : int SegmentedCurve::segment_from_u( double& param )
26 : : {
27 [ # # ]: 0 : if( is_periodic() )
28 : 0 : normalize_periodic_parameter( param );
29 : :
30 : 0 : int num_segments = point_count() - 1;
31 [ # # ][ # # ]: 0 : if( param < -CUBIT_RESABS ||
32 : 0 : param > (num_segments + CUBIT_RESABS) )
33 : 0 : return -1;
34 : :
35 : : // Could call trunc() here, but why? Need to cast to an
36 : : // int anyway. Also, the cast to int should be save
37 : : // because the magnitude of param is tested above.
38 : 0 : int segment_index = (int)param;
39 [ # # ]: 0 : if( segment_index == num_segments )
40 : 0 : --segment_index;
41 : :
42 : 0 : param -= segment_index;
43 : 0 : return segment_index;
44 : : }
45 : :
46 : 0 : PartitionCurve* SegmentedCurve::split( double param )
47 : : {
48 [ # # ]: 0 : int seg = segment_from_u(param);
49 [ # # ]: 0 : if( seg < 0 )
50 : 0 : return 0;
51 : :
52 [ # # ]: 0 : CubitVector beg = position(seg);
53 [ # # ]: 0 : CubitVector end = position(seg+1);
54 [ # # ][ # # ]: 0 : CubitVector pos = beg + param * (end - beg);
[ # # ]
55 : :
56 [ # # ][ # # ]: 0 : if( (pos - end).length_squared() < GEOMETRY_RESABS*GEOMETRY_RESABS )
[ # # ]
57 : : {
58 : 0 : seg++;
59 : 0 : param = 0;
60 [ # # ][ # # ]: 0 : beg = pos = end;
61 : :
62 [ # # ][ # # ]: 0 : if( seg == point_count() - 1 )
63 : 0 : return 0;
64 : : }
65 [ # # ][ # # ]: 0 : else if( (pos - beg).length_squared() < GEOMETRY_RESABS*GEOMETRY_RESABS )
[ # # ]
66 : : {
67 [ # # ]: 0 : if( seg == 0 )
68 : 0 : return 0;
69 : :
70 [ # # ]: 0 : pos = beg;
71 : 0 : param = 0;
72 : : }
73 : :
74 [ # # ][ # # ]: 0 : SegmentedCurve* new_curve = new SegmentedCurve( this, point_count() - seg );
[ # # ]
75 : :
76 [ # # ][ # # ]: 0 : new_curve->point_list[0] = pos;
77 [ # # ][ # # ]: 0 : for( int i = 1; i < new_curve->point_list.size(); i++ )
78 [ # # ][ # # ]: 0 : new_curve->point_list[i] = point_list[seg + i];
[ # # ]
79 [ # # ]: 0 : if( param == 0 )
80 : : {
81 [ # # ]: 0 : point_list.size( seg + 1 );
82 : : }
83 : : else
84 : : {
85 [ # # ]: 0 : point_list.size( seg + 2 );
86 [ # # ][ # # ]: 0 : point_list[seg+1] = pos;
87 : : }
88 : :
89 : 0 : return new_curve;
90 : : }
91 : :
92 : 0 : CubitStatus SegmentedCurve::combine( PartitionCurve* dead_curve )
93 : : {
94 [ # # ]: 0 : SegmentedCurve* dead = dynamic_cast<SegmentedCurve*>(dead_curve);
95 [ # # ][ # # ]: 0 : if( !dead || dead->partitioned_entity() != this->partitioned_entity() )
[ # # ][ # # ]
[ # # ]
96 : 0 : return CUBIT_FAILURE;
97 : :
98 [ # # ]: 0 : CubitVector this_start = this->position(0);
99 [ # # ]: 0 : CubitVector dead_start = dead->position(0);
100 [ # # ][ # # ]: 0 : CubitVector this_end = this->position( this->point_count() - 1 );
101 [ # # ][ # # ]: 0 : CubitVector dead_end = dead->position( dead->point_count() - 1 );
102 : :
103 : : int i;
104 : : bool append, reverse;
105 : 0 : const double tol_sqr = GEOMETRY_RESABS * GEOMETRY_RESABS;
106 [ # # ][ # # ]: 0 : if( (this_end - dead_start).length_squared() < tol_sqr )
[ # # ]
107 : : {
108 : 0 : append = true;
109 : 0 : reverse = false;
110 : : }
111 [ # # ][ # # ]: 0 : else if( (this_end - dead_end).length_squared() < tol_sqr )
[ # # ]
112 : : {
113 : 0 : append = true;
114 : 0 : reverse = true;
115 : : }
116 [ # # ][ # # ]: 0 : else if( (this_start - dead_end).length_squared() < tol_sqr )
[ # # ]
117 : : {
118 : 0 : append = false;
119 : 0 : reverse = false;
120 : : }
121 [ # # ][ # # ]: 0 : else if( (this_start - dead_start).length_squared() < tol_sqr )
[ # # ]
122 : : {
123 : 0 : append = false;
124 : 0 : reverse = true;
125 : : }
126 : : else
127 : : {
128 : 0 : assert(0);
129 : : return CUBIT_FAILURE;
130 : : }
131 : :
132 [ # # ]: 0 : if( reverse )
133 [ # # ]: 0 : dead->point_list.reverse();
134 : :
135 [ # # ]: 0 : int this_point_count = this->point_list.size();
136 [ # # ]: 0 : int dead_point_count = dead->point_list.size();
137 : 0 : int new_point_count = this_point_count + dead_point_count - 1;
138 [ # # ]: 0 : this->point_list.size(new_point_count);
139 : :
140 [ # # ]: 0 : if( append )
141 : : {
142 [ # # ]: 0 : for( i = 1; i < dead_point_count; i++ )
143 [ # # ][ # # ]: 0 : point_list[this_point_count + i - 1] = dead->point_list[i];
[ # # ]
144 : : }
145 : : else
146 : : {
147 [ # # ]: 0 : for( i = 1; i <= this_point_count; i++ )
148 [ # # ][ # # ]: 0 : point_list[new_point_count-i] = point_list[this_point_count-1];
[ # # ]
149 : :
150 [ # # ]: 0 : for( i = 0; i < dead_point_count; i++ )
151 [ # # ][ # # ]: 0 : this->point_list[i] = dead->point_list[i];
[ # # ]
152 : : }
153 : :
154 : 0 : return CUBIT_SUCCESS;
155 : : }
156 : :
157 : :
158 : :
159 : 0 : CubitBoolean SegmentedCurve::is_linear()
160 : : {
161 [ # # ]: 0 : int i, count = point_count();
162 [ # # ]: 0 : if( count == 2 ) return CUBIT_TRUE;
163 [ # # ][ # # ]: 0 : if( is_periodic() ) return CUBIT_FALSE;
164 : :
165 [ # # ]: 0 : CubitVector mean(0.0,0.0,0.0);
166 [ # # ][ # # ]: 0 : for( i = 1; i < count; i++ ) mean += (position(i)-position(i-1));
[ # # ][ # # ]
[ # # ]
167 [ # # ]: 0 : mean.normalize();
168 [ # # ]: 0 : for( i = 1; i < count; i++ )
169 : : {
170 [ # # ][ # # ]: 0 : if( (1-(mean % ~(position(i)-position(i-1)))) > CUBIT_RESABS )
[ # # ][ # # ]
[ # # ][ # # ]
171 : 0 : return CUBIT_FALSE;
172 : : }
173 : 0 : return CUBIT_TRUE;
174 : : }
175 : :
176 : 0 : CubitStatus SegmentedCurve::get_point_direction(
177 : : CubitVector& origin, CubitVector& direction )
178 : : {
179 [ # # ]: 0 : if( ! is_linear() ) return CUBIT_FAILURE;
180 [ # # ]: 0 : origin = position(0);
181 [ # # ][ # # ]: 0 : direction = ~(position(point_count()-1) - origin);
[ # # ]
182 : 0 : return CUBIT_SUCCESS;
183 : : }
184 : :
185 : 0 : double SegmentedCurve::length_from_u( double param1, double param2 )
186 : : {
187 [ # # ]: 0 : if( param1 > param2 )
188 : : {
189 : 0 : double temp = param1;
190 : 0 : param1 = param2;
191 : 0 : param2 = temp;
192 : : }
193 : :
194 [ # # ]: 0 : if( is_periodic() )
195 : : {
196 : 0 : normalize_periodic_parameter( param1 );
197 : 0 : normalize_periodic_parameter( param2 );
198 : : }
199 : :
200 : 0 : int first = (int)floor( param1 );
201 : 0 : int last = (int)floor( param2 );
202 : 0 : int seg_count = point_count() - 1;
203 : :
204 : : //check for errors, round a little
205 [ # # ]: 0 : if( first < 0 )
206 : : {
207 [ # # ]: 0 : if( param1 > -CUBIT_RESABS ) first = 0;
208 : 0 : else return -1.0;
209 : : }
210 [ # # ]: 0 : if( last < 0 )
211 : : {
212 [ # # ]: 0 : if( param2 > -CUBIT_RESABS ) last = 0;
213 : 0 : else return -1.0;
214 : : }
215 [ # # ]: 0 : if( last >= seg_count )
216 : : {
217 [ # # ]: 0 : if( param2 < (CUBIT_RESABS + seg_count) )
218 : 0 : last--;
219 : 0 : else return -1.0;
220 : : }
221 [ # # ]: 0 : if( first >= seg_count )
222 : : {
223 [ # # ]: 0 : if( param1 < (CUBIT_RESABS + seg_count) )
224 : 0 : first--;
225 : 0 : else return -1.0;
226 : : }
227 : :
228 : : //calculate the remaining length on the first segment
229 : :
230 : 0 : double length_sum = segment_length( first ) * (1 - (param1 - first) );
231 : :
232 : : //add up the remaining segments upto and including last
233 : :
234 [ # # ]: 0 : for( int i = first + 1; i <= last; i++ )
235 : 0 : length_sum += segment_length( i );
236 : :
237 : : // by including the last segment, we (may have) gone too far,
238 : : // so subtract back off the extra on the last segment
239 : :
240 : 0 : length_sum -= segment_length(last) * (1 - (param2 - last) );
241 : :
242 : 0 : return length_sum;
243 : :
244 : : }
245 : :
246 : 0 : CubitBoolean SegmentedCurve::get_param_range( double& lower, double& upper )
247 : : {
248 : 0 : lower = 0.0;
249 : 0 : upper = double(point_count() - 1);
250 : 0 : return CUBIT_TRUE;
251 : : }
252 : :
253 : 0 : CubitStatus SegmentedCurve::closest_point(
254 : : CubitVector const& location,
255 : : CubitVector& closest_location,
256 : : CubitVector* tangent_ptr,
257 : : CubitVector* curvature_ptr,
258 : : double* param)
259 : : {
260 : : double seg_param;
261 [ # # ]: 0 : int segment_no = closest_segment( location, &seg_param, &closest_location );
262 : :
263 [ # # ][ # # ]: 0 : if ( Surface* surf = dynamic_cast<Surface*>(partitioned_entity()) )
[ # # ]
264 : : {
265 [ # # ]: 0 : CubitVector seg_point(closest_location);
266 [ # # ]: 0 : surf->closest_point( seg_point, &closest_location );
267 : : }
268 : :
269 [ # # ]: 0 : if( tangent_ptr != NULL )
270 : : {
271 : : //First check if the closest point is at the join of
272 : : //two segments. If so, return the average of the two
273 : : //tangets.
274 [ # # ][ # # ]: 0 : if( (seg_param < CUBIT_RESABS) && (segment_no > 0) )
275 : : {
276 [ # # ]: 0 : CubitVector seg1_start = position( segment_no - 1 );
277 [ # # ]: 0 : CubitVector seg2_end = position( segment_no + 1 );
278 [ # # ][ # # ]: 0 : *tangent_ptr = seg2_end - seg1_start;
279 : : }
280 : :
281 : : //ditto
282 [ # # ][ # # ]: 0 : else if( ( (1.0 - seg_param) < CUBIT_RESABS ) &&
[ # # ]
283 [ # # ]: 0 : ( segment_no < (point_count() - 2) ) )
284 : : {
285 [ # # ]: 0 : CubitVector seg1_start = position( segment_no );
286 [ # # ]: 0 : CubitVector seg2_end = position( segment_no + 2 );
287 [ # # ][ # # ]: 0 : *tangent_ptr = seg2_end - seg1_start;
288 : : }
289 : :
290 : : //The segment_no is the index of the point beginning the segment.
291 : : //A segment_no equal to point_count() - 1, the last point is
292 : : //possible. So, for any segment point but the last, return the
293 : : //tangent of the segment beginning with the point at segment_no.
294 [ # # ][ # # ]: 0 : else if( segment_no < point_count() - 1 )
295 : : {
296 : : *tangent_ptr = this->position( segment_no + 1 )
297 [ # # ][ # # ]: 0 : - this->position( segment_no );
[ # # ][ # # ]
298 : : }
299 : :
300 [ # # ]: 0 : else if( segment_no == 0 )
301 : : {
302 : : *tangent_ptr = this->position( segment_no + 1 )
303 [ # # ][ # # ]: 0 : - this->position( segment_no );
[ # # ][ # # ]
304 : : }
305 : :
306 : : //If the point is the last one, return the direction of
307 : : //the last segment (this point and the previous one.)
308 : : else
309 : : {
310 : : *tangent_ptr = this->position( segment_no )
311 [ # # ][ # # ]: 0 : - this->position( segment_no - 1 );
[ # # ][ # # ]
312 : : }
313 : :
314 [ # # ]: 0 : tangent_ptr->normalize();
315 : : }
316 : :
317 : : //There is never a valid curvature for a segmented curve.
318 : : //The curvature is either infinity in the interior of segments,
319 : : //or zero at the points between segments. Just return zero.
320 [ # # ]: 0 : if( curvature_ptr != NULL )
321 : : {
322 [ # # ]: 0 : curvature_ptr->set( 0., 0., 0. );
323 : : }
324 : :
325 [ # # ]: 0 : if (param)
326 : : {
327 : 0 : *param = double(segment_no) + seg_param;
328 : : }
329 : :
330 : 0 : return CUBIT_SUCCESS;
331 : : }
332 : :
333 : 0 : CubitStatus SegmentedCurve::closest_point_trimmed(
334 : : CubitVector const& from_pt, CubitVector& result_pt )
335 : : {
336 : 0 : return closest_point( from_pt, result_pt );
337 : : }
338 : :
339 : 0 : int SegmentedCurve::closest_segment( CubitVector const& location,
340 : : double* seg_fraction,
341 : : CubitVector* closest_pt )
342 : : {
343 [ # # ]: 0 : int length_ = point_count();
344 : :
345 : 0 : int segment_no = 0;
346 [ # # ]: 0 : CubitVector start = position( 0 );
347 [ # # ]: 0 : CubitVector end = position( 1 );
348 [ # # ]: 0 : CubitVector dir = end - start;
349 [ # # ]: 0 : double seg_param = closest_point_on_segment( start, dir, location );
350 [ # # ][ # # ]: 0 : CubitVector point = start + seg_param * dir;
351 [ # # ][ # # ]: 0 : if( closest_pt ) *closest_pt = point;
352 [ # # ][ # # ]: 0 : double shortest = (point - location ).length_squared();
353 : :
354 [ # # ]: 0 : for( int i = 2; i < length_; i++ )
355 : : {
356 [ # # ]: 0 : start = end;
357 [ # # ][ # # ]: 0 : end = position( i );
358 [ # # ][ # # ]: 0 : dir = end - start;
359 [ # # ]: 0 : double param = closest_point_on_segment( start, dir, location );
360 [ # # ][ # # ]: 0 : point = start + param * dir;
[ # # ]
361 [ # # ][ # # ]: 0 : double dist = (point - location).length_squared();
362 [ # # ]: 0 : if( dist < shortest )
363 : : {
364 : 0 : shortest = dist;
365 [ # # ][ # # ]: 0 : if( closest_pt ) *closest_pt = point;
366 : 0 : segment_no = i - 1;
367 : 0 : seg_param = param;
368 : : }
369 : : }
370 : :
371 [ # # ]: 0 : if( seg_fraction ) *seg_fraction = seg_param;
372 : 0 : return segment_no;
373 : : }
374 : :
375 : 0 : double SegmentedCurve::u_from_position( const CubitVector& position )
376 : : {
377 : : double seg_param;
378 [ # # ]: 0 : int segment = closest_segment( position, &seg_param );
379 : 0 : return double(segment) + seg_param;
380 : : }
381 : :
382 : 0 : CubitStatus SegmentedCurve::position_from_u( double u, CubitVector& p)
383 : : {
384 : 0 : double fraction = u;
385 [ # # ]: 0 : int segment_no = segment_from_u(fraction);
386 [ # # ]: 0 : if( segment_no < 0 )
387 : 0 : return CUBIT_FAILURE;
388 : :
389 [ # # ]: 0 : CubitVector s = position( segment_no );
390 [ # # ]: 0 : CubitVector e = position( segment_no+1 );
391 [ # # ][ # # ]: 0 : p = s + fraction * ( e - s );
[ # # ][ # # ]
392 : :
393 [ # # ][ # # ]: 0 : if ( Surface* surf = dynamic_cast<Surface*>(partitioned_entity()) )
[ # # ]
394 : : {
395 [ # # ]: 0 : CubitVector seg_pos(p);
396 [ # # ]: 0 : surf->closest_point( seg_pos, &p );
397 : : }
398 : :
399 : 0 : return CUBIT_SUCCESS;
400 : : }
401 : :
402 : 0 : double SegmentedCurve::u_from_arc_length( double param, double length )
403 : : {
404 [ # # ]: 0 : if( fabs(length) < CUBIT_RESABS )
405 : 0 : return param;
406 : :
407 : 0 : double fraction = param;
408 [ # # ]: 0 : int segment = segment_from_u( fraction );
409 [ # # ]: 0 : if( segment < 0 )
410 : 0 : return param;
411 : :
412 : : //Find the length of the remaining portion of the first
413 : : //segment (after the base param.)
414 [ # # ]: 0 : double seg_len = segment_length( segment );
415 : : // BWC double len_sum = seg_len * ( 1.0 - param + segment );
416 : : double len_sum;
417 : :
418 [ # # ]: 0 : if(length < 0.0)
419 : 0 : len_sum = seg_len*(param-segment);
420 : : else
421 : 0 : len_sum = seg_len * ( 1.0 - param + segment );
422 : :
423 : : //If the passed base param and length correspond to a
424 : : //portion of the curve which lies entirely on a single
425 : : //segment, return the passed base param plus the
426 : : //fraction of the segment (the parameter range for a
427 : : //segment is one.)
428 : : //BWC if( len_sum >= length )
429 [ # # ]: 0 : if(length < 0.0)
430 : : {
431 [ # # ]: 0 : if(-len_sum < length)
432 [ # # ]: 0 : return param + ((seg_len > CUBIT_DBL_MIN ) ? length / seg_len : 0.0);
433 : : }
434 : : else
435 : : {
436 [ # # ]: 0 : if( len_sum >= length )
437 [ # # ]: 0 : return param + ((seg_len > CUBIT_DBL_MIN ) ? length / seg_len : 0.0);
438 : : }
439 : :
440 : : //Increment the total length until we have passed up
441 : : //the specified arc length.
442 : : /*
443 : : BWC
444 : : while( length > len_sum)
445 : : {
446 : : segment++;
447 : : if( segment >= point_count() - 1 ) return -1.0;
448 : : seg_len = segment_length( segment );
449 : : len_sum += seg_len;
450 : : if(fabs(len_sum-length) < GEOMETRY_RESABS)
451 : : len_sum = length;
452 : : }
453 : : */
454 [ # # ]: 0 : if(length < 0.0)
455 : : {
456 [ # # ]: 0 : while( fabs(length) > len_sum )
457 : : {
458 : 0 : segment--;
459 [ # # ]: 0 : if( segment < 0 ) return -1.0;
460 [ # # ]: 0 : seg_len = segment_length( segment );
461 : 0 : len_sum += seg_len;
462 [ # # ]: 0 : if(fabs(len_sum+length) < GEOMETRY_RESABS)
463 : 0 : len_sum = -length;
464 : : }
465 : : }
466 : : else
467 : : {
468 [ # # ]: 0 : while( length > len_sum )
469 : : {
470 : 0 : segment++;
471 [ # # ][ # # ]: 0 : if( segment >= point_count() - 1 ) return -1.0;
472 [ # # ]: 0 : seg_len = segment_length( segment );
473 : 0 : len_sum += seg_len;
474 [ # # ]: 0 : if(fabs(len_sum-length) < GEOMETRY_RESABS)
475 : 0 : len_sum = length;
476 : : }
477 : : }
478 : :
479 : : //Now subtract off the extra length on the last segment,
480 : : //the amount passed the specified arc length. The ratio
481 : : //of this length to the total length of the last segment
482 : : //is the about we overshot the desired parameter value.
483 [ # # ]: 0 : if(length < 0.0)
484 : : {
485 [ # # ]: 0 : if( seg_len > CUBIT_DBL_MIN )
486 : 0 : return (double)(segment) + (len_sum + length)/seg_len;
487 : : else
488 : 0 : return (double)(segment);
489 : : }
490 : : else
491 : : {
492 [ # # ]: 0 : if( seg_len > CUBIT_DBL_MIN )
493 : 0 : return (double)(segment + 1) - (len_sum - length)/seg_len;
494 : : else
495 : 0 : return (double)(segment + 1);
496 : : }
497 : : }
498 : :
499 : 0 : CubitBoolean SegmentedCurve::is_position_on( const CubitVector& pos )
500 : : {
501 : : //Get the segment to test on
502 [ # # ]: 0 : CubitVector v;
503 [ # # ]: 0 : closest_segment( pos, NULL, &v);
504 : :
505 [ # # ][ # # ]: 0 : return (pos - v).length() <= GEOMETRY_RESABS ? CUBIT_TRUE : CUBIT_FALSE;
[ # # ]
506 : : }
507 : :
508 : 0 : CubitBox SegmentedCurve::bounding_box() const
509 : : {
510 [ # # ]: 0 : CubitBox b( position( 0 ) );
511 [ # # ][ # # ]: 0 : for( int i = 1; i < point_count(); i++ )
512 [ # # ][ # # ]: 0 : b |= position( i );
513 : :
514 : 0 : return b;
515 : : }
516 : :
517 : 0 : double SegmentedCurve::measure()
518 : : {
519 : 0 : double len = 0;
520 [ # # ]: 0 : for( int i = 0; i < point_count() - 1; i++ )
521 : : {
522 : 0 : len += segment_length( i );
523 : : }
524 : 0 : return len;
525 : : }
526 : :
527 : 0 : CubitStatus SegmentedCurve::get_interior_extrema(
528 : : DLIList<CubitVector*>& interior_points,
529 : : CubitSense& return_sense )
530 : : {
531 : 0 : return_sense = CUBIT_FORWARD;
532 : :
533 : : //For each point, check the segments to either side. If any of deltaX,
534 : : //deltaY or deltaZ have opposite signs for the two segments, then the
535 : : //point is an extrema in x, y, or z, respectively.
536 : 0 : int count = point_count() - 1; //stop with second-to-last point
537 : 0 : int prev_index = 0;
538 : :
539 [ # # ]: 0 : for( int i = 1; i < count; i++ )
540 : : {
541 [ # # ][ # # ]: 0 : CubitVector curr = position(i+1) - position(i);
[ # # ]
542 [ # # ][ # # ]: 0 : CubitVector prev = position( i ) - position( prev_index );
[ # # ]
543 [ # # ][ # # ]: 0 : if( (prev.x()*curr.x() < 0.0) || (prev.y()*curr.y()<0.0) || (prev.z()*curr.z()<0.0) )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
544 : : {
545 [ # # ][ # # ]: 0 : interior_points.append( new CubitVector( position(i) ) );
[ # # ]
546 : 0 : prev_index = i;
547 : : }
548 : : }
549 : 0 : return CUBIT_SUCCESS;
550 : : }
551 : :
552 : 0 : CubitStatus SegmentedCurve::get_center_radius( CubitVector&, double& )
553 : 0 : { return CUBIT_FAILURE; }
554 : :
555 : :
556 : 0 : double SegmentedCurve::closest_point_on_segment(
557 : : const CubitVector& base,
558 : : const CubitVector& dir,
559 : : const CubitVector& location )
560 : : {
561 [ # # ]: 0 : if( dir.length_squared() < CUBIT_DBL_MIN ) return 0.0;
562 : :
563 : : //Find closest location to infinite line
564 [ # # ][ # # ]: 0 : double param = dir % ( location - base ) / dir.length_squared();
565 : :
566 : : //Trim to segment
567 [ # # ]: 0 : if( param < 0.0 ) param = 0.0;
568 [ # # ]: 0 : else if( param > 1.0 ) param = 1.0;
569 : :
570 : 0 : return param;
571 : : }
572 : :
573 : : //-------------------------------------------------------------------------
574 : : // Purpose : Check for G1 discontinuities
575 : : //
576 : : // Special Notes :
577 : : //
578 : : // Creator : Jason Kraftcheck
579 : : //
580 : : // Creation Date : 05/03/00
581 : : //-------------------------------------------------------------------------
582 : 0 : CubitBoolean SegmentedCurve::G1_discontinuous( double param,
583 : : CubitVector* minus_tangent,
584 : : CubitVector* plus_tangent )
585 : : {
586 [ # # ][ # # ]: 0 : if( is_periodic() ) normalize_periodic_parameter( param );
[ # # ]
587 : :
588 : 0 : double lower = floor( param );
589 : 0 : double upper = ceil( param );
590 : 0 : int first_point = -1;
591 [ # # ]: 0 : int last = point_count() - 1;
592 [ # # ]: 0 : if( last < 2 ) return CUBIT_FALSE;
593 : :
594 : : //If the parameter value corresponds to the start of a segment,
595 : : //and that segment is not the first one
596 [ # # ][ # # ]: 0 : if( ((param - lower) < CUBIT_RESABS) && (int(lower) != 0) )
597 : 0 : first_point = int(lower) - 1;
598 : : //If the parameter value corresponds to the end of a segment,
599 : : //and that segment is not the last one
600 [ # # ][ # # ]: 0 : else if( ((upper - param) < CUBIT_RESABS) && (int(upper) < last ) )
601 : 0 : first_point = int(upper);
602 : : //If the parameter value corresponds to the start or end of the
603 : : //curve, and the curve is a closed, periodic curve.
604 [ # # ][ # # ]: 0 : else if( is_periodic() && (fabs(start_param() - end_param()) < CUBIT_RESABS) &&
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
605 [ # # ][ # # ]: 0 : ((((param - lower) < CUBIT_RESABS) && (int(lower) == 0)) ||
606 [ # # ]: 0 : (((upper - param) < CUBIT_RESABS) && (int(upper) == last)) ) )
607 : 0 : first_point = last - 1;
608 : : //Otherwise the point is in the interior of a segment
609 : 0 : else return CUBIT_FALSE;
610 : :
611 : 0 : int third_point = first_point + 2;
612 [ # # ]: 0 : if( third_point > last )
613 : : {
614 [ # # ][ # # ]: 0 : if( is_periodic() )
615 : : {
616 [ # # ]: 0 : third_point = (third_point + 1) % point_count();
617 : : }
618 : : else
619 : : {
620 : 0 : return CUBIT_FALSE;
621 : : }
622 : : }
623 : :
624 [ # # ][ # # ]: 0 : CubitVector tan1, tan2;
625 [ # # ][ # # ]: 0 : tan1 = position( first_point + 1 ) - position( first_point );
[ # # ][ # # ]
626 [ # # ][ # # ]: 0 : tan2 = position( third_point ) - position( first_point + 1 );
[ # # ][ # # ]
627 [ # # ][ # # ]: 0 : if( (tan1 * tan2).length_squared() < CUBIT_RESABS )
[ # # ]
628 : 0 : return CUBIT_FALSE;
629 : :
630 [ # # ][ # # ]: 0 : if( minus_tangent ) *minus_tangent = tan1;
631 [ # # ][ # # ]: 0 : if( plus_tangent ) *plus_tangent = tan2;
632 : 0 : return CUBIT_TRUE;
633 : : }
634 : :
635 : :
636 : : //-------------------------------------------------------------------------
637 : : // Purpose : If the curve is periodic, adjust the param value to
638 : : // be in the base range.
639 : : //
640 : : // Special Notes :
641 : : //
642 : : // Creator : Jason Kraftcheck
643 : : //
644 : : // Creation Date : 05/15/00
645 : : //-------------------------------------------------------------------------
646 : 0 : void SegmentedCurve::normalize_periodic_parameter( double& u )
647 : : {
648 : : //The parameter range for a segmented curve is always (by my implementation)
649 : : //from zero to some positive n. And the period is equal to that n. This
650 : : //simplifies the following a lot. -jk
651 : : double period;
652 [ # # ][ # # ]: 0 : if( is_periodic( period ) )
653 : : {
654 [ # # ]: 0 : if( u > period )
655 : 0 : u = fmod( u, period );
656 [ # # ]: 0 : else if( u < -period )
657 : 0 : u = fmod( u, period ) + period;
658 [ # # ]: 0 : else if( u < 0.0 )
659 : 0 : u += period; //fmod() seems to be expensive, so avoid it here.
660 : : }
661 : 0 : }
662 : :
663 : : //-------------------------------------------------------------------------
664 : : // Purpose : Constructor
665 : : //
666 : : // Special Notes :
667 : : //
668 : : // Creator : Jason Kraftcheck
669 : : //
670 : : // Creation Date : 05/15/00
671 : : //-------------------------------------------------------------------------
672 : 0 : SegmentedCurve::SegmentedCurve( PartitionSurface* surf,
673 : : DLIList<CubitVector*>& points )
674 [ # # ][ # # ]: 0 : : point_list( points.size() )
675 : : {
676 [ # # ]: 0 : points.reset();
677 [ # # ][ # # ]: 0 : for( int i = 0; i < points.size(); i++ )
678 [ # # ][ # # ]: 0 : point_list[i] = *points.get_and_step();
[ # # ]
679 : :
680 [ # # ][ # # ]: 0 : surf->sub_entity_set().add_lower_order( this );
681 : 0 : }
682 : 0 : SegmentedCurve::SegmentedCurve( PartitionLump* vol,
683 : : DLIList<CubitVector*>& points )
684 [ # # ][ # # ]: 0 : : point_list( points.size() )
685 : : {
686 [ # # ]: 0 : points.reset();
687 [ # # ][ # # ]: 0 : for( int i = 0; i < points.size(); i++ )
688 [ # # ][ # # ]: 0 : point_list[i] = *points.get_and_step();
[ # # ]
689 : :
690 [ # # ][ # # ]: 0 : vol->sub_entity_set().add_lower_order( this );
691 : 0 : }
692 : :
693 : :
694 : 0 : SegmentedCurve::SegmentedCurve( SegmentedCurve* curve, int ptcount )
695 [ # # ]: 0 : : point_list(ptcount)
696 : : {
697 [ # # ][ # # ]: 0 : curve->sub_entity_set().add_lower_order(this);
698 : 0 : }
699 : :
700 : :
701 [ # # ]: 0 : SegmentedCurve::~SegmentedCurve()
702 : : {
703 [ # # ]: 0 : }
704 : :
705 : 0 : int SegmentedCurve::point_count() const
706 : : {
707 : 0 : return point_list.size();
708 : : }
709 : :
710 : 0 : double SegmentedCurve::segment_length( int segment_no ) const
711 : : {
712 [ # # ]: 0 : return (point_list[segment_no+1] - point_list[segment_no]).length();
713 : : }
714 : :
715 : 0 : CubitVector SegmentedCurve::position( int index ) const
716 : : {
717 : 0 : return point_list[index];
718 : : }
719 : :
720 : :
721 : 0 : CubitStatus SegmentedCurve::get_graphics( GMem& result,
722 : : double /*angle_tolerance*/,
723 : : double /*distance_tolerance*/,
724 : : double /*max_edge_length*/)
725 : : {
726 : 0 : result.allocate_polylines( point_count()-1 );
727 [ # # ]: 0 : for( int i = 0; i < point_count(); i++ )
728 : : {
729 [ # # ]: 0 : CubitVector v = position(i);
730 [ # # ][ # # ]: 0 : result.point_list()[i].x = (float)(v.x());
731 [ # # ][ # # ]: 0 : result.point_list()[i].y = (float)(v.y());
732 [ # # ][ # # ]: 0 : result.point_list()[i].z = (float)(v.z());
733 : : }
734 : 0 : result.pointListCount = point_count();
735 : 0 : return CUBIT_SUCCESS;
736 : : }
737 : :
738 : 0 : CubitBoolean SegmentedCurve::is_periodic( double& period )
739 : : {
740 [ # # ]: 0 : if( is_periodic() )
741 : : {
742 : 0 : period = end_param() - start_param();
743 : 0 : return CUBIT_TRUE;
744 : : }
745 : 0 : return CUBIT_FALSE;
746 : : }
747 : :
748 : 0 : CubitBoolean SegmentedCurve::is_periodic() const
749 : : {
750 : 0 : return start_point() == end_point();
751 : : }
752 : :
753 : 0 : CubitPointContainment SegmentedCurve::point_containment( const CubitVector& pos )
754 : : {
755 : 0 : const double tol_sqr = GEOMETRY_RESABS * GEOMETRY_RESABS;
756 [ # # ][ # # ]: 0 : if( (start_point()->coordinates() - pos).length_squared() < tol_sqr )
[ # # ]
757 : 0 : return CUBIT_PNT_BOUNDARY;
758 [ # # ][ # # ]: 0 : else if( (end_point()->coordinates() - pos).length_squared() < tol_sqr )
[ # # ]
759 : 0 : return CUBIT_PNT_BOUNDARY;
760 [ # # ]: 0 : else if( is_position_on( pos ) )
761 : 0 : return CUBIT_PNT_ON;
762 : : else
763 : 0 : return CUBIT_PNT_OFF;
764 : : }
765 : :
766 : :
767 : 0 : CubitStatus SegmentedCurve::get_segments( DLIList<CubitVector*>& list )
768 : : {
769 [ # # ]: 0 : for( int i = 0; i < point_count(); i++ )
770 [ # # ][ # # ]: 0 : list.append( new CubitVector( position(i) ) );
771 : 0 : return CUBIT_SUCCESS;
772 : : }
773 : :
774 : 0 : void SegmentedCurve::reverse_sense()
775 : : {
776 : 0 : point_list.reverse();
777 : 0 : reverse_point_order();
778 [ # # ]: 0 : if( owner() )
779 : 0 : owner()->notify_reversed(this);
780 : 0 : }
781 : :
782 : 0 : CubitStatus SegmentedCurve::save( CubitSimpleAttrib& attrib )
783 : : {
784 [ # # ]: 0 : DLIList<CubitVector*> segments;
785 [ # # ]: 0 : get_segments(segments);
786 : :
787 [ # # ][ # # ]: 0 : DLIList<int> topo;
788 [ # # ]: 0 : get_save_topology( topo );
789 : :
790 [ # # ][ # # ]: 0 : int id = sub_entity_set().get_id(this);
791 : :
792 [ # # ][ # # ]: 0 : return sub_entity_set().save_geometry( id, 1, &segments, 0, &topo, 0, attrib );
[ # # ]
793 : : }
794 : :
795 : 0 : SegmentedCurve* SegmentedCurve::construct( const CubitSimpleAttrib& attrib,
796 : : PartitionEntity* parent )
797 : : {
798 [ # # ]: 0 : PartitionSurface* owning_surf = dynamic_cast<PartitionSurface*>(parent);
799 [ # # ]: 0 : PartitionLump* owning_lump = dynamic_cast<PartitionLump*>(parent);
800 [ # # ][ # # ]: 0 : if( !owning_surf && !owning_lump )
801 : 0 : return 0;
802 : :
803 [ # # ]: 0 : DLIList<int> vertex_conn;
804 [ # # ][ # # ]: 0 : SegmentedCurve* result = new SegmentedCurve( parent, attrib, vertex_conn );
805 : :
806 [ # # ][ # # ]: 0 : if( vertex_conn.size() != 4 )
807 : : {
808 [ # # ][ # # ]: 0 : delete result;
809 : 0 : return 0;
810 : : }
811 : :
812 : 0 : PartitionPoint *start = 0, *end = 0;
813 : : PartitionEntity* ent;
814 [ # # ]: 0 : vertex_conn.reset();
815 [ # # ]: 0 : int set_id = vertex_conn.get_and_step();
816 [ # # ]: 0 : int ent_id = vertex_conn.get_and_step();
817 [ # # ][ # # ]: 0 : ent = PartitionEngine::instance().entity_from_id(set_id,ent_id,parent->sub_entity_set());
[ # # ]
818 [ # # ]: 0 : start = dynamic_cast<PartitionPoint*>(ent);
819 [ # # ]: 0 : set_id = vertex_conn.get_and_step();
820 [ # # ]: 0 : ent_id = vertex_conn.get_and_step();
821 [ # # ][ # # ]: 0 : ent = PartitionEngine::instance().entity_from_id(set_id,ent_id,parent->sub_entity_set());
[ # # ]
822 [ # # ]: 0 : end = dynamic_cast<PartitionPoint*>(ent);
823 [ # # ][ # # ]: 0 : if( !start || !end )
824 : : {
825 [ # # ][ # # ]: 0 : delete result;
826 : 0 : return 0;
827 : : }
828 : :
829 [ # # ]: 0 : result->start_point(start);
830 [ # # ]: 0 : result->end_point(end);
831 [ # # ]: 0 : return result;
832 : : }
833 : :
834 : :
835 : 0 : SegmentedCurve::SegmentedCurve( PartitionEntity* vol,
836 : : const CubitSimpleAttrib& attrib,
837 [ # # ]: 0 : DLIList<int>& vertex_conn )
838 : : {
839 [ # # ]: 0 : DLIList<CubitVector*> points;
840 [ # # ][ # # ]: 0 : DLIList<int> junk;
841 [ # # ][ # # ]: 0 : vol->sub_entity_set().add_lower_order( this, attrib, 1, points, junk, vertex_conn, junk );
842 : :
843 [ # # ]: 0 : points.reset();
844 [ # # ][ # # ]: 0 : point_list.size(points.size());
845 [ # # ][ # # ]: 0 : for( int i = 0; i < points.size(); i++ )
846 : : {
847 [ # # ]: 0 : CubitVector* pt = points.get_and_step();
848 [ # # ][ # # ]: 0 : point_list[i] = *pt;
849 : 0 : delete pt;
850 [ # # ]: 0 : }
851 : 0 : }
852 : :
853 : 0 : void SegmentedCurve::transform( const CubitTransformMatrix& xform )
854 : : {
855 : 0 : PartitionCurve::transform(xform);
856 [ # # ]: 0 : for( int i = 0; i < point_list.size(); i++ )
857 [ # # ][ # # ]: 0 : point_list[i] = xform * point_list[i];
858 : 0 : }
859 : :
860 : 0 : void SegmentedCurve::print_debug_info( const char* prefix, bool pss ) const
861 : : {
862 [ # # ]: 0 : if( prefix == 0 ) prefix = "";
863 : 0 : PartitionCurve::print_debug_info( prefix, pss );
864 [ # # ][ # # ]: 0 : PRINT_INFO("%sSegmentedCurve %p\n", prefix, (void*)this);
865 [ # # ][ # # ]: 0 : PRINT_INFO("%s%d segment points:\n", prefix, point_list.size());
866 : : int i;
867 [ # # ]: 0 : for( i = 0; i < point_list.size() - 1; i+= 2 )
868 : : {
869 [ # # ]: 0 : PRINT_INFO("%s (%f, %f, %f), (%f, %f, %f),\n",
870 : : prefix, point_list[i ].x(), point_list[i ].y(), point_list[i ].z(),
871 [ # # ]: 0 : point_list[i+1].x(), point_list[i+1].y(), point_list[i+1].z());
872 : : }
873 [ # # ]: 0 : if( i == point_list.size() - 1 )
874 : : {
875 [ # # ]: 0 : PRINT_INFO("%s (%f, %f, %f)\n", prefix, point_list[i].x(),
876 [ # # ]: 0 : point_list[i].y(), point_list[i].z());
877 : : }
878 : 0 : }
879 : :
880 : 0 : CubitStatus SegmentedCurve::get_spline_params
881 : : (
882 : : bool &rational, // return true/false
883 : : int °ree, // the degree of this spline
884 : : DLIList<CubitVector> &cntrl_pts, // xyz position of controlpoints
885 : : DLIList<double> &cntrl_pt_weights, // if rational, a weight for each cntrl point.
886 : : DLIList<double> &knots, // There should be order+cntrl_pts.size()-2 knots
887 : : bool &spline_is_reversed
888 : : ) const
889 : : {
890 [ # # ][ # # ]: 0 : PRINT_ERROR("Currently, Cubit is unable to determine spline parameters for SegmentedCurves.\n");
891 : 0 : return CUBIT_FAILURE;
892 : : }
893 : :
894 : 0 : CubitStatus SegmentedCurve::get_ellipse_params
895 : : (
896 : : CubitVector ¢er_vec,
897 : : CubitVector &normal,
898 : : CubitVector &major_axis,
899 : : double &radius_ratio
900 : : ) const
901 : : {
902 [ # # ][ # # ]: 0 : PRINT_ERROR("Currently, Cubit is unable to determine ellipse parameters for SegmentedCurves.\n");
903 : 0 : return CUBIT_FAILURE;
904 [ + - ][ + - ]: 6364 : }
|