mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-08 04:52:10 +00:00
a5de86aaf8
Deleted: Surface/Plane/OffsetSurface/BSplineSurface create_extended_surface(_dir), with create_extended_surface_dispatched, extend_side and MAX_EXTEND_HALVINGS/DOUBLINGS (CreateExtendedSurface on every kind), srf_adv::p1::extend_by_dist (N_SrfExtendByDist) and srf_adv::p2's ST_surxsdr (extend_by_dist_at_depth/_in_place, SrfContinuity, MAX_EXTEND_DEPTH). Their only callers were each other: every caller extends through surface::extend since the switch. remove_knot_conditional and extend_by_param_dist stay. difftest: their ops are removed with their FFI ops, C++ shim cases, fixtures and fuzz corpus entries (nlib.srf_adv_p1/p2, surface.surface_p2, surface.plane_p1, nurbs.b_spline_surface_n_lib_p1, surface.surf_of_extrusion_p2, surface.offset_surface; each unit passes in full; removed shim op numbers are left unused). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NvoxKMbMFSQU8tzRtoJhtT
1862 lines
62 KiB
C++
1862 lines
62 KiB
C++
// SPDX-License-Identifier: Apache-2.0
|
|
// difftest shim for unit `surface.surface_p2`: the SmSurface members owned by the unit
|
|
// (source/SMLib/src/SmSurface.cpp, source/SMLib/inc/SmSurface.h), called through `SmSurface*`
|
|
// on a base `SmSurface()` and on SmBSplineSurface objects so the virtual dispatch (derived
|
|
// override or base-class default) is upstream's, plus SmSurfaceEval, SmDerivSurfDefinition,
|
|
// SmDropCurveFail, the smsurf_* functions and the file-static helpers of SmSurface.cpp.
|
|
//
|
|
// Static functions and classes local to SmSurface.cpp cannot be linked against and the file
|
|
// cannot be recompiled inside a namespace (it defines SmSurface members), so the helpers used
|
|
// here are VERBATIM copies of upstream SmSurface.cpp (commit c9c5979), inside the namespace
|
|
// sc_srf_p2 (line ranges noted at each block; generated, do not edit by hand).
|
|
// SmLSIGlobalSolver's LocalSolve and IdenticalSolutions are defined as SM_ERR stubs: only its
|
|
// constructor and BranchMayContainAnswers are exercised.
|
|
//
|
|
// One entry point, sc_surface_surface_p2_eval(op, in, n_in, out, cap, out_len). Layouts are
|
|
// documented in crates/solidcore-ffi/src/units/surface_surface_p2.rs, which validates every
|
|
// input. The input starts with a surface block `ctor` (0: none, static op; 1: SmSurface();
|
|
// 2: SmBSplineSurface(gw_SURFACE*, FALSE, NULL) from `oob form n m p q r s cpts(x y z w) u v`;
|
|
// 3: a canonical SmTorus or SmCone written with WriteToDB to an ASCII stream, its planar
|
|
// generator flag optionally cleared in the record, and read back with SmSurface::ReadFromDB).
|
|
// `out` receives the op status (0 = SM_SUCCESS, else the SmStatus value) and the op's outputs.
|
|
#include "sc_shim.h"
|
|
|
|
#include "StdAfx.h"
|
|
#include <SmAssertArray.h>
|
|
#include <SmAxis2Placement.h>
|
|
#include <SmBSplineCurve.h>
|
|
#include <SmBSplineSurface.h>
|
|
#include <SmCone.h>
|
|
#include <SmContext.h>
|
|
#include <SmCurve.h>
|
|
#include <SmCurveCache.h>
|
|
#include <SmDatabaseIO.h>
|
|
#include <SmExtent1d.h>
|
|
#include <SmExtent2d.h>
|
|
#include <SmExtent3d.h>
|
|
#include <SmGeomUtility.h>
|
|
#include <SmGlobalSolver.h>
|
|
#include <SmLine.h>
|
|
#include <SmNurbsCrv.h>
|
|
#include <SmNurbsSrf.h>
|
|
#include <SmSolutionArray.h>
|
|
#include <SmSurface.h>
|
|
#include <SmSurfaceCache.h>
|
|
#include <SmTArray.h>
|
|
#include <SmTorus.h>
|
|
#include <SmTree.h>
|
|
#include <SmVector2d.h>
|
|
#include <SmVector3d.h>
|
|
#include <nurbs.h>
|
|
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "sc_sm.h"
|
|
|
|
using sc::flg;
|
|
using sc::put_dom;
|
|
using sc::put_vec;
|
|
using sc::st;
|
|
|
|
namespace sc_srf_p2
|
|
{
|
|
// clang-format off
|
|
// ---- verbatim: SmSurface.cpp lines 3826-3940: sm_CCLocalSolve
|
|
static SmStatus sm_CCLocalSolve
|
|
(const SmCurve & crCurve1,
|
|
const SmExtent1d & crInterval1,
|
|
SmContinuityType aeConts1[2],
|
|
const SmCurve & crCurve2,
|
|
const SmExtent1d & crInterval2,
|
|
SmContinuityType aeConts2[2],
|
|
SmSolverOperationType & eSolverOperation,
|
|
double d3dTolerance,
|
|
SmSolutionArray & rSolutions)
|
|
{
|
|
rSolutions.ReSet();
|
|
|
|
SM_ASSERT(eSolverOperation == SM_SO_MINIMIZE ||
|
|
eSolverOperation == SM_SO_MAXIMIZE);
|
|
|
|
SmBoolean bFoundAnswer;
|
|
SmSolution sSolution;
|
|
sSolution.m_lNumVariables = 2;
|
|
sSolution.m_eSolutionType = SM_ST_SINGLE_VALUE;
|
|
// If we have a total discontinuity (i.e. end of curve)
|
|
// then we always test. If we have a derivative
|
|
// discontinuity then we just test the ones on the left
|
|
// side - otherwise we would do each point two times.
|
|
SmPoint3d sPnt;
|
|
SmSolution sSol;
|
|
if (aeConts1[0] <= SM_CT_C0)
|
|
{
|
|
SER(crCurve1.EvaluatePoint(crInterval1.GetMin(),sPnt));
|
|
SER(crCurve2.LocalPointSolve(crInterval2,eSolverOperation,sPnt,
|
|
NULL,NULL,NULL,crInterval2.Evaluate(0.5),bFoundAnswer,sSol));
|
|
if (bFoundAnswer)
|
|
{
|
|
sSol.m_lNumVariables = 2;
|
|
sSol.m_vStart[1] = sSol.m_vStart[0];
|
|
sSol.m_vStart[0] = crInterval1.GetMin();
|
|
rSolutions.Add(sSol);
|
|
}
|
|
}
|
|
if (aeConts1[1] <= SM_CT_DISCONTINUOUS)
|
|
{
|
|
SER(crCurve1.EvaluatePoint(crInterval1.GetMax(),sPnt));
|
|
SER(crCurve2.LocalPointSolve(crInterval2,eSolverOperation,sPnt,
|
|
NULL,NULL,NULL,crInterval2.Evaluate(0.5),bFoundAnswer,sSol));
|
|
if (bFoundAnswer)
|
|
{
|
|
sSol.m_lNumVariables = 2;
|
|
sSol.m_vStart[1] = sSol.m_vStart[0];
|
|
sSol.m_vStart[0] = crInterval1.GetMax();
|
|
rSolutions.Add(sSol);
|
|
}
|
|
}
|
|
if (aeConts2[0] <= SM_CT_C0)
|
|
{
|
|
SER(crCurve2.EvaluatePoint(crInterval2.GetMin(),sPnt));
|
|
SER(crCurve1.LocalPointSolve(crInterval1,eSolverOperation,sPnt,
|
|
NULL,NULL,NULL,crInterval1.Evaluate(0.5),bFoundAnswer,sSol));
|
|
if (bFoundAnswer)
|
|
{
|
|
sSol.m_lNumVariables = 2;
|
|
sSol.m_vStart[1] = crInterval2.GetMin();
|
|
rSolutions.Add(sSol);
|
|
}
|
|
}
|
|
if (aeConts2[1] <= SM_CT_DISCONTINUOUS)
|
|
{
|
|
SER(crCurve2.EvaluatePoint(crInterval2.GetMax(),sPnt));
|
|
SER(crCurve1.LocalPointSolve(crInterval1,eSolverOperation,sPnt,
|
|
NULL,NULL,NULL,crInterval1.Evaluate(0.5),bFoundAnswer,sSol));
|
|
if (bFoundAnswer)
|
|
{
|
|
sSol.m_lNumVariables = 2;
|
|
sSol.m_vStart[1] = crInterval2.GetMax();
|
|
rSolutions.Add(sSol);
|
|
}
|
|
}
|
|
|
|
double daGuess1[4], daGuess2[4];
|
|
ULONG lNumGuess = 0;
|
|
|
|
if (lNumGuess == 0)
|
|
{
|
|
// Take midpoint of interval for guess.
|
|
lNumGuess = 1;
|
|
daGuess1[0] = crInterval1.Evaluate(0.5);
|
|
daGuess2[0] = crInterval2.Evaluate(0.5);
|
|
}
|
|
|
|
SmSolverOperationType eLocalSolverOp = eSolverOperation;
|
|
|
|
for (ULONG i=0; i<lNumGuess; i++)
|
|
{
|
|
SmBoolean bFoundSolution;
|
|
SmSolution sSolut;
|
|
SER(crCurve1.LocalCurveSolve(crInterval1,
|
|
crCurve2,
|
|
crInterval2,
|
|
eLocalSolverOp,
|
|
d3dTolerance,
|
|
NULL,
|
|
NULL,
|
|
daGuess1[i],
|
|
daGuess2[i],
|
|
bFoundSolution,
|
|
sSolut ));
|
|
|
|
if (bFoundSolution)
|
|
{
|
|
sSolut.m_lNumVariables = 2;
|
|
rSolutions.Add( sSolut );
|
|
}
|
|
}
|
|
return SM_SUCCESS;
|
|
|
|
} // end sm_CCLocalSolve
|
|
// ---- end verbatim
|
|
|
|
// ---- verbatim: SmSurface.cpp lines 7244-7258: s_MapUV, s_IsEven
|
|
static SmPoint2d s_MapUV
|
|
(double dInU,
|
|
double dInV,
|
|
SmOrientType eOrient,
|
|
double dDirU,
|
|
double dDirV )
|
|
{
|
|
SmPoint2d sRet( dInU, dInV );
|
|
if ( dDirU < 0 ) sRet.x = 1 - sRet.x;
|
|
if ( dDirV < 0 ) sRet.y = 1 - sRet.y;
|
|
if ( eOrient == SM_OT_OPPOSITE ) sRet.SwapXY();
|
|
|
|
return sRet;
|
|
}
|
|
static SmBoolean s_IsEven( int iNum ) { return ( (iNum/2) * 2 == iNum ); }
|
|
// ---- end verbatim
|
|
|
|
// ---- verbatim: SmSurface.cpp lines 11574-11614: sm_MergeDoubleArrays
|
|
static SmStatus sm_MergeDoubleArrays
|
|
(const SmTArray<double> & crParams1, // in : 1st input array - ordered by increasing values
|
|
const SmTArray<double> & crParams2, // in : 2nd input array - ordered by increasing values
|
|
SmTArray<double> & rSortedResults) // out: merged array - ordered:[increasing value]
|
|
// no duplicates.
|
|
{
|
|
// init output
|
|
rSortedResults.ReSet();
|
|
|
|
// low work - one or both of the arrays is empty
|
|
if (crParams1.GetSize() == 0) { rSortedResults.Append(crParams2); return SM_SUCCESS; }
|
|
if (crParams2.GetSize() == 0) { rSortedResults.Append(crParams1); return SM_SUCCESS; }
|
|
|
|
// arrive here when two arrays need to be merged
|
|
|
|
// iter while either list contains an item
|
|
ULONG lStart1 = 0;
|
|
ULONG lStart2 = 0;
|
|
while (lStart1 < crParams1.GetSize() && lStart2 < crParams2.GetSize())
|
|
{
|
|
double dP1 = (lStart1 < crParams1.GetSize()) ? crParams1[lStart1] : SM_BIG_DOUBLE ;
|
|
double dP2 = (lStart2 < crParams2.GetSize()) ? crParams2[lStart2] : SM_BIG_DOUBLE ;
|
|
|
|
// values within SM_EFF_ZERO of one another are merged into one
|
|
if (SM_ARE_SAME(dP1,dP2)) { rSortedResults.Add(dP1);
|
|
lStart1 ++;
|
|
lStart2 ++;
|
|
}
|
|
// else add next smallest value to output
|
|
else if (dP1 < dP2) { rSortedResults.Add(dP1);
|
|
lStart1 ++;
|
|
}
|
|
else { rSortedResults.Add(dP2);
|
|
lStart2 ++;
|
|
}
|
|
} // end while any items are left in either input array
|
|
|
|
// all done
|
|
return SM_SUCCESS;
|
|
|
|
} // end sm_MergeDoubleArrays
|
|
// ---- end verbatim
|
|
|
|
// ---- verbatim: SmSurface.cpp lines 13053-13063: sm_ConvertToParameterDelta
|
|
static double sm_ConvertToParameterDelta
|
|
(const SmVector3d & crTangentVector,
|
|
const SmVector3d & crDeltaVector)
|
|
{
|
|
double dTanLen = crTangentVector.Length();
|
|
if (dTanLen < SM_EFF_ZERO) return 0.0;
|
|
SmVector3d sUnitTan = crTangentVector / dTanLen;
|
|
double dDot = sUnitTan.Dot(crDeltaVector);
|
|
return dDot/dTanLen;
|
|
|
|
} // end sm_ConvertToParameterDelta
|
|
// ---- end verbatim
|
|
|
|
// ---- verbatim: SmSurface.cpp lines 17322-17374: sm_CsArePerpenDisjoint
|
|
static SmBoolean sm_CsArePerpenDisjoint
|
|
(const SmTreeNode & crCurveNode,
|
|
const SmTreeNode & crSurfaceNode)
|
|
{
|
|
// Surface node has a polar box
|
|
if( crSurfaceNode.m_eAuxDataType == SM_AD_BEZIER_SURFACE
|
|
|| crSurfaceNode.m_eAuxDataType == SM_AD_BEZIER_SURFACE_HEAD)
|
|
{
|
|
SmBezierPatch *pBezPatch = (SmBezierPatch*)crSurfaceNode.m_pData;
|
|
SmVector3d sConeVec;
|
|
double dConeAngleRad;
|
|
SER(crSurfaceNode.m_sBBox.ComputeConeBoundTo(crCurveNode.m_sBBox,
|
|
sConeVec,
|
|
dConeAngleRad));
|
|
//
|
|
if (dConeAngleRad > SM_PI/2.0)
|
|
{ return FALSE; }
|
|
|
|
//
|
|
if (pBezPatch->GetPolarBox().IsDisjointWithCone(sConeVec,dConeAngleRad))
|
|
{ return TRUE; }
|
|
|
|
//
|
|
if( crCurveNode.m_eAuxDataType != SM_AD_BEZIER_CURVE
|
|
&& crCurveNode.m_eAuxDataType != SM_AD_CURVE_DATA)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
SmBezierSpan * pBezSpan = (SmBezierSpan*)crCurveNode.m_pData; NER(pBezSpan);
|
|
SmCurveCache * pCurveCache = (SmCurveCache*)crCurveNode.m_pTree->GetOwner();
|
|
SmPoint3d sStart1, sEnd1;
|
|
SmExtent1d sIvl;
|
|
|
|
//
|
|
pBezSpan->GetEnds(*pCurveCache,sStart1,sEnd1,sIvl);
|
|
SmVector3d sLineVec1 = sEnd1 - sStart1;
|
|
if (sLineVec1.LengthSquared() > SM_EFF_ZERO_SQ)
|
|
{
|
|
double dCurveAngleRad = pBezSpan->m_dMaxTurningAngleDeg * SM_PI/180.0 + 3.0*SM_PI/180.0;
|
|
if (smgu_ConesAreDisjointPerpen(sLineVec1,
|
|
dCurveAngleRad,
|
|
sConeVec,
|
|
dConeAngleRad))
|
|
{ return TRUE ; }
|
|
}
|
|
}
|
|
|
|
// node does not have a polar box to check
|
|
return FALSE;
|
|
|
|
} // end sm_CsArePerpenDisjoint
|
|
// ---- end verbatim
|
|
|
|
// ---- verbatim: SmSurface.cpp lines 17886-18068: SmLSIGlobalSolver (class, constructor, BranchMayContainAnswers)
|
|
class SmLSIGlobalSolver : public SmGlobalSolver
|
|
{
|
|
public:
|
|
const SmSurface * m_pSurf; // surface being solved for
|
|
const SmExtent2d & m_crUVDomain; // intersection domain
|
|
SmPoint3d m_vLinePoint;
|
|
SmVector3d m_vLineVector; // Is this a UNIT vector ( should NOt be RCLxx )
|
|
const SmExtent1d * m_cpLineInterval; // Line intersection interval (a reference not owned)
|
|
SmBoolean m_bRayFire; // TRUE = Line intersection interval = [0,infinity]
|
|
// skip intersections with negative line param values
|
|
double m_dDistanceTolerance; // min dist between distinct 3d Points
|
|
|
|
// constructor/destructor
|
|
SmLSIGlobalSolver(SmTree * pSurfaceTree,
|
|
const SmExtent2d & crUVDomain,
|
|
const SmPoint3d & crLinePoint,
|
|
const SmVector3d & crLineVector,
|
|
const SmExtent1d * cpLineInterval,
|
|
SmBoolean bRayFire,
|
|
double dDistanceTolerance);
|
|
|
|
virtual ~SmLSIGlobalSolver() { m_cpLineInterval = NULL ;
|
|
m_dDistanceTolerance = SM_UNDEF_DOUBLE ;
|
|
}
|
|
|
|
//
|
|
virtual SmBoolean BranchMayContainAnswers(SmTreeNode * apBranch[SM_GS_MAX_TREES]);
|
|
|
|
// NewtonRaphson Driver: SmSolution->SmSolutionEnd->m_adParameters
|
|
// [0] line T
|
|
// [1] surface U
|
|
// [2] surface V
|
|
virtual SmStatus LocalSolve(SmTreeNode * apBranch[SM_GS_MAX_TREES],
|
|
SmBoolean & rbNeedsMoreSubdivision);
|
|
|
|
// return TRUE when two solutions are identical
|
|
virtual SmSolutionPairType IdenticalSolutions(const SmSolution & crSol1,
|
|
const SmSolution & crSol2,
|
|
const SmSolution *&pPreferredSol)
|
|
const;
|
|
|
|
} ; // end class SmLSIGlobalSolver
|
|
|
|
/*******************************************************************//**
|
|
PURPOSE: SmLSIGlobalSolver constructor
|
|
|
|
NOTES:
|
|
***********************************************************************/
|
|
SmLSIGlobalSolver::SmLSIGlobalSolver
|
|
(SmTree *pSurfaceTree,
|
|
const SmExtent2d & crUVDomain,
|
|
const SmPoint3d & crLinePoint,
|
|
const SmVector3d & crLineVector,
|
|
const SmExtent1d * cpLineInterval,
|
|
SmBoolean bRayFire,
|
|
double dDistanceTolerance)
|
|
: SmGlobalSolver(pSurfaceTree,2),
|
|
m_pSurf(SM_CAST_PTR(SmSurface, pSurfaceTree->GetOwnerObject())),
|
|
m_crUVDomain(crUVDomain),
|
|
m_vLinePoint(crLinePoint),
|
|
m_vLineVector(crLineVector),
|
|
m_cpLineInterval(cpLineInterval),
|
|
m_bRayFire(bRayFire),
|
|
m_dDistanceTolerance(dDistanceTolerance)
|
|
{
|
|
|
|
} // end SmLSIGlobalSolver::SmLSIGlobalSolver constructor
|
|
|
|
/*******************************************************************//**
|
|
PURPOSE: Check the Line/SurfaceTreeNode->SphereBoundingBox intersection
|
|
Return FAlSE when there is no intersection because there is
|
|
no possible line/BezierPatch(es) solution, else return TRUE.
|
|
|
|
NOTES:
|
|
Return TRUE = Possible Line/BezierPatch(es) intersection
|
|
FALSE= No possible intersections
|
|
***********************************************************************/
|
|
SmBoolean SmLSIGlobalSolver::BranchMayContainAnswers
|
|
(SmTreeNode * apBranch[SM_GS_MAX_TREES]) // in : apBranch[0] = Surface Cache Tree Node
|
|
{
|
|
// If we are normalizing and have a node with a surface do the
|
|
// angular test using the Gauss map of the normal.
|
|
|
|
// locals
|
|
SmTreeNode *pSurfaceNode = apBranch[0];
|
|
|
|
// compute SphereBound Radius for SurfaceNode with tolerance
|
|
SmPoint3d sSphCenter;
|
|
double dSphRadius, dMinRadius;
|
|
const SmExtent3d &rSurfBox = pSurfaceNode->GetBoundingBox() ;
|
|
rSurfBox.ComputeSphereBound(sSphCenter, dSphRadius, &dMinRadius);
|
|
double dRadDistSq = (dSphRadius + m_dDistanceTolerance)
|
|
* (dSphRadius + m_dDistanceTolerance) ;
|
|
|
|
// get Line/SphereCenter minimum distance
|
|
double dLineParam;
|
|
SER(smgu_LineClosestPoint(m_vLinePoint,m_vLineVector,sSphCenter,dLineParam));
|
|
SmPoint3d sPointOnLine = m_vLinePoint + dLineParam * m_vLineVector;
|
|
double dDistToLineSq = sPointOnLine.DistanceBetweenSquared(sSphCenter);
|
|
|
|
#ifdef SM_DEBUG_CODE
|
|
SmBoolean bDebugMe = FALSE ;
|
|
// draw
|
|
if(bDebugMe)
|
|
{
|
|
const SmObject *pObject = pSurfaceNode->GetOwnerObject() ;
|
|
SmSurface *pSurface = pObject->IsKindOf(SmSurface_TYPE) ? (SmSurface *)pObject : NULL ;
|
|
SmFace *pFace = pSurface ? (SmFace *)pSurface->GetFace() : NULL ;
|
|
SmBrep *pBrep = pFace ? pFace->GetBrep() : NULL ;
|
|
|
|
smgfx_Erase() ;
|
|
smgfx_SetLook(1,2, 0,0,1) ; if(pBrep) pBrep->Draw(TRUE) ; sm_GraphicsLoop() ;
|
|
smgfx_SetLook(1,2, 0,1,1) ; if(pSurface) pSurface->DrawUV() ; sm_GraphicsLoop() ;
|
|
smgfx_SetLook(1,2, 0,0,0) ; if(pFace) pFace->Draw(SM_DM_CROSSHATCH) ; sm_GraphicsLoop() ;
|
|
smgfx_SetLook(2,3, 1,0,0) ; pSurfaceNode->DrawBoundingBox() ; sm_GraphicsLoop() ;
|
|
smgfx_SetLook(3,4, 1,0,0) ; rSurfBox.Draw(pObject->GetContext()) ; sm_GraphicsLoop() ;
|
|
smgfx_SetLook(3,4, 1,0,0) ; m_vLinePoint.Draw() ; sm_GraphicsLoop() ;
|
|
(10.0 * m_vLineVector).Draw(&m_vLinePoint) ; sm_GraphicsLoop() ;
|
|
sm_GraphicsLoop() ;
|
|
}
|
|
#endif // SM_DEBUG_CODE
|
|
|
|
// when the Line is outside the SphereBound - No Answers possible
|
|
if (dDistToLineSq > dRadDistSq)
|
|
{ return FALSE; }
|
|
|
|
// For RayFiring - and sphere is behind rayStartPoint
|
|
if ( m_bRayFire
|
|
&& dLineParam < 0.0)
|
|
{
|
|
// and rayStart is outside of the sphereBound
|
|
double dDistToStartSq = m_vLinePoint.DistanceBetweenSquared(sSphCenter);
|
|
if (dDistToStartSq > dRadDistSq)
|
|
{
|
|
// no solution possible
|
|
return FALSE;
|
|
}
|
|
} // end RayFire check
|
|
|
|
// when given a line interval
|
|
if (m_cpLineInterval)
|
|
{
|
|
// If sphere is below line interval
|
|
if (dLineParam < m_cpLineInterval->GetMin())
|
|
{
|
|
// and intervalStartPoint is outside of SphereBound
|
|
SmPoint3d sStartPt = m_vLinePoint + m_cpLineInterval->GetMin()*m_vLineVector;
|
|
double dDistToStartSq = sStartPt.DistanceBetweenSquared(sSphCenter);
|
|
if (dDistToStartSq > dRadDistSq)
|
|
{
|
|
// no solution possible
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
// if sphere is above line interval
|
|
if (dLineParam > m_cpLineInterval->GetMax())
|
|
{
|
|
// and intervalEndPoint is outside of SphereBound
|
|
SmPoint3d sEndPt = m_vLinePoint + m_cpLineInterval->GetMax()*m_vLineVector;
|
|
double dDistToStartSq = sEndPt.DistanceBetweenSquared(sSphCenter);
|
|
if (dDistToStartSq > dRadDistSq)
|
|
{
|
|
// no solution possible
|
|
return FALSE;
|
|
}
|
|
}
|
|
} // end need to check interval bounds check
|
|
|
|
// check linePoint bounding box intersections
|
|
if( dDistToLineSq <= ( (dMinRadius + m_dDistanceTolerance)
|
|
* (dMinRadius + m_dDistanceTolerance))
|
|
|| rSurfBox.ContainsPoint3d(sPointOnLine, m_dDistanceTolerance))
|
|
{ return TRUE ; }
|
|
else // check lineVector for bounding box intersections
|
|
{ ULONG lNumFound ;
|
|
double dTEnter, dTExit ;
|
|
rSurfBox.IntersectLine(sPointOnLine, m_vLineVector, lNumFound, dTEnter, dTExit) ;
|
|
if( lNumFound > 0) { return TRUE ; }
|
|
else { return FALSE ; }
|
|
}
|
|
|
|
} // end SmLSIGlobalSolver::BranchMayContainAnswers
|
|
// ---- end verbatim
|
|
|
|
// ---- verbatim: SmSurface.cpp lines 23712-23756: sm_IntersectAndSplit
|
|
static SmStatus sm_IntersectAndSplit
|
|
(const SmBSplineCurve & crUVCurve, // in: Curve to be intersected
|
|
const SmExtent1d & crInterval, // in: Curve domain of interest
|
|
const SmPoint3d & crPlanePnt, // in:
|
|
const SmPoint3d & crPlaneNorm, // in:
|
|
SmTArray<double> & rSplitParameters) // in/out: Sorted list of curve parameters.
|
|
{
|
|
double dPlaneD = - crPlaneNorm.Dot( crPlanePnt );
|
|
SmSolution sData[16];
|
|
SmSolutionArray sSolutions(16,sData);
|
|
ULONG ii, jj;
|
|
|
|
SER(crUVCurve.GlobalPropertyAnalysis(crInterval,
|
|
SM_CP_PLANE_INTERSECTION,
|
|
&dPlaneD,
|
|
&crPlaneNorm,
|
|
SM_EFF_ZERO_SQRT,
|
|
sSolutions));
|
|
|
|
for ( ii=0; ii<sSolutions.GetSize(); ii++ )
|
|
{
|
|
double dT = sSolutions[ii].m_vStart[0];
|
|
ULONG lInsertIndex = rSplitParameters.GetSize();
|
|
SmBoolean bSplit = TRUE;
|
|
for ( jj=0; jj<rSplitParameters.GetSize(); jj++ )
|
|
{
|
|
if (smos_Fabs(dT - rSplitParameters[jj]) < SM_EFF_ZERO_SQRT)
|
|
{
|
|
bSplit = FALSE;
|
|
break;
|
|
}
|
|
else if (dT < rSplitParameters[jj])
|
|
{
|
|
lInsertIndex = jj;
|
|
break;
|
|
}
|
|
}
|
|
if ( bSplit )
|
|
{ rSplitParameters.InsertAt(lInsertIndex,dT,1); }
|
|
|
|
} // end for all solutions
|
|
|
|
return SM_SUCCESS;
|
|
|
|
} // end sm_IntersectAndSplit
|
|
// ---- end verbatim
|
|
|
|
// ---- verbatim: SmSurface.cpp lines 23764-23815: sm_IntersectCurveAndSplit
|
|
static SmStatus sm_IntersectCurveAndSplit
|
|
(const SmBSplineCurve & crUVCurve, // in : Curve to be intersected
|
|
const SmExtent1d & crInterval, // in : Curve domain of interest
|
|
const SmLine & crLine, // in : Other curve being intersected
|
|
const SmExtent1d & crLineInterval, // in : Interval of other curve to intersect
|
|
SmScaledZero sScaledZero, // in : Used as the 2d XSect distance for the Global XSect Solver
|
|
SmTArray<double> & rSplitParameters) // i/o: Accumulating list of all Curve/Bndry XSects Curve Param vals
|
|
{
|
|
// locals
|
|
SmSolution sData[16];
|
|
SmSolutionArray sSolutions(16,sData);
|
|
ULONG ii, jj;
|
|
|
|
// Find UVCurve/Line 2d XSects
|
|
SER(crUVCurve.GlobalCurveIntersect(crInterval,
|
|
crLine,
|
|
crLineInterval,
|
|
sScaledZero,
|
|
sSolutions));
|
|
|
|
// for every solution - sort new solutions into rSplitParameters
|
|
for ( ii=0; ii<sSolutions.GetSize(); ii++ )
|
|
{
|
|
double dT = sSolutions[ii].m_vStart[0];
|
|
ULONG lInsertIndex = rSplitParameters.GetSize();
|
|
SmBoolean bSplit = TRUE;
|
|
|
|
// for every input SplitParam - Find index for insertion - skip duplicates
|
|
for ( jj=0; jj<rSplitParameters.GetSize(); jj++ )
|
|
{
|
|
if (smos_Fabs(dT - rSplitParameters[jj]) < SmTol::GetEffZeroParam())
|
|
{
|
|
bSplit = FALSE;
|
|
break;
|
|
}
|
|
else if (dT < rSplitParameters[jj])
|
|
{
|
|
lInsertIndex = jj;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// insert new sorted solutions
|
|
if ( bSplit )
|
|
{ rSplitParameters.InsertAt(lInsertIndex,dT,1); }
|
|
|
|
} // end for all solutions
|
|
|
|
// all done
|
|
return SM_SUCCESS;
|
|
|
|
} // end sm_IntersectCurveAndSplit
|
|
// ---- end verbatim
|
|
|
|
// ---- verbatim: SmSurface.cpp lines 24009-24033: sm_SetUpBreaks
|
|
static SmStatus sm_SetUpBreaks
|
|
(SmTArray<double> & rBreaks,
|
|
const SmExtent1d & rIvl)
|
|
{
|
|
while (!rIvl.ContainsValue(rBreaks[0])) {
|
|
rBreaks.RemoveAt(0,1);
|
|
if (rBreaks.GetSize() == 0) {
|
|
rBreaks.Add(rIvl.GetMin());
|
|
break;
|
|
}
|
|
}
|
|
if (smos_Fabs(rBreaks[0]-rIvl.GetMin()) > SM_EFF_ZERO_SQRT) {
|
|
rBreaks.InsertAt(0,rIvl.GetMin(),1);
|
|
}
|
|
|
|
while (!rIvl.ContainsValue(rBreaks.GetLast())) {
|
|
rBreaks.RemoveLast();
|
|
if (rBreaks.GetSize() == 1) break;
|
|
}
|
|
if (smos_Fabs(rBreaks.GetLast()-rIvl.GetMax()) > SM_EFF_ZERO_SQRT) {
|
|
rBreaks.Add(rIvl.GetMax());
|
|
}
|
|
return SM_SUCCESS;
|
|
|
|
} // end sm_SetUpBreaks
|
|
// ---- end verbatim
|
|
|
|
// clang-format on
|
|
|
|
// LocalSolve and IdenticalSolutions of SmLSIGlobalSolver are other units' (surface.surface_p10,
|
|
// surface.surface_p5); stubbed so the class links.
|
|
SmStatus SmLSIGlobalSolver::LocalSolve(SmTreeNode*[SM_GS_MAX_TREES], SmBoolean&)
|
|
{
|
|
return SM_ERR;
|
|
}
|
|
SmSolutionPairType SmLSIGlobalSolver::IdenticalSolutions(const SmSolution&, const SmSolution&,
|
|
const SmSolution*&) const
|
|
{
|
|
return SM_SP_DIFFCOUNTS;
|
|
}
|
|
} // namespace sc_srf_p2
|
|
|
|
namespace
|
|
{
|
|
// Ops (keep in sync with crates/solidcore-ffi/src/units/surface_surface_p2.rs).
|
|
enum : int32_t
|
|
{
|
|
OP_EVAL = 0,
|
|
OP_EVAL_PT = 1,
|
|
OP_QUERIES = 2,
|
|
OP_KNOTS = 3,
|
|
OP_PARALLEL = 4,
|
|
OP_REVERSE = 5,
|
|
OP_REPARAM = 6,
|
|
OP_SWAP = 7,
|
|
OP_TRANSFORM = 8,
|
|
OP_TRIM = 9,
|
|
OP_SPLIT = 10,
|
|
OP_STEP_INV = 11,
|
|
// 12, 13: CreateExtendedSurface (both forms), removed with the port's fitted extension.
|
|
OP_ADJUST_STEP = 14,
|
|
OP_MAX_ANAL = 15,
|
|
OP_COPY = 16,
|
|
OP_COPY_ANAL = 17,
|
|
OP_DROP_FAST = 18,
|
|
OP_CONVERT_UV = 19,
|
|
OP_SEVAL = 20,
|
|
OP_GSSI = 21,
|
|
// static ops
|
|
OP_LIFT2 = 40,
|
|
OP_LIFT3 = 41,
|
|
OP_SCALE_STEP = 42,
|
|
OP_GEOM = 43,
|
|
OP_POINT_TYPE = 44,
|
|
OP_DROP_VECS = 45,
|
|
OP_PARAM_DELTA = 46,
|
|
OP_MERGE = 47,
|
|
OP_MAP_UV = 48,
|
|
OP_IS_EVEN = 49,
|
|
OP_BREAKS = 50,
|
|
OP_LIMITS = 51,
|
|
OP_DERIV_ASSERT = 52,
|
|
OP_CROSS = 53,
|
|
OP_CROSS_SKIN = 54,
|
|
OP_DCF = 55,
|
|
OP_CC_LOCAL = 56,
|
|
OP_ISECT_SPLIT = 57,
|
|
OP_ISECT_CURVE_SPLIT = 58,
|
|
OP_LSI = 59,
|
|
OP_CS_PERPEN = 60,
|
|
OP_PLANE_3D = 61,
|
|
OP_READ_DB = 62,
|
|
};
|
|
|
|
enum : int32_t
|
|
{
|
|
CT_NONE = 0,
|
|
CT_BASE = 1,
|
|
CT_BSPLINE = 2,
|
|
CT_REVOLUTION = 3,
|
|
};
|
|
|
|
struct Peek : SmBSplineSurface
|
|
{
|
|
static SmKnotType SmBSplineSurface::*kt() { return &Peek::m_eKnotType; }
|
|
static SmBSplineSurfaceForm SmBSplineSurface::*form() { return &Peek::m_eBSplineSurfaceForm; }
|
|
};
|
|
|
|
struct EvalPeek : SmSurfaceEval
|
|
{
|
|
static SmVector3d (SmSurfaceEval::*pvv())[3][3] { return &EvalPeek::m_sPVV; }
|
|
static SmBoolean SmSurfaceEval::*uv_set() { return &EvalPeek::m_bUVSet; }
|
|
static SmBoolean SmSurfaceEval::*normal_set() { return &EvalPeek::m_bNormalSet; }
|
|
static SmBoolean SmSurfaceEval::*sect_set() { return &EvalPeek::m_bSectDirSet; }
|
|
static SmBoolean SmSurfaceEval::*fails() { return &EvalPeek::m_bFailsEval; }
|
|
};
|
|
|
|
struct Rd
|
|
{
|
|
const double* in;
|
|
int64_t at;
|
|
double num() { return in[at++]; }
|
|
int64_t idx() { return (int64_t)in[at++]; }
|
|
bool flag() { return in[at++] != 0.0; }
|
|
SmPoint2d pt2()
|
|
{
|
|
double x = num();
|
|
double y = num();
|
|
return SmPoint2d(x, y);
|
|
}
|
|
SmVector3d vec()
|
|
{
|
|
double x = num();
|
|
double y = num();
|
|
double z = num();
|
|
return SmVector3d(x, y, z);
|
|
}
|
|
SmExtent2d domain()
|
|
{
|
|
double a = num();
|
|
double b = num();
|
|
double c = num();
|
|
double d = num();
|
|
return SmExtent2d(a, b, c, d);
|
|
}
|
|
SmExtent1d ivl()
|
|
{
|
|
double a = num();
|
|
double b = num();
|
|
return SmExtent1d(a, b);
|
|
}
|
|
SmExtent3d box()
|
|
{
|
|
SmVector3d a = vec();
|
|
SmVector3d b = vec();
|
|
SmExtent3d e;
|
|
e.AddPoint3d(a);
|
|
e.AddPoint3d(b);
|
|
return e;
|
|
}
|
|
};
|
|
|
|
void put2(std::vector<double>& o, const SmVector2d& v)
|
|
{
|
|
o.push_back(v.x);
|
|
o.push_back(v.y);
|
|
}
|
|
|
|
void put_str(std::vector<double>& o, const TCHAR* s)
|
|
{
|
|
std::vector<double> c;
|
|
for (const TCHAR* p = s; p && *p; ++p)
|
|
c.push_back((double)(unsigned)*p);
|
|
o.push_back((double)c.size());
|
|
o.insert(o.end(), c.begin(), c.end());
|
|
}
|
|
|
|
gw_SURFACE* read_nurb(Rd& rd)
|
|
{
|
|
gw_INDEX n = (gw_INDEX)rd.idx();
|
|
gw_INDEX m = (gw_INDEX)rd.idx();
|
|
gw_DEGREE p = (gw_DEGREE)rd.idx();
|
|
gw_DEGREE q = (gw_DEGREE)rd.idx();
|
|
gw_INDEX r = (gw_INDEX)rd.idx();
|
|
gw_INDEX s = (gw_INDEX)rd.idx();
|
|
gw_SURFACE* sur = sm_AllocateNurbSurface(n, m, p, q, r, s);
|
|
for (gw_INDEX i = 0; i <= n; i++)
|
|
for (gw_INDEX j = 0; j <= m; j++)
|
|
{
|
|
sur->net->Pw[i][j].x = rd.num();
|
|
sur->net->Pw[i][j].y = rd.num();
|
|
sur->net->Pw[i][j].z = rd.num();
|
|
sur->net->Pw[i][j].w = rd.num();
|
|
}
|
|
for (gw_INDEX i = 0; i <= r; i++)
|
|
sur->knu->U[i] = rd.num();
|
|
for (gw_INDEX i = 0; i <= s; i++)
|
|
sur->knv->U[i] = rd.num();
|
|
return sur;
|
|
}
|
|
|
|
SmBSplineSurface* read_bspline(Rd& rd, const SmContext& ctx)
|
|
{
|
|
bool oob = rd.flag();
|
|
SmBSplineSurfaceForm form = (SmBSplineSurfaceForm)rd.idx();
|
|
SmBSplineSurface* s = new (ctx) SmBSplineSurface(read_nurb(rd), FALSE, NULL);
|
|
s->GetOutOfBoundsEnabled() = oob ? TRUE : FALSE;
|
|
s->SetBSplineSurfaceForm(form);
|
|
return s;
|
|
}
|
|
|
|
// `has` then `has_nurb oob borrowed knot_type form [n m p q r s cpts u v]`; the base class has
|
|
// no state (`has` = 0).
|
|
void put_state(std::vector<double>& o, const SmSurface* srf)
|
|
{
|
|
const SmBSplineSurface* s = SM_CAST_PTR(SmBSplineSurface, srf);
|
|
o.push_back(flg(s != NULL));
|
|
if (!s)
|
|
return;
|
|
const gw_SURFACE* sur = s->GetGwNurbPointer();
|
|
o.push_back(flg(sur != NULL));
|
|
o.push_back(flg(s->IsOutOfBoundsEnabled()));
|
|
o.push_back(flg(s->IsNurbBorrowed()));
|
|
o.push_back((double)(s->*Peek::kt()));
|
|
o.push_back((double)(s->*Peek::form()));
|
|
if (!sur)
|
|
return;
|
|
gw_INDEX n = sur->net->n;
|
|
gw_INDEX m = sur->net->m;
|
|
gw_INDEX r = sur->knu->m;
|
|
gw_INDEX ss = sur->knv->m;
|
|
o.push_back((double)n);
|
|
o.push_back((double)m);
|
|
o.push_back((double)sur->p);
|
|
o.push_back((double)sur->q);
|
|
o.push_back((double)r);
|
|
o.push_back((double)ss);
|
|
for (gw_INDEX i = 0; i <= n; i++)
|
|
for (gw_INDEX j = 0; j <= m; j++)
|
|
{
|
|
o.push_back(sur->net->Pw[i][j].x);
|
|
o.push_back(sur->net->Pw[i][j].y);
|
|
o.push_back(sur->net->Pw[i][j].z);
|
|
o.push_back(sur->net->Pw[i][j].w);
|
|
}
|
|
for (gw_INDEX i = 0; i <= r; i++)
|
|
o.push_back(sur->knu->U[i]);
|
|
for (gw_INDEX i = 0; i <= ss; i++)
|
|
o.push_back(sur->knv->U[i]);
|
|
}
|
|
|
|
// Reads `dim n p m cpts knots` into SmBSplineCurve(gw_CURVE*, dim, FALSE).
|
|
SmBSplineCurve* read_curve(Rd& rd, const SmContext& ctx)
|
|
{
|
|
ULONG dim = (ULONG)rd.idx();
|
|
gw_INDEX n = (gw_INDEX)rd.idx();
|
|
gw_DEGREE p = (gw_DEGREE)rd.idx();
|
|
gw_INDEX m = (gw_INDEX)rd.idx();
|
|
gw_CURVE* cur = sm_AllocateNurbCurve(n, p, m);
|
|
for (gw_INDEX i = 0; i <= n; i++)
|
|
{
|
|
cur->pol->Pw[i].x = rd.num();
|
|
cur->pol->Pw[i].y = rd.num();
|
|
cur->pol->Pw[i].z = rd.num();
|
|
cur->pol->Pw[i].w = rd.num();
|
|
}
|
|
for (gw_INDEX i = 0; i <= m; i++)
|
|
cur->knt->U[i] = rd.num();
|
|
return new (ctx) SmBSplineCurve(cur, dim, FALSE);
|
|
}
|
|
|
|
// `dim has [n p m cpts knots]`.
|
|
void put_curve(std::vector<double>& o, const SmBSplineCurve* c)
|
|
{
|
|
o.push_back((double)c->GetDim());
|
|
const gw_CURVE* cur = c->GetGwNurbPointer();
|
|
o.push_back(flg(cur != NULL));
|
|
if (!cur)
|
|
return;
|
|
gw_INDEX n = cur->pol->n;
|
|
gw_INDEX m = cur->knt->m;
|
|
o.push_back((double)n);
|
|
o.push_back((double)cur->p);
|
|
o.push_back((double)m);
|
|
for (gw_INDEX i = 0; i <= n; i++)
|
|
{
|
|
o.push_back(cur->pol->Pw[i].x);
|
|
o.push_back(cur->pol->Pw[i].y);
|
|
o.push_back(cur->pol->Pw[i].z);
|
|
o.push_back(cur->pol->Pw[i].w);
|
|
}
|
|
for (gw_INDEX i = 0; i <= m; i++)
|
|
o.push_back(cur->knt->U[i]);
|
|
}
|
|
|
|
std::vector<SmVector3d> read_vecs(Rd& rd, int64_t k)
|
|
{
|
|
std::vector<SmVector3d> v;
|
|
for (int64_t i = 0; i < k; i++)
|
|
v.push_back(rd.vec());
|
|
return v;
|
|
}
|
|
|
|
SmTArray<SmVector3d> to_tarray(const std::vector<SmVector3d>& v)
|
|
{
|
|
SmTArray<SmVector3d> a;
|
|
for (const SmVector3d& x : v)
|
|
a.Add(x);
|
|
return a;
|
|
}
|
|
|
|
void put_solutions(std::vector<double>& o, SmSolutionArray& sols)
|
|
{
|
|
o.push_back((double)sols.GetSize());
|
|
for (ULONG i = 0; i < sols.GetSize(); i++)
|
|
{
|
|
const SmSolution& s = sols[i];
|
|
o.push_back((double)s.m_lNumVariables);
|
|
o.push_back((double)s.m_eSolutionType);
|
|
o.push_back(s.m_vStart.m_dSolutionValue);
|
|
o.push_back(s.m_vStart[0]);
|
|
o.push_back(s.m_vStart[1]);
|
|
}
|
|
}
|
|
|
|
void put_doubles(std::vector<double>& o, const SmTArray<double>& a)
|
|
{
|
|
o.push_back((double)a.GetSize());
|
|
for (ULONG i = 0; i < a.GetSize(); i++)
|
|
o.push_back(a[i]);
|
|
}
|
|
|
|
void put_seval(std::vector<double>& o, SmSurfaceEval& e)
|
|
{
|
|
o.push_back(flg(e.*EvalPeek::uv_set() == TRUE));
|
|
o.push_back(flg(e.*EvalPeek::normal_set() == TRUE));
|
|
o.push_back(flg(e.*EvalPeek::sect_set() == TRUE));
|
|
o.push_back(flg(e.*EvalPeek::fails() == TRUE));
|
|
put2(o, e.GetUV());
|
|
}
|
|
|
|
void surface_op(int32_t op, Rd& rd, const SmContext& ctx, SmSurface* s, std::vector<double>& o)
|
|
{
|
|
switch (op)
|
|
{
|
|
case OP_EVAL:
|
|
{
|
|
SmPoint2d uv = rd.pt2();
|
|
ULONG hu = (ULONG)rd.idx();
|
|
ULONG hv = (ULONG)rd.idx();
|
|
bool ul = rd.flag();
|
|
bool vl = rd.flag();
|
|
bool upper = rd.flag();
|
|
bool nzt = rd.flag();
|
|
std::vector<SmVector3d> d((hu + 1) * (hv + 1), SmVector3d(0.0, 0.0, 0.0));
|
|
SmStatus stt = s->Evaluate(uv, hu, hv, ul ? TRUE : FALSE, vl ? TRUE : FALSE,
|
|
upper ? TRUE : FALSE, d.data(), nzt ? TRUE : FALSE);
|
|
o.push_back(st(stt));
|
|
if (stt == SM_SUCCESS)
|
|
for (ULONG i = 0; i <= hu; i++)
|
|
for (ULONG j = 0; j <= hv; j++)
|
|
if (!upper || i + j <= hu)
|
|
put_vec(o, d[i * (hv + 1) + j]);
|
|
break;
|
|
}
|
|
case OP_EVAL_PT:
|
|
{
|
|
SmPoint2d uv = rd.pt2();
|
|
SmPoint3d p;
|
|
SmStatus stt = s->EvaluatePoint(uv, p);
|
|
o.push_back(st(stt));
|
|
if (stt == SM_SUCCESS)
|
|
put_vec(o, p);
|
|
break;
|
|
}
|
|
case OP_QUERIES:
|
|
{
|
|
o.push_back(0.0);
|
|
put_dom(o, s->GetNaturalUVDomain());
|
|
put_dom(o, s->GetSTEPUVDomain());
|
|
o.push_back((double)s->GetDegree(SM_SP_U));
|
|
o.push_back((double)s->GetDegree(SM_SP_V));
|
|
o.push_back((double)s->GetNumberControlPoints(SM_SP_U));
|
|
o.push_back((double)s->GetNumberControlPoints(SM_SP_V));
|
|
o.push_back(flg(s->IsBilinear()));
|
|
o.push_back((double)s->GetType());
|
|
put_str(o, s->GetTypeString());
|
|
put_str(o, s->GetClassString());
|
|
const SM_TYPE types[] = {SmSurface_TYPE, SmBSplineSurface_TYPE, SmPlane_TYPE,
|
|
SmAObject_TYPE, SmObject_TYPE, SmCurve_TYPE,
|
|
SmCone_TYPE, SmTorus_TYPE};
|
|
for (SM_TYPE t : types)
|
|
o.push_back(flg(s->IsKindOf(t)));
|
|
break;
|
|
}
|
|
case OP_KNOTS:
|
|
{
|
|
SmSurfParamType dir = (SmSurfParamType)rd.idx();
|
|
bool has_ivl = rd.flag();
|
|
SmExtent1d ivl = rd.ivl();
|
|
SmTArray<double> knots;
|
|
SmTArray<ULONG> mults;
|
|
SmStatus stt = s->GetKnots(dir, knots, &mults, has_ivl ? &ivl : NULL);
|
|
o.push_back(st(stt));
|
|
if (stt == SM_SUCCESS)
|
|
{
|
|
put_doubles(o, knots);
|
|
o.push_back((double)mults.GetSize());
|
|
for (ULONG i = 0; i < mults.GetSize(); i++)
|
|
o.push_back((double)mults[i]);
|
|
}
|
|
break;
|
|
}
|
|
case OP_PARALLEL:
|
|
{
|
|
SmVector3d v = rd.vec();
|
|
o.push_back(0.0);
|
|
o.push_back(flg(s->IsParallelToVector(v)));
|
|
break;
|
|
}
|
|
case OP_REVERSE:
|
|
{
|
|
SmSurfParamType dir = (SmSurfParamType)rd.idx();
|
|
o.push_back(st(s->Reverse(dir)));
|
|
put_state(o, s);
|
|
break;
|
|
}
|
|
case OP_REPARAM:
|
|
{
|
|
SmExtent2d d = rd.domain();
|
|
o.push_back(st(s->Reparameterize(d)));
|
|
put_state(o, s);
|
|
break;
|
|
}
|
|
case OP_SWAP:
|
|
{
|
|
o.push_back(st(s->SwapUV()));
|
|
put_state(o, s);
|
|
break;
|
|
}
|
|
case OP_TRANSFORM:
|
|
{
|
|
SmVector3d org = rd.vec();
|
|
SmVector3d z = rd.vec();
|
|
SmVector3d x = rd.vec();
|
|
bool has_scale = rd.flag();
|
|
SmVector3d scale = rd.vec();
|
|
SmAxis2Placement ax(org, z, x);
|
|
o.push_back(st(s->Transform(ax, has_scale ? &scale : NULL)));
|
|
put_state(o, s);
|
|
break;
|
|
}
|
|
case OP_TRIM:
|
|
{
|
|
SmExtent2d d = rd.domain();
|
|
o.push_back(st(s->TrimWithDomain(d)));
|
|
put_dom(o, d);
|
|
put_state(o, s);
|
|
break;
|
|
}
|
|
case OP_SPLIT:
|
|
{
|
|
double t = rd.num();
|
|
SmSurfParamType dir = (SmSurfParamType)rd.idx();
|
|
SmSurface* l = NULL;
|
|
SmSurface* r = NULL;
|
|
SmStatus stt = s->SplitAt(ctx, t, dir, l, r);
|
|
o.push_back(st(stt));
|
|
if (stt == SM_SUCCESS)
|
|
{
|
|
put_state(o, l);
|
|
put_state(o, r);
|
|
}
|
|
delete l;
|
|
delete r;
|
|
break;
|
|
}
|
|
case OP_STEP_INV:
|
|
{
|
|
SmExtent2d d = rd.domain();
|
|
SmVector3d p = rd.vec();
|
|
double tol = rd.num();
|
|
bool has_guess = rd.flag();
|
|
SmPoint2d guess = rd.pt2();
|
|
SmPoint2d uv;
|
|
SmLocationType loc = SM_LT_EXTERIOR;
|
|
SmStatus stt = s->STEPInversion(d, p, tol, uv, loc, has_guess ? &guess : NULL);
|
|
o.push_back(st(stt));
|
|
if (stt == SM_SUCCESS)
|
|
{
|
|
put2(o, uv);
|
|
o.push_back((double)loc);
|
|
}
|
|
break;
|
|
}
|
|
case OP_ADJUST_STEP:
|
|
{
|
|
SmExtent2d d = rd.domain();
|
|
o.push_back(st(s->AdjustSTEPUVDomain(d)));
|
|
put_state(o, s);
|
|
break;
|
|
}
|
|
case OP_MAX_ANAL:
|
|
{
|
|
SmExtent2d d = s->GetMaxAnalyticDomain();
|
|
o.push_back(0.0);
|
|
put_dom(o, d);
|
|
break;
|
|
}
|
|
case OP_COPY:
|
|
case OP_COPY_ANAL:
|
|
{
|
|
SmSurface* c = NULL;
|
|
SmStatus stt = op == OP_COPY ? s->Copy(ctx, c) : s->CopyAndAddAnalytics(ctx, c);
|
|
o.push_back(st(stt));
|
|
if (stt == SM_SUCCESS)
|
|
{
|
|
o.push_back((double)c->GetType());
|
|
put_state(o, c);
|
|
}
|
|
delete c;
|
|
break;
|
|
}
|
|
case OP_DROP_FAST:
|
|
{
|
|
SmExtent2d d = rd.domain();
|
|
SmVector3d p = rd.vec();
|
|
SmSolutionArray sols;
|
|
SmStatus stt = s->DropPointFast(d, SM_SO_MINIMIZE, p, NULL, 1.0e-6, NULL, SM_SR_ALL, sols);
|
|
o.push_back(st(stt));
|
|
break;
|
|
}
|
|
case OP_CONVERT_UV:
|
|
{
|
|
SmPoint2d uv = rd.pt2();
|
|
SmPoint2d a, b;
|
|
SmStatus s1 = s->ConvertUVFromSTEPToNURBS(uv, a);
|
|
SmStatus s2 = s->ConvertUVFromNURBSToSTEP(uv, b);
|
|
o.push_back(st(s1 != SM_SUCCESS ? s1 : s2));
|
|
put2(o, a);
|
|
put2(o, b);
|
|
break;
|
|
}
|
|
case OP_SEVAL:
|
|
{
|
|
int32_t ctor = (int32_t)rd.idx();
|
|
double u0 = rd.num();
|
|
double v0 = rd.num();
|
|
SmVector3d dir0 = rd.vec();
|
|
SmSurfaceEval e0(s);
|
|
SmSurfaceEval e1(s, u0, v0);
|
|
SmSurfaceEval e2(s, u0, v0, dir0);
|
|
SmSurfaceEval e;
|
|
e = ctor == 0 ? e0 : ctor == 1 ? e1 : e2;
|
|
o.push_back(0.0);
|
|
put_seval(o, e);
|
|
int64_t k = rd.idx();
|
|
for (int64_t i = 0; i < k; i++)
|
|
{
|
|
int32_t kind = (int32_t)rd.idx();
|
|
double a = rd.num();
|
|
double b = rd.num();
|
|
double c = rd.num();
|
|
switch (kind)
|
|
{
|
|
case 0: e.SetUV(SmPoint2d(a, b)); break;
|
|
case 1: e.SetUV(a, b); break;
|
|
case 2: e.SetSectDir(SmVector3d(a, b, c)); break;
|
|
default:
|
|
{
|
|
bool fails = e.FailsEval(FALSE) == TRUE;
|
|
o.push_back(fails ? (double)SM_ERR : 0.0);
|
|
if (!fails)
|
|
for (int ii = 0; ii < 3; ii++)
|
|
for (int jj = 0; ii + jj <= 2; jj++)
|
|
put_vec(o, (e.*EvalPeek::pvv())[ii][jj]);
|
|
break;
|
|
}
|
|
}
|
|
put_seval(o, e);
|
|
}
|
|
break;
|
|
}
|
|
case OP_GSSI:
|
|
{
|
|
SmExtent2d d = rd.domain();
|
|
SmBSplineSurface* other = read_bspline(rd, ctx);
|
|
SmExtent2d d2 = rd.domain();
|
|
bool has_tol = rd.flag();
|
|
SmApproxTol3d tol = rd.num();
|
|
bool has_move = rd.flag();
|
|
SmVector3d move = rd.vec();
|
|
// prog_test my_test_one_ssi: both B-reps translated by the same vector first
|
|
if (has_move)
|
|
{
|
|
SmAxis2Placement ax;
|
|
ax.Translate(move);
|
|
SmStatus ts = s->Transform(ax, NULL);
|
|
if (ts == SM_SUCCESS)
|
|
ts = other->Transform(ax, NULL);
|
|
if (ts != SM_SUCCESS)
|
|
{
|
|
o.push_back(st(ts));
|
|
delete other;
|
|
break;
|
|
}
|
|
}
|
|
// all outputs requested, as smTopoTest my_test_ssi does
|
|
SmBoolean edges[2] = {TRUE, TRUE};
|
|
SmTArray<SmCurve*> c3, c1, c2;
|
|
SmTArray<SmTsectCurveType> types;
|
|
SmTArray<double> devs;
|
|
SmStatus stt = s->GlobalSurfaceIntersect(ctx, d, *other, d2, edges, has_tol ? &tol : NULL,
|
|
NULL, &c3, &c1, &c2, &types, &devs);
|
|
o.push_back(st(stt));
|
|
// on success: `n`, `same` (the output arrays agree in length) and per curve: 3D
|
|
// curve, UV curve on this, UV curve on other (each `GetType()`, `0` when null, then
|
|
// `put_curve` for a B-spline), type, deviation
|
|
if (stt == SM_SUCCESS)
|
|
{
|
|
ULONG n = c3.GetSize();
|
|
o.push_back((double)n);
|
|
bool same = c1.GetSize() == n && c2.GetSize() == n && types.GetSize() == n &&
|
|
devs.GetSize() == n;
|
|
o.push_back(flg(same));
|
|
for (ULONG i = 0; same && i < n; i++)
|
|
{
|
|
const SmCurve* cs[3] = {c3[i], c1[i], c2[i]};
|
|
for (const SmCurve* c : cs)
|
|
{
|
|
o.push_back(c != NULL ? (double)c->GetType() : 0.0);
|
|
if (c != NULL && c->IsKindOf(SmBSplineCurve_TYPE))
|
|
put_curve(o, (const SmBSplineCurve*)c);
|
|
}
|
|
o.push_back((double)types[i]);
|
|
o.push_back(devs[i]);
|
|
}
|
|
}
|
|
for (ULONG i = 0; i < c3.GetSize(); i++)
|
|
delete c3[i];
|
|
for (ULONG i = 0; i < c1.GetSize(); i++)
|
|
delete c1[i];
|
|
for (ULONG i = 0; i < c2.GetSize(); i++)
|
|
delete c2[i];
|
|
delete other;
|
|
break;
|
|
}
|
|
default: o.push_back((double)SC_ERR_ARG); break;
|
|
}
|
|
}
|
|
|
|
void static_op(int32_t op, Rd& rd, SmContext& ctx, std::vector<double>& o)
|
|
{
|
|
switch (op)
|
|
{
|
|
case OP_LIFT2:
|
|
{
|
|
SmVector3d v[7];
|
|
for (int i = 0; i < 7; i++)
|
|
v[i] = rd.vec();
|
|
o.push_back(0.0);
|
|
put_vec(o, smsurf_LiftSecondDerivative(v[0], v[1], v[2], v[3], v[4], v[5], v[6]));
|
|
break;
|
|
}
|
|
case OP_LIFT3:
|
|
{
|
|
SmVector3d v[12];
|
|
for (int i = 0; i < 12; i++)
|
|
v[i] = rd.vec();
|
|
o.push_back(0.0);
|
|
put_vec(o, smsurf_LiftThirdDerivative(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7],
|
|
v[8], v[9], v[10], v[11]));
|
|
break;
|
|
}
|
|
case OP_SCALE_STEP:
|
|
{
|
|
ULONG hu = (ULONG)rd.idx();
|
|
ULONG hv = (ULONG)rd.idx();
|
|
bool ua = rd.flag();
|
|
bool va = rd.flag();
|
|
std::vector<SmVector3d> d = read_vecs(rd, (int64_t)((hu + 1) * (hv + 1)));
|
|
smsurf_ScaleSTEPAngularDerivatives(d.data(), hu, hv, ua ? TRUE : FALSE, va ? TRUE : FALSE);
|
|
o.push_back(0.0);
|
|
for (const SmVector3d& x : d)
|
|
put_vec(o, x);
|
|
break;
|
|
}
|
|
case OP_GEOM:
|
|
{
|
|
SmVector3d e[3][3];
|
|
for (int i = 0; i < 3; i++)
|
|
for (int j = 0; j < 3; j++)
|
|
e[i][j] = rd.vec();
|
|
double k, h, k1, k2;
|
|
SmVector3d efg, lmn, v1, v2;
|
|
SmStatus stt = smsurf_EvaluateGeometric(e, k, h, k1, k2, efg, lmn, v1, v2);
|
|
o.push_back(st(stt));
|
|
if (stt == SM_SUCCESS)
|
|
{
|
|
o.push_back(k);
|
|
o.push_back(h);
|
|
o.push_back(k1);
|
|
o.push_back(k2);
|
|
put_vec(o, efg);
|
|
put_vec(o, lmn);
|
|
put_vec(o, v1);
|
|
put_vec(o, v2);
|
|
put_vec(o, e[1][0]);
|
|
put_vec(o, e[0][1]);
|
|
}
|
|
break;
|
|
}
|
|
case OP_POINT_TYPE:
|
|
{
|
|
SmVector3d n = rd.vec();
|
|
SmVector3d uu = rd.vec();
|
|
SmVector3d vv = rd.vec();
|
|
bool want_uu = rd.flag();
|
|
bool want_vv = rd.flag();
|
|
SmSurfaceSideType su = (SmSurfaceSideType)rd.idx();
|
|
SmSurfaceSideType sv = SM_SS_ON;
|
|
SmLocalSurfaceType t =
|
|
smsurf_ComputeSurfacePointType(n, uu, vv, want_uu ? &su : NULL, want_vv ? &sv : NULL);
|
|
o.push_back(0.0);
|
|
o.push_back((double)t);
|
|
o.push_back((double)su);
|
|
break;
|
|
}
|
|
case OP_DROP_VECS:
|
|
{
|
|
SmVector3d du = rd.vec();
|
|
SmVector3d dv = rd.vec();
|
|
int64_t k = rd.idx();
|
|
std::vector<SmVector3d> v = read_vecs(rd, k);
|
|
std::vector<SmVector2d> r((size_t)k + 1, SmVector2d(0.0, 0.0));
|
|
SmStatus stt = smsurf_DropVectors(du, dv, (ULONG)k, v.data(), r.data());
|
|
o.push_back(st(stt));
|
|
if (stt == SM_SUCCESS)
|
|
for (int64_t i = 0; i < k; i++)
|
|
put2(o, r[(size_t)i]);
|
|
break;
|
|
}
|
|
case OP_PARAM_DELTA:
|
|
{
|
|
SmVector3d t = rd.vec();
|
|
SmVector3d d = rd.vec();
|
|
o.push_back(0.0);
|
|
o.push_back(sc_srf_p2::sm_ConvertToParameterDelta(t, d));
|
|
break;
|
|
}
|
|
case OP_MERGE:
|
|
{
|
|
SmTArray<double> a, b, r;
|
|
int64_t na = rd.idx();
|
|
for (int64_t i = 0; i < na; i++)
|
|
a.Add(rd.num());
|
|
int64_t nb = rd.idx();
|
|
for (int64_t i = 0; i < nb; i++)
|
|
b.Add(rd.num());
|
|
SmStatus stt = sc_srf_p2::sm_MergeDoubleArrays(a, b, r);
|
|
o.push_back(st(stt));
|
|
put_doubles(o, r);
|
|
break;
|
|
}
|
|
case OP_MAP_UV:
|
|
{
|
|
double u = rd.num();
|
|
double v = rd.num();
|
|
SmOrientType ot = (SmOrientType)rd.idx();
|
|
double du = rd.num();
|
|
double dv = rd.num();
|
|
o.push_back(0.0);
|
|
put2(o, sc_srf_p2::s_MapUV(u, v, ot, du, dv));
|
|
break;
|
|
}
|
|
case OP_IS_EVEN:
|
|
{
|
|
int i = (int)rd.num();
|
|
o.push_back(0.0);
|
|
o.push_back(flg(sc_srf_p2::s_IsEven(i)));
|
|
break;
|
|
}
|
|
case OP_BREAKS:
|
|
{
|
|
SmExtent1d ivl = rd.ivl();
|
|
SmTArray<double> b;
|
|
int64_t n = rd.idx();
|
|
for (int64_t i = 0; i < n; i++)
|
|
b.Add(rd.num());
|
|
SmStatus stt = sc_srf_p2::sm_SetUpBreaks(b, ivl);
|
|
o.push_back(st(stt));
|
|
put_doubles(o, b);
|
|
break;
|
|
}
|
|
case OP_LIMITS:
|
|
{
|
|
SmVector3d p = rd.vec();
|
|
o.push_back(0.0);
|
|
o.push_back(SmSurface::GetDerivativeLimit(p));
|
|
o.push_back(SmSurface::GetNormalLimit());
|
|
break;
|
|
}
|
|
case OP_DERIV_ASSERT:
|
|
{
|
|
SmBSplineCurve dummy;
|
|
SmDerivSurfDefinition d;
|
|
d.m_lNumSamples = (ULONG)rd.idx();
|
|
d.m_eTangencyType = (SmTangencyType)rd.idx();
|
|
d.m_dStartDerivDirAngleDeg = rd.num();
|
|
d.m_dEndDerivDirAngleDeg = rd.num();
|
|
d.m_pTangentReference = rd.flag() ? &dummy : NULL;
|
|
d.m_dStartTanLength = rd.num();
|
|
d.m_dEndTanScale = rd.num();
|
|
d.m_dStartAngleDeg = rd.num();
|
|
d.m_dEndAngleDeg = rd.num();
|
|
d.m_vVector = rd.vec();
|
|
d.m_eCurvatureType = (SmCurvatureType)rd.idx();
|
|
d.m_eBlendEndType = (SmBlendEndType)rd.idx();
|
|
d.m_dStartRadius = rd.num();
|
|
d.m_dEndRadScale = rd.num();
|
|
d.m_pCurvatureReference = rd.flag() ? &dummy : NULL;
|
|
d.m_bFlipCurvature = rd.flag() ? TRUE : FALSE;
|
|
bool with_list = rd.flag();
|
|
SmAssertArray list;
|
|
SmBoolean ok = d.AssertValid(with_list ? &list : NULL);
|
|
o.push_back(0.0);
|
|
o.push_back(flg(ok == TRUE));
|
|
o.push_back((double)list.GetSize());
|
|
for (ULONG i = 0; i < list.GetSize(); i++)
|
|
{
|
|
const SmAssertReport* r = list[i];
|
|
o.push_back((double)r->GetTestIndex());
|
|
o.push_back((double)r->GetTol3d());
|
|
o.push_back(r->GetValue());
|
|
}
|
|
o.push_back(flg(d.IsFromSurfaceBoundaryCurve() == TRUE));
|
|
o.push_back((double)d.GetNumDerivs());
|
|
o.push_back((double)d.GetClassType());
|
|
put_str(o, d.GetClassString());
|
|
// the default constructor
|
|
SmDerivSurfDefinition def;
|
|
o.push_back((double)def.m_lNumSamples);
|
|
o.push_back((double)def.m_eTangencyType);
|
|
o.push_back((double)def.m_eCurvatureType);
|
|
o.push_back((double)def.m_eBlendEndType);
|
|
o.push_back(def.m_dStartTanLength);
|
|
o.push_back(def.m_dEndTanScale);
|
|
put_vec(o, def.m_vVector);
|
|
break;
|
|
}
|
|
case OP_CROSS:
|
|
case OP_CROSS_SKIN:
|
|
{
|
|
SmDerivSurfDefinition d;
|
|
int64_t n = rd.idx();
|
|
int64_t flags = rd.idx(); // bits: s2 s3 ep e1 e2 e3
|
|
std::vector<SmVector3d> sp = read_vecs(rd, n);
|
|
int64_t n1 = rd.idx();
|
|
std::vector<SmVector3d> s1 = read_vecs(rd, n1);
|
|
SmTArray<SmVector3d> asp = to_tarray(sp), as1 = to_tarray(s1);
|
|
SmTArray<SmVector3d> opt[6];
|
|
for (int b = 0; b < 6; b++)
|
|
if (flags & (1 << b))
|
|
{
|
|
int64_t k = rd.idx();
|
|
opt[b] = to_tarray(read_vecs(rd, k));
|
|
}
|
|
auto p = [&](int b) { return (flags & (1 << b)) ? &opt[b] : (SmTArray<SmVector3d>*)NULL; };
|
|
SmTArray<SmBSplineCurve*> secs;
|
|
SmStatus stt = d.CreateCrossSectionCurves(ctx, secs, asp, as1, p(0), p(1), p(2), p(3), p(4), p(5));
|
|
o.push_back(st(stt));
|
|
if (op == OP_CROSS)
|
|
{
|
|
if (stt == SM_SUCCESS)
|
|
{
|
|
o.push_back((double)secs.GetSize());
|
|
for (ULONG i = 0; i < secs.GetSize(); i++)
|
|
put_curve(o, secs[i]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// rails and skin parameters follow
|
|
SmTArray<double> params;
|
|
int64_t np = rd.idx();
|
|
for (int64_t i = 0; i < np; i++)
|
|
params.Add(rd.num());
|
|
SmBSplineCurve* r1 = read_curve(rd, ctx);
|
|
SmBSplineCurve* r2 = rd.flag() ? read_curve(rd, ctx) : NULL;
|
|
double tol = rd.num();
|
|
if (stt == SM_SUCCESS)
|
|
{
|
|
SmBSplineSurface* skin = NULL;
|
|
SmStatus s2 = d.SkinDerivSurface(ctx, skin, secs, params, *r1, r2, tol);
|
|
o.push_back(st(s2));
|
|
if (s2 == SM_SUCCESS)
|
|
put_state(o, skin);
|
|
delete skin;
|
|
}
|
|
delete r1;
|
|
delete r2;
|
|
}
|
|
for (ULONG i = 0; i < secs.GetSize(); i++)
|
|
delete secs[i];
|
|
break;
|
|
}
|
|
case OP_DCF:
|
|
{
|
|
SmDropCurveFail f;
|
|
o.push_back(0.0);
|
|
o.push_back(flg(f.IsUnInit() == TRUE));
|
|
SmStatus fs = (SmStatus)rd.idx();
|
|
ULONG from = (ULONG)rd.idx();
|
|
SmCreateUVTrimCurvePathType path = (SmCreateUVTrimCurvePathType)rd.idx();
|
|
bool has_ctx = rd.flag();
|
|
SmExtent2d dom = rd.domain();
|
|
SmExtent1d ivl = rd.ivl();
|
|
double tol = rd.num();
|
|
double a10 = rd.num();
|
|
double a11 = rd.num();
|
|
SmBoolean b13 = (SmBoolean)rd.idx();
|
|
SmBoolean b14 = (SmBoolean)rd.idx();
|
|
SmBoolean b15 = (SmBoolean)rd.idx();
|
|
SmBoolean b16 = (SmBoolean)rd.idx();
|
|
SmBoolean b17 = (SmBoolean)rd.idx();
|
|
double a18 = rd.num();
|
|
SmBoolean b19 = (SmBoolean)rd.idx();
|
|
SmBoolean b20 = (SmBoolean)rd.idx();
|
|
SmSurfParamType clos = (SmSurfParamType)rd.idx();
|
|
ULONG sing = (ULONG)rd.idx();
|
|
ULONG asing = (ULONG)rd.idx();
|
|
int64_t npp = rd.idx();
|
|
SmTArray<SmPoint3d> poles = to_tarray(read_vecs(rd, npp));
|
|
int64_t npn = rd.idx();
|
|
SmTArray<SmPoint3d> normals = to_tarray(read_vecs(rd, npn));
|
|
int64_t ncp = rd.idx();
|
|
SmTArray<SmPoint3d> poly = to_tarray(read_vecs(rd, ncp));
|
|
SmTArray<double> knots;
|
|
int64_t nk = rd.idx();
|
|
for (int64_t i = 0; i < nk; i++)
|
|
knots.Add(rd.num());
|
|
int64_t nc = rd.idx();
|
|
SmTArray<SmBSplineCurve*> uvs;
|
|
for (int64_t i = 0; i < nc; i++)
|
|
uvs.Add(read_curve(rd, ctx));
|
|
f.Set(fs, from, path, has_ctx ? &ctx : NULL, dom, NULL, NULL, ivl, tol, a10, a11, NULL, b13,
|
|
b14, b15, b16, b17, a18, b19, b20, clos, &poles, &normals, sing, asing, NULL, &poly,
|
|
&knots, &uvs, NULL);
|
|
auto dump = [&](const SmDropCurveFail& g) {
|
|
o.push_back((double)g.m_sFailStatus);
|
|
o.push_back((double)g.m_lFromCall);
|
|
o.push_back((double)g.m_eCreatePathType);
|
|
o.push_back(flg(g.m_cpContext != NULL));
|
|
put_dom(o, g.m_sUVDomain);
|
|
o.push_back(g.m_sInterval.GetMin());
|
|
o.push_back(g.m_sInterval.GetMax());
|
|
o.push_back((double)g.m_sApproxTol3d);
|
|
o.push_back(g.m_dMaxDropToSurfArg);
|
|
o.push_back(g.m_dMaxApproxDev);
|
|
o.push_back((double)g.m_bKeepAllDropCurves);
|
|
o.push_back((double)g.m_bDegenCurve);
|
|
o.push_back((double)g.m_bDegenSurfU);
|
|
o.push_back((double)g.m_bDegenSurfV);
|
|
o.push_back((double)g.m_bDropDomainIsContained);
|
|
o.push_back(g.m_dMaxDropToSurf);
|
|
o.push_back((double)g.m_sSolutions.GetSize());
|
|
o.push_back((double)g.m_sUVCurves.GetSize());
|
|
for (ULONG i = 0; i < g.m_sUVCurves.GetSize(); i++)
|
|
put_curve(o, g.m_sUVCurves[i]);
|
|
o.push_back((double)g.m_bClosedU);
|
|
o.push_back((double)g.m_bClosedV);
|
|
o.push_back((double)g.m_eSrfClosure);
|
|
o.push_back((double)g.m_sSrfPolePoints.GetSize());
|
|
for (ULONG i = 0; i < g.m_sSrfPolePoints.GetSize(); i++)
|
|
put_vec(o, g.m_sSrfPolePoints[i]);
|
|
o.push_back((double)g.m_sSrfPoleNormals.GetSize());
|
|
for (ULONG i = 0; i < g.m_sSrfPoleNormals.GetSize(); i++)
|
|
put_vec(o, g.m_sSrfPoleNormals[i]);
|
|
o.push_back((double)g.m_lSingularities);
|
|
o.push_back((double)g.m_lApproxSingularities);
|
|
o.push_back((double)g.m_sCtrlPoly.GetSize());
|
|
for (ULONG i = 0; i < g.m_sCtrlPoly.GetSize(); i++)
|
|
put_vec(o, g.m_sCtrlPoly[i]);
|
|
o.push_back((double)g.m_sKnots.GetSize());
|
|
for (ULONG i = 0; i < g.m_sKnots.GetSize(); i++)
|
|
o.push_back(g.m_sKnots[i]);
|
|
};
|
|
o.push_back(flg(f.IsUnInit() == TRUE));
|
|
dump(f);
|
|
SmDropCurveFail g;
|
|
g = f;
|
|
dump(g);
|
|
f.UnInit();
|
|
o.push_back(flg(f.IsUnInit() == TRUE));
|
|
dump(f);
|
|
for (ULONG i = 0; i < uvs.GetSize(); i++)
|
|
delete uvs[i];
|
|
break;
|
|
}
|
|
case OP_CC_LOCAL:
|
|
{
|
|
SmBSplineCurve* c1 = read_curve(rd, ctx);
|
|
SmExtent1d i1 = rd.ivl();
|
|
SmContinuityType k1[2];
|
|
k1[0] = (SmContinuityType)rd.idx();
|
|
k1[1] = (SmContinuityType)rd.idx();
|
|
SmBSplineCurve* c2 = read_curve(rd, ctx);
|
|
SmExtent1d i2 = rd.ivl();
|
|
SmContinuityType k2[2];
|
|
k2[0] = (SmContinuityType)rd.idx();
|
|
k2[1] = (SmContinuityType)rd.idx();
|
|
SmSolverOperationType sop = (SmSolverOperationType)rd.idx();
|
|
double tol = rd.num();
|
|
SmSolutionArray sols;
|
|
SmStatus stt = sc_srf_p2::sm_CCLocalSolve(*c1, i1, k1, *c2, i2, k2, sop, tol, sols);
|
|
o.push_back(st(stt));
|
|
if (stt == SM_SUCCESS)
|
|
put_solutions(o, sols);
|
|
delete c1;
|
|
delete c2;
|
|
break;
|
|
}
|
|
case OP_ISECT_SPLIT:
|
|
{
|
|
SmBSplineCurve* c = read_curve(rd, ctx);
|
|
SmExtent1d ivl = rd.ivl();
|
|
SmVector3d pp = rd.vec();
|
|
SmVector3d pn = rd.vec();
|
|
SmTArray<double> sp;
|
|
int64_t n = rd.idx();
|
|
for (int64_t i = 0; i < n; i++)
|
|
sp.Add(rd.num());
|
|
SmStatus stt = sc_srf_p2::sm_IntersectAndSplit(*c, ivl, pp, pn, sp);
|
|
o.push_back(st(stt));
|
|
if (stt == SM_SUCCESS)
|
|
put_doubles(o, sp);
|
|
delete c;
|
|
break;
|
|
}
|
|
case OP_ISECT_CURVE_SPLIT:
|
|
{
|
|
SmBSplineCurve* c = read_curve(rd, ctx);
|
|
SmExtent1d ivl = rd.ivl();
|
|
SmVector3d lp = rd.vec();
|
|
SmVector3d lv = rd.vec();
|
|
SmExtent1d livl = rd.ivl();
|
|
double sz = rd.num();
|
|
SmTArray<double> sp;
|
|
int64_t n = rd.idx();
|
|
for (int64_t i = 0; i < n; i++)
|
|
sp.Add(rd.num());
|
|
SmLine* line = new (ctx) SmLine(lp, lv, livl, 1.0, 2, &ctx, NULL, FALSE);
|
|
SmStatus stt = sc_srf_p2::sm_IntersectCurveAndSplit(*c, ivl, *line, livl, sz, sp);
|
|
o.push_back(st(stt));
|
|
if (stt == SM_SUCCESS)
|
|
put_doubles(o, sp);
|
|
delete line;
|
|
delete c;
|
|
break;
|
|
}
|
|
case OP_LSI:
|
|
{
|
|
SmExtent3d box = rd.box();
|
|
SmVector3d lp = rd.vec();
|
|
SmVector3d lv = rd.vec();
|
|
bool has_ivl = rd.flag();
|
|
SmExtent1d ivl = rd.ivl();
|
|
bool ray = rd.flag();
|
|
double tol = rd.num();
|
|
SmTree tree((SmObject*)NULL);
|
|
SmTreeNode node;
|
|
node.m_sBBox = box;
|
|
node.m_pTree = &tree;
|
|
SmExtent2d dom(0.0, 0.0, 1.0, 1.0);
|
|
sc_srf_p2::SmLSIGlobalSolver gs(&tree, dom, lp, lv, has_ivl ? &ivl : NULL,
|
|
ray ? TRUE : FALSE, tol);
|
|
SmTreeNode* branch[SM_GS_MAX_TREES] = {&node};
|
|
SmBoolean r = gs.BranchMayContainAnswers(branch);
|
|
o.push_back(0.0);
|
|
o.push_back(flg(r == TRUE));
|
|
break;
|
|
}
|
|
case OP_CS_PERPEN:
|
|
{
|
|
SmAuxDataType ca = (SmAuxDataType)rd.idx();
|
|
SmExtent3d cb = rd.box();
|
|
SmAuxDataType sa = (SmAuxDataType)rd.idx();
|
|
SmExtent3d sb = rd.box();
|
|
SmTreeNode cn, sn;
|
|
cn.m_eAuxDataType = ca;
|
|
cn.m_sBBox = cb;
|
|
sn.m_eAuxDataType = sa;
|
|
sn.m_sBBox = sb;
|
|
SmBoolean r = sc_srf_p2::sm_CsArePerpenDisjoint(cn, sn);
|
|
o.push_back(0.0);
|
|
o.push_back(flg(r == TRUE));
|
|
break;
|
|
}
|
|
case OP_PLANE_3D:
|
|
{
|
|
int64_t k = rd.idx();
|
|
SmTArray<SmCurve*> crvs;
|
|
for (int64_t i = 0; i < k; i++)
|
|
crvs.Add(read_curve(rd, ctx));
|
|
double tol = rd.num();
|
|
SmSurface* plane = NULL;
|
|
SmTArray<ULONG> counts;
|
|
SmTArray<SmCurve*> ordered;
|
|
SmTArray<SmOrientType> orients;
|
|
SmTArray<ULONG> outer;
|
|
SmStatus stt = SmSurface::CreatePlaneWith3DCurves(ctx, crvs, tol, plane, counts, ordered,
|
|
orients, &outer);
|
|
o.push_back(st(stt));
|
|
delete plane;
|
|
for (ULONG i = 0; i < crvs.GetSize(); i++)
|
|
delete crvs[i];
|
|
break;
|
|
}
|
|
case OP_READ_DB:
|
|
{
|
|
SM_TYPE type = (SM_TYPE)rd.idx();
|
|
int32_t file_type = (int32_t)rd.idx();
|
|
ULONG version = (ULONG)rd.idx();
|
|
int64_t nb = rd.idx();
|
|
std::string bytes;
|
|
for (int64_t i = 0; i < nb; i++)
|
|
bytes.push_back((char)(unsigned char)rd.idx());
|
|
std::istringstream iss(bytes);
|
|
SmDatabaseIOStream db(file_type == 0 ? SM_ASCII : SM_BINARY, &iss);
|
|
SmSurface* s = NULL;
|
|
SmStatus stt = SmSurface::ReadFromDB(type, db, ctx, s, version);
|
|
o.push_back(st(stt));
|
|
if (stt == SM_SUCCESS && s)
|
|
put_state(o, s);
|
|
delete s;
|
|
break;
|
|
}
|
|
default: o.push_back((double)SC_ERR_ARG); break;
|
|
}
|
|
}
|
|
} // namespace
|
|
|
|
// The planar generator flag line of an ASCII SmSurfOfRevolution record (its value first).
|
|
const char* const PLANAR_LINE = "1 SmSurfOfRevolution Planar Generator Curve";
|
|
|
|
// A revolution record block `kind O X Y a b c swap inside non_planar`: SmTorus::CreateCanonical
|
|
// (kind 0: major a, minor b) or SmCone::CreateCanonical (kind 1: bot a, top b, height c),
|
|
// WriteToDB to an ASCII stream, the planar generator flag cleared in the record when
|
|
// non_planar is set (the way SmTorus/SmCone::ReadFromDB get a non-planar generator), then
|
|
// SmSurface::ReadFromDB. On failure writes the status and returns NULL.
|
|
static SmSurface* read_revolution(Rd& rd, const SmContext& ctx, std::vector<double>& o)
|
|
{
|
|
int64_t kind = rd.idx();
|
|
SmPoint3d org = rd.vec();
|
|
SmVector3d x = rd.vec();
|
|
SmVector3d y = rd.vec();
|
|
double a = rd.num();
|
|
double b = rd.num();
|
|
double c = rd.num();
|
|
SmBoolean swap = rd.flag() ? TRUE : FALSE;
|
|
SmBoolean inside = rd.flag() ? TRUE : FALSE;
|
|
bool non_planar = rd.flag();
|
|
SmAxis2Placement a2p(org, x, y);
|
|
SmSurface* made = NULL;
|
|
SM_TYPE type = SmTorus_TYPE;
|
|
SmStatus stt = SM_SUCCESS;
|
|
if (kind == 0)
|
|
{
|
|
SmTorus* t = NULL;
|
|
stt = SmTorus::CreateCanonical(ctx, a2p, a, b, t, swap, inside);
|
|
made = t;
|
|
}
|
|
else
|
|
{
|
|
SmCone* cn = NULL;
|
|
stt = SmCone::CreateCanonical(ctx, a2p, a, b, c, cn, swap, inside);
|
|
made = cn;
|
|
type = SmCone_TYPE;
|
|
}
|
|
if (stt != SM_SUCCESS || made == NULL)
|
|
{
|
|
o.push_back(st(stt == SM_SUCCESS ? SM_ERR : stt));
|
|
delete made;
|
|
return NULL;
|
|
}
|
|
// the format SmDatabaseIOFile::OpenFileForWrite sets for an ASCII file (a stream the
|
|
// caller passes in keeps the stream's own 6-digit default)
|
|
std::ostringstream oss;
|
|
oss.setf(std::ios::fixed);
|
|
oss.precision(16);
|
|
SmDatabaseIOStream writer(SM_ASCII, &oss);
|
|
stt = made->WriteToDB(writer, 30);
|
|
delete made;
|
|
if (stt != SM_SUCCESS)
|
|
{
|
|
o.push_back(st(stt));
|
|
return NULL;
|
|
}
|
|
std::string text = oss.str();
|
|
if (non_planar)
|
|
{
|
|
size_t at = text.find(PLANAR_LINE);
|
|
if (at == std::string::npos)
|
|
{
|
|
o.push_back((double)SC_ERR_ARG);
|
|
return NULL;
|
|
}
|
|
text[at] = '0';
|
|
}
|
|
std::istringstream iss(text);
|
|
SmDatabaseIOStream reader(SM_ASCII, &iss);
|
|
SmSurface* s = NULL;
|
|
stt = SmSurface::ReadFromDB(type, reader, ctx, s, 30);
|
|
if (stt != SM_SUCCESS || s == NULL)
|
|
{
|
|
o.push_back(st(stt == SM_SUCCESS ? SM_ERR : stt));
|
|
delete s;
|
|
return NULL;
|
|
}
|
|
return s;
|
|
}
|
|
|
|
SC_EXPORT int32_t sc_surface_surface_p2_eval(int32_t op, const double* in, int64_t n_in, double* out,
|
|
int64_t cap, int64_t* out_len)
|
|
{
|
|
(void)n_in;
|
|
SC_TRY
|
|
SmContext ctx;
|
|
std::vector<double> o;
|
|
Rd rd{in, 0};
|
|
int32_t ctor = (int32_t)rd.idx();
|
|
if (ctor == CT_NONE)
|
|
{
|
|
static_op(op, rd, ctx, o);
|
|
}
|
|
else
|
|
{
|
|
SmSurface* s = NULL;
|
|
if (ctor == CT_BASE)
|
|
s = new (ctx) SmSurface();
|
|
else if (ctor == CT_BSPLINE)
|
|
s = read_bspline(rd, ctx);
|
|
else if (ctor == CT_REVOLUTION)
|
|
{
|
|
s = read_revolution(rd, ctx, o);
|
|
if (s == NULL)
|
|
return sc_copy_out(o.data(), (int64_t)o.size(), out, cap, out_len);
|
|
}
|
|
else
|
|
return SC_ERR_ARG;
|
|
surface_op(op, rd, ctx, s, o);
|
|
delete s;
|
|
}
|
|
return sc_copy_out(o.data(), (int64_t)o.size(), out, cap, out_len);
|
|
SC_CATCH
|
|
}
|