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 NURBS surface
20 //
21 ////////////////////////////////////////////////////////////////
22 
23 #if !defined(OPENNURBS_NURBSSURFACE_INC_)
24 #define OPENNURBS_NURBSSURFACE_INC_
25 
26 class ON_CLASS ON_TensorProduct
27 {
28   // Pure virtual tensor passed to ON_NurbsSurface::TensorProduct()
29 public:
30   ON_TensorProduct();
31 
32   virtual
33   ~ON_TensorProduct();
34 
35   // Evaluate() must define a function T:R^dimA X R^dimB -> R^Dimension()
36   // such that
37   //
38   //          T(a*A0 + (1-a)*A1, B) = a*T(A0,B) + (1-a)*T(A1,B) and
39   //          T(A, b*B0 + (1-b)*B1) = b*T(A,B0) + (1-b)*T(A,B1).
40   virtual
41   int DimensionA() const = 0; // dimension of A space
42 
43   virtual
44   int DimensionB() const = 0; // dimension of B space
45 
46   virtual
47   int DimensionC() const = 0; // dimension of range space
48 
49   virtual
50   bool Evaluate( double,        // a
51                  const double*, // A
52                  double,        // b
53                  const double*, // B
54                  double*        // C
55                 ) = 0;
56 
57 };
58 
59 class ON_Brep;
60 class ON_NurbsSurface;
61 
62 class ON_CLASS ON_NurbsSurface : public ON_Surface
63 {
64   ON_OBJECT_DECLARE(ON_NurbsSurface);
65 
66 public:
67   /*
68   Description:
69     Use ON_NurbsSurface::New(...) instead of new ON_NurbsSurface(...)
70   Returns:
71     Pointer to an ON_NurbsSurface.  Destroy by calling delete.
72   Remarks:
73     See static ON_Brep* ON_Brep::New() for details.
74   */
75   static ON_NurbsSurface* New();
76   static ON_NurbsSurface* New(
77           const ON_NurbsSurface& nurbs_surface
78           );
79   static ON_NurbsSurface* New(
80             const ON_BezierSurface& bezier_surface
81             );
82   static ON_NurbsSurface* New(
83           int dimension,
84           ON_BOOL32 bIsRational,
85           int order0,
86           int order1,
87           int cv_count0,
88           int cv_count1
89           );
90 
91   ON_NurbsSurface();
92   ON_NurbsSurface(const ON_NurbsSurface& nurbs_surface);
93   ON_NurbsSurface(const ON_BezierSurface& bezier_surface);
94   ON_NurbsSurface(
95           int dimension,     // dimension (>= 1)
96           ON_BOOL32 bIsRational, // true to make a rational NURBS
97           int order0,       // order0 (>= 2)
98           int order1,       // order1 (>= 2)
99           int cv_count0,    // cv count0 (>= order0)
100           int cv_count1     // cv count1 (>= order1)
101           );
102 
103   // virtual ON_Object::SizeOf override
104   unsigned int SizeOf() const;
105 
106   // virtual ON_Object::DataCRC override
107   ON__UINT32 DataCRC(ON__UINT32 current_remainder) const;
108 
109   /*
110   Description:
111     See if this and other are same NURBS geometry.
112   Parameters:
113     other - [in] other NURBS surface
114     bIgnoreParameterization - [in] if true, parameterization
115              and orientaion are ignored.
116     tolerance - [in] tolerance to use when comparing
117                      control points.
118   Returns:
119     true if curves are tne same.
120   */
121   bool IsDuplicate(
122           const ON_NurbsSurface& other,
123           bool bIgnoreParameterization,
124           double tolerance = ON_ZERO_TOLERANCE
125           ) const;
126 
127   void Initialize(void);  // zeros all fields
128 
129   ON_BOOL32 Create(
130           int dim,  // dimension (>= 1)
131           ON_BOOL32 is_rat, // true to make a rational NURBS
132           int order0,  // order0 (>= 2)
133           int order1,  // order1 (>= 2)
134           int cv_count0,  // cv count0 (>= order0)
135           int cv_count1  // cv count1 (>= order1)
136           );
137 
138   /*
139   Description:
140     Create a ruled surface from two curves.
141   Parameters:
142     curveA - [in] (must have same NURBS form knots as curveB)
143     curveB - [in] (must have same NURBS form knots as curveA)
144     curveA_domain - [in] if not NULL, then this is a subdomain
145        of curveA to use for the ruled surface.
146     curveB_domain - [in] if not NULL, then this is a subdomain
147        of curveA to use for the ruled surface.
148   Returns:
149     @untitled table
150     0      failure
151     1      success - parameterization is exact
152     2      success - parameterization is not exact
153   Remarks:
154     The ruling parameter is the second surface parameter and
155     it is in the interval [0,1].
156     The true ruled surface has parameterization
157     srf(s,t) = (1.0-t)*curveA(s) + t*curveB(s).
158     The returned NURBS surface has parameterization
159     srf(s,t) = (1.0-t)*nurbs_curveA(s) + t*nurbs_curveB(s),
160     where nurbs_curveX is the NURBS form of curveX.  If the
161     parameterization of nurbs_curveX does not match the
162     parameterization of curveX, then 2 is returned.
163   */
164   virtual
165   int CreateRuledSurface(
166          const ON_Curve& curveA,
167          const ON_Curve& curveB,
168          const ON_Interval* curveA_domain = NULL,
169          const ON_Interval* curveB_domain = NULL
170          );
171 
172   /*
173   Description:
174     Create a cone surface from a curve to a point.
175   Parameters:
176     apex_point - [in]
177     curve - [in]
178     curve_domain - [in] if not NULL, then this is a subdomain
179        of curve to use for the ruled surface.
180   Returns:
181     @untitled table
182     0      failure
183     1      success - parameterization is exact
184     2      success - parameterization is not exact
185   Remarks:
186     The ruling parameter is the second surface parameter and
187     it is in the interval [0,1].
188     The true cone surface has parameterization
189     srf(s,t) = (1.0-t)*curve(s) + t*apex_point.
190     The returned NURBS surface has parameterization
191     srf(s,t) = (1.0-t)*nurbs_curve(s) + t*apex_point,
192     where nurbs_curve is the NURBS form of curve.  If the
193     parameterization of nurbs_curve does not match the
194     parameterization of curve, then 2 is returned.
195   */
196   int CreateConeSurface(
197          ON_3dPoint apex_point,
198          const ON_Curve& curve,
199          const ON_Interval* curve_domain = NULL
200          );
201 
202   /*
203   Description:
204     Collapse the side of a NURBS surface to a single point.
205   Parameters:
206     side - [in] 0 = collapse south side,
207                 1 = collapse east side,
208                 2 = collapse north side,
209                 3 = collapse west side
210     point - [in] point to collapse to.  If point is ON_unset_point,
211                 the the current location of the start of the side
212                 is used.
213   Returns:
214     True if successful.
215   Remarks:
216     If the surface is rational, the weights of the side control
217     points must be set before calling CollapseSide.
218   */
219   bool CollapseSide(
220     int side,
221     ON_3dPoint point = ON_unset_point
222     );
223 
224   void Destroy();
225 
226   virtual ~ON_NurbsSurface();
227 
228   void EmergencyDestroy(); // call if memory used by this class becomes invalid
229 
230   ON_NurbsSurface& operator=(const ON_NurbsSurface&);
231 
232   /*
233   Description:
234     Set NURBS surface equal to bezier surface with domain [0,1]x[0,1].
235   Parameters:
236     bezier_surface - [in]
237   */
238 	ON_NurbsSurface& operator=(
239     const ON_BezierSurface& bezier_surface
240     );
241 
242   /////////////////////////////////////////////////////////////////
243   // ON_Object overrides
244 
245   /*
246   Description:
247     Tests an object to see if its data members are correctly
248     initialized.
249   Parameters:
250     text_log - [in] if the object is not valid and text_log
251         is not NULL, then a brief englis description of the
252         reason the object is not valid is appened to the log.
253         The information appended to text_log is suitable for
254         low-level debugging purposes by programmers and is
255         not intended to be useful as a high level user
256         interface tool.
257   Returns:
258     @untitled table
259     true     object is valid
260     false    object is invalid, uninitialized, etc.
261   Remarks:
262     Overrides virtual ON_Object::IsValid
263   */
264   ON_BOOL32 IsValid( ON_TextLog* text_log = NULL ) const;
265 
266   void Dump( ON_TextLog& ) const; // for debugging
267 
268   ON_BOOL32 Write(
269          ON_BinaryArchive&  // open binary file
270        ) const;
271 
272   ON_BOOL32 Read(
273          ON_BinaryArchive&  // open binary file
274        );
275 
276   /////////////////////////////////////////////////////////////////
277   // ON_Geometry overrides
278 
279   int Dimension() const;
280 
281   ON_BOOL32 GetBBox( // returns true if successful
282          double*,    // minimum
283          double*,    // maximum
284          ON_BOOL32 = false  // true means grow box
285          ) const;
286 
287   ON_BOOL32 Transform(
288          const ON_Xform&
289          );
290 
291   // virtual ON_Geometry::IsDeformable() override
292   bool IsDeformable() const;
293 
294   // virtual ON_Geometry::MakeDeformable() override
295   bool MakeDeformable();
296 
297   ON_BOOL32 SwapCoordinates(
298         int, int        // indices of coords to swap
299         );
300 
301   /////////////////////////////////////////////////////////////////
302   // ON_Surface overrides
303 
304   ON_BOOL32 SetDomain(
305     int dir, // 0 sets first parameter's domain, 1 gets second parameter's domain
306     double t0,
307     double t1
308     );
309 
310   ON_Interval Domain(
311     int // 0 gets first parameter's domain, 1 gets second parameter's domain
312     ) const;
313 
314 
315   /*
316   Description:
317     Get an estimate of the size of the rectangle that would
318     be created if the 3d surface where flattened into a rectangle.
319   Parameters:
320     width - [out]  (corresponds to the first surface parameter)
321     height - [out] (corresponds to the first surface parameter)
322   Remarks:
323     overrides virtual ON_Surface::GetSurfaceSize
324   Returns:
325     true if successful.
326   */
327   ON_BOOL32 GetSurfaceSize(
328       double* width,
329       double* height
330       ) const;
331 
332   int SpanCount(
333     int // 0 gets first parameter's domain, 1 gets second parameter's domain
334     ) const; // number of smooth spans in curve
335 
336   ON_BOOL32 GetSpanVector( // span "knots"
337     int, // 0 gets first parameter's domain, 1 gets second parameter's domain
338     double* // array of length SpanCount() + 1
339     ) const; //
340 
341   int Degree( // returns maximum algebraic degree of any span
342                   // ( or a good estimate if curve spans are not algebraic )
343     int // 0 gets first parameter's domain, 1 gets second parameter's domain
344     ) const;
345 
346   ON_BOOL32 GetParameterTolerance( // returns tminus < tplus: parameters tminus <= s <= tplus
347          int,     // 0 gets first parameter, 1 gets second parameter
348          double,  // t = parameter in domain
349          double*, // tminus
350          double*  // tplus
351          ) const;
352 
353   /*
354   Description:
355     Test a surface to see if it is planar.
356   Parameters:
357     plane - [out] if not NULL and true is returned,
358                   the plane parameters are filled in.
359     tolerance - [in] tolerance to use when checking
360   Returns:
361     true if there is a plane such that the maximum distance from
362     the surface to the plane is <= tolerance.
363   Remarks:
364     Overrides virtual ON_Surface::IsPlanar.
365   */
366   ON_BOOL32 IsPlanar(
367         ON_Plane* plane = NULL,
368         double tolerance = ON_ZERO_TOLERANCE
369         ) const;
370 
371   ON_BOOL32 IsClosed(   // true if NURBS surface is closed (either surface has
372         int // dir // clamped end knots and euclidean location of start
373         ) const;   // CV = euclidean location of end CV, or surface is
374                    // periodic.)
375 
376   ON_BOOL32 IsPeriodic( // true if NURBS surface is periodic (degree > 1,
377         int // dir // periodic knot vector, last degree many CVs
378         ) const;   // are duplicates of first degree many CVs.)
379 
380   ON_BOOL32 IsSingular( // true if surface side is collapsed to a point
381         int        // side of parameter space to test
382                    // 0 = south, 1 = east, 2 = north, 3 = west
383         ) const;
384 
385   /*
386   Description:
387     Search for a derivatitive, tangent, or curvature
388     discontinuity.
389   Parameters:
390     dir - [in] If 0, then "u" parameter is checked.  If 1, then
391                the "v" parameter is checked.
392     c - [in] type of continity to test for.
393     t0 - [in] Search begins at t0. If there is a discontinuity
394               at t0, it will be ignored.  This makes it
395               possible to repeatedly call GetNextDiscontinuity
396               and step through the discontinuities.
397     t1 - [in] (t0 != t1)  If there is a discontinuity at t1 is
398               will be ingored unless c is a locus discontinuity
399               type and t1 is at the start or end of the curve.
400     t - [out] if a discontinuity is found, then *t reports the
401           parameter at the discontinuity.
402     hint - [in/out] if GetNextDiscontinuity will be called
403        repeatedly, passing a "hint" with initial value *hint=0
404        will increase the speed of the search.
405     dtype - [out] if not NULL, *dtype reports the kind of
406         discontinuity found at *t.  A value of 1 means the first
407         derivative or unit tangent was discontinuous.  A value
408         of 2 means the second derivative or curvature was
409         discontinuous.  A value of 0 means teh curve is not
410         closed, a locus discontinuity test was applied, and
411         t1 is at the start of end of the curve.
412     cos_angle_tolerance - [in] default = cos(1 degree) Used only
413         when c is ON::G1_continuous or ON::G2_continuous.  If the
414         cosine of the angle between two tangent vectors is
415         <= cos_angle_tolerance, then a G1 discontinuity is reported.
416     curvature_tolerance - [in] (default = ON_SQRT_EPSILON) Used
417         only when c is ON::G2_continuous.  If K0 and K1 are
418         curvatures evaluated from above and below and
419         |K0 - K1| > curvature_tolerance, then a curvature
420         discontinuity is reported.
421   Returns:
422     Parametric continuity tests c = (C0_continuous, ..., G2_continuous):
423 
424       true if a parametric discontinuity was found strictly
425       between t0 and t1. Note well that all curves are
426       parametrically continuous at the ends of their domains.
427 
428     Locus continuity tests c = (C0_locus_continuous, ...,G2_locus_continuous):
429 
430       true if a locus discontinuity was found strictly between
431       t0 and t1 or at t1 is the at the end of a curve.
432       Note well that all open curves (IsClosed()=false) are locus
433       discontinuous at the ends of their domains.  All closed
434       curves (IsClosed()=true) are at least C0_locus_continuous at
435       the ends of their domains.
436   */
437   bool GetNextDiscontinuity(
438                   int dir,
439                   ON::continuity c,
440                   double t0,
441                   double t1,
442                   double* t,
443                   int* hint=NULL,
444                   int* dtype=NULL,
445                   double cos_angle_tolerance=ON_DEFAULT_ANGLE_TOLERANCE_COSINE,
446                   double curvature_tolerance=ON_SQRT_EPSILON
447                   ) const;
448 
449   /*
450   Description:
451     Test continuity at a surface parameter value.
452   Parameters:
453     c - [in] continuity to test for
454     s - [in] surface parameter to test
455     t - [in] surface parameter to test
456     hint - [in] evaluation hint
457     point_tolerance - [in] if the distance between two points is
458         greater than point_tolerance, then the surface is not C0.
459     d1_tolerance - [in] if the difference between two first derivatives is
460         greater than d1_tolerance, then the surface is not C1.
461     d2_tolerance - [in] if the difference between two second derivatives is
462         greater than d2_tolerance, then the surface is not C2.
463     cos_angle_tolerance - [in] default = cos(1 degree) Used only when
464         c is ON::G1_continuous or ON::G2_continuous.  If the cosine
465         of the angle between two normal vectors
466         is <= cos_angle_tolerance, then a G1 discontinuity is reported.
467     curvature_tolerance - [in] (default = ON_SQRT_EPSILON) Used only when
468         c is ON::G2_continuous.  If K0 and K1 are curvatures evaluated
469         from above and below and |K0 - K1| > curvature_tolerance,
470         then a curvature discontinuity is reported.
471   Returns:
472     true if the surface has at least the c type continuity at the parameter t.
473   Remarks:
474     Overrides virtual ON_Surface::IsContinuous
475   */
476   bool IsContinuous(
477     ON::continuity c,
478     double s,
479     double t,
480     int* hint = NULL,
481     double point_tolerance=ON_ZERO_TOLERANCE,
482     double d1_tolerance=ON_ZERO_TOLERANCE,
483     double d2_tolerance=ON_ZERO_TOLERANCE,
484     double cos_angle_tolerance=ON_DEFAULT_ANGLE_TOLERANCE_COSINE,
485     double curvature_tolerance=ON_SQRT_EPSILON
486     ) const;
487 
488   ON_BOOL32 Reverse(  // reverse parameterizatrion, Domain changes from [a,b] to [-b,-a]
489     int // dir  0 = "s", 1 = "t"
490     );
491 
492   ON_BOOL32 Transpose(); // transpose surface parameterization (swap "s" and "t")
493 
494   ON_BOOL32 Evaluate( // returns false if unable to evaluate
495          double, double, // evaluation parameter
496          int,            // number of derivatives (>=0)
497          int,            // array stride (>=Dimension())
498          double*,        // array of length stride*(ndir+1)*(ndir+2)/2
499          int = 0,        // optional - determines which quadrant to evaluate from
500                          //         0 = default
501                          //         1 from NE quadrant
502                          //         2 from NW quadrant
503                          //         3 from SW quadrant
504                          //         4 from SE quadrant
505          int* = 0        // optional - evaluation hint (int[2]) used to speed
506                          //            repeated evaluations
507          ) const;
508 
509   /*
510   Description:
511     Get isoparametric curve.
512     Overrides virtual ON_Surface::IsoCurve.
513   Parameters:
514     dir - [in] 0 first parameter varies and second parameter is constant
515                  e.g., point on IsoCurve(0,c) at t is srf(t,c)
516                1 first parameter is constant and second parameter varies
517                  e.g., point on IsoCurve(1,c) at t is srf(c,t)
518 
519     c - [in] value of constant parameter
520   Returns:
521     Isoparametric curve.
522   */
523   ON_Curve* IsoCurve(
524          int dir,
525          double c
526          ) const;
527 
528   /*
529   Description:
530     Removes the portions of the surface outside of the specified interval.
531     Overrides virtual ON_Surface::Trim.
532 
533   Parameters:
534     dir - [in] 0  The domain specifies an sub-interval of Domain(0)
535                   (the first surface parameter).
536                1  The domain specifies an sub-interval of Domain(1)
537                   (the second surface parameter).
538     domain - [in] interval of the surface to keep. If dir is 0, then
539         the portions of the surface with parameters (s,t) satisfying
540         s < Domain(0).Min() or s > Domain(0).Max() are trimmed away.
541         If dir is 1, then the portions of the surface with parameters
542         (s,t) satisfying t < Domain(1).Min() or t > Domain(1).Max()
543         are trimmed away.
544   */
545   ON_BOOL32 Trim(
546          int dir,
547          const ON_Interval& domain
548          );
549 
550   /*
551    Description:
552      Where possible, analytically extends surface to include domain.
553    Parameters:
554      dir - [in] 0  new Domain(0) will include domain.
555                    (the first surface parameter).
556                 1  new Domain(1) will include domain.
557                    (the second surface parameter).
558      domain - [in] if domain is not included in surface domain,
559      surface will be extended so that its domain includes domain.
560      Will not work if surface is closed in direction dir.
561      Original surface is identical to the restriction of the
562      resulting surface to the original surface domain,
563    Returns:
564      true if successful.
565      */
566   bool Extend(
567     int dir,
568     const ON_Interval& domain
569     );
570 
571 
572   /*
573   Description:
574     Splits (divides) the surface into two parts at the
575     specified parameter.
576     Overrides virtual ON_Surface::Split.
577 
578   Parameters:
579     dir - [in] 0  The surface is split vertically.  The "west" side
580                   is returned in "west_or_south_side" and the "east"
581                   side is returned in "east_or_north_side".
582                1  The surface is split horizontally.  The "south" side
583                   is returned in "west_or_south_side" and the "north"
584                   side is returned in "east_or_north_side".
585     c - [in] value of constant parameter in interval returned
586                by Domain(dir)
587     west_or_south_side - [out] west/south portion of surface returned here
588     east_or_north_side - [out] east/north portion of surface returned here
589 
590   Example:
591 
592           ON_NurbsSurface srf = ...;
593           int dir = 1;
594           ON_NurbsSurface* south_side = 0;
595           ON_NurbsSurface* north_side = 0;
596           srf.Split( dir, srf.Domain(dir).Mid() south_side, north_side );
597 
598   */
599   ON_BOOL32 Split(
600          int dir,
601          double c,
602          ON_Surface*& west_or_south_side,
603          ON_Surface*& east_or_north_side
604          ) const;
605 
606   /*
607   Description:
608     Offset surface.
609   Parameters:
610     offset_distance - [in] offset distance
611     tolerance - [in] Some surfaces do not have an exact offset that
612       can be represented using the same class of surface definition.
613       In that case, the tolerance specifies the desired accuracy.
614     max_deviation - [out] If this parameter is not NULL, the maximum
615       deviation from the returned offset to the true offset is returned
616       here.  This deviation is zero except for cases where an exact
617       offset cannot be computed using the same class of surface definition.
618   Returns:
619     Offset surface.
620   */
621   ON_Surface* Offset(
622         double offset_distance,
623         double tolerance,
624         double* max_deviation = NULL
625         ) const;
626 
627   int GetNurbForm( // returns 0: unable to create NURBS representation
628                    //            with desired accuracy.
629                    //         1: success - returned NURBS parameterization
630                    //            matches the surface's to wthe desired accuracy
631                    //         2: success - returned NURBS point locus matches
632                    //            the surfaces's to the desired accuracy but, on
633                    //            the interior of the surface's domain, the
634                    //            surface's parameterization and the NURBS
635                    //            parameterization may not match to the
636                    //            desired accuracy.
637         ON_NurbsSurface&,
638         double = 0.0 // tolerance
639         ) const;
640 
641   /////////////////////////////////////////////////////////////////
642   // Interface
643 
644   /*
645   Description:
646     Get the maximum length of a nurb surface's control polygon
647     rows and/or columns
648   Parameters:
649     dir - [in] 0 to get "u" direction length, 1 to get "v"
650                direction length
651     length - [out] maximum length of a polygon "row" in the
652                    specified direction
653   Returns:
654     true if successful.
655   */
656   double ControlPolygonLength( int dir ) const;
657 
658 
659   bool IsRational(  // true if NURBS surface is rational
660         void
661         ) const;
662 
663   int CVSize(       // number of doubles per control vertex
664         void        // = IsRational() ? Dim()+1 : Dim()
665         ) const;
666 
667   int Order(        // order = degree + 1
668         int         // dir 0 = "s", 1 = "t"
669         ) const;
670 
671   int CVCount(      // number of control vertices
672         int         // dir 0 = "s", 1 = "t"
673         ) const;
674 
675   int CVCount(      // total number of control vertices
676         void
677         ) const;
678 
679   int KnotCount(    // total number of knots in knot vector
680         int dir         // dir 0 = "s", 1 = "t"
681         ) const;
682 
683   /*
684   Description:
685     Expert user function to get a pointer to control vertex
686     memory.  If you are not an expert user, please use
687     ON_NurbsSurface::GetCV( ON_3dPoint& ) or
688     ON_NurbsSurface::GetCV( ON_4dPoint& ).
689   Parameters:
690     i - [in] (0 <= i < m_cv_count[0])
691     j - [in] (0 <= j < m_cv_count[1])
692   Returns:
693     Pointer to control vertex.
694   Remarks:
695     If the NURBS surface is rational, the format of the
696     returned array is a homogeneos rational point with
697     length m_dim+1.  If the NURBS surface is not rational,
698     the format of the returned array is a nonrational
699     euclidean point with length m_dim.
700   See Also
701     ON_NurbsSurface::CVStyle
702     ON_NurbsSurface::GetCV
703     ON_NurbsSurface::Weight
704   */
705   double* CV(
706         int i,
707         int j
708         ) const;
709 
710   /*
711   Description:
712     Returns the style of control vertices in the m_cv array.
713   Returns:
714     @untitled table
715     ON::not_rational                m_is_rat is false
716     ON::homogeneous_rational        m_is_rat is true
717   */
718   ON::point_style CVStyle() const;
719 
720   double Weight(        // get value of control vertex weight
721         int i, int j   // CV index ( 0 <= i <= CVCount(0), 0 <= j <= CVCount(1)
722         ) const;
723 
724   ON_BOOL32 SetWeight(      // get value of control vertex weight
725         int i, int j,   // CV index ( 0 <= i <= CVCount(0), 0 <= j <= CVCount(1)
726         double weight
727         );
728 
729   ON_BOOL32 SetCV(              // set a single control vertex
730         int i, int j,   // CV index ( 0 <= i <= CVCount(0), 0 <= j <= CVCount(1)
731         ON::point_style, // style of input point
732         const double* cv    // value of control vertex
733         );
734 
735   ON_BOOL32 SetCV(               // set a single control vertex
736         int i, int j,   // CV index ( 0 <= i <= CVCount(0), 0 <= j <= CVCount(1)
737         const ON_3dPoint& cv// value of control vertex
738                            // If NURBS is rational, weight
739                            // will be set to 1.
740         );
741 
742   ON_BOOL32 SetCV(              // set a single control vertex
743         int i, int j,   // CV index ( 0 <= i <= CVCount(0), 0 <= j <= CVCount(1)
744         const ON_4dPoint& cv// value of control vertex
745         );
746 
747   ON_BOOL32 SetCVRow(          // Sets CV( *, row_index )
748        int row_index,               // row_index >= 0 and < m_cv_count[1]
749        const ON_3dPoint& cv // value of control vertex
750                           // If NURBS is rational, weight
751                           // will be set to 1.
752        );
753 
754   ON_BOOL32 SetCVRow(          // Sets CV( *, row_index )
755        int row_index,               // row_index >= 0 and < m_cv_count[1]
756        int v_stride,               // v stride
757        const double* v     // v[] = values (same dim and is_rat as surface)
758        );
759 
760   ON_BOOL32 SetCVColumn(       // Sets CV( col_index, * )
761        int col_index,               // col_index >= 0 and < m_cv_count[0]
762        const ON_3dPoint& cv // value of control vertex
763                           // If NURBS is rational, weight
764                           // will be set to 1.
765        );
766 
767   ON_BOOL32 SetCVColumn(       // Sets CV( col_index, * )
768        int col_index,               // col_index >= 0 and < m_cv_count[0]
769        int v_stride,               // v stride
770        const double* v     // v[] = values (same dim and is_rat as surface)
771        );
772 
773   ON_BOOL32 GetCV(              // get a single control vertex
774         int i, int j,   // CV index ( 0 <= i <= CVCount(0), 0 <= j <= CVCount(1)
775         ON::point_style, // style to use for output point
776         double* cv          // array of length >= CVSize()
777         ) const;
778 
779   ON_BOOL32 GetCV(              // get a single control vertex
780         int i, int j,   // CV index ( 0 <= i <= CVCount(0), 0 <= j <= CVCount(1)
781         ON_3dPoint& cv     // gets euclidean cv when NURBS is rational
782         ) const;
783 
784   ON_BOOL32 GetCV(              // get a single control vertex
785         int i, int j,   // CV index ( 0 <= i <= CVCount(0), 0 <= j <= CVCount(1)
786         ON_4dPoint& cv     // gets homogeneous cv
787         ) const;
788 
789   int SetKnot(
790         int dir,    // dir 0 = "s", 1 = "t"
791         int knot_index,            // knot index ( 0 to KnotCount - 1 )
792         double knot_value         // value for knot
793         );
794 
795   double Knot(
796         int dir,    // dir 0 = "s", 1 = "t"
797         int knot_index  // knot index ( >= 0 and < Order + CV_count - 2 )
798         ) const;
799 
800   int KnotMultiplicity(
801         int dir,    // dir 0 = "s", 1 = "t"
802         int knot_index            // knot index ( >= 0 and < Order + CV_count - 2 )
803         ) const;
804 
805   const double* Knot(   // knot[] array
806         int dir    // dir 0 = "s", 1 = "t"
807         ) const;
808 
809   // Description:
810   //   Make knot vector a clamped uniform knot vector
811   //   based on the current values of m_order and m_cv_count.
812   //   Does not change values of control vertices.
813   // Parameters:
814   //   dir - [in] 0 = u knots, 1 = v knots
815   //   delta - [in] (>0.0) knot spacing.
816   // Returns:
817   //   true if successful.
818   // Remarks:
819   //   Allocates m_knot[] if it is not big enough.
820   // See Also:
821   //   ON_MakeClampedUniformKnotVector
822   bool MakeClampedUniformKnotVector(
823     int dir,
824     double delta = 1.0
825     );
826 
827   // Description:
828   //   Make knot vector a periodic uniform knot vector
829   //   based on the current values of m_order and m_cv_count.
830   //   Does not change values of control vertices.
831   // Parameters:
832   //   dir - [in] 0 = u knots, 1 = v knots
833   //   delta - [in] (>0.0) knot spacing.
834   // Returns:
835   //   true if successful.
836   // Remarks:
837   //   Allocates m_knot[] if it is not big enough.
838   // See Also:
839   //   ON_MakePeriodicUniformKnotVector
840   bool MakePeriodicUniformKnotVector(
841     int dir,
842     double delta = 1.0
843     );
844 
845 
846   bool IsClamped( // determine if knot vector is clamped
847         int dir,    // dir 0 = "s", 1 = "t"
848         int end = 2 // end to check: 0 = start, 1 = end, 2 = start and end
849         ) const;
850 
851   double SuperfluousKnot(
852            int dir,    // dir 0 = "s", 1 = "t"
853            int end  // 0 = start, 1 = end
854            ) const;
855 
856   double GrevilleAbcissa(
857            int dir,  // dir
858            int cv_index  // index (0 <= index < CVCount(dir)
859            ) const;
860 
861   bool GetGrevilleAbcissae( // see ON_GetGrevilleAbcissa() for details
862            int dir,      // dir
863            double* g   // g[cv count]
864            ) const;
865 
866   bool SetClampedGrevilleKnotVector(
867            int dir,          // dir
868            int g_stride,          // g_stride
869            const double* g // g[], CVCount(dir) many Greville abcissa
870            );
871 
872   bool SetPeriodicGrevilleKnotVector(
873            int dir,          // dir
874            int g_stride,          // g_stride
875            const double* g // g[], Greville abcissa
876            );
877 
878   bool ZeroCVs(); // zeros all CVs (any weights set to 1);
879 
880   bool ClampEnd(
881             int dir,         // dir 0 = "s", 1 = "t"
882             int end // 0 = clamp start, 1 = clamp end, 2 = clamp start and end
883             );
884 
885   bool InsertKnot(
886            int dir,         // dir 0 = "s", 1 = "t"
887            double knot_value, // value of knot
888            int knot_multiplicity=1   // multiplicity of knot ( >= 1 and <= degree )
889            );
890 
891   bool MakeRational();
892 
893   bool MakeNonRational();
894 
895   bool IncreaseDegree(
896            int dir,  // dir 0 = "s", 1 = "t"
897            int desired_degree  //  desired_degree
898            );
899 
900   bool ChangeDimension(
901            int desired_dimension  //  desired_dimension
902            );
903 
904   /*
905   Description:
906     If the surface is closed in direction dir, then modify it so that
907     the seam is at parameter t in the dir direction.
908   Parameters:
909 		dir - [in] must be 0 or 1
910     t -		[in] dir parameter of seam, must have Domain(dir).Includes(t).
911                The resulting surface domain in the dir direction will start at t.
912   Returns:
913     true if successful.
914   */
915   ON_BOOL32 ChangeSurfaceSeam(
916 						int dir,
917             double t
918             );
919 
920 
921   // Creates a tensor product nurbs surface with srf(s,t) = T(A(s),B(t));
922   ON_BOOL32 TensorProduct(
923         const ON_NurbsCurve&, // A
924         const ON_NurbsCurve&, // B
925         ON_TensorProduct&     // T
926         );
927 
928   /////////////////////////////////////////////////////////////////
929   // Tools for managing CV and knot memory
930   ON_BOOL32 ReserveKnotCapacity( // returns false if allocation fails
931                     // does not change m_order or m_cv_count
932     int dir, // dir 0 = "s", 1 = "t"
933     int knot_array_capacity // minimum capacity of m_knot[] array
934     );
935   ON_BOOL32 ReserveCVCapacity(  // returns false if allocation fails
936                     // does not change m_order or m_cv_count
937     int cv_array_capacity // minimum capacity of m_cv[] array
938     );
939 
940   /*
941   Description:
942     Convert a NURBS surface bispan into a bezier surface.
943   Parameters:
944     span_index0 - [in] Specifies the "u" span and must satisfy
945          0 <= span_index0 <= m_cv_count[0]-m_order[0]
946          m_knot[0][span_index0+m_order[0]-2] < m_knot[0][span_index0+m_order[0]-1]
947     span_index1 - [in] Specifies the "v" span and must satisfy
948          0 <= span_index1 <= m_cv_count[1]-m_order[1]
949          m_knot[1][span_index1+m_order[1]-2] < m_knot[1][span_index1+m_order[1]-1]
950     bezier_surface - [out] bezier surface returned here
951   Returns:
952     true if successful
953     false if input is not valid
954   */
955   ON_BOOL32 ConvertSpanToBezier(
956       int span_index0,
957       int span_index1,
958       ON_BezierSurface& bezier_surface
959       ) const;
960 
961   /////////////////////////////////////////////////////////////////
962   // Implementation
963 public:
964   // NOTE: These members are left "public" so that expert users may efficiently
965   //       create NURBS curves using the default constructor and borrow the
966   //       knot and CV arrays from their native NURBS representation.
967   //       No technical support will be provided for users who access these
968   //       members directly.  If you can't get your stuff to work, then use
969   //       the constructor with the arguments and the SetKnot() and SetCV()
970   //       functions to fill in the arrays.
971 
972   int     m_dim;            // (>=1)
973 
974   int     m_is_rat;         // 1 for rational B-splines. (Control vertices
975                             // use homogeneous form.)
976                             // 0 for non-rational B-splines. (Control
977                             // verticies do not have a weight coordinate.)
978 
979   int     m_order[2];       // order = degree+1 (>=2)
980 
981   int     m_cv_count[2];    // number of control vertices ( >= order )
982 
983   // knot vector memory
984 
985   int     m_knot_capacity[2]; // If m_knot_capacity > 0, then m_knot[]
986                               // is an array of at least m_knot_capacity
987                               // doubles whose memory is managed by the
988                               // ON_NurbsSurface class using rhmalloc(),
989                               // onrealloc(), and rhfree().
990                               // If m_knot_capacity is 0 and m_knot is
991                               // not NULL, then  m_knot[] is assumed to
992                               // be big enough for any requested operation
993                               // and m_knot[] is not deleted by the
994                               // destructor.
995 
996   double* m_knot[2];        // Knot vector. ( The knot vector has length
997                             // m_order+m_cv_count-2. )
998 
999   // control vertex net memory
1000 
1001   int     m_cv_stride[2];   // The pointer to start of "CV[i]" is
1002                             //   m_cv + i*m_cv_stride.
1003 
1004   int     m_cv_capacity;    // If m_cv_capacity > 0, then m_cv[] is an array
1005                             // of at least m_cv_capacity doubles whose
1006                             // memory is managed by the ON_NurbsSurface
1007                             // class using rhmalloc(), onrealloc(), and rhfree().
1008                             // If m_cv_capacity is 0 and m_cv is not
1009                             // NULL, then m_cv[] is assumed to be big enough
1010                             // for any requested operation and m_cv[] is not
1011                             // deleted by the destructor.
1012 
1013   double* m_cv;             // Control points.
1014                             // If m_is_rat is false, then control point is
1015                             //
1016                             //          ( CV(i)[0], ..., CV(i)[m_dim-1] ).
1017                             //
1018                             // If m_is_rat is true, then the control point
1019                             // is stored in HOMOGENEOUS form and is
1020                             //
1021                             //         [ CV(i)[0], ..., CV(i)[m_dim] ].
1022                             //
1023 };
1024 
1025 
1026 class ON_CLASS ON_NurbsCage : public ON_Geometry
1027 {
1028   ON_OBJECT_DECLARE(ON_NurbsCage);
1029 
1030 public:
1031   ON_NurbsCage();
1032 
1033   ON_NurbsCage(
1034     int dim,
1035     bool is_rat,
1036     int order0,
1037     int order1,
1038     int order2,
1039     int cv_count0,
1040     int cv_count1,
1041     int cv_count2
1042     );
1043 
1044   ON_NurbsCage(
1045     const ON_BoundingBox& bbox,
1046     int order0,
1047     int order1,
1048     int order2,
1049     int cv_count0,
1050     int cv_count1,
1051     int cv_count2
1052     );
1053 
1054   ON_NurbsCage(
1055     const ON_3dPoint* box_corners, // array of 8 3d points
1056     int order0,
1057     int order1,
1058     int order2,
1059     int cv_count0,
1060     int cv_count1,
1061     int cv_count2
1062     );
1063 
1064   ON_NurbsCage( const ON_BezierCage& src );
1065 
1066   ~ON_NurbsCage();
1067 
1068   ON_NurbsCage(const ON_NurbsCage& src);
1069 
1070   ON_NurbsCage& operator=(const ON_NurbsCage& src);
1071 
1072   ON_NurbsCage& operator=(const ON_BezierCage& src);
1073 
1074 
1075   /*
1076   Description:
1077     Overrides the pure virtual ON_Object::IsValid function.
1078   Parameters:
1079     text_log - [in] If not null and the object is invalid,
1080                     a brief description of the problem
1081                     suitable for debugging C++ code
1082                     is printed in this log.
1083   Returns:
1084     True if the orders are at least two, dimension is positive,
1085     knot vectors are valid, and the other fields are valid
1086     for the specified orders and dimension.
1087   */
1088   ON_BOOL32 IsValid(
1089           ON_TextLog* text_log = NULL
1090           ) const;
1091 
1092   /*
1093   Description:
1094     Overrides the pure virtual ON_Object::Dump function.
1095   Parameters:
1096     text_log - [in] A listing of the values of the members.
1097   */
1098   void Dump( ON_TextLog& text_log) const;
1099 
1100   /*
1101   Description:
1102     Overrides the pure virtual ON_Object::SizeOf function.
1103   Returns:
1104     An estimate of the amount of memory used by the class
1105     and its members.
1106   */
1107   unsigned int SizeOf() const;
1108 
1109   // virtual ON_Object::DataCRC override
1110   ON__UINT32 DataCRC(ON__UINT32 current_remainder) const;
1111 
1112   /*
1113   Description:
1114     Overrides the pure virtual ON_Object::Read function.
1115     Reads the definition of this class from an
1116     archive previously saved by ON_BezierVolue::Write.
1117   Parameters:
1118     archive - [in] target archive
1119   Returns:
1120     True if successful.
1121   */
1122   ON_BOOL32 Read(
1123     ON_BinaryArchive& archive
1124     );
1125 
1126   /*
1127   Description:
1128     Overrides the pure virtual ON_Object::Write function.
1129     Saves the definition of this class in serial binary
1130     form that can be read by ON_BezierVolue::Read.
1131   Parameters:
1132     archive - [in] target archive
1133   Returns:
1134     True if successful.
1135   */
1136   ON_BOOL32 Write(
1137     ON_BinaryArchive& archive
1138     ) const;
1139 
1140   /*
1141   Description:
1142     Overrides the pure virtual ON_Object::ObjectType function.
1143     Saves the definition of this class in serial binary
1144     form that can be read by ON_BezierVolue::Read.
1145   Parameters:
1146     archive - [in] target archive
1147   Returns:
1148     True if successful.
1149   */
1150   ON::object_type ObjectType() const;
1151 
1152   /*
1153   Description:
1154     Overrides the pure virtual ON_Object::DestroyRuntimeCache function.
1155     Saves the definition of this class in serial binary
1156     form that can be read by ON_BezierVolue::Read.
1157   Parameters:
1158     bDelete - [in] if true, the cache is deleted.  If false, the
1159        pointers to the cache are set to zero; this is done when
1160        the cache memory was allocated from a pool that has
1161        been destroyed and an attempt to free the memory would
1162        result in a crash.
1163   Returns:
1164     True if successful.
1165   */
1166   void DestroyRuntimeCache(
1167     bool bDelete = true
1168     );
1169 
1170 
1171   /*
1172   Description:
1173     Overrides virtual ON_Geometry::Dimension function.
1174     Gets a tight bounding box with respect to the coordinate
1175     system specified by the frame parameter.
1176   Parameters:
1177     bbox - [in/out]
1178     bGrowBox - [in] If true, the input bbox is grown to include
1179         this object's bounding box.
1180     frame - [in] if not null, this specifies the coordinate system
1181                 frame.
1182   Returns:
1183     True if successful.
1184   */
1185   int Dimension() const;
1186 
1187   /*
1188   Description:
1189     Overrides virtual ON_Geometry::GetBBox function.
1190     Gets the world axis aligned bounding box that contains
1191     the NURBS volume's control points.  The NURBS volume
1192     maps the unit cube into this box.
1193   Parameters:
1194     boxmin - [in] array of Dimension() doubles
1195     boxmax - [in] array of Dimension() doubles
1196     bGrowBox =  [in] if true and the input is a valid box
1197                           then the input box is grown to
1198                           include this object's bounding box.
1199   Returns:
1200     true if successful.
1201   */
1202   ON_BOOL32 GetBBox(
1203          double* boxmin,
1204          double* boxmax,
1205          int bGrowBox = false
1206          ) const;
1207 
1208   /*
1209 	Description:
1210     Get tight bounding box.
1211 	Parameters:
1212 		tight_bbox - [in/out] tight bounding box
1213 		bGrowBox -[in]	(default=false)
1214       If true and the input tight_bbox is valid, then returned
1215       tight_bbox is the union of the input tight_bbox and the
1216       surface's tight bounding box.
1217 		xform -[in] (default=NULL)
1218       If not NULL, the tight bounding box of the transformed
1219       surface is calculated.  The surface is not modified.
1220 	Returns:
1221     True if a valid tight_bbox is returned.
1222   */
1223 	bool GetTightBoundingBox(
1224 			ON_BoundingBox& tight_bbox,
1225       int bGrowBox = false,
1226 			const ON_Xform* xform = 0
1227       ) const;
1228 
1229   /*
1230   Description:
1231     Overrides virtual ON_Geometry::Transform function.
1232     Transforms NURBS volume.
1233   Parameters:
1234     xform - [in]
1235   Returns:
1236     true if successful.
1237   */
1238   ON_BOOL32 Transform(
1239          const ON_Xform& xform
1240          );
1241 
1242   /*
1243   Description:
1244     Overrides virtual ON_Geometry::IsDeformable function.
1245   Returns:
1246     True because a NURBS volume can be accuratly modified
1247     with "squishy" transformations like projections,
1248     shears, an non-uniform scaling.
1249   */
1250   bool IsDeformable() const;
1251 
1252   /*
1253   Description:
1254     Overrides virtual ON_Geometry::MakeDeformable function.
1255   Returns:
1256     True because NURBS volumes are deformable.
1257   */
1258   bool MakeDeformable();
1259 
1260   /*
1261   Returns:
1262     True if the cage is a parallelogram within the tolerance.
1263     This means the cage can be used as a starting point
1264     for cage deformations.
1265   */
1266   bool IsParallelogram(double tolerance) const;
1267 
1268   bool Create(
1269     int dim,
1270     bool is_rat,
1271     int order0,
1272     int order1,
1273     int order2,
1274     int cv_count0,
1275     int cv_count1,
1276     int cv_count2
1277     );
1278 
1279   /*
1280   Description:
1281     Create a Nurbs volume with corners defined by a bounding box.
1282   Parameters:
1283     box_corners - [in] 8 points that define corners of the volume
1284 
1285             7______________6
1286             |\             |\
1287             | \            | \
1288             |  \ _____________\
1289             |   4          |   5
1290             |   |          |   |
1291             |   |          |   |
1292             3---|----------2   |
1293             \   |          \   |
1294              \  |z          \  |
1295             y \ |            \ |
1296                \0_____________\1
1297                        x
1298 
1299   */
1300   bool Create(
1301     const ON_BoundingBox& bbox,
1302     int order0,
1303     int order1,
1304     int order2,
1305     int cv_count0,
1306     int cv_count1,
1307     int cv_count2
1308     );
1309 
1310   /*
1311   Description:
1312     Create a nurbs volume from a 3d box
1313   Parameters:
1314     box_corners - [in] 8 points that define corners of the volume
1315 
1316             7______________6
1317             |\             |\
1318             | \            | \
1319             |  \ _____________\
1320             |   4          |   5
1321             |   |          |   |
1322             |   |          |   |
1323             3---|----------2   |
1324             \   |          \   |
1325              \  |t          \  |
1326             s \ |            \ |
1327                \0_____________\1
1328                        r
1329 
1330   */
1331   bool Create(
1332     const ON_3dPoint* box_corners,
1333     int order0,
1334     int order1,
1335     int order2,
1336     int cv_count0,
1337     int cv_count1,
1338     int cv_count2
1339     );
1340 
1341   void Destroy();
1342 
1343   void EmergencyDestroy(); // call if memory used by ON_NurbsCage becomes invalid
1344 
1345   ON_Interval Domain(
1346     int // dir 0 = "r", 1 = "s", 2 = "t"
1347     ) const;
1348 
1349   bool Reverse(
1350     int dir // dir 0 = "r", 1 = "s", 2 = "t"
1351     );
1352 
1353   bool Transpose(
1354     int dir0,
1355     int dir1
1356     );
1357 
1358   bool ClampEnd(
1359             int dir,         // dir 0 = "r", 1 = "s", 2 = "t"
1360             int end // 0 = clamp start, 1 = clamp end, 2 = clamp start and end
1361             );
1362 
1363   bool InsertKnot(
1364            int dir,         // dir 0 = "r", 1 = "s", 2 = "t"
1365            double knot_value, // value of knot
1366            int knot_multiplicity=1   // multiplicity of knot ( >= 1 and <= degree )
1367            );
1368 
1369   ON_BOOL32 IncreaseDegree(
1370            int dir,  // dir 0 = "r", 1 = "s", 2 = "t"
1371            int desired_degree  //  desired_degree
1372            );
1373 
1374   ON_BOOL32 ChangeDimension(
1375            int desired_dimension  //  desired_dimension
1376            );
1377 
1378   /*
1379   Description:
1380     Evaluate the NURBS cage
1381   Parameters:
1382     r - [in]
1383     s - [in]
1384     t - [in] (r,s,t) = evaluation parameters
1385     der_count - [in]  (>= 0)
1386     v_stride - [in] (>= m_dim)
1387     v - [out] An array of length v_stride*(der_count+1)(der_count+2)*(der_count+3)/6.
1388               The evaluation results are stored in this array.
1389 
1390                 P = v[0],...,v[m_dim-1]
1391                 Dr = v[v_stride],...
1392                 Ds = v[2*v_stride],...
1393                 Dt = v[3*v_stride],...
1394 
1395               In general, Dr^i Ds^j Dt^k is returned in v[n],...,v[n+m_dim-1], where
1396 
1397                d = (i+j+k)
1398                n = v_stride*( d*(d+1)*(d+2)/6 + (j+k)*(j+k+1)/2 + k)
1399 
1400     side - [in] specifies the span to use for the evaluation
1401                 when r, s, or t is at a knot value.
1402             0 = default
1403             1 = from upper NE quadrant
1404             2 = from upper NW quadrant
1405             3 = from upper SW quadrant
1406             4 = from upper SE quadrant
1407             5 = from lower NE quadrant
1408             6 = from lower NW quadrant
1409             7 = from lower SW quadrant
1410             8 = from lower SE quadrant
1411     hint - [in/out] If a bunch of evaluations will be performed that
1412                     tend to occur in the same region, then
1413                     hint[3] can be used to speed the search for
1414                     the evaluation span.  The input value is
1415                     used as a search hint and the output value
1416                     records the span used for that evaluation.
1417   Example:
1418 
1419           int der_count = 2;
1420           int v_stride = dim;
1421           double v[v_stride*(der_count+1)*(der_count+2)*(der_count+3)/6];
1422           int side = 0;
1423           int hint[3]; hint[0] = 0; hint[1] = 0; hint[2] = 0;
1424           bool rc = cage.Evaluate(r,s,t,der_count,v_stride,v,side,hint);
1425 
1426           ON_3dPoint P = v;
1427 
1428           // first order partial derivatives
1429           ON_3dVector Dr = v + v_stride;
1430           ON_3dVector Ds = v + 2*v_stride;
1431           ON_3dVector Dt = v + 3*v_stride;
1432 
1433           // second order partial derivatives
1434           ON_3dVector Drr = v + 4*v_stride;
1435           ON_3dVector Drs = v + 5*v_stride;
1436           ON_3dVector Drt = v + 6*v_stride;
1437           ON_3dVector Dss = v + 7*v_stride;
1438           ON_3dVector Dst = v + 8*v_stride;
1439           ON_3dVector Dtt = v + 8*v_stride;
1440 
1441   Returns:
1442     True if successful
1443   See Also:
1444     ON_NurbsCage::PointAt
1445   */
1446   bool Evaluate(
1447          double r,
1448          double s,
1449          double t,
1450          int der_count,
1451          int v_stride,
1452          double* v,
1453          int side=0,
1454          int* hint=0
1455          ) const;
1456 
1457   /*
1458   Description:
1459     Evaluates bezer volume map.
1460   Parameters:
1461     rst - [in]
1462   Returns:
1463     Value of the nurbs volume map at (r,s,t).
1464   */
1465   ON_3dPoint PointAt(
1466          double r,
1467          double s,
1468          double t
1469          ) const;
1470 
1471   ON_NurbsSurface* IsoSurface(
1472          int dir,
1473          double c,
1474          ON_NurbsSurface* srf = 0
1475          ) const;
1476 
1477   bool Trim(
1478          int dir,
1479          const ON_Interval& domain
1480          );
1481 
1482   bool Extend(
1483     int dir,
1484     const ON_Interval& domain
1485     );
1486 
1487   /*
1488   Description:
1489     Evaluates bezer volume map.
1490   Parameters:
1491     rst - [in]
1492   Returns:
1493     Value of the nurbs volume map at (rst.x,rst.y,rst.z).
1494   */
1495   ON_3dPoint PointAt(
1496          ON_3dPoint rst
1497          ) const;
1498 
1499   bool IsRational() const;
1500 
1501   int CVSize() const;
1502 
1503   int Order(
1504         int dir     // dir 0 = "r", 1 = "s", 2 = "t"
1505         ) const;
1506 
1507   int CVCount(      // number of control vertices
1508         int         // dir 0 = "r", 1 = "s", 2 = "t"
1509         ) const;
1510 
1511   int CVCount(      // total number of control vertices
1512         void
1513         ) const;
1514 
1515   int KnotCount(    // total number of knots in knot vector
1516         int dir     // dir 0 = "r", 1 = "s", 2 = "t"
1517         ) const;
1518 
1519   int Degree(
1520         int dir
1521         ) const;
1522 
1523 
1524   int SpanCount(
1525     int dir         // dir 0 = "r", 1 = "s", 2 = "t"
1526     ) const;
1527 
1528   bool GetSpanVector(
1529     int dir,        // dir 0 = "r", 1 = "s", 2 = "t"
1530     double* span_vector
1531     ) const;
1532 
1533   /*
1534   Description:
1535     Expert user function to get a pointer to control vertex
1536     memory.  If you are not an expert user, please use
1537     ON_NurbsCage::GetCV( ON_3dPoint& ) or
1538     ON_NurbsCage::GetCV( ON_4dPoint& ).
1539   Parameters:
1540     cv_index0 - [in] (0 <= cv_index0 < m_order[0])
1541     cv_index1 - [in] (0 <= cv_index1 < m_order[1])
1542   Returns:
1543     Pointer to control vertex.
1544   Remarks:
1545     If the Nurbs surface is rational, the format of the
1546     returned array is a homogeneos rational point with
1547     length m_dim+1.  If the Nurbs surface is not rational,
1548     the format of the returned array is a nonrational
1549     euclidean point with length m_dim.
1550   See Also
1551     ON_NurbsCage::CVStyle
1552     ON_NurbsCage::GetCV
1553     ON_NurbsCage::Weight
1554   */
1555   double* CV(
1556         int i,
1557         int j,
1558         int k
1559         ) const;
1560 
1561   /*
1562   Description:
1563     Returns the style of control vertices in the m_cv array.
1564   Returns:
1565     @untitled table
1566     ON::not_rational                m_is_rat is false
1567     ON::homogeneous_rational        m_is_rat is true
1568   */
1569   ON::point_style CVStyle() const;
1570 
1571   double Weight(        // get value of control vertex weight
1572         int i,
1573         int j,
1574         int k
1575         ) const;
1576 
1577   bool SetWeight(      // get value of control vertex weight
1578         int i,
1579         int j,
1580         int k,
1581         double w
1582         );
1583 
1584   bool SetCV(              // set a single control vertex
1585         int i,
1586         int j,
1587         int k,
1588         ON::point_style, // style of input point
1589         const double*     // value of control vertex
1590         );
1591 
1592   // set a single control vertex
1593   // If NURBS is rational, weight
1594   // will be set to 1.
1595   bool SetCV(
1596         int i,
1597         int j,
1598         int k,
1599         const ON_3dPoint& point
1600         );
1601 
1602   // set a single control vertex
1603   // value of control vertex
1604   // If NURBS is not rational, euclidean
1605   // location of homogeneous point will
1606   // be used.
1607   bool SetCV(
1608         int i,
1609         int j,
1610         int k,
1611         const ON_4dPoint& hpoint
1612         );
1613 
1614   bool GetCV(              // get a single control vertex
1615         int i,
1616         int j,
1617         int k,
1618         ON::point_style, // style to use for output point
1619         double*           // array of length >= CVSize()
1620         ) const;
1621 
1622   bool GetCV(              // get a single control vertex
1623         int i,
1624         int j,
1625         int k,
1626         ON_3dPoint&      // gets euclidean cv when NURBS is rational
1627         ) const;
1628 
1629   bool GetCV(              // get a single control vertex
1630         int i,
1631         int j,
1632         int k,
1633         ON_4dPoint&      // gets homogeneous cv
1634         ) const;
1635 
1636   /*
1637   Parameters:
1638     dir - [in] 0 = "r", 1 = "s", 2 = "t"
1639     knot_index - [in] 0 <= knot_index < KnotCount(dir)
1640     knot_value - [in]
1641   Returns:
1642     True if dir and knot_index parameters were valid and knot value
1643     was set.
1644   */
1645   bool SetKnot(
1646         int dir,
1647         int knot_index,
1648         double knot_value
1649         );
1650 
1651   /*
1652   Parameters:
1653     dir - [in] 0 = "r", 1 = "s", 2 = "t"
1654     knot_index - [in] 0 <= knot_index < KnotCount(dir)
1655   Returns:
1656     Value of knot or ON_UNSET_VALUE if input parameters are not valid.
1657   */
1658   double Knot(
1659         int dir,
1660         int knot_index
1661         ) const;
1662 
1663   bool ZeroCVs(); // zeros control vertices and, if rational, sets weights to 1
1664 
1665   bool MakeRational();
1666 
1667   bool MakeNonRational();
1668 
1669   bool IsClosed(   // true if NURBS cage is closed (either cage has
1670         int // dir // clamped end knots and euclidean location of start
1671         ) const;   // CV = euclidean location of end CV, or cage is
1672                    // periodic.)
1673 
1674   bool IsPeriodic( // true if NURBS cage is periodic (degree > 1,
1675         int // dir // periodic knot vector, last degree many CVs
1676         ) const;   // are duplicates of first degree many CVs.)
1677 
1678   bool IsSingular( // true if cage side is collapsed to a point
1679         int        // side of parameter space to test
1680                    // 0 = south, 1 = east, 2 = north, 3 = west
1681         ) const;
1682 
1683   double GrevilleAbcissa(
1684           int dir,    // dir
1685           int gindex  // index (0 <= index < CVCount(dir)
1686           ) const;
1687 
1688   /////////////////////////////////////////////////////////////////
1689   // Tools for managing CV and knot memory
1690 
1691   /*
1692   Description:
1693     cv_capacity - [in] number of doubles to reserve
1694   */
1695   bool ReserveCVCapacity(
1696     int cv_capacity
1697     );
1698 
1699   bool ReserveKnotCapacity(
1700     int dir,
1701     int cv_capacity
1702     );
1703 
1704   /////////////////////////////////////////////////////////////////
1705   // Implementation
1706 public:
1707   // NOTE: These members are left "public" so that expert users may efficiently
1708   //       create nurbs curves using the default constructor and borrow the
1709   //       knot and CV arrays from their native NURBS representation.
1710   //       No technical support will be provided for users who access these
1711   //       members directly.  If you can't get your stuff to work, then use
1712   //       the constructor with the arguments and the SetKnot() and SetCV()
1713   //       functions to fill in the arrays.
1714 
1715 
1716   int     m_dim;
1717   bool    m_is_rat;
1718   int     m_order[3];
1719   int     m_cv_count[3];
1720   int     m_knot_capacity[3];
1721   double* m_knot[3];
1722   int     m_cv_stride[3];
1723   int     m_cv_capacity;
1724   double* m_cv;
1725 };
1726 
1727 ON_DECL
1728 bool ON_GetCageXform(
1729           const ON_NurbsCage& cage,
1730           ON_Xform& cage_xform
1731           );
1732 
1733 
1734 class ON_CLASS ON_MorphControl : public ON_Geometry
1735 {
1736   ON_OBJECT_DECLARE(ON_MorphControl);
1737 
1738 public:
1739   ON_MorphControl();
1740   ~ON_MorphControl();
1741   // C++ default copy construction and operator= work fine.
1742 
1743 
1744   void Destroy();
1745 
1746 
1747   /////////////////////////////////////////////////////////
1748   //
1749   // ON_Object virtual functions
1750   //
1751 
1752   void MemoryRelocate();
1753 
1754   ON_BOOL32 IsValid( ON_TextLog* text_log = NULL ) const;
1755 
1756   void Dump( ON_TextLog& ) const;
1757 
1758   unsigned int SizeOf() const;
1759 
1760   ON_BOOL32 Write(
1761     ON_BinaryArchive& archive
1762     ) const;
1763 
1764   ON_BOOL32 Read(
1765     ON_BinaryArchive& archive
1766     );
1767 
1768   ON::object_type ObjectType() const;
1769 
1770   void DestroyRuntimeCache( bool bDelete = true );
1771 
1772   /////////////////////////////////////////////////////////
1773   //
1774   // ON_Geometry virtual functions
1775   //
1776 
1777   int Dimension() const;
1778 
1779   ON_BOOL32 GetBBox(
1780          double* boxmin,
1781          double* boxmax,
1782          int bGrowBox = false
1783          ) const;
1784 
1785 	bool GetTightBoundingBox(
1786 			ON_BoundingBox& tight_bbox,
1787       int bGrowBox = false,
1788 			const ON_Xform* xform = 0
1789       ) const;
1790 
1791   void ClearBoundingBox();
1792 
1793   ON_BOOL32 Transform(
1794          const ON_Xform& xform
1795          );
1796 
1797   ON_BOOL32 HasBrepForm() const;
1798 
1799   ON_Brep* BrepForm( ON_Brep* brep = NULL ) const;
1800 
1801 
1802   /*
1803   Returns:
1804     True if the target NURBS object is rational
1805   */
1806   bool IsRational() const;
1807 
1808   /*
1809   Description:
1810     Makes the target NURBS object rational.
1811   */
1812   bool MakeRational();
1813 
1814   /*
1815   Description:
1816     Makes the target NURBS object non-rational.
1817   */
1818   bool MakeNonRational();
1819 
1820   /*
1821   Returns:
1822     Number of control points in the target NURBS object.
1823   */
1824   int CVCount() const;
1825 
1826   int CVCount(int dir) const;
1827   int Order(int dir) const;
1828   const double* Knot(int dir) const;
1829   ON_3dex MaxCVIndex() const;
1830   const double* CV(ON_3dex) const;
1831   double Weight(ON_3dex) const;
1832 
1833   /////////////////////////////////////////////////////////
1834   //
1835   // Localizers
1836   //
1837 
1838   /*
1839   Description:
1840     Adds localizer with support near the controling NURBS object.
1841   Parameters:
1842     support_distance - [in] >= 0
1843       If the distance a point to the controls NURBS
1844       curve/surface/cage is less than or equal to support_distance,
1845       then MorphPoint() deformation has 100% effect.
1846 
1847     falloff_distance - [in] > 0
1848       If the distance a point to the controls NURBS
1849       curve/surface/cage is more than support_distance+falloff_distance,
1850       then MorphPoint() deformation does not move the point.
1851       As the distance varies from support_distance to
1852       support_distance+falloff_distance the deformation attenuates
1853       from 100% to 0%.
1854   */
1855   bool AddControlLocalizer(
1856     double support_distance,
1857     double falloff_distance
1858     );
1859 
1860   bool AddSphereLocalizer(
1861     ON_3dPoint center,
1862     double support_distance,
1863     double falloff_distance
1864     );
1865 
1866   bool AddCylinderLocalizer(
1867     ON_Line axis,
1868     double support_distance,
1869     double falloff_distance
1870     );
1871 
1872   bool AddBoxLocalizer(
1873     ON_BoundingBox bbox,
1874     double support_distance,
1875     double falloff_distance
1876     );
1877 
1878   bool AddPlaneLocalizer(
1879     const ON_Plane& plane,
1880     double support_distance,
1881     double falloff_distance
1882     );
1883 
1884   bool AddConvexPolygonLocalizer(
1885     const ON_SimpleArray<ON_Plane>& planes,
1886     double support_distance,
1887     double falloff_distance
1888     );
1889 
1890   /////////////////////////////////////////////////////////
1891   //
1892   //
1893 
1894   // Get a cage_morph that can be passed to Morph functions
1895   bool GetCageMorph( class ON_CageMorph& cage_morph ) const;
1896 
1897   bool IsIdentity( const ON_BoundingBox& bbox ) const;
1898 
1899   int m_varient; // 1= curve, 2 = surface, 3 = cage
1900 
1901   // The value of m_varient determines which nurbs object
1902   // controls the cage
1903   ON_NurbsCurve   m_nurbs_curve0;
1904   ON_NurbsCurve   m_nurbs_curve;
1905   ON_Interval     m_nurbs_curve_domain;
1906 
1907   ON_NurbsSurface m_nurbs_surface0;
1908   ON_NurbsSurface m_nurbs_surface;
1909   ON_Interval     m_nurbs_surface_domain[2];
1910 
1911   ON_Xform        m_nurbs_cage0;
1912   ON_NurbsCage    m_nurbs_cage;
1913 
1914   // Rhino captive object ids
1915   ON_UuidList m_captive_id;
1916 
1917   // Use ON_GetCageXform to set m_cage_xform.
1918 
1919   // Used to localize the deformation
1920   ON_ClassArray<ON_Localizer> m_localizers;
1921 
1922   // ON_SpaceMorphOptions
1923   double m_sporh_tolerance;
1924   bool   m_sporh_bQuickPreview;
1925   bool   m_sporh_bPreserveStructure;
1926 };
1927 
1928 
1929 class ON_CLASS ON_CageMorph : public ON_SpaceMorph
1930 {
1931 public:
1932   ON_CageMorph();
1933   ~ON_CageMorph();
1934 
1935   bool IsIdentity( const ON_BoundingBox& bbox ) const;
1936 
1937   const ON_MorphControl* m_control;
1938 };
1939 
1940 
1941 // Description:
1942 //   Get an ON_NurbsSurface definition of a quadrilateral.
1943 // Parameters:
1944 //   P - [in]
1945 //   Q - [in]
1946 //   R - [in]
1947 //   S - [in] corners in counter clockwise layer
1948 //   nurbs_surface - [in] if this pointer is not NULL,
1949 //       then this ON_NurbsSurface is used to return
1950 //       the quadrilateral.
1951 // Returns:
1952 //   An ON_NurbsSurface representation of the quadrilateral.
1953 ON_DECL
1954 ON_NurbsSurface* ON_NurbsSurfaceQuadrilateral(
1955              const ON_3dPoint& P,
1956              const ON_3dPoint& Q,
1957              const ON_3dPoint& R,
1958              const ON_3dPoint& S,
1959              ON_NurbsSurface* nurbs_surface = NULL
1960              );
1961 
1962 #if defined(ON_DLL_TEMPLATE)
1963 // This stuff is here because of a limitation in the way Microsoft
1964 // handles templates and DLLs.  See Microsoft's knowledge base
1965 // article ID Q168958 for details.
1966 #pragma warning( push )
1967 #pragma warning( disable : 4231 )
1968 ON_DLL_TEMPLATE template class ON_CLASS ON_ClassArray<ON_NurbsCurve>;
1969 ON_DLL_TEMPLATE template class ON_CLASS ON_ObjectArray<ON_NurbsCurve>;
1970 ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray<ON_NurbsCurve*>;
1971 ON_DLL_TEMPLATE template class ON_CLASS ON_ClassArray<ON_NurbsSurface>;
1972 ON_DLL_TEMPLATE template class ON_CLASS ON_ObjectArray<ON_NurbsSurface>;
1973 ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray<ON_NurbsSurface*>;
1974 ON_DLL_TEMPLATE template class ON_CLASS ON_ClassArray<ON_NurbsCage>;
1975 ON_DLL_TEMPLATE template class ON_CLASS ON_ObjectArray<ON_NurbsCage>;
1976 ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray<ON_NurbsCage*>;
1977 #pragma warning( pop )
1978 #endif
1979 
1980 #endif
1981