// SPDX-License-Identifier: Apache-2.0 // Unit surface.surface_p9. Calls the pinned SmSurface methods and the file-local // SmCSIGlobalSolver class (declaration reproduced from SmSurface.cpp:13781). #include "sc_shim.h" #include "StdAfx.h" #include #include #include #include #include #include #include #include #include #include #include #include class SmCSIGlobalSolver : public SmGlobalSolver { public: const SmSurface* m_pSurf; SmBoolean m_bFoundCoincidence; const SmExtent1d& m_crInterval; const SmExtent2d& m_crUVDomain; SmCSIGlobalSolver(SmTree*, SmTree*, SmBoolean, const SmExtent1d&, const SmExtent2d&); virtual SmStatus LocalSolve(SmTreeNode* [SM_GS_MAX_TREES], SmBoolean&); virtual SmSolutionPairType IdenticalSolutions(const SmSolution&, const SmSolution&, const SmSolution*&) const; }; // The reference constructor is protected; expose it without changing its body. class ScP9Revolution : public SmSurfOfRevolution { public: explicit ScP9Revolution(SmBSplineCurve* generator) : SmSurfOfRevolution(generator, SmPoint3d(0,0,0), SmVector3d(1,0,0), SmVector3d(0,1,0), SmExtent2d(0,0,360,1), FALSE) {} }; SC_EXPORT int32_t sc_surface_surface_p9_eval(int32_t op, int32_t surface_kind, const double* xyz, const double* bounds, int32_t direction, double chord, double angle, double max_side, int32_t diagonals, const double* line, double* output, int64_t cap, int64_t* out_len) { SC_TRY SmContext context; gw_CPOINT points[3][3]; gw_CPOINT* rows[3] = {points[0],points[1],points[2]}; for (int i=0;i<3;i++) for(int j=0;j<3;j++) { auto& p=points[i][j]; const int at=3*(3*i+j); p.x=xyz[at];p.y=xyz[at+1];p.z=xyz[at+2];p.w=NL_NOW; } double knots[6]={0,0,0,1,1,1}; SmSurface* surface = NULL; if (surface_kind == 2) { gw_CPOINT cp[2]={{1,0,0,NL_NOW},{1,0,1,NL_NOW}}; double ck[4]={0,0,1,1}; SmBSplineCurve* generator = new(context) SmBSplineCurve(3,1,3,1,cp,ck); ScP9Revolution* revolution = new(context) ScP9Revolution(generator); if (revolution->MakeNurb() != SM_SUCCESS) { delete revolution; return SC_ERR_ARG; } surface = revolution; } else if (surface_kind == 1) { surface = new(context) SmPlane(SmPoint3d(0,0,0), SmVector3d(1,0,0), SmVector3d(0,1,0), SmVector2d(1,1), SmExtent2d(0,0,1,1), &context); } else { surface = new(context) SmBSplineSurface(2,2,2,2,5,5,rows,knots,knots); } SmExtent2d domain(bounds[0],bounds[1],bounds[2],bounds[3]); std::vector out; auto status=[](SmStatus r){return r==SM_SUCCESS ? 0.0 : (double)r;}; if(op==0) { // All six sampled isos degenerate => dMaxLength stays -1. For 0 < // max_side < 1 the negative count converted to ULONG is undefined. // Test the actual C++ curves; poles or short endpoints alone are valid. if (max_side > 0.0 && max_side < 1.0) { bool all_degenerate = true; for (int i = 0; i <= 5; ++i) { const SmPoint2d uv = domain.Evaluate((double)i / 5.0, (double)i / 5.0); SmBSplineCurve* iso = NULL; const SmStatus r = surface->CreateIsoParametricCurve(context, (SmSurfParamType)direction, direction == SM_SP_V ? uv.y : uv.x, max_side / 100.0, iso); if (r != SM_SUCCESS || !iso) { delete iso; delete surface; return SC_ERR_ARG; } const bool degenerate = iso->IsDegenerate() == TRUE; delete iso; if (!degenerate) { all_degenerate = false; break; } } if (all_degenerate) { delete surface; return SC_ERR_ARG; } } SmTArray splits; SmStatus r=surface->FindTessellationSplits((SmSurfParamType)direction,domain,chord,angle,max_side,splits,diagonals?TRUE:FALSE); out.push_back(status(r)); if(r==SM_SUCCESS) for(ULONG i=0;iCreateIsoBoundaries(context,(SmSurfParamType)direction,SmApproxTol3d(chord),a,b); out.push_back(status(r)); if(r==SM_SUCCESS) { out.push_back((a?1.0:0.0)+(b?1.0:0.0)); for(auto curve:{a,b}) if(curve) for(int i=0;i<=4;i++) { SmPoint3d p; SmStatus er=curve->EvaluatePoint(curve->GetNaturalInterval().Evaluate((double)i/4.0),p); if(er!=SM_SUCCESS) { delete a;delete b;delete surface;return SC_ERR_ARG; } out.push_back(p.x);out.push_back(p.y);out.push_back(p.z); } } delete a;delete b; } else if(op==2) { gw_CPOINT cp[2]={{line[0],line[1],line[2],NL_NOW},{line[3],line[4],line[5],NL_NOW}}; double ck[4]={0,0,1,1}; SmBSplineCurve* curve=new(context) SmBSplineCurve(3,1,3,1,cp,ck); bool setup_failed=false; { SmExtent1d interval(0.0,1.0); SmCurveCache cc(*curve,interval,TRUE,0.01); SmSurfaceCache sc(*surface,surface->GetNaturalUVDomain(),0.01); SmStatus r=cc.Tessellate(); if(r==SM_SUCCESS) r=sc.BuildTree(NULL); if(r==SM_SUCCESS) { SmCSIGlobalSolver solver(cc.GetTree(),sc.GetTree(),FALSE,interval,domain); SmSolutionArray solutions;solver.SetSolutions(&solutions); solver.SetSolverOperation(SM_SO_INTERSECT);solver.Set3DTolerance(1e-6);solver.SetSolutionRequested(SM_SR_ALL); SmTreeNode* branch[SM_GS_MAX_TREES]={cc.GetTree()->GetFirstLeafNode(),sc.GetTree()->GetFirstLeafNode(),NULL}; SmBoolean more=FALSE;r=solver.LocalSolve(branch,more); out.push_back(status(r)); if(r==SM_SUCCESS) { out.push_back(more==TRUE?1.0:0.0);out.push_back((double)solutions.GetSize()); for(ULONG i=0;i