1 /* $NoKeywords: $ */
2 /*
3 //
4 // Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved.
5 // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
6 // McNeel & Associates.
7 //
8 // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
9 // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
10 // MERCHANTABILITY ARE HEREBY DISCLAIMED.
11 //
12 // For complete openNURBS copyright information see <http://www.opennurbs.org>.
13 //
14 ////////////////////////////////////////////////////////////////
15 */
16 
17 ////////////////////////////////////////////////////////////////
18 //
19 //   Definition of poly curve (composite curve)
20 //
21 ////////////////////////////////////////////////////////////////
22 
23 #if !defined(OPENNURBS_POLYCURVE_INC_)
24 #define OPENNURBS_POLYCURVE_INC_
25 
26 /*
27  Description:
28 		An ON_PolyCurve is an ON_Curve represented by a sequence of
29 	contiguous ON_Curve segments.    A valid polycurve is represented
30 	by an array m_segment of Count()>=1 curve objects	and a strictly
31 	increasing array m_t of Count()+1 parameter values.  The i-th
32 	curve segment,  when considered as part of the polycurve, is affinely
33 	reparamaterized from m_t[i] to m_t[i+1], i.e., m_segment[i].Domain()[0]
34 	is mapped to 	m_t[i] and m_segment[i].Domain()[1] is mapped to m_t[i+1].
35 */
36 class ON_PolyCurve;
37 class ON_CLASS ON_PolyCurve : public ON_Curve
38 {
39   ON_OBJECT_DECLARE(ON_PolyCurve);
40 
41 public:
42   // virtual ON_Object::DestroyRuntimeCache override
43   void DestroyRuntimeCache( bool bDelete = true );
44 
45 public:
46   ON_PolyCurve();
47   ON_PolyCurve( int ); // int = initial capacity - use when a good estimate
48                         // of the number of segments is known.
49   ON_PolyCurve(const ON_PolyCurve&);
50 
51   void Destroy();
52 
53   virtual ~ON_PolyCurve();
54 
55   void EmergencyDestroy(); // call if memory used by ON_PolyCurve becomes invalid
56 
57 	ON_PolyCurve& operator=(const ON_PolyCurve&);
58 
59   /////////////////////////////////////////////////////////////////
60   // ON_Object overrides
61 
62   // virtual ON_Object::SizeOf override
63   unsigned int SizeOf() const;
64 
65   // virtual ON_Object::DataCRC override
66   ON__UINT32 DataCRC(ON__UINT32 current_remainder) const;
67 
68   /*
69   Description:
70     Tests an object to see if its data members are correctly
71     initialized.
72   Parameters:
73     text_log - [in] if the object is not valid and text_log
74         is not NULL, then a brief englis description of the
75         reason the object is not valid is appened to the log.
76         The information appended to text_log is suitable for
77         low-level debugging purposes by programmers and is
78         not intended to be useful as a high level user
79         interface tool.
80   Returns:
81     @untitled table
82     true     object is valid
83     false    object is invalid, uninitialized, etc.
84   Remarks:
85     Overrides virtual ON_Object::IsValid
86   */
87   ON_BOOL32 IsValid( ON_TextLog* text_log = NULL ) const;
88 
89   /*
90   Description:
91     Tests an object to see if its data members are correctly
92     initialized.
93   Parameters:
94     bAllowGaps - [in]
95       If true, gaps are allowed between polycurve segments.
96       If false, gaps are not allowed between polycurve segments.
97     text_log - [in] if the object is not valid and text_log
98         is not NULL, then a brief englis description of the
99         reason the object is not valid is appened to the log.
100         The information appended to text_log is suitable for
101         low-level debugging purposes by programmers and is
102         not intended to be useful as a high level user
103         interface tool.
104   Returns:
105     @untitled table
106     true     object is valid
107     false    object is invalid, uninitialized, etc.
108   Remarks:
109     Overrides virtual ON_Object::IsValid
110   */
111   bool IsValid( bool bAllowGaps, ON_TextLog* text_log ) const;
112 
113 
114   void Dump( ON_TextLog& ) const; // for debugging
115 
116   ON_BOOL32 Write(
117          ON_BinaryArchive&  // open binary file
118        ) const;
119 
120   ON_BOOL32 Read(
121          ON_BinaryArchive&  // open binary file
122        );
123 
124   /////////////////////////////////////////////////////////////////
125   // ON_Geometry overrides
126 
127   int Dimension() const;
128 
129   ON_BOOL32 GetBBox( // returns true if successful
130          double*,    // minimum
131          double*,    // maximum
132          ON_BOOL32 = false  // true means grow box
133          ) const;
134 
135   /*
136 	Description:
137     Get tight bounding box.
138 	Parameters:
139 		tight_bbox - [in/out] tight bounding box
140 		bGrowBox -[in]	(default=false)
141       If true and the input tight_bbox is valid, then returned
142       tight_bbox is the union of the input tight_bbox and the
143       curve's tight bounding box.
144 		xform -[in] (default=NULL)
145       If not NULL, the tight bounding box of the transformed
146       curve is calculated.  The curve is not modified.
147 	Returns:
148     True if a valid tight_bbox is returned.
149   */
150 	bool GetTightBoundingBox(
151 			ON_BoundingBox& tight_bbox,
152       int bGrowBox = false,
153 			const ON_Xform* xform = 0
154       ) const;
155 
156   ON_BOOL32 Transform(
157          const ON_Xform&
158          );
159 
160   // virtual ON_Geometry::IsDeformable() override
161   bool IsDeformable() const;
162 
163   // virtual ON_Geometry::MakeDeformable() override
164   bool MakeDeformable();
165 
166   ON_BOOL32 SwapCoordinates(
167         int, int        // indices of coords to swap
168         );
169 
170   // virtual ON_Geometry override
171   bool EvaluatePoint( const class ON_ObjRef& objref, ON_3dPoint& P ) const;
172 
173   /////////////////////////////////////////////////////////////////
174   // ON_Curve overrides
175 
176   ON_Curve* DuplicateCurve() const;
177 
178   ON_Interval Domain() const;
179 
180   // Description:
181   //   virtual ON_Curve::SetDomain override.
182   //   Set the domain of the curve
183   // Parameters:
184   //   t0 - [in]
185   //   t1 - [in] new domain will be [t0,t1]
186   // Returns:
187   //   true if successful.
188   ON_BOOL32 SetDomain(
189         double t0,
190         double t1
191         );
192 
193   bool ChangeDimension(
194           int desired_dimension
195           );
196 
197   /*
198   Description:
199     If this curve is closed, then modify it so that
200     the start/end point is at curve parameter t.
201   Parameters:
202     t - [in] curve parameter of new start/end point.  The
203              returned curves domain will start at t.
204   Returns:
205     true if successful.
206   Remarks:
207     Overrides virtual ON_Curve::ChangeClosedCurveSeam
208   */
209   ON_BOOL32 ChangeClosedCurveSeam(
210             double t
211             );
212 
213   int SpanCount() const; // number of smooth spans in curve
214 
215   ON_BOOL32 GetSpanVector( // span "knots"
216          double* // array of length SpanCount() + 1
217          ) const; //
218 
219   int Degree( // returns maximum algebraic degree of any span
220                   // ( or a good estimate if curve spans are not algebraic )
221     ) const;
222 
223   ON_BOOL32 IsLinear( // true if curve locus is a line segment between
224                  // between specified points
225         double = ON_ZERO_TOLERANCE // tolerance to use when checking linearity
226         ) const;
227 
228   /*
229   Description:
230     Several types of ON_Curve can have the form of a polyline including
231     a degree 1 ON_NurbsCurve, an ON_PolylineCurve, and an ON_PolyCurve
232     all of whose segments are some form of polyline.  IsPolyline tests
233     a curve to see if it can be represented as a polyline.
234   Parameters:
235     pline_points - [out] if not NULL and true is returned, then the
236         points of the polyline form are returned here.
237     t - [out] if not NULL and true is returned, then the parameters of
238         the polyline points are returned here.
239   Returns:
240     @untitled table
241     0        curve is not some form of a polyline
242     >=2      number of points in polyline form
243   */
244   int IsPolyline(
245         ON_SimpleArray<ON_3dPoint>* pline_points = NULL,
246         ON_SimpleArray<double>* pline_t = NULL
247         ) const;
248 
249   ON_BOOL32 IsArc( // ON_Arc.m_angle > 0 if curve locus is an arc between
250               // specified points
251         const ON_Plane* = NULL, // if not NULL, test is performed in this plane
252         ON_Arc* = NULL, // if not NULL and true is returned, then arc parameters
253                          // are filled in
254         double = ON_ZERO_TOLERANCE    // tolerance to use when checking
255         ) const;
256 
257   ON_BOOL32 IsPlanar(
258         ON_Plane* = NULL, // if not NULL and true is returned, then plane parameters
259                            // are filled in
260         double = ON_ZERO_TOLERANCE    // tolerance to use when checking
261         ) const;
262 
263   ON_BOOL32 IsInPlane(
264         const ON_Plane&, // plane to test
265         double = ON_ZERO_TOLERANCE    // tolerance to use when checking
266         ) const;
267 
268   ON_BOOL32 IsClosed(  // true if curve is closed (either curve has
269         void      // clamped end knots and euclidean location of start
270         ) const;  // CV = euclidean location of end CV, or curve is
271                   // periodic.)
272 
273   ON_BOOL32 IsPeriodic(  // true if curve is a single periodic segment
274         void
275         ) const;
276 
277   /*
278   Description:
279     Search for a derivatitive, tangent, or curvature discontinuity.
280   Parameters:
281     c - [in] type of continity to test for.  If ON::C1_continuous
282     t0 - [in] search begins at t0
283     t1 - [in] (t0 < t1) search ends at t1
284     t - [out] if a discontinuity is found, the *t reports the
285           parameter at the discontinuity.
286     hint - [in/out] if GetNextDiscontinuity will be called repeatedly,
287        passing a "hint" with initial value *hint=0 will increase the speed
288        of the search.
289     dtype - [out] if not NULL, *dtype reports the kind of discontinuity
290         found at *t.  A value of 1 means the first derivative or unit tangent
291         was discontinuous.  A value of 2 means the second derivative or
292         curvature was discontinuous.
293     cos_angle_tolerance - [in] default = cos(1 degree) Used only when
294         c is ON::G1_continuous or ON::G2_continuous.  If the cosine
295         of the angle between two tangent vectors
296         is <= cos_angle_tolerance, then a G1 discontinuity is reported.
297     curvature_tolerance - [in] (default = ON_SQRT_EPSILON) Used only when
298         c is ON::G2_continuous or ON::Gsmooth_continuous.
299         ON::G2_continuous:
300           If K0 and K1 are curvatures evaluated
301           from above and below and |K0 - K1| > curvature_tolerance,
302           then a curvature discontinuity is reported.
303         ON::Gsmooth_continuous:
304           If K0 and K1 are curvatures evaluated from above and below
305           and the angle between K0 and K1 is at least twice angle tolerance
306           or ||K0| - |K1|| > (max(|K0|,|K1|) > curvature_tolerance,
307           then a curvature discontinuity is reported.
308   Returns:
309     true if a discontinuity was found on the interior of the interval (t0,t1).
310   Remarks:
311     Overrides ON_Curve::GetNextDiscontinuity.
312   */
313   bool GetNextDiscontinuity(
314                   ON::continuity c,
315                   double t0,
316                   double t1,
317                   double* t,
318                   int* hint=NULL,
319                   int* dtype=NULL,
320                   double cos_angle_tolerance=ON_DEFAULT_ANGLE_TOLERANCE_COSINE,
321                   double curvature_tolerance=ON_SQRT_EPSILON
322                   ) const;
323 
324   /*
325   Description:
326     Test continuity at a curve parameter value.
327   Parameters:
328     c - [in] continuity to test for
329     t - [in] parameter to test
330     hint - [in] evaluation hint
331     point_tolerance - [in] if the distance between two points is
332         greater than point_tolerance, then the curve is not C0.
333     d1_tolerance - [in] if the difference between two first derivatives is
334         greater than d1_tolerance, then the curve is not C1.
335     d2_tolerance - [in] if the difference between two second derivatives is
336         greater than d2_tolerance, then the curve is not C2.
337     cos_angle_tolerance - [in] default = cos(1 degree) Used only when
338         c is ON::G1_continuous or ON::G2_continuous.  If the cosine
339         of the angle between two tangent vectors
340         is <= cos_angle_tolerance, then a G1 discontinuity is reported.
341     curvature_tolerance - [in] (default = ON_SQRT_EPSILON) Used only when
342         c is ON::G2_continuous or ON::Gsmooth_continuous.
343         ON::G2_continuous:
344           If K0 and K1 are curvatures evaluated
345           from above and below and |K0 - K1| > curvature_tolerance,
346           then a curvature discontinuity is reported.
347         ON::Gsmooth_continuous:
348           If K0 and K1 are curvatures evaluated from above and below
349           and the angle between K0 and K1 is at least twice angle tolerance
350           or ||K0| - |K1|| > (max(|K0|,|K1|) > curvature_tolerance,
351           then a curvature discontinuity is reported.
352   Returns:
353     true if the curve has at least the c type continuity at the parameter t.
354   Remarks:
355     Overrides ON_Curve::IsContinuous.
356   */
357   bool IsContinuous(
358     ON::continuity c,
359     double t,
360     int* hint = NULL,
361     double point_tolerance=ON_ZERO_TOLERANCE,
362     double d1_tolerance=ON_ZERO_TOLERANCE,
363     double d2_tolerance=ON_ZERO_TOLERANCE,
364     double cos_angle_tolerance=ON_DEFAULT_ANGLE_TOLERANCE_COSINE,
365     double curvature_tolerance=ON_SQRT_EPSILON
366     ) const;
367 
368   ON_BOOL32 Reverse();       // reverse parameterizatrion
369                         // Domain changes from [a,b] to [-b,-a]
370 
371   /*
372   Description:
373     Force the curve to start at a specified point.
374   Parameters:
375     start_point - [in]
376   Returns:
377     true if successful.
378   Remarks:
379     Some start points cannot be moved.  Be sure to check return
380     code.
381   See Also:
382     ON_Curve::SetEndPoint
383     ON_Curve::PointAtStart
384     ON_Curve::PointAtEnd
385   */
386   // virtual
387   ON_BOOL32 SetStartPoint(
388           ON_3dPoint start_point
389           );
390 
391   /*
392   Description:
393     Force the curve to end at a specified point.
394   Parameters:
395     end_point - [in]
396   Returns:
397     true if successful.
398   Remarks:
399     Some end points cannot be moved.  Be sure to check return
400     code.
401   See Also:
402     ON_Curve::SetStartPoint
403     ON_Curve::PointAtStart
404     ON_Curve::PointAtEnd
405   */
406   //virtual
407   ON_BOOL32 SetEndPoint(
408           ON_3dPoint end_point
409           );
410 
411   ON_BOOL32 Evaluate( // returns false if unable to evaluate
412          double,         // evaluation parameter
413          int,            // number of derivatives (>=0)
414          int,            // array stride (>=Dimension())
415          double*,        // array of length stride*(ndir+1)
416          int = 0,        // optional - determines which side to evaluate from
417                          //         0 = default
418                          //      <  0 to evaluate from below,
419                          //      >  0 to evaluate from above
420          int* = 0        // optional - evaluation hint (int) used to speed
421                          //            repeated evaluations
422          ) const;
423 
424   // Description:
425   //   virtual ON_Curve::Trim override.
426   //   Removes portions of the curve outside the specified interval.
427   // Parameters:
428   //   domain - [in] interval of the curve to keep.  Portions of the
429   //      curve before curve(domain[0]) and after curve(domain[1]) are
430   //      removed.
431   // Returns:
432   //   true if successful.
433   ON_BOOL32 Trim(
434     const ON_Interval& domain
435     );
436 
437   // Description:
438   //   Where possible, analytically extends curve to include domain.
439   // Parameters:
440   //   domain - [in] if domain is not included in curve domain,
441   //   curve will be extended so that its domain includes domain.
442   //   Will not work if curve is closed. Original curve is identical
443   //   to the restriction of the resulting curve to the original curve domain,
444   // Returns:
445   //   true if successful.
446   bool Extend(
447     const ON_Interval& domain
448     );
449 
450   // Description:
451   //   virtual ON_Curve::Split override.
452   //   Divide the curve at the specified parameter.  The parameter
453   //   must be in the interior of the curve's domain.  The pointers
454   //   passed to Split must either be NULL or point to an ON_Curve
455   //   object of the same of the same type.  If the pointer is NULL,
456   //   then a curve will be created in Split().  You may pass "this"
457   //   as one of the pointers to Split().
458   // Parameters:
459   //   t - [in] parameter in interval Domain().
460   //   left_side - [out] left portion of curve
461   //   right_side - [out] right portion of curve
462   // Example:
463   //   For example, if crv were an ON_NurbsCurve, then
464   //
465   //     ON_NurbsCurve right_side;
466   //     crv.Split( crv.Domain().Mid() &crv, &right_side );
467   //
468   //   would split crv at the parametric midpoint, put the left side
469   //   in crv, and return the right side in right_side.
470   ON_BOOL32 Split(
471       double t,    // t = curve parameter to split curve at
472       ON_Curve*& left_side, // left portion returned here
473       ON_Curve*& right_side // right portion returned here
474     ) const;
475 
476   int GetNurbForm( // returns 0: unable to create NURBS representation
477                    //            with desired accuracy.
478                    //         1: success - returned NURBS parameterization
479                    //            matches the curve's to wthe desired accuracy
480                    //         2: success - returned NURBS point locus matches
481                    //            the curve's to the desired accuracy but, on
482                    //            the interior of the curve's domain, the
483                    //            curve's parameterization and the NURBS
484                    //            parameterization may not match to the
485                    //            desired accuracy.
486         ON_NurbsCurve&,
487         double = 0.0,
488         const ON_Interval* = NULL     // OPTIONAL subdomain of polycurve
489         ) const;
490 
491   int HasNurbForm( // returns 0: unable to create NURBS representation
492                    //            with desired accuracy.
493                    //         1: success - returned NURBS parameterization
494                    //            matches the curve's to wthe desired accuracy
495                    //         2: success - returned NURBS point locus matches
496                    //            the curve's to the desired accuracy but, on
497                    //            the interior of the curve's domain, the
498                    //            curve's parameterization and the NURBS
499                    //            parameterization may not match to the
500                    //            desired accuracy.
501         ) const;
502 
503   // virtual ON_Curve::GetCurveParameterFromNurbFormParameter override
504   ON_BOOL32 GetCurveParameterFromNurbFormParameter(
505         double, // nurbs_t
506         double* // curve_t
507         ) const;
508 
509   // virtual ON_Curve::GetNurbFormParameterFromCurveParameter override
510   ON_BOOL32 GetNurbFormParameterFromCurveParameter(
511         double, // curve_t
512         double* // nurbs_t
513         ) const;
514 
515   /////////////////////////////////////////////////////////////////
516   // Interface
517 
518   int Count() const; // number of segment curves
519 
520   // These operator[] functions return NULL if index is out of range
521   ON_Curve* operator[](int) const;
522 
523   /*
524   Description:
525     Returns a pointer to a segment curve.
526   Parameters:
527     segment_index - [in] 0 based index  (0 <= segment_index < Count() )
528   Returns:
529     A pointer to the segment curve.  Returns NULL if segment_index < 0
530     or segment_index >= Count().
531   */
532   ON_Curve* SegmentCurve(
533     int segment_index
534     ) const;
535 
536   /*
537   Description:
538     Converts a polycurve parameter to a segment curve parameter.
539   Parameters:
540     polycurve_parameter - [in]
541   Returns:
542     Segment curve evaluation parameter or ON_UNSET_VALUE if the
543     segment curve parameter cannot be computed.
544   See Also:
545     ON_PolyCurve::PolyCurveParameter
546   */
547   double SegmentCurveParameter(
548     double polycurve_parameter
549     ) const;
550 
551   /*
552   Description:
553     Converts a segment curve parameter to a polycurve parameter.
554   Parameters:
555     segment_index - [in]
556     segmentcurve_parameter - [in]
557   Returns:
558     Polycurve evaluation parameter or ON_UNSET_VALUE if the
559     polycurve curve parameter cannot be computed.
560   See Also:
561     ON_PolyCurve::SegmentCurveParameter
562   */
563   double PolyCurveParameter(
564     int segment_index,
565     double segmentcurve_parameter
566     ) const;
567 
568   /*
569   Description:
570     Returns the polycurve subdomain assigned to a segment curve.
571   Parameters:
572     segment_index - [in] 0 based index  (0 <= segment_index < Count() )
573   Returns:
574     The polycurve subdomain assigned to a segment curve.
575     Returns ([ON_UNSET_VALUE,ON_UNSET_VALUE) if segment_index < 0
576     or segment_index >= Count().
577   */
578   ON_Interval SegmentDomain(
579     int segment_index
580     ) const;
581 
582   /*
583   Description:
584     Find the segment used for evaluation at polycurve_parameter.
585   Parameters:
586     polycurve_parameter - [in]
587   Returns:
588     index of the segment used for evaluation at polycurve_parameter.
589     If polycurve_parameter < Domain.Min(), then 0 is returned.
590     If polycurve_parameter > Domain.Max(), then Count()-1 is returned.
591   */
592   int SegmentIndex(
593     double polycurve_parameter
594     ) const;
595 
596   /*
597   Description:
598     Find the segments with support on sub_domain.
599   Parameters:
600     sub_domain - [in] increasing interval
601     segment_index0 - [out]
602     segment_index1 - [out] segments with index i where
603       *segment_index0 <= i < *segment_index1 are the segments
604       with support on the sub_domain
605   Returns:
606     number of segments with support on sub_domain.
607   */
608   int SegmentIndex(
609     ON_Interval sub_domain,
610     int* segment_index0,
611     int* segment_index1
612     ) const;
613 
614   ON_Curve* FirstSegmentCurve() const; // returns NULL if count = 0
615 
616   ON_Curve* LastSegmentCurve() const;  // returns NULL if count = 0
617 
618   /*
619   Description:
620     Search the curve for gaps between the sub curve segments.
621   Parameters:
622     segment_index0 - [in]
623       The search for gaps starts at with the comparing
624       the end of segment[segment_index0] and the start of
625       segment[segment_index0+1].
626   Returns:
627     0:
628       No gaps were found.
629     i > segment_index0:
630       The end of polycuve segment[i-1] is not coincident
631       with the start of polycurve segment[i].
632   */
633   int FindNextGap( int segment_index0 ) const;
634 
635   /*
636   Description:
637     Determine if there is a gap between the end of
638     segment[segment_index] and the start of segment[segment_index+1].
639   Parameters:
640     segment_index - [in]
641       >= 0
642   Returns:
643     true:
644       segment_index was valid and there is a gap between
645       the end of segment[segment_index] and the start of
646       segment[segment_index+1].
647   */
648   bool HasGapAt( int segment_index ) const;
649 
650   // Replace calls to HasGap() with FindNextGap(0)
651   ON_DEPRECATED int HasGap() const;
652 
653   /*
654   Description:
655     Modify the one or both locations at the end of
656     segment[gap_index-1] and the start of segment[gap_index]
657     so they are coindicent.
658   Parameters:
659     gap_index - [in] 1 <= gap_index < Count()
660       If the locations at the end of segment[gap_index-1] and
661       the start of segment[gap_index] are not identical, then
662       an attempt is made to modify the segments so these
663       locations are closer.
664     ends_to_modify - [in]
665       0: (suggested)
666         The code will decide what segments to modify.
667       1:
668         modify the end location of segment[gap_index-1]
669       2:
670         modify the start location of segment[gap_index]
671   Returns:
672     True if a modification was performed and HasGap(gap_index-1)
673     returns 0 after the modification.
674     False if no modification was preformed because there
675     was no gap or because one could not be performed.
676   Remarks:
677     Note that passing the return value from FindNextGap() will
678     close the gap found by FindNextGap().
679   */
680   bool CloseGap( int gap_index, int segments_to_modify );
681 
682   /*
683   Description:
684     Searches for and closes all gaps that can be found.
685   Returns:
686     Number of gaps that were closed.
687   */
688   int CloseGaps();
689 
690   void Reserve( int ); // make sure capacity is at least the specified count
691 
692   // ON_Curve pointers added with Prepend(), Append(), PrependAndMatch(), AppendANdMatch(),and Insert() are deleted
693   // by ~ON_PolyCurve(). Use ON_CurveProxy( ON_Curve*) if you want
694   // the original curve segment to survive ~ON_PolyCurve().
695   ON_BOOL32 Prepend( ON_Curve* ); // Prepend curve.
696   ON_BOOL32 Append( ON_Curve* );  // Append curve.
697   ON_BOOL32 Insert(
698            int, // segment_index,
699            ON_Curve*
700            );
701 
702   //PrependAndMatch() and AppendAndMatch() return false if this->IsCLosed() or
703   //this->Count() > 0 and curve is closed
704   ON_BOOL32 PrependAndMatch(ON_Curve*); //Prepend and match end of curve to start of polycurve
705   ON_BOOL32 AppendAndMatch(ON_Curve*);  //Append and match start of curve to end of polycurve
706 
707   ON_BOOL32 Remove(); // delete last segment and reduce count by 1
708   ON_BOOL32 Remove( int ); // delete specified segment and reduce count by 1
709 
710   //////////
711   // Use the HarvestSegment() function when you want to prevent a
712   // segment from being destroyed by ~ON_PolyCurve().  HarvestSegment()
713   // replaces the polycurve segment with a NULL.  Count() and parameter
714   // information remains unchanged.
715   ON_Curve* HarvestSegment( int );
716 
717 	/*
718   Returns:
719     True if a curve in the m_segment[] array is an ON_PolyCurve.
720   */
721   bool IsNested() const;
722 
723 	/*
724   Description:
725     Same as RemoveNestingEx().
726   Remarks:
727     RemoveNestingEx was added to avoid breaking the SDK.
728   */
729 	void RemoveNesting();
730 
731   /*
732   Description:
733     Removes the nested of polycurves. The result will have not
734     have an  ON_PolyCurve  as a segment but will have identical
735     locus and parameterization.
736   Returns:
737     True if a nested polycurve was removed.  False
738     if no nested polycurves were found.
739   */
740 	bool RemoveNestingEx();
741 
742   /*
743   Returns:
744     True if the domains of the curves in the m_segment[] array exactly
745     match the domains of the segments specified in the m_t[] array.
746     Put another way, returns true if SegmentDomain(i) = SegmentCurve(i).Domain()
747     for every segment index.
748   */
749 	bool HasSynchronizedSegmentDomains() const;
750 
751   /*
752   Description:
753     Sets the domain of the curve int the m_segment[] array to exactly
754     match the domain defined in the m_t[] array.  This is not required,
755     but can simplify some coding situations.
756   Returns:
757     True if at least one segment was reparameterized. False if no
758     changes were made.
759   */
760 	bool SynchronizeSegmentDomains();
761 
762 
763 
764 
765 	//////////
766 	// Expert user function
767 	//   Sets the m_segment[index] to crv.
768 	void SetSegment(int index, ON_Curve* crv);
769 
770 	//////////
771   /*
772   Description:
773 	  Expert user function to set the m_t[] array.
774   Parameters:
775     t - [in] increasing array of SegmentCount()+1 parameters.
776   Returns
777     True if successful.
778   */
779   bool SetParameterization( const double* t );
780 
781 /*
782 	Description:
783 		Lookup a parameter in the m_t array, optionally using a built in snap tolerance to
784 		snap a parameter value to an element of m_t.
785 	Parameters:
786 		t    - [in]	  	parameter
787 		index -[out]	index into m_t such that if the function returns true then t is equal
788 									to, or is within tolerance of m_t[index].
789 					  			if function returns false then the value of index is
790 
791 									 @table
792 												condition									value of index
793 						  			t<m_t[0] or m_t is empty				-1
794 										m_t[i] < t < m_t[i+1]				i for 0<=i<=m_t.Count()-2
795 										t>m_t[ m_t.Count()-1]				m_t.Count()-1
796 
797 		bEnableSnap -[in]  if true use tolerance when comparing to m_t values
798 	Returns
799 		true if the t is exactly equal to, or within tolerance of
800 		(only if bEnableSnap==true) m_t[index].
801 */
802 	bool ParameterSearch(double t, int& index, bool bEnableSnap) const;
803 
804   /*
805   Returns:
806     Reference to m_segment.
807   */
808   const ON_CurveArray& SegmentCurves() const;
809 
810   /*
811   Returns:
812     Reference to m_t.
813   */
814   const ON_SimpleArray<double>& SegmentParameters() const;
815 
816   /////////////////////////////////////////////////////////////////
817   // Implementation
818 private:
819   // The curves in this array are deleted by ~ON_PolyCurve().
820   // Use ON_CurveProxy classes if you don't want ON_PolyCurve()
821   // to destroy the curve.
822 
823   ON_CurveArray m_segment;  // array of pointers to curves
824                              // all have the same dimension
825                              // and are contiguous to tolerance
826 
827   ON_SimpleArray<double> m_t; // ON_PolyCurve segment parameterizations
828 };
829 
830 
831 #endif
832