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