mirror of
https://github.com/mcneel/opennurbs.git
synced 2026-02-28 19:16:09 +08:00
572 lines
13 KiB
C++
572 lines
13 KiB
C++
//
|
|
// Copyright (c) 1993-2022 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>.
|
|
//
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
#include "opennurbs.h"
|
|
|
|
#if !defined(ON_COMPILING_OPENNURBS)
|
|
// This check is included in all opennurbs source .c and .cpp files to insure
|
|
// ON_COMPILING_OPENNURBS is defined when opennurbs source is compiled.
|
|
// When opennurbs source is being compiled, ON_COMPILING_OPENNURBS is defined
|
|
// and the opennurbs .h files alter what is declared and how it is declared.
|
|
#error ON_COMPILING_OPENNURBS must be defined when compiling opennurbs
|
|
#endif
|
|
|
|
ON_OBJECT_IMPLEMENT(ON_SurfaceProxy,ON_Surface,"4ED7D4E2-E947-11d3-BFE5-0010830122F0");
|
|
|
|
ON_SurfaceProxy::ON_SurfaceProxy() : m_surface(0), m_bTransposed(0)
|
|
{}
|
|
|
|
ON_SurfaceProxy::ON_SurfaceProxy( const ON_Surface* s ) : m_surface(s), m_bTransposed(0)
|
|
{}
|
|
|
|
ON_SurfaceProxy::ON_SurfaceProxy( const ON_SurfaceProxy& src ) : ON_Surface(src), m_surface(0), m_bTransposed(0)
|
|
{
|
|
*this = src;
|
|
}
|
|
|
|
unsigned int ON_SurfaceProxy::SizeOf() const
|
|
{
|
|
unsigned int sz = ON_Surface::SizeOf();
|
|
sz += (sizeof(*this) - sizeof(ON_Surface));
|
|
// Do not add in size of m_surface - its memory is not
|
|
// managed by this class.
|
|
return sz;
|
|
}
|
|
|
|
ON__UINT32 ON_SurfaceProxy::DataCRC(ON__UINT32 current_remainder) const
|
|
{
|
|
if ( m_surface )
|
|
current_remainder = m_surface->DataCRC(current_remainder);
|
|
current_remainder = ON_CRC32(current_remainder,sizeof(m_bTransposed),&m_bTransposed);
|
|
return current_remainder;
|
|
}
|
|
|
|
ON_SurfaceProxy& ON_SurfaceProxy::operator=( const ON_SurfaceProxy& src )
|
|
{
|
|
if ( this != &src ) {
|
|
ON_Surface::operator=(src);
|
|
m_surface = src.m_surface;
|
|
m_bTransposed = src.m_bTransposed;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
ON_SurfaceProxy::~ON_SurfaceProxy()
|
|
{
|
|
m_surface = 0;
|
|
}
|
|
|
|
void ON_SurfaceProxy::SetProxySurface( const ON_Surface* proxy_surface )
|
|
{
|
|
// setting m_surface=0 prevents crashes if user has deleted
|
|
// "real" surface before calling SetProxySurface().
|
|
m_surface = 0;
|
|
|
|
DestroySurfaceTree();
|
|
if ( proxy_surface == this )
|
|
proxy_surface = 0;
|
|
m_surface = proxy_surface;
|
|
m_bTransposed = false;
|
|
}
|
|
|
|
const ON_Surface* ON_SurfaceProxy::ProxySurface() const
|
|
{
|
|
return m_surface;
|
|
}
|
|
|
|
bool ON_SurfaceProxy::ProxySurfaceIsTransposed() const
|
|
{
|
|
return m_bTransposed;
|
|
}
|
|
|
|
|
|
ON_Surface* ON_SurfaceProxy::DuplicateSurface() const
|
|
{
|
|
ON_Surface* dup_srf = 0;
|
|
if ( m_surface )
|
|
{
|
|
dup_srf = m_surface->Duplicate();
|
|
if ( m_bTransposed && dup_srf )
|
|
dup_srf->Transpose();
|
|
}
|
|
return dup_srf;
|
|
}
|
|
|
|
|
|
bool ON_SurfaceProxy::IsValid( ON_TextLog* text_log ) const
|
|
{
|
|
return ( m_surface ) ? m_surface->IsValid(text_log) : false;
|
|
}
|
|
|
|
void
|
|
ON_SurfaceProxy::Dump( ON_TextLog& dump ) const
|
|
{
|
|
dump.Print("ON_SurfaceProxy uses %x\n",m_surface);
|
|
if (m_surface )
|
|
m_surface->Dump(dump);
|
|
}
|
|
|
|
bool
|
|
ON_SurfaceProxy::Write(
|
|
ON_BinaryArchive& // open binary file
|
|
) const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
ON_SurfaceProxy::Read(
|
|
ON_BinaryArchive& // open binary file
|
|
)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
int
|
|
ON_SurfaceProxy::Dimension() const
|
|
{
|
|
return ( m_surface ) ? m_surface->Dimension() : 0;
|
|
}
|
|
|
|
bool ON_SurfaceProxy::GetBBox( // returns true if successful
|
|
double* boxmin, // minimum
|
|
double* boxmax, // maximum
|
|
bool bGrowBox
|
|
) const
|
|
{
|
|
return ( m_surface ) ? m_surface->GetBBox(boxmin,boxmax,bGrowBox) : false;
|
|
}
|
|
|
|
bool
|
|
ON_SurfaceProxy::Transform(
|
|
const ON_Xform& // xform - formal parameter intentionally ignored in this virtual function
|
|
)
|
|
{
|
|
return false; // cannot modify m_surface
|
|
}
|
|
|
|
|
|
ON_Interval
|
|
ON_SurfaceProxy::Domain( int dir ) const
|
|
{
|
|
ON_Interval d;
|
|
if ( m_bTransposed ) {
|
|
dir = (dir) ? 0 : 1;
|
|
}
|
|
if ( m_surface )
|
|
d = m_surface->Domain(dir);
|
|
return d;
|
|
}
|
|
|
|
bool ON_SurfaceProxy::GetSurfaceSize(
|
|
double* width,
|
|
double* height
|
|
) const
|
|
{
|
|
bool rc = false;
|
|
if ( m_surface )
|
|
{
|
|
if ( m_bTransposed )
|
|
{
|
|
double* ptr = width;
|
|
width = height;
|
|
height = ptr;
|
|
}
|
|
rc = m_surface->GetSurfaceSize(width,height);
|
|
}
|
|
else
|
|
{
|
|
if ( width )
|
|
*width = 0.0;
|
|
if ( height )
|
|
*height = 0.0;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
int
|
|
ON_SurfaceProxy::SpanCount( int dir ) const
|
|
{
|
|
if ( m_bTransposed ) {
|
|
dir = (dir) ? 0 : 1;
|
|
}
|
|
return ( m_surface ) ? m_surface->SpanCount(dir) : false;
|
|
}
|
|
|
|
bool
|
|
ON_SurfaceProxy::GetSpanVector( int dir, double* s ) const
|
|
{
|
|
if ( m_bTransposed ) {
|
|
dir = (dir) ? 0 : 1;
|
|
}
|
|
return ( m_surface ) ? m_surface->GetSpanVector(dir,s) : false;
|
|
}
|
|
|
|
int
|
|
ON_SurfaceProxy::Degree( int dir ) const
|
|
{
|
|
if ( m_bTransposed ) {
|
|
dir = (dir) ? 0 : 1;
|
|
}
|
|
return ( m_surface ) ? m_surface->Degree(dir) : false;
|
|
}
|
|
|
|
|
|
bool
|
|
ON_SurfaceProxy::GetParameterTolerance(
|
|
int dir,
|
|
double t, // t = parameter in domain
|
|
double* tminus, // tminus
|
|
double* tplus // tplus
|
|
) const
|
|
{
|
|
if ( m_bTransposed ) {
|
|
dir = (dir) ? 0 : 1;
|
|
}
|
|
return ( m_surface ) ? m_surface->GetParameterTolerance(dir,t,tminus,tplus) : false;
|
|
}
|
|
|
|
bool
|
|
ON_SurfaceProxy::IsClosed( int dir ) const
|
|
{
|
|
if ( m_bTransposed ) {
|
|
dir = (dir) ? 0 : 1;
|
|
}
|
|
return ( m_surface ) ? m_surface->IsClosed( dir ) : false;
|
|
}
|
|
|
|
ON_Surface::ISO
|
|
ON_SurfaceProxy::IsIsoparametric( // returns isoparametric status of 2d curve
|
|
const ON_Curve& crv,
|
|
const ON_Interval* subdomain
|
|
) const
|
|
{
|
|
// this is a virtual override of an ON_Surface::IsIsoparametric
|
|
|
|
const ON_Curve* pC = &crv;
|
|
ON_Curve* pTranC = nullptr;
|
|
if(m_bTransposed)
|
|
{
|
|
pTranC = crv.DuplicateCurve();
|
|
pTranC->SwapCoordinates(0,1);
|
|
pC = pTranC;
|
|
}
|
|
|
|
ON_Surface::ISO iso = m_surface->IsIsoparametric( *pC, subdomain);
|
|
|
|
if (pTranC)
|
|
{
|
|
switch(iso)
|
|
{
|
|
case x_iso:
|
|
iso = y_iso;
|
|
break;
|
|
case y_iso:
|
|
iso = x_iso;
|
|
break;
|
|
case W_iso:
|
|
iso = S_iso;
|
|
break;
|
|
case S_iso:
|
|
iso = W_iso;
|
|
break;
|
|
case N_iso:
|
|
iso = E_iso;
|
|
break;
|
|
case E_iso:
|
|
iso = N_iso;
|
|
break;
|
|
default:
|
|
// intentionally ignoring other ON_Surface::ISO enum values
|
|
break;
|
|
}
|
|
delete pTranC;
|
|
}
|
|
|
|
return iso;
|
|
}
|
|
|
|
ON_Surface::ISO
|
|
ON_SurfaceProxy::IsIsoparametric( // returns isoparametric status based on bounding box
|
|
const ON_BoundingBox& box
|
|
) const
|
|
{
|
|
// this is a virtual override of an ON_Surface::IsIsoparametric
|
|
const ON_BoundingBox* pbox = &box;
|
|
ON_BoundingBox Tbox( ON_3dPoint( box.m_min[1],box.m_min[0],0.0),
|
|
ON_3dPoint( box.m_max[1],box.m_max[0],0.0) );
|
|
if(m_bTransposed)
|
|
pbox = &Tbox;
|
|
|
|
ON_Surface::ISO iso = m_surface->IsIsoparametric( *pbox);
|
|
|
|
if( m_bTransposed){
|
|
switch(iso)
|
|
{
|
|
case x_iso:
|
|
iso = y_iso;
|
|
break;
|
|
case y_iso:
|
|
iso = x_iso;
|
|
break;
|
|
case W_iso:
|
|
iso = S_iso;
|
|
break;
|
|
case S_iso:
|
|
iso = W_iso;
|
|
break;
|
|
case N_iso:
|
|
iso = E_iso;
|
|
break;
|
|
case E_iso:
|
|
iso = N_iso;
|
|
break;
|
|
default:
|
|
// intentionally ignoring other ON_Surface::ISO enum values
|
|
break;
|
|
}
|
|
}
|
|
return iso;
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ON_SurfaceProxy::IsPlanar(
|
|
ON_Plane* plane,
|
|
double tolerance
|
|
) const
|
|
{
|
|
bool rc = false;
|
|
if ( m_surface )
|
|
{
|
|
rc = m_surface->IsPlanar( plane, tolerance );
|
|
if (rc && m_bTransposed && plane )
|
|
plane->Flip();
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
bool
|
|
ON_SurfaceProxy::IsPeriodic( int dir ) const
|
|
{
|
|
if ( m_bTransposed ) {
|
|
dir = (dir) ? 0 : 1;
|
|
}
|
|
return ( m_surface ) ? m_surface->IsPeriodic( dir ) : false;
|
|
}
|
|
|
|
bool ON_SurfaceProxy::GetNextDiscontinuity(
|
|
int dir,
|
|
ON::continuity c,
|
|
double t0,
|
|
double t1,
|
|
double* t,
|
|
int* hint,
|
|
int* dtype,
|
|
double cos_angle_tolerance,
|
|
double curvature_tolerance
|
|
) const
|
|
{
|
|
// untested code
|
|
bool rc = false;
|
|
|
|
if ( 0 != m_surface && dir >= 0 && dir <= 1 )
|
|
{
|
|
rc = m_surface->GetNextDiscontinuity(m_bTransposed?1-dir:dir,c,t0,t1,t,hint,dtype,cos_angle_tolerance,curvature_tolerance);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
bool
|
|
ON_SurfaceProxy::IsSingular( int side ) const
|
|
{
|
|
if ( m_bTransposed ) {
|
|
switch(side) {
|
|
case 0:
|
|
side = 3;
|
|
break;
|
|
case 1:
|
|
side = 2;
|
|
break;
|
|
case 2:
|
|
side = 1;
|
|
break;
|
|
case 3:
|
|
side = 0;
|
|
break;
|
|
}
|
|
}
|
|
return ( m_surface ) ? m_surface->IsSingular( side ) : false;
|
|
}
|
|
|
|
bool
|
|
ON_SurfaceProxy::Reverse(
|
|
int // dir - formal parameter intentionally ignored in this virtual function
|
|
)
|
|
{
|
|
return false; // cannot modify m_surface
|
|
}
|
|
|
|
bool
|
|
ON_SurfaceProxy::Transpose()
|
|
{
|
|
DestroySurfaceTree();
|
|
m_bTransposed = (m_bTransposed) ? false : true;
|
|
return true;
|
|
}
|
|
|
|
bool ON_SurfaceProxy::IsContinuous(
|
|
ON::continuity desired_continuity,
|
|
double s,
|
|
double t,
|
|
int* hint, // default = nullptr,
|
|
double point_tolerance, // default=ON_ZERO_TOLERANCE
|
|
double d1_tolerance, // default==ON_ZERO_TOLERANCE
|
|
double d2_tolerance, // default==ON_ZERO_TOLERANCE
|
|
double cos_angle_tolerance, // default==ON_DEFAULT_ANGLE_TOLERANCE_COSINE
|
|
double curvature_tolerance // default==ON_SQRT_EPSILON
|
|
) const
|
|
{
|
|
bool rc = true;
|
|
if ( m_surface )
|
|
{
|
|
if ( m_bTransposed )
|
|
{
|
|
double x = s;
|
|
s = t;
|
|
t = x;
|
|
}
|
|
rc = m_surface->IsContinuous( desired_continuity, s, t, hint,
|
|
point_tolerance, d1_tolerance, d2_tolerance,
|
|
cos_angle_tolerance, curvature_tolerance );
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
ON_SurfaceProxy::Evaluate( // returns false if unable to evaluate
|
|
double s, double t, // evaluation parameters
|
|
int der_count, // number of derivatives (>=0)
|
|
int v_stride, // v[] array stride (>=Dimension())
|
|
double* v, // v[] array of length stride*(ndir+1)
|
|
int side, // optional - determines which side to evaluate from
|
|
// 0 = default
|
|
// < 0 to evaluate from below,
|
|
// > 0 to evaluate from above
|
|
int* hint // optional - evaluation hint (int) used to speed
|
|
// repeated evaluations
|
|
) const
|
|
{
|
|
if ( m_bTransposed ) {
|
|
double x = s; s = t; t = x;
|
|
}
|
|
return ( m_surface ) ? m_surface->Evaluate(s,t,der_count,v_stride,v,side,hint) : false;
|
|
}
|
|
|
|
|
|
ON_Curve* ON_SurfaceProxy::IsoCurve(
|
|
int dir,
|
|
double c
|
|
) const
|
|
{
|
|
ON_Curve* isocurve = 0;
|
|
|
|
if ( m_bTransposed )
|
|
{
|
|
dir = 1-dir;
|
|
}
|
|
|
|
if ( 0 != m_surface && dir >= 0 && dir <= 1 )
|
|
{
|
|
isocurve = m_surface->IsoCurve( dir, c );
|
|
}
|
|
|
|
return isocurve;
|
|
}
|
|
|
|
|
|
int ON_SurfaceProxy::GetNurbForm( // returns 0: unable to create NURBS representation
|
|
// with desired accuracy.
|
|
// 1: success - returned NURBS parameterization
|
|
// matches the surface's to the desired accuracy
|
|
// 2: success - returned NURBS point locus matches
|
|
// the surfaces's to the desired accuracy but, on
|
|
// the interior of the surface's domain, the
|
|
// surface's parameterization and the NURBS
|
|
// parameterization may not match to the
|
|
// desired accuracy.
|
|
ON_NurbsSurface& nurbs,
|
|
double tolerance
|
|
) const
|
|
{
|
|
int rc = ( m_surface ) ? m_surface->GetNurbForm(nurbs,tolerance) : 0;
|
|
if ( rc && m_bTransposed ) {
|
|
if (!nurbs.Transpose())
|
|
rc = 0;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
int
|
|
ON_SurfaceProxy::HasNurbForm( // returns 0: unable to create NURBS representation
|
|
// with desired accuracy.
|
|
// 1: success - returned NURBS parameterization
|
|
// matches the surface's to the desired accuracy
|
|
// 2: success - returned NURBS point locus matches
|
|
// the surfaces's to the desired accuracy but, on
|
|
// the interior of the surface's domain, the
|
|
// surface's parameterization and the NURBS
|
|
// parameterization may not match to the
|
|
// desired accuracy.
|
|
) const
|
|
|
|
{
|
|
if (!m_surface)
|
|
return 0;
|
|
return m_surface->HasNurbForm();
|
|
}
|
|
|
|
bool ON_SurfaceProxy::GetSurfaceParameterFromNurbFormParameter(
|
|
double nurbs_s, double nurbs_t,
|
|
double* surface_s, double* surface_t
|
|
) const
|
|
{
|
|
bool rc = false;
|
|
if ( m_surface )
|
|
{
|
|
rc = m_bTransposed
|
|
? m_surface->GetSurfaceParameterFromNurbFormParameter(nurbs_t,nurbs_s,surface_t,surface_s)
|
|
: m_surface->GetSurfaceParameterFromNurbFormParameter(nurbs_s,nurbs_t,surface_s,surface_t);
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
bool ON_SurfaceProxy::GetNurbFormParameterFromSurfaceParameter(
|
|
double surface_s, double surface_t,
|
|
double* nurbs_s, double* nurbs_t
|
|
) const
|
|
{
|
|
bool rc = false;
|
|
if ( m_surface )
|
|
{
|
|
rc = m_bTransposed
|
|
? m_surface->GetNurbFormParameterFromSurfaceParameter(surface_t,surface_s,nurbs_t,nurbs_s)
|
|
: m_surface->GetNurbFormParameterFromSurfaceParameter(surface_s,surface_t,nurbs_s,nurbs_t);
|
|
}
|
|
return rc;
|
|
}
|