// // 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 . // //////////////////////////////////////////////////////////////// #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_SumSurface, ON_Surface, "C4CD5359-446D-4690-9FF5-29059732472B" ); void ON_SumSurface::DestroyRuntimeCache( bool bDelete ) { ON_Surface::DestroyRuntimeCache(bDelete); if ( 0 != m_curve[0] ) m_curve[0]->DestroyRuntimeCache(bDelete); if ( 0 != m_curve[1] ) m_curve[1]->DestroyRuntimeCache(bDelete); // 15 August 2003 Dale Lear: // Added the call to destroy the cached bounding box m_bbox.Destroy(); } ON_SumSurface* ON_SumSurface::New() { return new ON_SumSurface(); } ON_SumSurface* ON_SumSurface::New( const ON_SumSurface& rev_surface ) { return new ON_SumSurface(rev_surface); } ON_SumSurface::ON_SumSurface() { ON__SET__THIS__PTR(m_s_ON_SumSurface_ptr); m_curve[0] = nullptr; m_curve[1] = nullptr; } ON_SumSurface::~ON_SumSurface() { Destroy(); } void ON_SumSurface::Destroy() { // GBA 24-Sept-2004. Since there now could be a surface tree it need to be cleared out. DestroyRuntimeCache(); for ( int i = 0; i < 2; i++ ) { if ( m_curve[i] ) { delete m_curve[i]; m_curve[i] = nullptr; } } m_bbox = ON_BoundingBox::EmptyBoundingBox; m_basepoint = ON_3dPoint::Origin; } void ON_SumSurface::EmergencyDestroy() { m_curve[0] = nullptr; m_curve[1] = nullptr; m_bbox = ON_BoundingBox::EmptyBoundingBox; m_basepoint = ON_3dPoint::Origin; } void ON_SumSurface::Internal_CopyFrom(const ON_SumSurface& src) { m_curve[0] = nullptr; m_curve[1] = nullptr; for ( int i = 0; i < 2; i++ ) { if ( nullptr != src.m_curve[i] ) m_curve[i] = src.m_curve[i]->DuplicateCurve(); } m_basepoint = src.m_basepoint; m_bbox = src.m_bbox; } ON_SumSurface::ON_SumSurface( const ON_SumSurface& src ) : ON_Surface(src) { ON__SET__THIS__PTR(m_s_ON_SumSurface_ptr); m_curve[0] = nullptr; m_curve[1] = nullptr; Internal_CopyFrom(src); } unsigned int ON_SumSurface::SizeOf() const { unsigned int sz = ON_Surface::SizeOf(); if ( m_curve[0] ) sz += m_curve[0]->SizeOf(); if ( m_curve[1] ) sz += m_curve[1]->SizeOf(); return sz; } ON__UINT32 ON_SumSurface::DataCRC(ON__UINT32 current_remainder) const { if ( m_curve[0] ) current_remainder = m_curve[0]->DataCRC(current_remainder); if ( m_curve[1] ) current_remainder = m_curve[1]->DataCRC(current_remainder); return current_remainder; } ON_SumSurface& ON_SumSurface::operator=(const ON_SumSurface& src ) { if ( this != &src ) { Destroy(); ON_Surface::operator=(src); Internal_CopyFrom(src); } return *this; } bool ON_SumSurface::Create( const ON_Curve& curve, ON_3dVector vector ) { Destroy(); bool rc = false; if ( !vector.IsZero() ) { ON_Curve* pCurve = curve.DuplicateCurve(); rc = Create( pCurve, vector ); } return rc; } bool ON_SumSurface::Create( ON_Curve* pCurve, ON_3dVector vector ) { Destroy(); bool rc = false; if ( !vector.IsZero() ) { ON_LineCurve* pLineCurve = new ON_LineCurve( ON_Line( ON_3dPoint::Origin, vector ) ); pLineCurve->SetDomain( 0.0, vector.Length() ); m_curve[0] = pCurve; m_curve[1] = pLineCurve; m_basepoint.Set(0.0,0.0,0.0); ON_BoundingBox bbox0 = pCurve->BoundingBox(); ON_BoundingBox bbox1 = bbox0; bbox1.m_min += vector; bbox1.m_max += vector; m_bbox.Union( bbox0, bbox1 ); rc = true; } return rc; } bool ON_SumSurface::Create( const ON_Curve& curve, const ON_Curve& path_curve ) { Destroy(); ON_Curve* pCurve = curve.DuplicateCurve(); ON_Curve* pPathCurve = path_curve.DuplicateCurve(); bool rc = Create( pCurve, pPathCurve ); return rc; } bool ON_SumSurface::Create( ON_Curve* pCurve, ON_Curve* pPathCurve ) { Destroy(); bool rc = false; if ( pCurve && pPathCurve ) { m_curve[0] = pCurve; m_curve[1] = pPathCurve; m_basepoint = ON_3dPoint::Origin - pPathCurve->PointAtStart(); m_bbox.Destroy(); BoundingBox(); rc = true; } return rc; } //////////////////////////////////////////////////////////// // // overrides of virtual ON_Object functions // bool ON_SumSurface::IsValid( ON_TextLog* text_log ) const { for ( int i = 0; i < 2; i++ ) { if ( !m_curve[i] ) { if ( text_log ) text_log->Print("ON_SumSurface.m_curve[%d] is nullptr.\n",i); return false; } if ( m_curve[i]->Dimension() != 3 ) { if ( text_log ) text_log->Print("ON_SumSurface.m_curve[%d]->m_dim = %d (should be 3).\n",i,m_curve[i]->Dimension()); return false; } if ( !m_curve[i]->IsValid(text_log) ) { if ( text_log ) text_log->Print("ON_SumSurface.m_curve[%d] is not valid.\n",i); return false; } } if ( !m_basepoint.IsValid() ) { if ( text_log ) text_log->Print("ON_SumSurface.m_basepoint is not valid.\n"); return false; } return true; } void ON_SumSurface::Dump( ON_TextLog& dump ) const { ON_Object::Dump(dump); dump.PushIndent(); dump.Print("basepoint = "); dump.Print(m_basepoint); dump.Print("\n"); for ( int i = 0; i < 2; i++ ) { if ( m_curve[i] ) { dump.Print("m_curve[%d]:\n",i); dump.PushIndent(); m_curve[i]->Dump(dump); dump.PopIndent(); } else dump.Print("m_curve[%d] = nullptr\n",i); } } bool ON_SumSurface::Write( ON_BinaryArchive& file ) const { bool rc = file.Write3dmChunkVersion(1,0); if ( rc ) { rc = file.WriteVector( m_basepoint ); rc = file.WriteBoundingBox( m_bbox ); if ( rc ) rc = file.WriteObject( m_curve[0] ); if ( rc ) rc = file.WriteObject( m_curve[1] ); } return rc; } bool ON_SumSurface::Read( ON_BinaryArchive& file ) { Destroy(); int major_version = 0; int minor_version = 0; bool rc = file.Read3dmChunkVersion( &major_version, &minor_version ); if (rc && major_version == 1 ) { ON_Object* obj; rc = file.ReadVector( m_basepoint ); if (rc) rc = file.ReadBoundingBox( m_bbox ); obj = 0; if (rc) rc = file.ReadObject(&obj); if (rc) { m_curve[0] = ON_Curve::Cast(obj); if ( !m_curve[0] ) delete obj; } obj = 0; if (rc) rc = file.ReadObject(&obj); if (rc) { m_curve[1] = ON_Curve::Cast(obj); if ( !m_curve[1] ) delete obj; } } return rc; } //////////////////////////////////////////////////////////// // // overrides of virtual ON_Geometry functions // int ON_SumSurface::Dimension() const { int dim = 0; if ( m_curve[0] && m_curve[1] ) { dim = m_curve[0]->Dimension(); if ( dim > 0 ) { if ( dim != m_curve[1]->Dimension() ) dim = 0; } } return dim; } void ON_SumSurface::ClearBoundingBox() { m_bbox.Destroy(); } bool ON_SumSurface::GetBBox( // returns true if successful double* boxmin, // boxmin[dim] double* boxmax, // boxmax[dim] bool bGrowBox ) const { bool rc = m_bbox.IsValid(); if (!rc ) { // lazy bounding box evaluation ON_BoundingBox bboxA, bboxB; if ( m_curve[0] ) bboxA = m_curve[0]->BoundingBox(); if ( m_curve[1] ) bboxB = m_curve[1]->BoundingBox(); if ( bboxA.IsValid() && bboxB.IsValid() ) { ON_SumSurface* pS = const_cast(this); pS->m_bbox.m_min = bboxA.m_min + bboxB.m_min + m_basepoint; pS->m_bbox.m_max = bboxA.m_max + bboxB.m_max + m_basepoint; } rc = m_bbox.IsValid(); } if ( rc ) { int dim = Dimension(); int j; ON_BoundingBox bbox; if ( bGrowBox && boxmin && boxmax ) { for ( j = 0; j < 3 && j < dim; j++ ) { bbox.m_min[j] = boxmin[j]; bbox.m_max[j] = boxmax[j]; } if ( !bbox.IsValid() ) bbox = m_bbox; else bbox.Union(m_bbox); } else bbox = m_bbox; dim = Dimension(); for ( j = 0; j < 3 && j < dim; j++ ) { if(boxmin) boxmin[j] = bbox.m_min[j]; if(boxmax) boxmax[j] = bbox.m_max[j]; } for ( j = 3; j < dim; j++ ) { if (boxmin) boxmin[j] = 0.0; if (boxmax) boxmax[j] = 0.0; } } return rc; } bool ON_SumSurface::IsDeformable() const { bool rc = true; if ( m_curve[0] ) rc = m_curve[0]->IsDeformable(); if (rc && m_curve[1] ) rc = m_curve[1]->IsDeformable(); return rc; } bool ON_SumSurface::MakeDeformable() { bool rc = true; if ( m_curve[0] && !m_curve[0]->IsDeformable() ) { DestroyRuntimeCache(); rc = rc && m_curve[0]->MakeDeformable(); } if (m_curve[1] && !m_curve[1]->IsDeformable() ) { DestroyRuntimeCache(); rc = rc && m_curve[1]->MakeDeformable(); } return rc; } bool ON_SumSurface::Transform( const ON_Xform& xform ) { DestroyRuntimeCache(); TransformUserData(xform); bool rc = false; ON_3dPoint A0, A1, A2; if ( m_curve[0] ) { A0 = m_curve[0]->PointAtStart(); rc = m_curve[0]->Transform(xform); } if ( m_curve[1] ) { A1 = m_curve[1]->PointAtStart(); if ( !m_curve[1]->Transform(xform) ) rc = false; } else rc = false; if ( rc ) { // because xform may be affine A2 = m_basepoint; m_basepoint = xform*(A0+A1+A2) - xform*A0 - xform*A1; } m_bbox.Destroy(); m_bbox = BoundingBox(); return rc; } //////////////////////////////////////////////////////////// // // overrides of virtual ON_Surface functions // bool ON_SumSurface::SetDomain( int dir, // 0 sets first parameter's domain, 1 gets second parameter's domain double t0, double t1 ) { bool rc = false; if ( t0 < t1 && dir >= 0 && dir <= 1 ) { if ( 0 != m_curve[dir] ) { rc = m_curve[dir]->SetDomain(t0,t1) ? true : false; DestroyRuntimeCache(); } } return rc; } ON_Interval ON_SumSurface::Domain( int dir ) const { ON_Interval domain; if ( dir == 0 && m_curve[0] ) domain = m_curve[0]->Domain(); else if ( dir == 1 && m_curve[1] ) domain = m_curve[1]->Domain(); return domain; } bool ON_SumSurface::GetSurfaceSize( double* width, double* height ) const { bool rc = true; double* ptr[2]; ptr[0] = width; ptr[1] = height; int j; for ( j = 0; j < 2; j++ ) { if ( ptr[j] == nullptr ) continue; *ptr[j] = 0.0; if (m_curve[j] == nullptr) { rc = false; continue; } int i, imax = 64, hint = 0; double length_estimate = 0.0; const double d = 1.0 / ((double)imax); ON_Interval cdom = m_curve[j]->Domain(); ON_3dPoint pt0 = ON_3dPoint::UnsetPoint; ON_3dPoint pt; for ( i = 0; i <= imax; i++ ) { if (m_curve[j]->EvPoint(cdom.ParameterAt(i * d), pt, 0, &hint) && pt.IsValid()) { if (pt0 != ON_3dPoint::UnsetPoint) length_estimate += pt0.DistanceTo(pt); pt0 = pt; } else rc = false; } if (length_estimate > 0.0) *ptr[j] = length_estimate; else rc = false; } return rc; } int ON_SumSurface::SpanCount( int dir ) const { int span_count = 0; if ( dir == 0 && m_curve[0] ) span_count = m_curve[0]->SpanCount(); else if ( dir == 1 && m_curve[1] ) span_count = m_curve[1]->SpanCount(); return span_count; } bool ON_SumSurface::GetSpanVector( int dir, double* s ) const { bool rc = false; if ( dir == 0 && m_curve[0] ) rc = m_curve[0]->GetSpanVector(s); else if ( dir == 1 && m_curve[1] ) rc = m_curve[1]->GetSpanVector(s); return rc; } int ON_SumSurface::Degree( int dir ) const { int degree = 0; if ( dir == 0 && m_curve[0] ) degree = m_curve[0]->Degree(); else if ( dir == 1 && m_curve[1] ) degree = m_curve[1]->Degree(); return degree; } bool ON_SumSurface::GetParameterTolerance( // returns tminus < tplus: parameters tminus <= s <= tplus int dir, // 0 gets first parameter, 1 gets second parameter double t, // t = parameter in domain double* tminus, // tminus double* tplus // tplus ) const { bool rc = false; if ( dir == 0 && m_curve[0] ) rc = m_curve[0]->GetParameterTolerance(t,tminus,tplus); else if ( dir == 1 && m_curve[1] ) rc = m_curve[1]->GetParameterTolerance(t,tminus,tplus); return rc; } bool ON_SumSurface::IsPlanar( ON_Plane* plane, double tolerance ) const { ON_Plane pln; ON_3dPoint center; ON_3dVector normal, du, dv; ON_Interval udom = Domain(0); ON_Interval vdom = Domain(1); bool rc = EvNormal( udom.ParameterAt(0.5), vdom.ParameterAt(0.5), center, du, dv, normal ); if (rc) { if ( fabs( normal.Length() - 1.0 ) > 0.01 ) rc = false; else { pln.origin = center; pln.zaxis = normal; if ( du.Unitize() ) { pln.xaxis = du; pln.yaxis = ON_CrossProduct( pln.zaxis, pln.xaxis ); pln.yaxis.Unitize(); pln.UpdateEquation(); } else if ( dv.Unitize() ) { pln.yaxis = dv; pln.xaxis = ON_CrossProduct( pln.yaxis, pln.zaxis ); pln.xaxis.Unitize(); pln.UpdateEquation(); } else { pln.CreateFromNormal( center, normal ); } if ( plane ) *plane = pln; int j; for ( j = 0; j < 2 && rc ; j++ ) { pln.origin = m_curve[j]->PointAtStart(); pln.UpdateEquation(); rc = m_curve[j]->IsInPlane( pln, tolerance ); } if (rc && plane ) { pln.origin = center; pln.UpdateEquation(); *plane = pln; } } } return rc; } bool ON_SumSurface::IsClosed( int dir ) const { bool rc = false; if ( dir == 0 && m_curve[0] ) rc = m_curve[0]->IsClosed(); else if ( dir == 1 && m_curve[1] ) rc = m_curve[1]->IsClosed(); return rc; } bool ON_SumSurface::IsPeriodic( int dir ) const { bool rc = false; if ( dir == 0 && m_curve[0] ) rc = m_curve[0]->IsPeriodic(); else if ( dir == 1 && m_curve[1] ) rc = m_curve[1]->IsPeriodic(); return rc; } bool ON_SumSurface::IsSingular( int side ) const { return false; } bool ON_SumSurface::GetNextDiscontinuity( int dir, ON::continuity c, double t0, double t1, double* t, int* hint, int* dtype, double cos_angle_tolerance, double curvature_tolerance ) const { // 28 Jan 2005 - untested code bool rc = false; if ( 0 == dir || 1 == dir ) { if (0 != m_curve[dir] ) { rc = m_curve[dir]->GetNextDiscontinuity( c, t0,t1,t, (hint?&hint[dir]:0), dtype, cos_angle_tolerance, curvature_tolerance); } } return rc; } bool ON_SumSurface::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_curve[0] && m_curve[1] ) { int crv_hint[2] = {0,0}; if ( hint ) { crv_hint[0] = (*hint) & 0xFFFF; crv_hint[1] = ((*hint) & 0xFFFF0000) >> 16; } rc = m_curve[0]->IsContinuous( desired_continuity, s, &crv_hint[0], point_tolerance, d1_tolerance, d2_tolerance, cos_angle_tolerance, curvature_tolerance ); if (rc ) rc = m_curve[1]->IsContinuous( desired_continuity, t, &crv_hint[1], point_tolerance, d1_tolerance, d2_tolerance, cos_angle_tolerance, curvature_tolerance ); if ( hint ) { *hint = ( (crv_hint[0]&0xFFFF) | (crv_hint[1]<<16) ); } } return rc; } bool ON_SumSurface::Reverse( int dir ) { bool rc = false; if ( dir == 0 && m_curve[0] ) rc = m_curve[0]->Reverse(); else if ( dir == 1 && m_curve[1] ) rc = m_curve[1]->Reverse(); DestroySurfaceTree(); return rc; } bool ON_SumSurface::Transpose() { ON_Curve* c = m_curve[0]; m_curve[0] = m_curve[1]; m_curve[1] = c; DestroySurfaceTree(); return true; } bool ON_SumSurface::Evaluate( // returns false if unable to evaluate double s, double t, // evaluation parameters int nder, // number of derivatives (>=0) int v_stride, // array stride (>=Dimension()) double* v, // array of length stride*(ndir+1)*(ndir+2)/2 int side, // 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* hint // optional - evaluation hint (int[2]) used to speed // repeated evaluations ) const { bool rc = false; const int dim = Dimension(); if ( dim > 0 ) { int crv_hint[2] = {0,0}; if ( hint ) { crv_hint[0] = (*hint) & 0xFFFF; crv_hint[1] = ((*hint) & 0xFFFF0000) >> 16; } double* v0 = (double*)onmalloc( 2*(nder+1)*dim*sizeof(*v0) ); double* v1 = v0 + (nder+1)*dim; int side0, side1; switch(side) { case 1: side0 = 1; side1 = 1; break; case 2: side0 = -1; side1 = 1; break; case 3: side0 = -1; side1 = -1; break; case 4: side0 = 1; side1 = -1; break; default: side0 = 1; side1 = 1; break; } rc = m_curve[0]->Evaluate(s,nder,dim,v0,side0,hint ? &crv_hint[0] : 0); if ( rc ) rc = m_curve[1]->Evaluate(t,nder,dim,v1,side1,hint ? &crv_hint[1] : 0); if (rc) { int j,ds,dt,der; for ( j = 0; j < dim; j++ ) { v[j] = m_basepoint[j] + v0[j] + v1[j]; } for ( der = 1; der <= nder; der++ ) { for ( ds = der, dt = 0; ds >= 0; ds--, dt++ ) { v += v_stride; for ( j = 0; j < dim; j++ ) v[j] = 0.0; // Mar 18 CCW - Fixed bug in evaluator that // returned non-zero values for mixed partials. if (ds && dt) continue; if ( ds ) { for ( j = 0; j < dim; j++ ) v[j] += v0[j+dim*ds]; } if ( dt ) { for ( j = 0; j < dim; j++ ) v[j] += v1[j+dim*dt]; } } } } if ( hint ) { *hint = crv_hint[0] | (crv_hint[1] << 16); } onfree(v0); } return rc; } ON_Curve* ON_SumSurface::IsoCurve(int dir, double c ) const { ON_Curve* iso_curve = 0; if ( dir >= 0 && dir <= 1 && m_curve[0] && m_curve[1] ) { iso_curve = m_curve[dir]->Duplicate(); ON_3dPoint p = m_curve[1-dir]->PointAt(c); ON_3dVector v = p + m_basepoint; if ( !v.IsZero() ) { if ( !iso_curve->Translate(v) ) { delete iso_curve; iso_curve = 0; } } } return iso_curve; } class ON_SumTensor : public ON_TensorProduct { public: int dim; ON_3dPoint basepoint; int DimensionA() const; int DimensionB() const; int DimensionC() const; bool Evaluate( double, // a const double*, // A double, // b const double*, // B double* // C ); }; int ON_SumTensor::DimensionA() const { return dim; } int ON_SumTensor::DimensionB() const { return dim; } int ON_SumTensor::DimensionC() const { return dim; } bool ON_SumTensor::Evaluate( double a, const double* CurveA, double b, const double* CurveB, double* SrfPoint ) { SrfPoint[0] = a*CurveA[0] + b*CurveB[0] + basepoint.x; SrfPoint[1] = a*CurveA[1] + b*CurveB[1] + basepoint.y; SrfPoint[2] = a*CurveA[2] + b*CurveB[2] + basepoint.z; return true; } int ON_SumSurface::GetNurbForm( ON_NurbsSurface& nurbs_surface, double tolerance ) const { nurbs_surface.Destroy(); int rc = 0; int dim = Dimension(); if ( dim > 0 ) { ON_NurbsCurve tmpA, tmpB; int rcA = 0; int rcB = 0; const ON_NurbsCurve* nurbs_curveA=0; const ON_NurbsCurve* nurbs_curveB=0; nurbs_curveA = ON_NurbsCurve::Cast(m_curve[0]); if ( !nurbs_curveA ) { rcA = 1; rcA = m_curve[0]->GetNurbForm( tmpA, tolerance ); if ( rcA > 0 ) nurbs_curveA = &tmpA; } if ( nurbs_curveA ) { rcB = 1; nurbs_curveB = ON_NurbsCurve::Cast(m_curve[1]); if ( !nurbs_curveB ) { rcB = m_curve[1]->GetNurbForm( tmpB, tolerance ); if ( rcB > 0 ) nurbs_curveB = &tmpB; } } if ( nurbs_curveA && nurbs_curveB ) { ON_SumTensor sum_tensor; sum_tensor.dim = dim; sum_tensor.basepoint = m_basepoint; if ( !nurbs_surface.TensorProduct( *nurbs_curveA, *nurbs_curveB, sum_tensor ) ) nurbs_surface.Destroy(); else rc = (rcA >= rcB) ? rcA : rcB; } } return rc; } int ON_SumSurface::HasNurbForm() const { if (Dimension() <= 0) return 0; int rc = 1; int i; for (i=0; i<2; i++){ int nf = m_curve[i]->HasNurbForm(); if (nf == 0) return 0; if (nf == 2) rc = 2; } return rc; } bool ON_SumSurface::GetSurfaceParameterFromNurbFormParameter( double nurbs_s, double nurbs_t, double* surface_s, double* surface_t ) const { // NOTE: overrides ON_Surface virtual function bool rc = (m_curve[0] && m_curve[1]) ? true : false; *surface_s = nurbs_s; *surface_t = nurbs_t; if ( m_curve[0] ) { if ( !m_curve[0]->GetCurveParameterFromNurbFormParameter( nurbs_s, surface_s ) ) rc = false; } if ( m_curve[1] ) { if (!m_curve[1]->GetCurveParameterFromNurbFormParameter( nurbs_t, surface_t )) rc = false; } return rc; } bool ON_SumSurface::GetNurbFormParameterFromSurfaceParameter( double surface_s, double surface_t, double* nurbs_s, double* nurbs_t ) const { // NOTE: overrides ON_Surface virtual function bool rc = (m_curve[0] && m_curve[1]) ? true : false; *nurbs_s = surface_s; *nurbs_t = surface_t; if ( m_curve[0] ) { if ( !m_curve[0]->GetNurbFormParameterFromCurveParameter( surface_s, nurbs_s ) ) rc = false; } if ( m_curve[1] ) { if (!m_curve[1]->GetNurbFormParameterFromCurveParameter( surface_t, nurbs_t )) rc = false; } return rc; } bool ON_SumSurface::Trim(int dir, const ON_Interval& domain ) { if ( dir < 0 || dir > 1 ) return false; ON_Interval current_domain = Domain(dir); if ( current_domain[0] == ON_UNSET_VALUE && current_domain[1] == ON_UNSET_VALUE ) current_domain = domain; ON_Interval trim_domain; trim_domain.Intersection(domain, Domain(dir) ); if ( !trim_domain.IsIncreasing() ) return false; if (trim_domain[0] == current_domain[0] && trim_domain[1] == current_domain[1] ) return true; m_bbox.Destroy(); DestroySurfaceTree(); return m_curve[dir]->Trim(trim_domain); } bool ON_SumSurface::Extend( int dir, const ON_Interval& domain ) { if ( dir < 0 || dir > 1 ) return false; if (IsClosed(dir)) return false; //ON_Interval current_domain = Domain(dir); if (nullptr == m_curve[dir]) return false; bool rc = m_curve[dir]->Extend(domain); if (rc) { DestroySurfaceTree(); m_bbox.Destroy(); } return rc; } bool ON_SumSurface::Split(int dir, double c, ON_Surface*& west_or_south_side, ON_Surface*& east_or_north_side ) const { if ( dir < 0 || dir > 1 ) return false; if ( !Domain(dir).Includes( c, true ) ) return false; ON_SumSurface* left_srf = 0; ON_SumSurface* right_srf = 0; if ( west_or_south_side ) { left_srf = ON_SumSurface::Cast( west_or_south_side ); if ( !left_srf ) return false; left_srf->DestroySurfaceTree(); left_srf->m_bbox.Destroy(); } if ( east_or_north_side ) { right_srf = ON_SumSurface::Cast( east_or_north_side ); if ( !right_srf ) return false; right_srf->DestroySurfaceTree(); right_srf->m_bbox.Destroy(); } if (!left_srf) left_srf = ON_SumSurface::New(*this); else if (left_srf != this) *left_srf = *this; if (!right_srf) right_srf = ON_SumSurface::New(*this); else if (right_srf != this) *right_srf = *this; if (left_srf == this && right_srf == this) return false; if (left_srf != this) { delete left_srf->m_curve[dir]; left_srf->m_curve[dir] = 0; } if (right_srf != this) { delete right_srf->m_curve[dir]; right_srf->m_curve[dir] = 0; } if (!m_curve[dir]->Split(c, left_srf->m_curve[dir], right_srf->m_curve[dir])){ if (!west_or_south_side) delete left_srf; if (!east_or_north_side) delete right_srf; return false; } if (!west_or_south_side) west_or_south_side = left_srf; if (!east_or_north_side) east_or_north_side = right_srf; return true; } /* bool ON_SumSurface::GetSurfaceParameterFromNurbFormParameter( double nurbs_s, double nurbs_t, double* surface_s, double* surface_t ) const { // NOTE: overrides ON_Surface virtual function bool rc; if ( m_curve[0] ) { rc = m_curve[0]->GetCurveParameterFromNurbFormParameter( nurbs_s, surface_s ); } else { rc = false; *surface_s = nurbs_s; } if ( m_curve[1] ) { if ( m_curve[1]->GetCurveParameterFromNurbFormParameter( nurbs_t, surface_t ) ) rc = false; } else { rc = false; *surface_t = nurbs_t; } return rc; } bool ON_SumSurface::GetNurbFormParameterFromSurfaceParameter( double surface_s, double surface_t, double* nurbs_s, double* nurbs_t ) const { // NOTE: overrides ON_Surface virtual function bool rc; if ( m_curve[0] ) { rc = m_curve[0]->GetNurbFormParameterFromCurveParameter( surface_s, nurbs_s ); } else { rc = false; *surface_s = nurbs_s; } if ( m_curve[1] ) { if ( m_curve[1]->GetNurbFormParameterFromCurveParameter( surface_t, nurbs_t ) ) rc = false; } else { rc = false; *surface_t = nurbs_t; } return rc; } */