Files
opennurbs/opennurbs_nurbssurface.h
Bozo The Builder 488533eb7a Sync changes from upstream repository
Co-authored-by: Andrew le Bihan <andy@mcneel.com>
Co-authored-by: Brian Gillespie <brian@mcneel.com>
Co-authored-by: Dale Lear <dalelear@mcneel.com>
Co-authored-by: Giulio Piacentino <giulio@mcneel.com>
Co-authored-by: Greg Arden <greg@mcneel.com>
Co-authored-by: Lars <lars@mcneel.com>
Co-authored-by: Lowell <lowell@mcneelcom>
Co-authored-by: Nathan Letwory <nathan@mcneel.com>
Co-authored-by: Pierre Cuvilliers <pierre@mcneel.com>
Co-authored-by: Tim Hemmelman <tim@mcneel.com>
2020-12-16 05:49:44 -08:00

2163 lines
65 KiB
C++

/* $NoKeywords: $ */
/*
//
// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved.
// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
// McNeel & Associates.
//
// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
// MERCHANTABILITY ARE HEREBY DISCLAIMED.
//
// For complete openNURBS copyright information see <http://www.opennurbs.org>.
//
////////////////////////////////////////////////////////////////
*/
////////////////////////////////////////////////////////////////
//
// Definition of NURBS surface
//
////////////////////////////////////////////////////////////////
#if !defined(OPENNURBS_NURBSSURFACE_INC_)
#define OPENNURBS_NURBSSURFACE_INC_
class ON_CLASS ON_TensorProduct
{
// Pure virtual tensor passed to ON_NurbsSurface::TensorProduct()
public:
ON_TensorProduct();
virtual
~ON_TensorProduct();
// Evaluate() must define a function T:R^dimA X R^dimB -> R^Dimension()
// such that
//
// T(a*A0 + (1-a)*A1, B) = a*T(A0,B) + (1-a)*T(A1,B) and
// T(A, b*B0 + (1-b)*B1) = b*T(A,B0) + (1-b)*T(A,B1).
virtual
int DimensionA() const = 0; // dimension of A space
virtual
int DimensionB() const = 0; // dimension of B space
virtual
int DimensionC() const = 0; // dimension of range space
virtual
bool Evaluate( double, // a
const double*, // A
double, // b
const double*, // B
double* // C
) = 0;
};
class ON_Brep;
class ON_NurbsSurface;
class ON_CLASS ON_NurbsSurface : public ON_Surface
{
ON_OBJECT_DECLARE(ON_NurbsSurface);
public:
/*
Description:
Use ON_NurbsSurface::New(...) instead of new ON_NurbsSurface(...)
Returns:
Pointer to an ON_NurbsSurface. Destroy by calling delete.
Remarks:
See static ON_Brep* ON_Brep::New() for details.
*/
static ON_NurbsSurface* New();
static ON_NurbsSurface* New(
const ON_NurbsSurface& nurbs_surface
);
static ON_NurbsSurface* New(
const ON_BezierSurface& bezier_surface
);
static ON_NurbsSurface* New(
int dimension,
bool bIsRational,
int order0,
int order1,
int cv_count0,
int cv_count1
);
ON_NurbsSurface();
ON_NurbsSurface(const ON_NurbsSurface& nurbs_surface);
ON_NurbsSurface(const ON_BezierSurface& bezier_surface);
ON_NurbsSurface(
int dimension, // dimension (>= 1)
bool bIsRational, // true to make a rational NURBS
int order0, // order0 (>= 2)
int order1, // order1 (>= 2)
int cv_count0, // cv count0 (>= order0)
int cv_count1 // cv count1 (>= order1)
);
// virtual ON_Object::SizeOf override
unsigned int SizeOf() const override;
// virtual ON_Object::DataCRC override
ON__UINT32 DataCRC(ON__UINT32 current_remainder) const override;
/*
Description:
See if this and other are same NURBS geometry.
Parameters:
other - [in] other NURBS surface
bIgnoreParameterization - [in] if true, parameterization
and orientaion are ignored.
tolerance - [in] tolerance to use when comparing
control points.
Returns:
true if curves are tne same.
*/
bool IsDuplicate(
const ON_NurbsSurface& other,
bool bIgnoreParameterization,
double tolerance = ON_ZERO_TOLERANCE
) const;
void Initialize(void); // zeros all fields
bool Create(
int dim, // dimension (>= 1)
bool is_rat, // true to make a rational NURBS
int order0, // order0 (>= 2)
int order1, // order1 (>= 2)
int cv_count0, // cv count0 (>= order0)
int cv_count1 // cv count1 (>= order1)
);
/*
Description:
Create a ruled surface from two curves.
Parameters:
curveA - [in] (must have same NURBS form knots as curveB)
curveB - [in] (must have same NURBS form knots as curveA)
curveA_domain - [in] if not nullptr, then this is a subdomain
of curveA to use for the ruled surface.
curveB_domain - [in] if not nullptr, then this is a subdomain
of curveA to use for the ruled surface.
Returns:
@untitled table
0 failure
1 success - parameterization is exact
2 success - parameterization is not exact
Remarks:
The ruling parameter is the second surface parameter and
it is in the interval [0,1].
The true ruled surface has parameterization
srf(s,t) = (1.0-t)*curveA(s) + t*curveB(s).
The returned NURBS surface has parameterization
srf(s,t) = (1.0-t)*nurbs_curveA(s) + t*nurbs_curveB(s),
where nurbs_curveX is the NURBS form of curveX. If the
parameterization of nurbs_curveX does not match the
parameterization of curveX, then 2 is returned.
*/
virtual
int CreateRuledSurface(
const ON_Curve& curveA,
const ON_Curve& curveB,
const ON_Interval* curveA_domain = nullptr,
const ON_Interval* curveB_domain = nullptr
);
/*
Description:
Create a cone surface from a curve to a point.
Parameters:
apex_point - [in]
curve - [in]
curve_domain - [in] if not nullptr, then this is a subdomain
of curve to use for the ruled surface.
Returns:
@untitled table
0 failure
1 success - parameterization is exact
2 success - parameterization is not exact
Remarks:
The ruling parameter is the second surface parameter and
it is in the interval [0,1].
The true cone surface has parameterization
srf(s,t) = (1.0-t)*curve(s) + t*apex_point.
The returned NURBS surface has parameterization
srf(s,t) = (1.0-t)*nurbs_curve(s) + t*apex_point,
where nurbs_curve is the NURBS form of curve. If the
parameterization of nurbs_curve does not match the
parameterization of curve, then 2 is returned.
*/
int CreateConeSurface(
ON_3dPoint apex_point,
const ON_Curve& curve,
const ON_Interval* curve_domain = nullptr
);
/*
Description:
Collapse the side of a NURBS surface to a single point.
Parameters:
side - [in] 0 = south west,
1 = south east,
2 = north east,
3 = north west
point - [in] point to collapse to. If point is ON_3dPoint::UnsetPoint,
the the current location of the start of the side
is used.
Returns:
True if successful.
Remarks:
If the surface is rational, the weights of the side control
points must be set before calling CollapseSide.
*/
bool CollapseSide(
int side,
ON_3dPoint point = ON_3dPoint::UnsetPoint
);
void Destroy();
virtual ~ON_NurbsSurface();
void EmergencyDestroy(); // call if memory used by this class becomes invalid
ON_NurbsSurface& operator=(const ON_NurbsSurface&);
/*
Description:
Set NURBS surface equal to bezier surface with domain [0,1]x[0,1].
Parameters:
bezier_surface - [in]
*/
ON_NurbsSurface& operator=(
const ON_BezierSurface& bezier_surface
);
/////////////////////////////////////////////////////////////////
// ON_Object overrides
bool IsValid( class ON_TextLog* text_log = nullptr ) const override;
void Dump( ON_TextLog& ) const override; // for debugging
bool Write(
ON_BinaryArchive& // open binary file
) const override;
bool Read(
ON_BinaryArchive& // open binary file
) override;
/////////////////////////////////////////////////////////////////
// ON_Geometry overrides
int Dimension() const override;
// virtual ON_Geometry GetBBox override
bool GetBBox( double* boxmin, double* boxmax, bool bGrowBox = false ) const override;
bool Transform(
const ON_Xform&
) override;
// virtual ON_Geometry::IsDeformable() override
bool IsDeformable() const override;
// virtual ON_Geometry::MakeDeformable() override
bool MakeDeformable() override;
bool SwapCoordinates(
int, int // indices of coords to swap
) override;
/////////////////////////////////////////////////////////////////
// ON_Surface overrides
bool SetDomain(
int dir, // 0 sets first parameter's domain, 1 gets second parameter's domain
double t0,
double t1
) override;
ON_Interval Domain(
int // 0 gets first parameter's domain, 1 gets second parameter's domain
) const override;
/*
Description:
Get an estimate of the size of the rectangle that would
be created if the 3d surface where flattened into a rectangle.
Parameters:
width - [out] (corresponds to the first surface parameter)
height - [out] (corresponds to the first surface parameter)
Remarks:
overrides virtual ON_Surface::GetSurfaceSize
Returns:
true if successful.
*/
bool GetSurfaceSize(
double* width,
double* height
) const override;
int SpanCount(
int // 0 gets first parameter's domain, 1 gets second parameter's domain
) const override; // number of smooth spans in curve
bool GetSpanVector( // span "knots"
int, // 0 gets first parameter's domain, 1 gets second parameter's domain
double* // array of length SpanCount() + 1
) const override; //
int Degree( // returns maximum algebraic degree of any span
// ( or a good estimate if curve spans are not algebraic )
int // 0 gets first parameter's domain, 1 gets second parameter's domain
) const override;
bool GetParameterTolerance( // returns tminus < tplus: parameters tminus <= s <= tplus
int, // 0 gets first parameter, 1 gets second parameter
double, // t = parameter in domain
double*, // tminus
double* // tplus
) const override;
/*
Description:
Test a surface to see if it is planar.
Parameters:
plane - [out] if not nullptr and true is returned,
the plane parameters are filled in.
tolerance - [in] tolerance to use when checking
Returns:
true if there is a plane such that the maximum distance from
the surface to the plane is <= tolerance.
Remarks:
Overrides virtual ON_Surface::IsPlanar.
*/
bool IsPlanar(
ON_Plane* plane = nullptr,
double tolerance = ON_ZERO_TOLERANCE
) const override;
bool IsClosed( // true if NURBS surface is closed (either surface has
int // dir // clamped end knots and euclidean location of start
) const override; // CV = euclidean location of end CV, or surface is
// periodic.)
bool IsPeriodic( // true if NURBS surface is periodic (degree > 1,
int // dir // periodic knot vector, last degree many CVs
) const override; // are duplicates of first degree many CVs.)
bool IsSingular( // true if surface side is collapsed to a point
int // side of parameter space to test
// 0 = south, 1 = east, 2 = north, 3 = west
) const override;
/*
Description:
Search for a derivatitive, tangent, or curvature
discontinuity.
Parameters:
dir - [in] If 0, then "u" parameter is checked. If 1, then
the "v" parameter is checked.
c - [in] type of continity to test for.
t0 - [in] Search begins at t0. If there is a discontinuity
at t0, it will be ignored. This makes it
possible to repeatedly call GetNextDiscontinuity
and step through the discontinuities.
t1 - [in] (t0 != t1) If there is a discontinuity at t1 is
will be ingored unless c is a locus discontinuity
type and t1 is at the start or end of the curve.
t - [out] if a discontinuity is found, then *t reports the
parameter at the discontinuity.
hint - [in/out] if GetNextDiscontinuity will be called
repeatedly, passing a "hint" with initial value *hint=0
will increase the speed of the search.
dtype - [out] if not nullptr, *dtype reports the kind of
discontinuity found at *t. A value of 1 means the first
derivative or unit tangent was discontinuous. A value
of 2 means the second derivative or curvature was
discontinuous. A value of 0 means teh curve is not
closed, a locus discontinuity test was applied, and
t1 is at the start of end of the curve.
cos_angle_tolerance - [in] default = cos(1 degree) Used only
when c is ON::continuity::G1_continuous or ON::continuity::G2_continuous. If the
cosine of the angle between two tangent vectors is
<= cos_angle_tolerance, then a G1 discontinuity is reported.
curvature_tolerance - [in] (default = ON_SQRT_EPSILON) Used
only when c is ON::continuity::G2_continuous. If K0 and K1 are
curvatures evaluated from above and below and
|K0 - K1| > curvature_tolerance, then a curvature
discontinuity is reported.
Returns:
Parametric continuity tests c = (C0_continuous, ..., G2_continuous):
true if a parametric discontinuity was found strictly
between t0 and t1. Note well that all curves are
parametrically continuous at the ends of their domains.
Locus continuity tests c = (C0_locus_continuous, ...,G2_locus_continuous):
true if a locus discontinuity was found strictly between
t0 and t1 or at t1 is the at the end of a curve.
Note well that all open curves (IsClosed()=false) are locus
discontinuous at the ends of their domains. All closed
curves (IsClosed()=true) are at least C0_locus_continuous at
the ends of their domains.
*/
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 override;
/*
Description:
Test continuity at a surface parameter value.
Parameters:
c - [in] continuity to test for
s - [in] surface parameter to test
t - [in] surface parameter to test
hint - [in] evaluation hint
point_tolerance - [in] if the distance between two points is
greater than point_tolerance, then the surface is not C0.
d1_tolerance - [in] if the difference between two first derivatives is
greater than d1_tolerance, then the surface is not C1.
d2_tolerance - [in] if the difference between two second derivatives is
greater than d2_tolerance, then the surface is not C2.
cos_angle_tolerance - [in] default = cos(1 degree) Used only when
c is ON::continuity::G1_continuous or ON::continuity::G2_continuous. If the cosine
of the angle between two normal vectors
is <= cos_angle_tolerance, then a G1 discontinuity is reported.
curvature_tolerance - [in] (default = ON_SQRT_EPSILON) Used only when
c is ON::continuity::G2_continuous. If K0 and K1 are curvatures evaluated
from above and below and |K0 - K1| > curvature_tolerance,
then a curvature discontinuity is reported.
Returns:
true if the surface has at least the c type continuity at the parameter t.
Remarks:
Overrides virtual ON_Surface::IsContinuous
*/
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 override;
bool Reverse( // reverse parameterizatrion, Domain changes from [a,b] to [-b,-a]
int // dir 0 = "s", 1 = "t"
) override;
bool Transpose() override; // transpose surface parameterization (swap "s" and "t")
bool Evaluate( // returns false if unable to evaluate
double, double, // evaluation parameter
int, // number of derivatives (>=0)
int, // array stride (>=Dimension())
double*, // array of length stride*(ndir+1)*(ndir+2)/2
int = 0, // optional - determines which quadrant to evaluate from
// 0 = default
// 1 from NE quadrant
// 2 from NW quadrant
// 3 from SW quadrant
// 4 from SE quadrant
int* = 0 // optional - evaluation hint (int[2]) used to speed
// repeated evaluations
) const override;
/*
Description:
Get isoparametric curve.
Overrides virtual ON_Surface::IsoCurve.
Parameters:
dir - [in] 0 first parameter varies and second parameter is constant
e.g., point on IsoCurve(0,c) at t is srf(t,c)
1 first parameter is constant and second parameter varies
e.g., point on IsoCurve(1,c) at t is srf(c,t)
c - [in] value of constant parameter
Returns:
Isoparametric curve.
*/
ON_Curve* IsoCurve(
int dir,
double c
) const override;
/*
Description:
Removes the portions of the surface outside of the specified interval.
Overrides virtual ON_Surface::Trim.
Parameters:
dir - [in] 0 The domain specifies an sub-interval of Domain(0)
(the first surface parameter).
1 The domain specifies an sub-interval of Domain(1)
(the second surface parameter).
domain - [in] interval of the surface to keep. If dir is 0, then
the portions of the surface with parameters (s,t) satisfying
s < Domain(0).Min() or s > Domain(0).Max() are trimmed away.
If dir is 1, then the portions of the surface with parameters
(s,t) satisfying t < Domain(1).Min() or t > Domain(1).Max()
are trimmed away.
*/
bool Trim(
int dir,
const ON_Interval& domain
) override;
/*
Description:
Where possible, analytically extends surface to include domain.
Parameters:
dir - [in] 0 new Domain(0) will include domain.
(the first surface parameter).
1 new Domain(1) will include domain.
(the second surface parameter).
domain - [in] if domain is not included in surface domain,
surface will be extended so that its domain includes domain.
Will not work if surface is closed in direction dir.
Original surface is identical to the restriction of the
resulting surface to the original surface domain,
Returns:
true if successful.
*/
bool Extend(
int dir,
const ON_Interval& domain
) override;
/*
Description:
Splits (divides) the surface into two parts at the
specified parameter.
Overrides virtual ON_Surface::Split.
Parameters:
dir - [in] 0 The surface is split vertically. The "west" side
is returned in "west_or_south_side" and the "east"
side is returned in "east_or_north_side".
1 The surface is split horizontally. The "south" side
is returned in "west_or_south_side" and the "north"
side is returned in "east_or_north_side".
c - [in] value of constant parameter in interval returned
by Domain(dir)
west_or_south_side - [out] west/south portion of surface returned here
east_or_north_side - [out] east/north portion of surface returned here
Example:
ON_NurbsSurface srf = ...;
int dir = 1;
ON_NurbsSurface* south_side = 0;
ON_NurbsSurface* north_side = 0;
srf.Split( dir, srf.Domain(dir).Mid() south_side, north_side );
*/
bool Split(
int dir,
double c,
ON_Surface*& west_or_south_side,
ON_Surface*& east_or_north_side
) const override;
/*
Description:
Offset surface.
Parameters:
offset_distance - [in] offset distance
tolerance - [in] Some surfaces do not have an exact offset that
can be represented using the same class of surface definition.
In that case, the tolerance specifies the desired accuracy.
max_deviation - [out] If this parameter is not nullptr, the maximum
deviation from the returned offset to the true offset is returned
here. This deviation is zero except for cases where an exact
offset cannot be computed using the same class of surface definition.
Returns:
Offset surface.
*/
ON_Surface* Offset(
double offset_distance,
double tolerance,
double* max_deviation = nullptr
) const;
// virtual ON_Surface::GetNurbForm() override.
// The ON_NurbsSurface version returns 1 and a copy of the ON_NurbsSurface.
int GetNurbForm(
ON_NurbsSurface&,
double = 0.0
) const override;
// virtual ON_Surface::HasNurbForm() override.
// The ON_NurbsSurface version returns 1.
int HasNurbForm(
) const override;
/*
Description:
Approximate the entire NURBS surface with a single nonrational cubic bezier surface.
Typically, the NURBS surface has only a few bispans.
Parameters:
max_deviation - [in]
If max_deviation >= 0.0, then the approximation is returned only
if the deviation sample is <= max_deviation.
bezierSurface - [out]
Returns:
ON_DBL_QNAN: no bezier surface is returned.
If a bezier surface is returned, then the maximum deviation between
the bezier suface this NURBS surface sampled at the Greville abcissa.
*/
double GetCubicBezierApproximation(
double max_deviation,
class ON_BezierSurface& bezierSurface
) const;
/*
Description:
Approximate the entire NURBS surface with a single nonrational cubic bezier surface.
Typically, the NURBS surface has only a few bispans.
Parameters:
max_deviation - [in]
If max_deviation >= 0.0, then the approximation is returned only
if the deviation sample is <= max_deviation.
bezierSurface - [out]
Returns:
ON_DBL_QNAN: no bezier surface is returned.
If a bezier surface is returned, then the maximum deviation between
the bezier suface this NURBS surface sampled at the Greville abcissa.
*/
double GetCubicBezierApproximation(
double max_deviation,
ON_3dPoint bezCV[4][4]
) const;
/////////////////////////////////////////////////////////////////
// Interface
/*
Description:
Get the maximum length of a nurb surface's control polygon
rows and/or columns
Parameters:
dir - [in] 0 to get "u" direction length, 1 to get "v"
direction length
length - [out] maximum length of a polygon "row" in the
specified direction
Returns:
true if successful.
*/
double ControlPolygonLength( int dir ) const;
bool IsRational( // true if NURBS surface is rational
void
) const;
int CVSize( // number of doubles per control vertex
void // = IsRational() ? Dim()+1 : Dim()
) const;
int Order( // order = degree + 1
int // dir 0 = "s", 1 = "t"
) const;
int CVCount( // number of control vertices
int // dir 0 = "s", 1 = "t"
) const;
int CVCount( // total number of control vertices
void
) const;
int KnotCount( // total number of knots in knot vector
int dir // dir 0 = "s", 1 = "t"
) const;
/*
Description:
Expert user function to get a pointer to control vertex
memory. If you are not an expert user, please use
ON_NurbsSurface::GetCV( ON_3dPoint& ) or
ON_NurbsSurface::GetCV( ON_4dPoint& ).
Parameters:
i - [in] (0 <= i < m_cv_count[0])
j - [in] (0 <= j < m_cv_count[1])
Returns:
Pointer to control vertex.
Remarks:
If the NURBS surface is rational, the format of the
returned array is a homogeneos rational point with
length m_dim+1. If the NURBS surface is not rational,
the format of the returned array is a nonrational
euclidean point with length m_dim.
See Also
ON_NurbsSurface::CVStyle
ON_NurbsSurface::GetCV
ON_NurbsSurface::Weight
*/
double* CV(
int i,
int j
) const;
double* CV(
ON_2dex cvdex
) const;
double* CV(
ON_2udex cvdex
) const;
/*
Parameters:
i - [in]
zero based control point index
j - [in]
zero based control point index
Returns:
Control point as an ON_4dPoint.
Remarks:
If i, j, or the nurbs surface is not valid, then ON_4dPoint::Nan is returned.
If dim < 3, unused coordinates are zero.
If dim >= 4, the first three coordinates are returned.
If is_rat is false, the weight is 1.
*/
const ON_4dPoint ControlPoint(
int i,
int j
) const;
/*
Description:
Returns the style of control vertices in the m_cv array.
Returns:
@untitled table
ON::not_rational m_is_rat is false
ON::homogeneous_rational m_is_rat is true
*/
ON::point_style CVStyle() const;
double Weight( // get value of control vertex weight
int i, int j // CV index ( 0 <= i <= CVCount(0), 0 <= j <= CVCount(1)
) const;
/*
Description:
Set value of control vertex weight.
If surface is non-rational, it will be converted to rational.
*/
bool SetWeight(
int i, int j, // CV index ( 0 <= i <= CVCount(0), 0 <= j <= CVCount(1)
double weight // value of control point weight
);
bool SetCV( // set a single control vertex
int i, int j, // CV index ( 0 <= i <= CVCount(0), 0 <= j <= CVCount(1)
ON::point_style, // style of input point
const double* cv // value of control vertex
);
bool SetCV( // set a single control vertex
int i, int j, // CV index ( 0 <= i <= CVCount(0), 0 <= j <= CVCount(1)
const ON_3dPoint& cv// value of control vertex
// If NURBS is rational, weight
// will be set to 1.
);
bool SetCV( // set a single control vertex
int i, int j, // CV index ( 0 <= i <= CVCount(0), 0 <= j <= CVCount(1)
const ON_4dPoint& cv// value of control vertex
);
bool SetCVRow( // Sets CV( *, row_index )
int row_index, // row_index >= 0 and < m_cv_count[1]
const ON_3dPoint& cv // value of control vertex
// If NURBS is rational, weight
// will be set to 1.
);
bool SetCVRow( // Sets CV( *, row_index )
int row_index, // row_index >= 0 and < m_cv_count[1]
int v_stride, // v stride
const double* v // v[] = values (same dim and is_rat as surface)
);
bool SetCVColumn( // Sets CV( col_index, * )
int col_index, // col_index >= 0 and < m_cv_count[0]
const ON_3dPoint& cv // value of control vertex
// If NURBS is rational, weight
// will be set to 1.
);
bool SetCVColumn( // Sets CV( col_index, * )
int col_index, // col_index >= 0 and < m_cv_count[0]
int v_stride, // v stride
const double* v // v[] = values (same dim and is_rat as surface)
);
bool GetCV( // get a single control vertex
int i, int j, // CV index ( 0 <= i <= CVCount(0), 0 <= j <= CVCount(1)
ON::point_style, // style to use for output point
double* cv // array of length >= CVSize()
) const;
bool GetCV( // get a single control vertex
int i, int j, // CV index ( 0 <= i <= CVCount(0), 0 <= j <= CVCount(1)
ON_3dPoint& cv // gets euclidean cv when NURBS is rational
) const;
bool GetCV( // get a single control vertex
int i, int j, // CV index ( 0 <= i <= CVCount(0), 0 <= j <= CVCount(1)
ON_4dPoint& cv // gets homogeneous cv
) const;
bool SetKnot(
int dir, // dir 0 = "s", 1 = "t"
int knot_index, // knot index ( 0 to KnotCount - 1 )
double knot_value // value for knot
);
double Knot(
int dir, // dir 0 = "s", 1 = "t"
int knot_index // knot index ( >= 0 and < Order + CV_count - 2 )
) const;
int KnotMultiplicity(
int dir, // dir 0 = "s", 1 = "t"
int knot_index // knot index ( >= 0 and < Order + CV_count - 2 )
) const;
const double* Knot( // knot[] array
int dir // dir 0 = "s", 1 = "t"
) const;
// Description:
// Make knot vector a clamped uniform knot vector
// based on the current values of m_order and m_cv_count.
// Does not change values of control vertices.
// Parameters:
// dir - [in] 0 = u knots, 1 = v knots
// delta - [in] (>0.0) knot spacing.
// Returns:
// true if successful.
// Remarks:
// Allocates m_knot[] if it is not big enough.
// See Also:
// ON_MakeClampedUniformKnotVector
bool MakeClampedUniformKnotVector(
int dir,
double delta = 1.0
);
// Description:
// Make knot vector a periodic uniform knot vector
// based on the current values of m_order and m_cv_count.
// Does not change values of control vertices.
// Parameters:
// dir - [in] 0 = u knots, 1 = v knots
// delta - [in] (>0.0) knot spacing.
// Returns:
// true if successful.
// Remarks:
// Allocates m_knot[] if it is not big enough.
// See Also:
// ON_MakePeriodicUniformKnotVector
bool MakePeriodicUniformKnotVector(
int dir,
double delta = 1.0
);
/*
Description:
Test the knot vector to see if it is clamped.
Parameters:
dir:
0: first parameter
1: second parameter
end:
0: test start
1: test end
2: test start and end.
*/ bool IsClamped(
int dir,
int end = 2
) const;
/*
Description:
Test the side of a surface to see if it's natural (Zero 2nd derivative).
Parameters:
dir:
0: first parameter
1: second parameter
end:
0: test start
1: test end
2: test start and end.
*/
bool IsNatural( // determine if knot vector is clamped
int dir, // dir 0 = "s", 1 = "t"
int end = 2 // end to check: 0 = start, 1 = end, 2 = start and end
) const;
/*
Description:
Test a surface to see if it's natural (Zero 2nd derivative) on an iso curve.
Parameters:
dir:
0: first parameter
1: second parameter
t_count - [in]
t - [in]
t[] is a list of parameters to check.
*/
bool IsNatural( // determine if knot vector is clamped
int dir, // dir 0 = "s", 1 = "t"
size_t t_count,
const double* t
) const;
double SuperfluousKnot(
int dir, // dir 0 = "s", 1 = "t"
int end // 0 = start, 1 = end
) const;
double GrevilleAbcissa(
int dir, // dir
int cv_index // index (0 <= index < CVCount(dir)
) const;
bool GetGrevilleAbcissae( // see ON_GetGrevilleAbcissa() for details
int dir, // dir
double* g // g[cv count]
) const;
bool SetClampedGrevilleKnotVector(
int dir, // dir
int g_stride, // g_stride
const double* g // g[], CVCount(dir) many Greville abcissa
);
bool SetPeriodicGrevilleKnotVector(
int dir, // dir
int g_stride, // g_stride
const double* g // g[], Greville abcissa
);
bool ZeroCVs(); // zeros all CVs (any weights set to 1);
bool ClampEnd(
int dir, // dir 0 = "s", 1 = "t"
int end // 0 = clamp start, 1 = clamp end, 2 = clamp start and end
);
bool InsertKnot(
int dir, // dir 0 = "s", 1 = "t"
double knot_value, // value of knot
int knot_multiplicity=1 // multiplicity of knot ( >= 1 and <= degree )
);
bool MakeRational();
bool MakeNonRational();
bool IncreaseDegree(
int dir, // dir 0 = "s", 1 = "t"
int desired_degree // desired_degree
);
bool ChangeDimension(
int desired_dimension // desired_dimension
);
/*
Description:
If the surface is closed in direction dir, then modify it so that
the seam is at parameter t in the dir direction.
Parameters:
dir - [in] must be 0 or 1
t - [in] dir parameter of seam, must have Domain(dir).Includes(t).
The resulting surface domain in the dir direction will start at t.
Returns:
true if successful.
*/
bool ChangeSurfaceSeam(
int dir,
double t
);
// Creates a tensor product nurbs surface with srf(s,t) = T(A(s),B(t));
bool TensorProduct(
const ON_NurbsCurve&, // A
const ON_NurbsCurve&, // B
ON_TensorProduct& // T
);
/////////////////////////////////////////////////////////////////
// Tools for managing CV and knot memory
bool ReserveKnotCapacity( // returns false if allocation fails
// does not change m_order or m_cv_count
int dir, // dir 0 = "s", 1 = "t"
int knot_array_capacity // minimum capacity of m_knot[] array
);
bool ReserveCVCapacity( // returns false if allocation fails
// does not change m_order or m_cv_count
int cv_array_capacity // minimum capacity of m_cv[] array
);
/*
Description:
Convert a NURBS surface bispan into a bezier surface.
Parameters:
span_index0 - [in] Specifies the "u" span and must satisfy
0 <= span_index0 <= m_cv_count[0]-m_order[0]
m_knot[0][span_index0+m_order[0]-2] < m_knot[0][span_index0+m_order[0]-1]
span_index1 - [in] Specifies the "v" span and must satisfy
0 <= span_index1 <= m_cv_count[1]-m_order[1]
m_knot[1][span_index1+m_order[1]-2] < m_knot[1][span_index1+m_order[1]-1]
bezier_surface - [out] bezier surface returned here
Returns:
true if successful
false if input is not valid
*/
bool ConvertSpanToBezier(
int span_index0,
int span_index1,
ON_BezierSurface& bezier_surface
) const;
/*
Description:
Create an ON_NurbsSurface satisfying Hermite interpolation conditions at a grid of points.
Parameters:
u_Parameters
v_Parameters - [in] Specifies the "u"( or "v") parameters defining the grid of parameter values
u_Parameters.Count()>1
u_Parameters are strictly increasing, i.e. u_Parameters[i] < u_Parameters[i+1]
same conditions on v_Parameters
Let n = u_Parameters.Count() and m = v_Parameters.Count().
Each of GridPoints, u_Tangents, v_Tangents and TwistVectors are data on a grid of parameters.
The size of each of these arrays must be n x m, s
GridPoints.Count() == n and GridPoints[i].Count() == m.
GridPoints - [in] Grid of points to interpolate.
u_Tangents - [in] Grid of Tangent directions ( actually first derivatives) to interpolate.
v_Tangents - [in] Grid of Tangent directions ( actually first derivatives) to interpolate.
TwistVectors - [in] Grid of twist vectors (mixed second partial derovative) to interpolate.
hermite_surface -[in] optional existing ON_NurbsSurface returned here.
Returns:
A hermite-surface satisfying interpolation conditions. Null if error.
Notes:
The Hermite surface, H, is bicubic on each patch [u_i, u_(i+1)] x [v_j, v_(j+1)]
and satisfies
H( u_i, v_j) = GridData[i][j]
H_u(u_i, v_j) = u_Tangents[i][j]
H_v(u_i, v_j) = v_Tangents[i][j]
H_uv(u_i, v_j) = Twist[i][j]
*/
static
class ON_NurbsSurface* CreateHermiteSurface(
const ON_SimpleArray<double>& u_Parameters,
const ON_SimpleArray<double>& v_Parameters,
const ON_ClassArray<ON_SimpleArray<ON_3dPoint>>& GridPoints,
const ON_ClassArray<ON_SimpleArray<ON_3dVector>>& u_Tangents,
const ON_ClassArray<ON_SimpleArray<ON_3dVector>>& v_Tangents,
const ON_ClassArray<ON_SimpleArray<ON_3dVector>>& TwistVectors,
class ON_NurbsSurface* hermite_surface = 0);
public:
#if defined(ON_COMPILING_OPENNURBS)
static void ON_Internal_ConvertToCurve(const ON_NurbsSurface& srf, int dir,
ON_NurbsCurve& crv);
static void ON_Internal_ConvertFromCurve(ON_NurbsCurve& crv, int dir,
ON_NurbsSurface& srf);
static bool ON_Internal_MakeKnotVectorsCompatible(
ON_NurbsCurve& nurbs_curveA, ON_NurbsCurve& nurbs_curveB);
#endif // ON_COMPILING_OPENNURBS
/////////////////////////////////////////////////////////////////
// Implementation
public:
// NOTE: These members are left "public" so that expert users may efficiently
// create NURBS curves using the default constructor and borrow the
// knot and CV arrays from their native NURBS representation.
// No technical support will be provided for users who access these
// members directly. If you can't get your stuff to work, then use
// the constructor with the arguments and the SetKnot() and SetCV()
// functions to fill in the arrays.
int m_dim; // (>=1)
int m_is_rat; // 1 for rational B-splines. (Control vertices
// use homogeneous form.)
// 0 for non-rational B-splines. (Control
// verticies do not have a weight coordinate.)
int m_order[2]; // order = degree+1 (>=2)
int m_cv_count[2]; // number of control vertices ( >= order )
// knot vector memory
int m_knot_capacity[2]; // If m_knot_capacity > 0, then m_knot[]
// is an array of at least m_knot_capacity
// doubles whose memory is managed by the
// ON_NurbsSurface class using rhmalloc(),
// onrealloc(), and rhfree().
// If m_knot_capacity is 0 and m_knot is
// not nullptr, then m_knot[] is assumed to
// be big enough for any requested operation
// and m_knot[] is not deleted by the
// destructor.
double* m_knot[2]; // Knot vector. ( The knot vector has length
// m_order+m_cv_count-2. )
// control vertex net memory
int m_cv_stride[2]; // The pointer to start of "CV[i]" is
// m_cv + i*m_cv_stride.
int m_cv_capacity; // If m_cv_capacity > 0, then m_cv[] is an array
// of at least m_cv_capacity doubles whose
// memory is managed by the ON_NurbsSurface
// class using rhmalloc(), onrealloc(), and rhfree().
// If m_cv_capacity is 0 and m_cv is not
// nullptr, then m_cv[] is assumed to be big enough
// for any requested operation and m_cv[] is not
// deleted by the destructor.
double* m_cv; // Control points.
// If m_is_rat is false, then control point is
//
// ( CV(i)[0], ..., CV(i)[m_dim-1] ).
//
// If m_is_rat is true, then the control point
// is stored in HOMOGENEOUS form and is
//
// [ CV(i)[0], ..., CV(i)[m_dim] ].
//
};
class ON_CLASS ON_NurbsCage : public ON_Geometry
{
ON_OBJECT_DECLARE(ON_NurbsCage);
public:
ON_NurbsCage();
ON_NurbsCage(
int dim,
bool is_rat,
int order0,
int order1,
int order2,
int cv_count0,
int cv_count1,
int cv_count2
);
ON_NurbsCage(
const ON_BoundingBox& bbox,
int order0,
int order1,
int order2,
int cv_count0,
int cv_count1,
int cv_count2
);
ON_NurbsCage(
const ON_3dPoint* box_corners, // array of 8 3d points
int order0,
int order1,
int order2,
int cv_count0,
int cv_count1,
int cv_count2
);
ON_NurbsCage( const ON_BezierCage& src );
~ON_NurbsCage();
ON_NurbsCage(const ON_NurbsCage& src);
ON_NurbsCage& operator=(const ON_NurbsCage& src);
ON_NurbsCage& operator=(const ON_BezierCage& src);
bool IsValid( class ON_TextLog* text_log = nullptr ) const override;
/*
Description:
Overrides the pure virtual ON_Object::Dump function.
Parameters:
text_log - [in] A listing of the values of the members.
*/
void Dump( ON_TextLog& text_log) const override;
/*
Description:
Overrides the pure virtual ON_Object::SizeOf function.
Returns:
An estimate of the amount of memory used by the class
and its members.
*/
unsigned int SizeOf() const override;
// virtual ON_Object::DataCRC override
ON__UINT32 DataCRC(ON__UINT32 current_remainder) const override;
/*
Description:
Overrides the pure virtual ON_Object::Read function.
Reads the definition of this class from an
archive previously saved by ON_BezierVolue::Write.
Parameters:
archive - [in] target archive
Returns:
True if successful.
*/
bool Read(
ON_BinaryArchive& archive
) override;
/*
Description:
Overrides the pure virtual ON_Object::Write function.
Saves the definition of this class in serial binary
form that can be read by ON_BezierVolue::Read.
Parameters:
archive - [in] target archive
Returns:
True if successful.
*/
bool Write(
ON_BinaryArchive& archive
) const override;
/*
Description:
Overrides the pure virtual ON_Object::ObjectType function.
Saves the definition of this class in serial binary
form that can be read by ON_BezierVolue::Read.
Parameters:
archive - [in] target archive
Returns:
True if successful.
*/
ON::object_type ObjectType() const override;
/*
Description:
Overrides the pure virtual ON_Object::DestroyRuntimeCache function.
Saves the definition of this class in serial binary
form that can be read by ON_BezierVolue::Read.
Parameters:
bDelete - [in] if true, the cache is deleted. If false, the
pointers to the cache are set to zero; this is done when
the cache memory was allocated from a pool that has
been destroyed and an attempt to free the memory would
result in a crash.
Returns:
True if successful.
*/
void DestroyRuntimeCache(
bool bDelete = true
) override;
/*
Description:
Overrides virtual ON_Geometry::Dimension function.
Gets a tight bounding box with respect to the coordinate
system specified by the frame parameter.
Parameters:
bbox - [in/out]
bGrowBox - [in] If true, the input bbox is grown to include
this object's bounding box.
frame - [in] if not null, this specifies the coordinate system
frame.
Returns:
True if successful.
*/
int Dimension() const override;
// virtual ON_Geometry GetBBox override
bool GetBBox( double* boxmin, double* boxmax, bool bGrowBox = false ) const override;
// virtual ON_Geometry GetTightBoundingBox override
bool GetTightBoundingBox( class ON_BoundingBox& tight_bbox, bool bGrowBox = false, const class ON_Xform* xform = nullptr ) const override;
/*
Description:
Overrides virtual ON_Geometry::Transform function.
Transforms NURBS volume.
Parameters:
xform - [in]
Returns:
true if successful.
*/
bool Transform(
const ON_Xform& xform
) override;
/*
Description:
Overrides virtual ON_Geometry::IsDeformable function.
Returns:
True because a NURBS volume can be accuratly modified
with "squishy" transformations like projections,
shears, an non-uniform scaling.
*/
bool IsDeformable() const override;
/*
Description:
Overrides virtual ON_Geometry::MakeDeformable function.
Returns:
True because NURBS volumes are deformable.
*/
bool MakeDeformable() override;
/*
Returns:
True if the cage is a parallelogram within the tolerance.
This means the cage can be used as a starting point
for cage deformations.
*/
bool IsParallelogram(double tolerance) const;
bool Create(
int dim,
bool is_rat,
int order0,
int order1,
int order2,
int cv_count0,
int cv_count1,
int cv_count2
);
/*
Description:
Create a Nurbs volume with corners defined by a bounding box.
Parameters:
box_corners - [in] 8 points that define corners of the volume
7______________6
|\ |\
| \ | \
| \ _____________\
| 4 | 5
| | | |
| | | |
3---|----------2 |
\ | \ |
\ |z \ |
y \ | \ |
\0_____________\1
x
*/
bool Create(
const ON_BoundingBox& bbox,
int order0,
int order1,
int order2,
int cv_count0,
int cv_count1,
int cv_count2
);
/*
Description:
Create a nurbs volume from a 3d box
Parameters:
box_corners - [in] 8 points that define corners of the volume
7______________6
|\ |\
| \ | \
| \ _____________\
| 4 | 5
| | | |
| | | |
3---|----------2 |
\ | \ |
\ |t \ |
s \ | \ |
\0_____________\1
r
*/
bool Create(
const ON_3dPoint* box_corners,
int order0,
int order1,
int order2,
int cv_count0,
int cv_count1,
int cv_count2
);
void Destroy();
void EmergencyDestroy(); // call if memory used by ON_NurbsCage becomes invalid
ON_Interval Domain(
int // dir 0 = "r", 1 = "s", 2 = "t"
) const;
bool Reverse(
int dir // dir 0 = "r", 1 = "s", 2 = "t"
);
bool Transpose(
int dir0,
int dir1
);
bool ClampEnd(
int dir, // dir 0 = "r", 1 = "s", 2 = "t"
int end // 0 = clamp start, 1 = clamp end, 2 = clamp start and end
);
bool InsertKnot(
int dir, // dir 0 = "r", 1 = "s", 2 = "t"
double knot_value, // value of knot
int knot_multiplicity=1 // multiplicity of knot ( >= 1 and <= degree )
);
bool IncreaseDegree(
int dir, // dir 0 = "r", 1 = "s", 2 = "t"
int desired_degree // desired_degree
);
bool ChangeDimension(
int desired_dimension // desired_dimension
);
/*
Description:
Evaluate the NURBS cage
Parameters:
r - [in]
s - [in]
t - [in] (r,s,t) = evaluation parameters
der_count - [in] (>= 0)
v_stride - [in] (>= m_dim)
v - [out] An array of length v_stride*(der_count+1)(der_count+2)*(der_count+3)/6.
The evaluation results are stored in this array.
P = v[0],...,v[m_dim-1]
Dr = v[v_stride],...
Ds = v[2*v_stride],...
Dt = v[3*v_stride],...
In general, Dr^i Ds^j Dt^k is returned in v[n],...,v[n+m_dim-1], where
d = (i+j+k)
n = v_stride*( d*(d+1)*(d+2)/6 + (j+k)*(j+k+1)/2 + k)
side - [in] specifies the span to use for the evaluation
when r, s, or t is at a knot value.
0 = default
1 = from upper NE quadrant
2 = from upper NW quadrant
3 = from upper SW quadrant
4 = from upper SE quadrant
5 = from lower NE quadrant
6 = from lower NW quadrant
7 = from lower SW quadrant
8 = from lower SE quadrant
hint - [in/out] If a bunch of evaluations will be performed that
tend to occur in the same region, then
hint[3] can be used to speed the search for
the evaluation span. The input value is
used as a search hint and the output value
records the span used for that evaluation.
Example:
int der_count = 2;
int v_stride = dim;
double v[v_stride*(der_count+1)*(der_count+2)*(der_count+3)/6];
int side = 0;
int hint[3]; hint[0] = 0; hint[1] = 0; hint[2] = 0;
bool rc = cage.Evaluate(r,s,t,der_count,v_stride,v,side,hint);
ON_3dPoint P = v;
// first order partial derivatives
ON_3dVector Dr = v + v_stride;
ON_3dVector Ds = v + 2*v_stride;
ON_3dVector Dt = v + 3*v_stride;
// second order partial derivatives
ON_3dVector Drr = v + 4*v_stride;
ON_3dVector Drs = v + 5*v_stride;
ON_3dVector Drt = v + 6*v_stride;
ON_3dVector Dss = v + 7*v_stride;
ON_3dVector Dst = v + 8*v_stride;
ON_3dVector Dtt = v + 8*v_stride;
Returns:
True if successful
See Also:
ON_NurbsCage::PointAt
*/
bool Evaluate(
double r,
double s,
double t,
int der_count,
int v_stride,
double* v,
int side=0,
int* hint=0
) const;
/*
Description:
Evaluates bezer volume map.
Parameters:
rst - [in]
Returns:
Value of the nurbs volume map at (r,s,t).
*/
ON_3dPoint PointAt(
double r,
double s,
double t
) const;
ON_NurbsSurface* IsoSurface(
int dir,
double c,
ON_NurbsSurface* srf = 0
) const;
bool Trim(
int dir,
const ON_Interval& domain
);
bool Extend(
int dir,
const ON_Interval& domain
);
/*
Description:
Evaluates bezer volume map.
Parameters:
rst - [in]
Returns:
Value of the nurbs volume map at (rst.x,rst.y,rst.z).
*/
ON_3dPoint PointAt(
ON_3dPoint rst
) const;
bool IsRational() const;
int CVSize() const;
int Order(
int dir // dir 0 = "r", 1 = "s", 2 = "t"
) const;
int CVCount( // number of control vertices
int // dir 0 = "r", 1 = "s", 2 = "t"
) const;
int CVCount( // total number of control vertices
void
) const;
int KnotCount( // total number of knots in knot vector
int dir // dir 0 = "r", 1 = "s", 2 = "t"
) const;
int Degree(
int dir
) const;
int SpanCount(
int dir // dir 0 = "r", 1 = "s", 2 = "t"
) const;
bool GetSpanVector(
int dir, // dir 0 = "r", 1 = "s", 2 = "t"
double* span_vector
) const;
/*
Description:
Expert user function to get a pointer to control vertex
memory. If you are not an expert user, please use
ON_NurbsCage::GetCV( ON_3dPoint& ) or
ON_NurbsCage::GetCV( ON_4dPoint& ).
Parameters:
cv_index0 - [in] (0 <= cv_index0 < m_order[0])
cv_index1 - [in] (0 <= cv_index1 < m_order[1])
Returns:
Pointer to control vertex.
Remarks:
If the Nurbs surface is rational, the format of the
returned array is a homogeneos rational point with
length m_dim+1. If the Nurbs surface is not rational,
the format of the returned array is a nonrational
euclidean point with length m_dim.
See Also
ON_NurbsCage::CVStyle
ON_NurbsCage::GetCV
ON_NurbsCage::Weight
*/
double* CV(
int i,
int j,
int k
) const;
/*
Description:
Returns the style of control vertices in the m_cv array.
Returns:
@untitled table
ON::not_rational m_is_rat is false
ON::homogeneous_rational m_is_rat is true
*/
ON::point_style CVStyle() const;
double Weight( // get value of control vertex weight
int i,
int j,
int k
) const;
bool SetWeight( // get value of control vertex weight
int i,
int j,
int k,
double w
);
bool SetCV( // set a single control vertex
int i,
int j,
int k,
ON::point_style, // style of input point
const double* // value of control vertex
);
// set a single control vertex
// If NURBS is rational, weight
// will be set to 1.
bool SetCV(
int i,
int j,
int k,
const ON_3dPoint& point
);
// set a single control vertex
// value of control vertex
// If NURBS is not rational, euclidean
// location of homogeneous point will
// be used.
bool SetCV(
int i,
int j,
int k,
const ON_4dPoint& hpoint
);
bool GetCV( // get a single control vertex
int i,
int j,
int k,
ON::point_style, // style to use for output point
double* // array of length >= CVSize()
) const;
bool GetCV( // get a single control vertex
int i,
int j,
int k,
ON_3dPoint& // gets euclidean cv when NURBS is rational
) const;
bool GetCV( // get a single control vertex
int i,
int j,
int k,
ON_4dPoint& // gets homogeneous cv
) const;
/*
Parameters:
dir - [in] 0 = "r", 1 = "s", 2 = "t"
knot_index - [in] 0 <= knot_index < KnotCount(dir)
knot_value - [in]
Returns:
True if dir and knot_index parameters were valid and knot value
was set.
*/
bool SetKnot(
int dir,
int knot_index,
double knot_value
);
/*
Parameters:
dir - [in] 0 = "r", 1 = "s", 2 = "t"
knot_index - [in] 0 <= knot_index < KnotCount(dir)
Returns:
Value of knot or ON_UNSET_VALUE if input parameters are not valid.
*/
double Knot(
int dir,
int knot_index
) const;
bool ZeroCVs(); // zeros control vertices and, if rational, sets weights to 1
bool MakeRational();
bool MakeNonRational();
bool IsClosed( // true if NURBS cage is closed (either cage has
int // dir // clamped end knots and euclidean location of start
) const; // CV = euclidean location of end CV, or cage is
// periodic.)
bool IsPeriodic( // true if NURBS cage is periodic (degree > 1,
int // dir // periodic knot vector, last degree many CVs
) const; // are duplicates of first degree many CVs.)
bool IsSingular( // true if cage side is collapsed to a point
int // side of parameter space to test
// 0 = south, 1 = east, 2 = north, 3 = west
) const;
double GrevilleAbcissa(
int dir, // dir
int gindex // index (0 <= index < CVCount(dir)
) const;
/////////////////////////////////////////////////////////////////
// Tools for managing CV and knot memory
/*
Description:
cv_capacity - [in] number of doubles to reserve
*/
bool ReserveCVCapacity(
int cv_capacity
);
bool ReserveKnotCapacity(
int dir,
int cv_capacity
);
/////////////////////////////////////////////////////////////////
// Implementation
public:
// NOTE: These members are left "public" so that expert users may efficiently
// create nurbs curves using the default constructor and borrow the
// knot and CV arrays from their native NURBS representation.
// No technical support will be provided for users who access these
// members directly. If you can't get your stuff to work, then use
// the constructor with the arguments and the SetKnot() and SetCV()
// functions to fill in the arrays.
int m_dim;
bool m_is_rat;
int m_order[3];
int m_cv_count[3];
int m_knot_capacity[3];
double* m_knot[3];
int m_cv_stride[3];
int m_cv_capacity;
double* m_cv;
};
ON_DECL
bool ON_GetCageXform(
const ON_NurbsCage& cage,
ON_Xform& cage_xform
);
class ON_CLASS ON_MorphControl : public ON_Geometry
{
ON_OBJECT_DECLARE(ON_MorphControl);
public:
ON_MorphControl();
virtual ~ON_MorphControl();
// C++ default copy construction and operator= work fine.
void Destroy();
/////////////////////////////////////////////////////////
//
// ON_Object virtual functions
//
void MemoryRelocate() override;
bool IsValid( class ON_TextLog* text_log = nullptr ) const override;
void Dump( ON_TextLog& ) const override;
unsigned int SizeOf() const override;
bool Write(
ON_BinaryArchive& archive
) const override;
bool Read(
ON_BinaryArchive& archive
) override;
ON::object_type ObjectType() const override;
void DestroyRuntimeCache( bool bDelete = true ) override;
/////////////////////////////////////////////////////////
//
// ON_Geometry virtual functions
//
int Dimension() const override;
// virtual ON_Geometry GetBBox override
bool GetBBox( double* boxmin, double* boxmax, bool bGrowBox = false ) const override;
// virtual ON_Geometry GetTightBoundingBox override
bool GetTightBoundingBox( class ON_BoundingBox& tight_bbox, bool bGrowBox = false, const class ON_Xform* xform = nullptr ) const override;
void ClearBoundingBox() override;
bool Transform(
const ON_Xform& xform
) override;
bool HasBrepForm() const override;
ON_Brep* BrepForm( ON_Brep* brep = nullptr ) const override;
/*
Returns:
True if the target NURBS object is rational
*/
bool IsRational() const;
/*
Description:
Makes the target NURBS object rational.
*/
bool MakeRational();
/*
Description:
Makes the target NURBS object non-rational.
*/
bool MakeNonRational();
/*
Returns:
Number of control points in the target NURBS object.
*/
int CVCount() const;
int CVCount(int dir) const;
int Order(int dir) const;
const double* Knot(int dir) const;
ON_3dex MaxCVIndex() const;
const double* CV(ON_3dex) const;
double Weight(ON_3dex) const;
/////////////////////////////////////////////////////////
//
// Localizers
//
/*
Description:
Adds localizer with support near the controling NURBS object.
Parameters:
support_distance - [in] >= 0
If the distance a point to the controls NURBS
curve/surface/cage is less than or equal to support_distance,
then MorphPoint() deformation has 100% effect.
falloff_distance - [in] > 0
If the distance a point to the controls NURBS
curve/surface/cage is more than support_distance+falloff_distance,
then MorphPoint() deformation does not move the point.
As the distance varies from support_distance to
support_distance+falloff_distance the deformation attenuates
from 100% to 0%.
*/
bool AddControlLocalizer(
double support_distance,
double falloff_distance
);
bool AddSphereLocalizer(
ON_3dPoint center,
double support_distance,
double falloff_distance
);
bool AddCylinderLocalizer(
ON_Line axis,
double support_distance,
double falloff_distance
);
bool AddBoxLocalizer(
ON_BoundingBox bbox,
double support_distance,
double falloff_distance
);
bool AddPlaneLocalizer(
const ON_Plane& plane,
double support_distance,
double falloff_distance
);
bool AddConvexPolygonLocalizer(
const ON_SimpleArray<ON_Plane>& planes,
double support_distance,
double falloff_distance
);
/////////////////////////////////////////////////////////
//
//
// Get a cage_morph that can be passed to Morph functions
bool GetCageMorph( class ON_CageMorph& cage_morph ) const;
bool IsIdentity( const ON_BoundingBox& bbox ) const;
int m_varient; // 1= curve, 2 = surface, 3 = cage
// The value of m_varient determines which nurbs object
// controls the cage
ON_NurbsCurve m_nurbs_curve0;
ON_NurbsCurve m_nurbs_curve;
ON_Interval m_nurbs_curve_domain;
ON_NurbsSurface m_nurbs_surface0;
ON_NurbsSurface m_nurbs_surface;
ON_Interval m_nurbs_surface_domain[2];
ON_Xform m_nurbs_cage0 = ON_Xform::IdentityTransformation;
ON_NurbsCage m_nurbs_cage;
// Rhino captive object ids
ON_UuidList m_captive_id;
// Use ON_GetCageXform to set m_cage_xform.
// Used to localize the deformation
ON_ClassArray<ON_Localizer> m_localizers;
// ON_SpaceMorphOptions
double m_sporh_tolerance;
bool m_sporh_bQuickPreview;
bool m_sporh_bPreserveStructure;
};
class ON_CLASS ON_CageMorph : public ON_SpaceMorph
{
public:
ON_CageMorph();
virtual ~ON_CageMorph();
bool IsIdentity( const ON_BoundingBox& bbox ) const override;
const ON_MorphControl* m_control;
};
// Description:
// Get an ON_NurbsSurface definition of a quadrilateral.
// Parameters:
// P - [in]
// Q - [in]
// R - [in]
// S - [in] corners in counter clockwise layer
// nurbs_surface - [in] if this pointer is not nullptr,
// then this ON_NurbsSurface is used to return
// the quadrilateral.
// Returns:
// An ON_NurbsSurface representation of the quadrilateral.
ON_DECL
ON_NurbsSurface* ON_NurbsSurfaceQuadrilateral(
const ON_3dPoint& P,
const ON_3dPoint& Q,
const ON_3dPoint& R,
const ON_3dPoint& S,
ON_NurbsSurface* nurbs_surface = nullptr
);
#if defined(ON_DLL_TEMPLATE)
ON_DLL_TEMPLATE template class ON_CLASS ON_ClassArray<ON_SimpleArray<ON_3dPoint>>;
ON_DLL_TEMPLATE template class ON_CLASS ON_ClassArray<ON_SimpleArray<ON_3dVector>>;
#endif
/*
Description:
Create an ON_NurbsSurface satisfying Hermite interpolation conditions at a grid of points.
Remarks:
See static ON_NurbsSurface::CreateHermiteSurface for details.
*/
class ON_CLASS ON_HermiteSurface
{
public:
ON_HermiteSurface();
// Constructs a u_count by v_count grid.
ON_HermiteSurface(int u_count, int v_count);
~ON_HermiteSurface();
// Constructs a u_count by v_count grid.
bool Create(int u_count, int v_count);
bool IsValid() const;
// Returns the number of parameters in the "u" direction.
int UCount() const;
// Returns the number of parameters in the "v" direction.
int VCount() const;
// Specifies the "u" parameters defining the grid of parameter values.
// These parameters are strictly increasing.
double UParameterAt(int u) const;
void SetUParameterAt(int u, double param);
// Specifies the "v" parameters defining the grid of parameter values.
// These parameters are strictly increasing.
double VParameterAt(int v) const;
void SetVParameterAt(int v, double param);
// Grid of points to interpolate.
ON_3dPoint PointAt(int u, int v) const;
void SetPointAt(int u, int v, const ON_3dPoint& point);
// Grid of "u" tangent directions (actually first derivatives) to interpolate.
ON_3dVector UTangentAt(int u, int v) const;
void SetUTangentAt(int u, int v, const ON_3dVector& dir);
// Grid of "v" tangent directions (actually first derivatives) to interpolate.
ON_3dVector VTangentAt(int u, int v) const;
void SetVTangentAt(int u, int v, const ON_3dVector& dir);
// Grid of twist vectors (mixed second partial derivatives) to interpolate.
ON_3dVector TwistAt(int u, int v) const;
void SetTwistAt(int u, int v, const ON_3dVector& dir);
// Create an ON_NurbsSurface satisfying Hermite interpolation conditions at a grid of points
ON_NurbsSurface* NurbsSurface(ON_NurbsSurface* pNurbsSurface = nullptr);
public:
// The "u" parameters defining the grid of parameter values.
const ON_SimpleArray<double>& UParameters() const;
// The "v" parameters defining the grid of parameter values.
const ON_SimpleArray<double>& VParameters() const;
// Grid of points to interpolate.
const ON_ClassArray<ON_SimpleArray<ON_3dPoint>>& GridPoints() const;
// Grid of "u" tangent directions (actually first derivatives) to interpolate.
const ON_ClassArray<ON_SimpleArray<ON_3dVector>>& UTangents() const;
// Grid of "v" tangent directions (actually first derivatives) to interpolate.
const ON_ClassArray<ON_SimpleArray<ON_3dVector>>& VTangents() const;
// Grid of twist vectors (mixed second partial derivatives) to interpolate.
const ON_ClassArray<ON_SimpleArray<ON_3dVector>>& Twists() const;
private:
int m_u_count;
int m_v_count;
ON_SimpleArray<double> m_u_parameters;
ON_SimpleArray<double> m_v_parameters;
ON_ClassArray<ON_SimpleArray<ON_3dPoint>> m_grid_points;
ON_ClassArray<ON_SimpleArray<ON_3dVector>> m_u_tangents;
ON_ClassArray<ON_SimpleArray<ON_3dVector>> m_v_tangents;
ON_ClassArray<ON_SimpleArray<ON_3dVector>> m_twists;
private:
ON_HermiteSurface(const ON_HermiteSurface&) = delete;
ON_HermiteSurface& operator=(const ON_HermiteSurface&) = default;
bool InBounds(int u, int v) const;
void Destroy();
};
#if defined(ON_DLL_TEMPLATE)
ON_DLL_TEMPLATE template class ON_CLASS ON_ClassArray<ON_NurbsCurve>;
ON_DLL_TEMPLATE template class ON_CLASS ON_ObjectArray<ON_NurbsCurve>;
ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray<ON_NurbsCurve*>;
ON_DLL_TEMPLATE template class ON_CLASS ON_ClassArray<ON_NurbsSurface>;
ON_DLL_TEMPLATE template class ON_CLASS ON_ObjectArray<ON_NurbsSurface>;
ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray<ON_NurbsSurface*>;
ON_DLL_TEMPLATE template class ON_CLASS ON_ClassArray<ON_NurbsCage>;
ON_DLL_TEMPLATE template class ON_CLASS ON_ObjectArray<ON_NurbsCage>;
ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray<ON_NurbsCage*>;
#endif
#endif