Changeset View
Changeset View
Standalone View
Standalone View
extern/opennurbs/opennurbs_sumsurface.cpp
- This file was added.
| /* $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>. | |||||
| // | |||||
| //////////////////////////////////////////////////////////////// | |||||
| */ | |||||
| #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() : m_basepoint(0.0,0.0,0.0) | |||||
| { | |||||
| ON__SET__THIS__PTR(m_s_ON_SumSurface_ptr); | |||||
| m_curve[0] = 0; | |||||
| m_curve[1] = 0; | |||||
| } | |||||
| 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] = 0; | |||||
| } | |||||
| } | |||||
| m_bbox.Destroy(); | |||||
| m_basepoint.Set(0.0,0.0,0.0); | |||||
| } | |||||
| void ON_SumSurface::EmergencyDestroy() | |||||
| { | |||||
| m_curve[0] = 0; | |||||
| m_curve[1] = 0; | |||||
| } | |||||
| ON_SumSurface::ON_SumSurface( const ON_SumSurface& src ) | |||||
| { | |||||
| ON__SET__THIS__PTR(m_s_ON_SumSurface_ptr); | |||||
| m_curve[0] = 0; | |||||
| m_curve[1] = 0; | |||||
| *this = 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(); | |||||
| for ( int i = 0; i < 2; i++ ) | |||||
| { | |||||
| if ( src.m_curve[i] ) | |||||
| { | |||||
| ON_Object* obj = src.m_curve[i]->DuplicateCurve(); | |||||
| m_curve[i] = ON_Curve::Cast(obj); | |||||
| if ( !m_curve[i] ) | |||||
| delete obj; | |||||
| } | |||||
| } | |||||
| m_basepoint = src.m_basepoint; | |||||
| m_bbox = src.m_bbox; | |||||
| } | |||||
| 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<ON_SumSurface*>(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; | |||||
| if ( ! (*ptr[j] > 0.0) ) | |||||
| { | |||||
| int i, imax = 64, hint = 0; | |||||
| double length_estimate = 0.0, 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 ) ) | |||||
| { | |||||
| if ( pt0 != ON_3dPoint::UnsetPoint ) | |||||
| length_estimate += pt0.DistanceTo(pt); | |||||
| pt0 = pt; | |||||
| } | |||||
| } | |||||
| *ptr[j] = length_estimate; | |||||
| } | |||||
| } | |||||
| 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; | |||||
| } | |||||
| */ | |||||