mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-08 13:01:52 +00:00
875291c4d9
125 shims carried private copies of the same small helpers (put_vec, st, nl_status, Rd, dump_crv, read_nurb, ...). Move the most common, byte-identical form of each into three headers grouped by the upstream API they need, and have those shims pull them in with `using sc::<name>;`. Shims with a different variant keep their own copy; files touched by open PRs are left alone. `the_context()` stays per shim (its function-local SmContext must not be shared). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FBLgPenT24P1dunqnZR1Dj
610 lines
19 KiB
C++
610 lines
19 KiB
C++
// SPDX-License-Identifier: Apache-2.0
|
|
// difftest shim for unit `intersect.surface_drop_lib_p2`: SmDropPt::SetProperties and
|
|
// SmDropPt::GetNextPoint (the file-local class SmDropPt) and the static helpers
|
|
// sm_AddToCurve and sm_FlushCrv of upstream source/SMLib/src/SmSurfaceDropLib.cpp, on real
|
|
// SmPlane, SmBSplineSurface and SmSurfOfRevolution surfaces and SmLine, SmCircle and
|
|
// SmBSplineCurve curves, with the SmOffsetSurface(d, surface, FALSE, lSingularities) that
|
|
// DropCurve builds.
|
|
//
|
|
// SmDropPt and the helpers are local to that file, so this translation unit compiles the
|
|
// upstream source itself (same flags as the kernel), at global scope, as the p1 shim does:
|
|
// * every header the file includes is included first, so its own #includes are no-ops;
|
|
// * SmSurface::DropCurve / DropAndTrimCurve / DropIsoCurve (which the file defines) are
|
|
// renamed before any header is read, so this TU's definitions get new names;
|
|
// * SmDropPt and my_AssertAndDrawDropCurve are renamed so they cannot clash with the
|
|
// library's (or the p1 shim's) copies.
|
|
//
|
|
// One entry point, sc_intersect_surface_drop_lib_p2_run(in, n_in, out, cap, out_len): one
|
|
// op per call. The layouts are documented in
|
|
// crates/solidcore-ffi/src/units/intersect_surface_drop_lib_p2.rs, which validates the
|
|
// inputs; every read here is bounds checked as well (a bad program is SC_ERR_ARG). Inputs
|
|
// that reach a path upstream leaves undefined (GetNextPoint's ignored start evaluation
|
|
// status) report REJECTED.
|
|
#define DropCurve sc_sdl2_DropCurve
|
|
#define DropAndTrimCurve sc_sdl2_DropAndTrimCurve
|
|
#define DropIsoCurve sc_sdl2_DropIsoCurve
|
|
|
|
#include "sc_shim.h"
|
|
|
|
#include "StdAfx.h"
|
|
#include <SmAssertArray.h>
|
|
#include <SmBSplineCurve.h>
|
|
#include <SmBSplineSurface.h>
|
|
#include <SmBrep.h>
|
|
#include <SmCircle.h>
|
|
#include <SmCompositeCurve.h>
|
|
#include <SmContext.h>
|
|
#include <SmCrvOnSurf.h>
|
|
#include <SmCurveCache.h>
|
|
#include <SmEdge.h>
|
|
#include <SmExtent1d.h>
|
|
#include <SmExtent2d.h>
|
|
#include <SmFace.h>
|
|
#include <SmGauss.h>
|
|
#include <SmGeomUtility.h>
|
|
#include <SmGlobalSolver.h>
|
|
#include <SmGraphicsOutput.h>
|
|
#include <SmHermiteCurve.h>
|
|
#include <SmLine.h>
|
|
#include <SmLocalSolve1d.h>
|
|
#include <SmLocalSolveNd.h>
|
|
#include <SmNurbsCrv.h>
|
|
#include <SmNurbsSrf.h>
|
|
#include <SmOffsetSurface.h>
|
|
#include <SmPlane.h>
|
|
#include <SmSolutionArray.h>
|
|
#include <SmSurfOfRevolution.h>
|
|
#include <SmSurface.h>
|
|
#include <SmSurfaceDropCurve.h>
|
|
#include <SmTArray.h>
|
|
#include <SmVector2d.h>
|
|
#include <SmVector3d.h>
|
|
#include <nurbs.h>
|
|
|
|
#include <stdexcept>
|
|
#include <vector>
|
|
|
|
#define SmDropPt sc_sdl2_SmDropPt
|
|
#define my_AssertAndDrawDropCurve sc_sdl2_my_AssertAndDrawDropCurve
|
|
#include "../../../upstream/source/SMLib/src/SmSurfaceDropLib.cpp"
|
|
|
|
#include "sc_sm.h"
|
|
|
|
using sc::put_uv;
|
|
using sc::put_vec;
|
|
using sc::st;
|
|
|
|
namespace sc_sdl2
|
|
{
|
|
enum
|
|
{
|
|
OP_SET = 1,
|
|
OP_NEXT = 2,
|
|
OP_ADD = 3,
|
|
OP_FLUSH = 4,
|
|
};
|
|
|
|
// Op status of an op the shim does not run (undefined upstream).
|
|
const double REJECTED = -2.0;
|
|
// Record of an op whose surface of revolution could not be made.
|
|
const double NO_SURFACE = -3.0;
|
|
|
|
struct Bad : std::runtime_error
|
|
{
|
|
Bad() : std::runtime_error("bad program") {}
|
|
};
|
|
|
|
struct Rd
|
|
{
|
|
const double* in;
|
|
int64_t n;
|
|
int64_t at;
|
|
double num()
|
|
{
|
|
if (at >= n)
|
|
throw Bad();
|
|
return in[at++];
|
|
}
|
|
int64_t idx(int64_t lo, int64_t hi)
|
|
{
|
|
double d = num();
|
|
if (!(d >= (double)lo && d <= (double)hi) || d != (double)(int64_t)d)
|
|
throw Bad();
|
|
return (int64_t)d;
|
|
}
|
|
SmVector3d vec()
|
|
{
|
|
double x = num();
|
|
double y = num();
|
|
double z = num();
|
|
return SmVector3d(x, y, z);
|
|
}
|
|
SmPoint2d uv()
|
|
{
|
|
double x = num();
|
|
double y = num();
|
|
return SmPoint2d(x, y);
|
|
}
|
|
SmExtent2d dom4()
|
|
{
|
|
double a = num();
|
|
double b = num();
|
|
double c = num();
|
|
double d = num();
|
|
return SmExtent2d(a, b, c, d);
|
|
}
|
|
};
|
|
|
|
// Objects made for one op; deleted on every return.
|
|
struct Owned
|
|
{
|
|
std::vector<SmSurface*> surfaces;
|
|
std::vector<SmCurve*> curves;
|
|
~Owned()
|
|
{
|
|
for (size_t i = 0; i < curves.size(); i++)
|
|
delete curves[i];
|
|
for (size_t i = 0; i < surfaces.size(); i++)
|
|
delete surfaces[i];
|
|
}
|
|
};
|
|
|
|
// `0 a[3] b[3]` SmLine (its NURB made), `1 c[3] x[3] y[3] d0 d1 r` SmCircle, or
|
|
// `2 p ncp cpts(x y z w) knots` SmBSplineCurve (dim 3).
|
|
SmCurve* read_curve(Rd& rd, const SmContext& ctx, Owned& own)
|
|
{
|
|
int64_t kind = rd.idx(0, 2);
|
|
if (kind == 0)
|
|
{
|
|
SmPoint3d a = rd.vec();
|
|
SmPoint3d b = rd.vec();
|
|
SmLine* l = new (ctx) SmLine(a, b, 3, &ctx);
|
|
own.curves.push_back(l);
|
|
l->GetOrCreateGwNurbPointer();
|
|
return l;
|
|
}
|
|
if (kind == 1)
|
|
{
|
|
SmPoint3d c = rd.vec();
|
|
SmVector3d x = rd.vec();
|
|
SmVector3d y = rd.vec();
|
|
double d0 = rd.num();
|
|
double d1 = rd.num();
|
|
double r = rd.num();
|
|
SmCircle* cc = new (ctx) SmCircle(c, x, y, SmExtent1d(d0, d1), r, 3, &ctx);
|
|
own.curves.push_back(cc);
|
|
return cc;
|
|
}
|
|
int64_t p = rd.idx(1, 8);
|
|
int64_t ncp = rd.idx(2, 64);
|
|
if (p >= ncp)
|
|
throw Bad();
|
|
int64_t n = ncp - 1;
|
|
int64_t m = n + p + 1;
|
|
std::vector<double> v;
|
|
for (int64_t i = 0; i < 4 * ncp + m + 1; i++)
|
|
v.push_back(rd.num());
|
|
gw_CURVE* cur = sm_AllocateNurbCurve((gw_INDEX)n, (gw_DEGREE)p, (gw_INDEX)m);
|
|
for (int64_t i = 0; i <= n; i++)
|
|
{
|
|
cur->pol->Pw[i].x = v[4 * i];
|
|
cur->pol->Pw[i].y = v[4 * i + 1];
|
|
cur->pol->Pw[i].z = v[4 * i + 2];
|
|
cur->pol->Pw[i].w = v[4 * i + 3];
|
|
}
|
|
for (int64_t i = 0; i <= m; i++)
|
|
cur->knt->U[i] = v[4 * ncp + i];
|
|
SmBSplineCurve* c = new (ctx) SmBSplineCurve(cur, 3, FALSE);
|
|
own.curves.push_back(c);
|
|
return c;
|
|
}
|
|
|
|
// `0 o x y scale dom` SmPlane (with its NURB made), `1 p q nu nv net(x y z w) u v` SmBSplineSurface, or
|
|
// `2 gen point[3] axis[3] swap` SmSurfOfRevolution::CreateCanonical with the generator a
|
|
// line `0 a b` or a circle `1 c x y d0 d1 r` (see read_curve). NULL when CreateCanonical
|
|
// fails.
|
|
SmSurface* read_surface(Rd& rd, const SmContext& ctx, Owned& own)
|
|
{
|
|
int64_t kind = rd.idx(0, 2);
|
|
if (kind == 0)
|
|
{
|
|
SmPoint3d o = rd.vec();
|
|
SmVector3d x = rd.vec();
|
|
SmVector3d y = rd.vec();
|
|
SmVector2d s = rd.uv();
|
|
SmExtent2d d = rd.dom4();
|
|
SmPlane* srf = new (ctx) SmPlane(o, x, y, s, d, &ctx);
|
|
// Make the plane's NURB up front: const queries (GetNextPoint's evaluations) would
|
|
// make and keep it later, changing later point solves; the Rust plane never keeps a
|
|
// NURB made by a read-only query, so both sides start with it (plan/findings.md).
|
|
srf->GetOrCreateGwNurbPointer();
|
|
own.surfaces.push_back(srf);
|
|
return srf;
|
|
}
|
|
if (kind == 1)
|
|
{
|
|
gw_DEGREE p = (gw_DEGREE)rd.idx(1, 8);
|
|
gw_DEGREE q = (gw_DEGREE)rd.idx(1, 8);
|
|
gw_INDEX nu = (gw_INDEX)rd.idx(2, 33);
|
|
gw_INDEX nv = (gw_INDEX)rd.idx(2, 33);
|
|
if (p >= nu || q >= nv)
|
|
throw Bad();
|
|
gw_INDEX n = nu - 1;
|
|
gw_INDEX m = nv - 1;
|
|
gw_INDEX r = n + p + 1;
|
|
gw_INDEX s = m + q + 1;
|
|
std::vector<double> v;
|
|
for (int64_t i = 0; i < 4 * (int64_t)nu * nv + r + 1 + s + 1; i++)
|
|
v.push_back(rd.num());
|
|
gw_SURFACE* sur = sm_AllocateNurbSurface(n, m, p, q, r, s);
|
|
size_t k = 0;
|
|
for (gw_INDEX i = 0; i <= n; i++)
|
|
for (gw_INDEX j = 0; j <= m; j++)
|
|
{
|
|
sur->net->Pw[i][j].x = v[k++];
|
|
sur->net->Pw[i][j].y = v[k++];
|
|
sur->net->Pw[i][j].z = v[k++];
|
|
sur->net->Pw[i][j].w = v[k++];
|
|
}
|
|
for (gw_INDEX i = 0; i <= r; i++)
|
|
sur->knu->U[i] = v[k++];
|
|
for (gw_INDEX i = 0; i <= s; i++)
|
|
sur->knv->U[i] = v[k++];
|
|
SmSurface* srf = new (ctx) SmBSplineSurface(sur, FALSE, &ctx);
|
|
own.surfaces.push_back(srf);
|
|
return srf;
|
|
}
|
|
int64_t gk = rd.idx(0, 1);
|
|
SmBSplineCurve* gen = NULL;
|
|
if (gk == 0)
|
|
{
|
|
SmPoint3d a = rd.vec();
|
|
SmPoint3d b = rd.vec();
|
|
SmLine* l = new (ctx) SmLine(a, b, 3, &ctx);
|
|
l->GetOrCreateGwNurbPointer();
|
|
gen = l;
|
|
}
|
|
else
|
|
{
|
|
SmPoint3d c = rd.vec();
|
|
SmVector3d x = rd.vec();
|
|
SmVector3d y = rd.vec();
|
|
double d0 = rd.num();
|
|
double d1 = rd.num();
|
|
double r = rd.num();
|
|
gen = new (ctx) SmCircle(c, x, y, SmExtent1d(d0, d1), r, 3, &ctx);
|
|
}
|
|
SmPoint3d pt = rd.vec();
|
|
SmVector3d ax = rd.vec();
|
|
bool swap = rd.idx(0, 1) != 0;
|
|
SmSurfOfRevolution* rev = NULL;
|
|
if (SmSurfOfRevolution::CreateCanonical(ctx, gen, pt, ax, rev, swap ? TRUE : FALSE) != SM_SUCCESS ||
|
|
rev == NULL)
|
|
{
|
|
delete rev;
|
|
return NULL;
|
|
}
|
|
own.surfaces.push_back(rev);
|
|
return rev;
|
|
}
|
|
|
|
SmBoolean tri(Rd& rd)
|
|
{
|
|
return (SmBoolean)rd.idx(0, 2);
|
|
}
|
|
|
|
// The 38-value drop point state: t good crv[3][3] uv[2][2] pd3d[2][3] normal[3]
|
|
// from_left_u from_left_v drop_to_surf approx_dev normal_to_crv srf_to_crv speed_ratio
|
|
// on_boundary on_seam on_pole degen leaving entering deriv_rtn.
|
|
void read_pt(Rd& rd, sc_sdl2_SmDropPt& p)
|
|
{
|
|
p.m_dT = rd.num();
|
|
p.m_bGoodDrop = tri(rd);
|
|
for (int i = 0; i < 3; i++)
|
|
p.m_CrvPD[i] = rd.vec();
|
|
for (int i = 0; i < 2; i++)
|
|
p.m_UVPD[i] = rd.uv();
|
|
for (int i = 0; i < 2; i++)
|
|
p.m_3dPD[i] = rd.vec();
|
|
p.m_SrfNormal = rd.vec();
|
|
p.m_bFromLeftU = tri(rd);
|
|
p.m_bFromLeftV = tri(rd);
|
|
p.m_dDropToSurf = rd.num();
|
|
p.m_dApproxDev = rd.num();
|
|
p.m_dNormalToCrvAngDeg = rd.num();
|
|
p.m_dSrfToCrvAngDeg = rd.num();
|
|
p.m_dSrfToCrvSpeedRatio = rd.num();
|
|
p.m_bOnBoundary = tri(rd);
|
|
p.m_bOnSeam = tri(rd);
|
|
p.m_bOnPole = tri(rd);
|
|
p.m_bDegenCurve = tri(rd);
|
|
p.m_bLeavingDomain = tri(rd);
|
|
p.m_bEnteringDomain = tri(rd);
|
|
double r = rd.num();
|
|
if (!(r >= 0.0 && r <= 1.0e8) || r != (double)(int64_t)r)
|
|
throw Bad();
|
|
p.m_eDropDerivRtn = (SmStatus)(int64_t)r;
|
|
}
|
|
|
|
void put_pt(std::vector<double>& o, const sc_sdl2_SmDropPt& p)
|
|
{
|
|
o.push_back(p.m_dT);
|
|
o.push_back((double)p.m_bGoodDrop);
|
|
for (int i = 0; i < 3; i++)
|
|
put_vec(o, p.m_CrvPD[i]);
|
|
for (int i = 0; i < 2; i++)
|
|
put_uv(o, p.m_UVPD[i]);
|
|
for (int i = 0; i < 2; i++)
|
|
put_vec(o, p.m_3dPD[i]);
|
|
put_vec(o, p.m_SrfNormal);
|
|
o.push_back((double)p.m_bFromLeftU);
|
|
o.push_back((double)p.m_bFromLeftV);
|
|
o.push_back(p.m_dDropToSurf);
|
|
o.push_back(p.m_dApproxDev);
|
|
o.push_back(p.m_dNormalToCrvAngDeg);
|
|
o.push_back(p.m_dSrfToCrvAngDeg);
|
|
o.push_back(p.m_dSrfToCrvSpeedRatio);
|
|
o.push_back((double)p.m_bOnBoundary);
|
|
o.push_back((double)p.m_bOnSeam);
|
|
o.push_back((double)p.m_bOnPole);
|
|
o.push_back((double)p.m_bDegenCurve);
|
|
o.push_back((double)p.m_bLeavingDomain);
|
|
o.push_back((double)p.m_bEnteringDomain);
|
|
o.push_back((double)p.m_eDropDerivRtn);
|
|
}
|
|
|
|
// `degree ncp cpts(x y z w) nknots knots mults ivl_min ivl_max` of a B-spline curve.
|
|
void put_curve(std::vector<double>& o, SmBSplineCurve* c)
|
|
{
|
|
gw_CURVE* cur = c->GetOrCreateGwNurbPointer();
|
|
if (cur == NULL)
|
|
throw Bad();
|
|
o.push_back((double)cur->p);
|
|
o.push_back((double)(cur->pol->n + 1));
|
|
for (gw_INDEX i = 0; i <= cur->pol->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);
|
|
}
|
|
SmTArray<double> knots;
|
|
SmTArray<ULONG> mults;
|
|
if (c->GetKnots(knots, &mults) != SM_SUCCESS)
|
|
throw Bad();
|
|
o.push_back((double)knots.GetSize());
|
|
for (ULONG i = 0; i < knots.GetSize(); i++)
|
|
o.push_back(knots[i]);
|
|
for (ULONG i = 0; i < mults.GetSize(); i++)
|
|
o.push_back((double)mults[i]);
|
|
SmExtent1d ivl = c->GetNaturalInterval();
|
|
o.push_back(ivl.GetMin());
|
|
o.push_back(ivl.GetMax());
|
|
}
|
|
|
|
SmSurfParamType closure_of(int64_t c)
|
|
{
|
|
return c == 0 ? SM_SP_U : c == 1 ? SM_SP_V : c == 2 ? SM_SP_BOTH : SM_SP_NEITHER;
|
|
}
|
|
|
|
// The growing curve state after AddToCurve / FlushCrv: `npoly poly(x y z) nknots knots
|
|
// ncurves curves`; the curves are deleted.
|
|
void put_state(std::vector<double>& o, SmTArray<SmPoint3d>& poly, SmTArray<double>& knots,
|
|
SmTArray<SmBSplineCurve*>& curves)
|
|
{
|
|
o.push_back((double)poly.GetSize());
|
|
for (ULONG i = 0; i < poly.GetSize(); i++)
|
|
put_vec(o, poly[i]);
|
|
o.push_back((double)knots.GetSize());
|
|
for (ULONG i = 0; i < knots.GetSize(); i++)
|
|
o.push_back(knots[i]);
|
|
o.push_back((double)curves.GetSize());
|
|
for (ULONG i = 0; i < curves.GetSize(); i++)
|
|
put_curve(o, curves[i]);
|
|
}
|
|
|
|
// The unused curve / surface arguments of sm_AddToCurve and sm_FlushCrv.
|
|
SmCurve& unused_curve(const SmContext& ctx, Owned& own)
|
|
{
|
|
SmLine* l = new (ctx) SmLine(SmPoint3d(0, 0, 0), SmPoint3d(1, 0, 0), 3, &ctx);
|
|
own.curves.push_back(l);
|
|
return *l;
|
|
}
|
|
|
|
SmSurface& unused_surface(const SmContext& ctx, Owned& own)
|
|
{
|
|
SmSurface* s = new (ctx) SmPlane(SmPoint3d(0, 0, 0), SmVector3d(1, 0, 0), SmVector3d(0, 1, 0),
|
|
SmVector2d(1, 1), SmExtent2d(0, 0, 1, 1), &ctx);
|
|
own.surfaces.push_back(s);
|
|
return *s;
|
|
}
|
|
|
|
struct Curves
|
|
{
|
|
SmTArray<SmBSplineCurve*> a;
|
|
~Curves()
|
|
{
|
|
for (ULONG i = 0; i < a.GetSize(); i++)
|
|
delete a[i];
|
|
}
|
|
};
|
|
|
|
void run(Rd& rd, std::vector<double>& o)
|
|
{
|
|
SmContext ctx;
|
|
Owned own;
|
|
int64_t op = rd.idx(OP_SET, OP_FLUSH);
|
|
switch (op)
|
|
{
|
|
case OP_SET:
|
|
{
|
|
SmSurface* s = read_surface(rd, ctx, own);
|
|
sc_sdl2_SmDropPt p(0.0, FALSE);
|
|
read_pt(rd, p);
|
|
double dist = rd.num();
|
|
ULONG sing = (ULONG)rd.idx(0, 31);
|
|
double tol = rd.num();
|
|
SmExtent2d d = rd.dom4();
|
|
SmBoolean adjust = (SmBoolean)rd.idx(0, 1);
|
|
if (s == NULL)
|
|
{
|
|
o.push_back(NO_SURFACE);
|
|
return;
|
|
}
|
|
SmOffsetSurface off(dist, *s, FALSE, sing);
|
|
SmStatus stt = p.SetProperties(*s, off, sing, tol, d, adjust);
|
|
o.push_back(st(stt));
|
|
put_pt(o, p);
|
|
o.push_back(off.GetOffsetDistance());
|
|
return;
|
|
}
|
|
case OP_NEXT:
|
|
{
|
|
SmSurface* s = read_surface(rd, ctx, own);
|
|
SmCurve* c = read_curve(rd, ctx, own);
|
|
sc_sdl2_SmDropPt a(0.0, FALSE);
|
|
read_pt(rd, a);
|
|
double dist = rd.num();
|
|
ULONG sing = (ULONG)rd.idx(0, 31);
|
|
bool has_poles = rd.idx(0, 1) != 0;
|
|
SmTArray<SmPoint3d> poles;
|
|
if (has_poles)
|
|
for (int i = 0; i < 4; i++)
|
|
poles.Add(rd.vec());
|
|
SmExtent2d d = rd.dom4();
|
|
SmSurfParamType closure = closure_of(rd.idx(0, 3));
|
|
double tol = rd.num();
|
|
double tx = rd.num();
|
|
double ty = rd.num();
|
|
double end_t = rd.num();
|
|
if (s == NULL)
|
|
{
|
|
o.push_back(NO_SURFACE);
|
|
return;
|
|
}
|
|
// GetNextPoint ignores the status of its start evaluation (a path not ported)
|
|
double zu = SM_EFF_ZERO * (1.0 + d.GetUInterval().GetLength());
|
|
double zv = SM_EFF_ZERO * (1.0 + d.GetVInterval().GetLength());
|
|
if (d.ContainsPoint2d(a.m_UVPD[0], smos_Max(zu, zv)) && !(a.m_bOnBoundary && a.m_bLeavingDomain))
|
|
{
|
|
SmVector3d p, su, sv, suv, suu, svv;
|
|
if (s->Evaluate2ndDerivatives(a.m_UVPD[0], a.m_bFromLeftU, a.m_bFromLeftV, p, su, sv, suv, suu, svv) !=
|
|
SM_SUCCESS)
|
|
{
|
|
o.push_back(REJECTED);
|
|
return;
|
|
}
|
|
}
|
|
SmOffsetSurface off(dist, *s, FALSE, sing);
|
|
sc_sdl2_SmDropPt b(0.0, FALSE);
|
|
SmStatus stt = a.GetNextPoint(*s, off, sing, has_poles ? &poles : NULL, d, closure, *c, tol, tx, ty, end_t, b);
|
|
o.push_back(st(stt));
|
|
put_pt(o, b);
|
|
o.push_back(off.GetOffsetDistance());
|
|
return;
|
|
}
|
|
case OP_ADD:
|
|
{
|
|
SmSurface* s = read_surface(rd, ctx, own);
|
|
SmExtent2d d = rd.dom4();
|
|
double tol = rd.num();
|
|
double tx = rd.num();
|
|
double ty = rd.num();
|
|
int64_t np = rd.idx(0, 20000);
|
|
std::vector<sc_sdl2_SmDropPt> pts(np, sc_sdl2_SmDropPt(0.0, FALSE));
|
|
for (int64_t i = 0; i < np; i++)
|
|
read_pt(rd, pts[i]);
|
|
int64_t ns = rd.idx(0, 20000);
|
|
std::vector<std::pair<int64_t, int64_t>> spans;
|
|
for (int64_t i = 0; i < ns; i++)
|
|
{
|
|
int64_t ia = rd.idx(0, np - 1);
|
|
int64_t ib = rd.idx(0, np - 1);
|
|
spans.push_back(std::make_pair(ia, ib));
|
|
}
|
|
bool flush = rd.idx(0, 1) != 0;
|
|
if (s == NULL)
|
|
{
|
|
o.push_back(NO_SURFACE);
|
|
return;
|
|
}
|
|
SmCurve& crv = unused_curve(ctx, own);
|
|
SmTArray<SmPoint3d> poly;
|
|
SmTArray<double> knots;
|
|
Curves curves;
|
|
bool failed = false;
|
|
for (size_t i = 0; i < spans.size() && !failed; i++)
|
|
{
|
|
SmBoolean ch = FALSE;
|
|
SmStatus stt = sm_AddToCurve(ctx, *s, d, crv, pts[spans[i].first], pts[spans[i].second], poly, knots,
|
|
tol, tx, ty, curves.a, ch);
|
|
o.push_back(st(stt));
|
|
o.push_back((double)ch);
|
|
failed = stt != SM_SUCCESS;
|
|
}
|
|
if (flush && !failed)
|
|
{
|
|
SmBoolean ch = FALSE;
|
|
SmStatus stt = sm_FlushCrv(ctx, *s, d, crv, poly, knots, tx, ty, curves.a, ch);
|
|
o.push_back(st(stt));
|
|
o.push_back((double)ch);
|
|
}
|
|
put_state(o, poly, knots, curves.a);
|
|
return;
|
|
}
|
|
case OP_FLUSH:
|
|
{
|
|
SmExtent2d d = rd.dom4();
|
|
double tx = rd.num();
|
|
double ty = rd.num();
|
|
int64_t np = rd.idx(0, 20000);
|
|
SmTArray<SmPoint3d> poly;
|
|
for (int64_t i = 0; i < np; i++)
|
|
poly.Add(rd.vec());
|
|
int64_t nk = rd.idx(0, 20000);
|
|
SmTArray<double> knots;
|
|
for (int64_t i = 0; i < nk; i++)
|
|
knots.Add(rd.num());
|
|
// the shapes sm_AddToCurve builds: no knots, or 1 + 3 (n - 1) points for n >= 2
|
|
// increasing knots (others read past the arrays or are undefined in NLib)
|
|
if (nk != 0 && (nk < 2 || np != 1 + 3 * (nk - 1)))
|
|
throw Bad();
|
|
for (int64_t i = 1; i < nk; i++)
|
|
if (!(knots[(ULONG)i] > knots[(ULONG)(i - 1)]))
|
|
throw Bad();
|
|
Curves curves;
|
|
SmBoolean ch = FALSE;
|
|
SmStatus stt = sm_FlushCrv(ctx, unused_surface(ctx, own), d, unused_curve(ctx, own), poly, knots, tx, ty, curves.a, ch);
|
|
o.push_back(st(stt));
|
|
o.push_back((double)ch);
|
|
put_state(o, poly, knots, curves.a);
|
|
return;
|
|
}
|
|
default:
|
|
throw Bad();
|
|
}
|
|
}
|
|
} // namespace sc_sdl2
|
|
|
|
SC_EXPORT int32_t sc_intersect_surface_drop_lib_p2_run(const double* in, int64_t n_in, double* out, int64_t cap,
|
|
int64_t* out_len)
|
|
{
|
|
if (in == nullptr || n_in < 1 || out_len == nullptr || (out == nullptr && cap > 0))
|
|
return SC_ERR_ARG;
|
|
SC_TRY
|
|
sc_sdl2::Rd rd{in, n_in, 0};
|
|
std::vector<double> o;
|
|
try
|
|
{
|
|
sc_sdl2::run(rd, o);
|
|
}
|
|
catch (const sc_sdl2::Bad&)
|
|
{
|
|
return SC_ERR_ARG;
|
|
}
|
|
if (rd.at != n_in)
|
|
return SC_ERR_ARG;
|
|
return sc_copy_out(o.data(), (int64_t)o.size(), out, cap, out_len);
|
|
SC_CATCH
|
|
}
|