// SPDX-License-Identifier: Apache-2.0 // Native SmApiQueries.cpp calls on concrete analytic/NURBS geometry and B-reps. // Fixed 22-double layout, validated by query_api_queries.rs. Graph construction // and raw export reuse the established topology-edgeuse harness; no query result // is manufactured from the graph export. #include "sc_edgeuse_graph.h" #include #include #include #include #include namespace { SmCurve* api_curve(const double* a) { const auto& ctx = the_context(); SmPoint3d p(a[0], a[1], a[2]); SmVector3d v(a[3], a[4], a[5]); double s = a[6]; int kind = (int)a[21]; if (kind == 0) return new (ctx) SmLine(p, v, SmExtent1d(a[7], a[8]), s, 3, &ctx, nullptr, a[18]?TRUE:FALSE); if (kind == 1) return new (ctx) SmCircle(p, SmVector3d(1, 0, 0), SmVector3d(0, 1, 0), SmExtent1d(0, 360), s, 3, &ctx, nullptr, a[18]?TRUE:FALSE); if (kind == 2) return new (ctx) SmEllipse(p, SmVector3d(1, 0, 0), SmVector3d(0, 1, 0), SmExtent1d(0, 360), s, s*0.5, 3, &ctx, nullptr, a[18]?TRUE:FALSE); // Cubic Bezier, also exercising zero endpoint derivatives when v is zero. gw_CURVE* c = sm_AllocateNurbCurve(3, 3, 7); const SmPoint3d pts[] = { p, p+s*v, p+SmVector3d(s, s, 0), p+SmVector3d(2*s, 0, s) }; for (int i = 0;i<4;++i) { c->pol->Pw[i].x = pts[i].x; c->pol->Pw[i].y = pts[i].y; c->pol->Pw[i].z = pts[i].z; c->pol->Pw[i].w = 1; } for (int i = 0;i<8;++i)c->knt->U[i] = i<4?0:1; return new (ctx) SmBSplineCurve(c, 3, FALSE, &ctx); } SmSurface* api_surface(const double* a) { const auto& ctx = the_context(); if ((int)a[21] == 4)return new (ctx) SmPlane(SmPoint3d(a[0], a[1], a[2]), SmVector3d(a[3], a[4], a[5]), &ctx); if ((int)a[21] == 8 || (int)a[21] == 9) { const bool sphere = (int)a[21] == 9; const int n = sphere?4:1, degree = sphere?2:1, r = sphere?7:3; gw_SURFACE* s = sm_AllocateNurbSurface(n, 8, degree, 2, r, 11); const double xy[9][2] = {{1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}, {-1, -1}, {0, -1}, {1, -1}, {1, 0}}; const double radial[5] = {0, 1, 1, 1, 0}, height[5] = {1, 1, 0, -1, -1}; const double w = smos_Sqrt(0.5); for (int i = 0;i <= n;++i)for (int j = 0;j<9;++j) { const double wi = sphere && i%2?w:1, wj = j%2?w:1, weight = wi*wj; const double rad = sphere?radial[i]:1, z = sphere?height[i]:(double)i; s->net->Pw[i][j].x = (a[0]+a[6]*rad*xy[j][0])*weight; s->net->Pw[i][j].y = (a[1]+a[6]*rad*xy[j][1])*weight; s->net->Pw[i][j].z = (a[2]+a[6]*z)*weight; s->net->Pw[i][j].w = weight; } const double ku_sphere[8] = { 0, 0, 0, 0.5, 0.5, 1, 1, 1 }; const double kv[12] = { 0, 0, 0, 0.25, 0.25, 0.5, 0.5, 0.75, 0.75, 1, 1, 1 }; for (int i = 0;i <= r;++i)s->knu->U[i] = sphere?ku_sphere[i]:(i<2?0:1); for (int j = 0;j<12;++j)s->knv->U[j] = kv[j]; return new (ctx) SmBSplineSurface(s, FALSE, nullptr); } gw_SURFACE* s = sm_AllocateNurbSurface(2, 2, 2, 2, 5, 5); for (int i = 0;i<3;++i)for (int j = 0;j<3;++j) { s->net->Pw[i][j].x = a[0]+a[6]*i; s->net->Pw[i][j].y = a[1]+a[6]*j; s->net->Pw[i][j].z = a[2]+(i == 1 && j == 1?a[6]:0); s->net->Pw[i][j].w = 1; } for (int i = 0;i<6;++i) { s->knu->U[i] = i<3?0:1; s->knv->U[i] = i<3?0:1; } return new (ctx) SmBSplineSurface(s, FALSE, nullptr); } void api_point(std::vector& o, SmStatus status, const SmPoint3d& p, double dist) { o.push_back(st(status)); if (status == SM_SUCCESS) { put_vec(o, p); o.push_back(dist); } } } SC_EXPORT int32_t sc_query_api_queries_eval(int32_t op, const double* a, int64_t n, double* out, int64_t cap, int64_t* len) { if (!a || n != 22 || op<0 || op>26)return SC_ERR_ARG; SC_TRY const auto& ctx = the_context(); std::vector o; SmPoint3d p(a[11], a[12], a[13]), q; double t = 0, d = 0; bool null = a[16] != 0; int kind = (int)a[21]; if (op == 1 || op == 2) { std::unique_ptr c(api_curve(a)); if (!c)return SC_ERR_ARG; if (op == 1) { SmStatus s = SmApiCurveClosestPoint(null?nullptr:c.get(), p, q, t, d); api_point(o, s, q, d); if (s == SM_SUCCESS)o.push_back(t); } else { SmTArray ps; SmTArray ts, ds; SmStatus s = SmApiCurveClosestPointAll(null?nullptr:c.get(), p, ps, ts, ds); o.push_back(st(s)); if (s == SM_SUCCESS) { o.push_back(ps.GetSize()); for (ULONG i = 0;i s(api_surface(a)); SmTArray uv; SmStatus status = SmApiSurfaceClosestPoint(null?nullptr:s.get(), p, q, uv, d); api_point(o, status, q, d); if (status == SM_SUCCESS) { o.push_back(uv.GetSize()); for (ULONG i = 0;iCreateWireEdgeFromCurve(api_curve(a), SmExtent1d(a[7], a[8]), e); } else if (kind == 4 || kind == 5 || kind == 8 || kind == 9) { SmFace* f = nullptr; status = b.brep->CreateFaceFromSurface(api_surface(a), SmExtent2d(SmPoint2d(a[7], a[8]), SmPoint2d(a[9], a[10])), f); } else if (kind == 6) { delete b.brep; b.brep = nullptr; status = SmApiCreateBox(SmPoint3d(a[0], a[1], a[2]), a[6], a[6], a[6], b.brep); } if (status != SM_SUCCESS || !b.brep)return SC_ERR_ARG; Graph g; walk(b.brep, g); size_t sel = (size_t)a[20]; SmEdge* e = g.edges.empty()?nullptr:g.edges[sel%g.edges.size()]; SmFace* f = g.faces.empty()?nullptr:g.faces[sel%g.faces.size()]; SmVertex* v = g.vertices.empty()?nullptr:g.vertices[sel%g.vertices.size()]; if (e && a[19] >= 0)e->SetTolerance(a[19], FALSE, FALSE); if (e && a[17])e->SetCurve(nullptr, TRUE, FALSE, FALSE); if ((op == 11 || op == 26) && f && a[18] != 0) { SmTArray loops; f->GetUpwardLoopuses(loops); if (loops.GetSize() > 0) { SmTArray uses; loops[loops.GetSize()-1]->GetEdgeuses(uses); if (uses.GetSize() > 0) uses[uses.GetSize()-1]->SetOrientation(SM_OT_UNKNOWN); } } if (op == 0 || op == 26) { o.push_back(0); export_graph(b.brep, g, o); } else { if (null) { e = nullptr; f = nullptr; v = nullptr; } SmBrep* bp = null?nullptr:b.brep; SmPoint3d lo, hi; int cl = 0; switch (op) { case 4:case 5:case 6: { status = op == 4?SmApiGetClosestPoint(bp, p, q, d):op == 5?SmApiBrepClosestPoint(bp, p, q, d):SM_SUCCESS; if (op == 6) { SmTArray ps; SmTArray ds; status = SmApiBrepClosestPointAll(bp, p, ps, ds); o.push_back(st(status)); if (status == SM_SUCCESS) { o.push_back(ps.GetSize()); for (ULONG i = 0;i es; status = SmApiGetEdges(bp, es); o.push_back(st(status)); if (status == SM_SUCCESS) { o.push_back(es.GetSize()); for (ULONG i = 0;i fs; status = SmApiGetFaces(bp, fs); o.push_back(st(status)); if (status == SM_SUCCESS) { o.push_back(fs.GetSize()); for (ULONG i = 0;i ns; SmTArray es; SmTArray os; status = SmApiFaceGetBoundaryLoops(f, ns, es, os); o.push_back(st(status)); if (status == SM_SUCCESS) { o.push_back(ns.GetSize()); for (ULONG i = 0;i