Files
opennurbs/opennurbs_surfaceproxy.cpp
2024-08-22 01:43:04 -07:00

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;
}