10C Inc 1: core modeling

Binds the modeling core the app builds every feature out of — 93 of its 138
symbols now resolve, up from 34. New modules: GeomAbs, Geom2d, Geom,
TCollection, TColgp, TColStd, GProp, BRepGProp, Bnd, BRepBndLib, Adaptor3d,
BRepAdaptor, GeomLProp, GeomAPI, BRepBuilderAPI, BOPAlgo, BRepAlgoAPI,
BRepPrimAPI, GC, BRepMesh; gp and BRep_Tool completed.

Three structural decisions:

- BRepBuilderAPI_MakeShape carries Build/Shape/Generated/Modified/IsDeleted for
  every maker in the binding, so the booleans, the primitives and (later) the
  fillet builders all answer the app's duck-typed provenance layer through
  ordinary virtual dispatch. History lists come back copied, so they outlive
  the builder.
- The executing two-argument BRepAlgoAPI constructors stay unbound; operands go
  in through SetArguments/SetTools. Section keeps Init1/Init2, which are plain
  setters. BOPAlgo moved up from Inc 2 — SetGlue needs its enum.
- Adaptor3d is registered although the app never imports it: every method it
  calls on BRepAdaptor_Curve/Surface is a virtual declared there, so binding
  them once on the bases leaves mod_BRepAdaptor.cpp with just constructors.

Gate: tests/test_inc1_modeling.py against reference values gen_fixtures.py now
records from the stock wheel — measurements, per-face area/centroid in map
order, mesh counts, and the boolean history map compared exactly, since that is
the substrate the app's topological naming is built on.

tools/sigdiff.py compares our bound surface against stock's, because a wrong
nb::init<> is silent: MakePrism's five-argument form bound OCCT's semi-infinite
gp_Dir overload (gp_Dir converts from gp_Vec), producing a valid solid of the
wrong shape with the flags shifted along. The fixture digest caught it; sigdiff
finds the class of bug directly, and now reports only one deliberate deviation.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DfriM8XUkn7uYf5Dwe2xo6
This commit is contained in:
2026-08-10 19:52:52 +02:00
parent 091a2ad0cf
commit 2c2c4e4712
32 changed files with 2732 additions and 18 deletions

View File

@@ -31,6 +31,27 @@ void register_TopExp(nb::module_ &);
void register_Poly(nb::module_ &);
void register_BRep(nb::module_ &);
void register_BinTools(nb::module_ &);
// Inc 1 — core modeling
void register_GeomAbs(nb::module_ &);
void register_TCollection(nb::module_ &);
void register_TColgp(nb::module_ &);
void register_TColStd(nb::module_ &);
void register_GProp(nb::module_ &);
void register_BRepGProp(nb::module_ &);
void register_Bnd(nb::module_ &);
void register_BRepBndLib(nb::module_ &);
void register_Geom2d(nb::module_ &);
void register_Geom(nb::module_ &);
void register_Adaptor3d(nb::module_ &);
void register_BRepAdaptor(nb::module_ &);
void register_GeomLProp(nb::module_ &);
void register_GeomAPI(nb::module_ &);
void register_BRepBuilderAPI(nb::module_ &);
void register_BOPAlgo(nb::module_ &);
void register_BRepAlgoAPI(nb::module_ &);
void register_BRepPrimAPI(nb::module_ &);
void register_GC(nb::module_ &);
void register_BRepMesh(nb::module_ &);
void register_ext(nb::module_ &);
NB_MODULE(_OCP, m) {
@@ -51,6 +72,29 @@ NB_MODULE(_OCP, m) {
register_BRep(m);
register_BinTools(m);
// Inc 1. Order follows the class hierarchy: a declared base must be
// registered before anything that derives from it.
register_GeomAbs(m);
register_TCollection(m);
register_TColgp(m);
register_TColStd(m);
register_GProp(m);
register_BRepGProp(m);
register_Bnd(m);
register_BRepBndLib(m);
register_Geom2d(m);
register_Geom(m);
register_Adaptor3d(m); // before BRepAdaptor: it declares the bases
register_BRepAdaptor(m);
register_GeomLProp(m);
register_GeomAPI(m);
register_BRepBuilderAPI(m); // declares the MakeShape base the rest use
register_BOPAlgo(m);
register_BRepAlgoAPI(m);
register_BRepPrimAPI(m);
register_GC(m);
register_BRepMesh(m);
register_ext(m);
m.attr("__all_modules__") = ocp_module_registry();

View File

@@ -0,0 +1,69 @@
/*
OCP.Adaptor3d — the abstract curve/surface interface the app actually
programs against.
Not imported by the app, but it is where every method it calls on a
BRepAdaptor_Curve/Surface is *declared*: GetType, the parameter bounds,
Value/D1 and the quadric accessors are all virtuals here. Binding them
once on the bases keeps mod_BRepAdaptor.cpp down to constructors, and any
later adaptor (Geom2dAdaptor, Adaptor3d_CurveOnSurface) inherits the
surface for free.
These are transients in OCCT 7.6+, so they are declared against
Standard_Transient and never get nb::init<>.
D1 keeps its out-parameters, because the app pre-allocates the gp_Pnt/gp_Vec
and reads them back (`adaptor.D1(u, v, pnt, d1u, d1v)`) — same as stock.
*/
#include "../common/occt_module.h"
#include "../common/occt_policies.h"
#include <Adaptor3d_Curve.hxx>
#include <Adaptor3d_Surface.hxx>
#include <gp_Circ.hxx>
#include <gp_Cone.hxx>
#include <gp_Cylinder.hxx>
#include <gp_Elips.hxx>
#include <gp_Lin.hxx>
#include <gp_Pln.hxx>
#include <gp_Pnt.hxx>
#include <gp_Sphere.hxx>
#include <gp_Vec.hxx>
void register_Adaptor3d(nb::module_ &root) {
nb::module_ m = ocp_submodule(root, "Adaptor3d");
nb::class_<Adaptor3d_Curve, Standard_Transient>(m, "Adaptor3d_Curve")
.def("GetType", &Adaptor3d_Curve::GetType)
.def("FirstParameter", &Adaptor3d_Curve::FirstParameter)
.def("LastParameter", &Adaptor3d_Curve::LastParameter)
.def("Value", &Adaptor3d_Curve::Value, "U"_a, OCP_RETURN_COPY)
.def("D0", &Adaptor3d_Curve::D0, "U"_a, "P"_a)
.def("D1", &Adaptor3d_Curve::D1, "U"_a, "P"_a, "V"_a)
.def("Line", &Adaptor3d_Curve::Line, OCP_RETURN_COPY)
.def("Circle", &Adaptor3d_Curve::Circle, OCP_RETURN_COPY)
.def("Ellipse", &Adaptor3d_Curve::Ellipse, OCP_RETURN_COPY)
.def("IsClosed", &Adaptor3d_Curve::IsClosed)
.def("IsPeriodic", &Adaptor3d_Curve::IsPeriodic);
nb::class_<Adaptor3d_Surface, Standard_Transient>(m, "Adaptor3d_Surface")
.def("GetType", &Adaptor3d_Surface::GetType)
.def("FirstUParameter", &Adaptor3d_Surface::FirstUParameter)
.def("LastUParameter", &Adaptor3d_Surface::LastUParameter)
.def("FirstVParameter", &Adaptor3d_Surface::FirstVParameter)
.def("LastVParameter", &Adaptor3d_Surface::LastVParameter)
.def("IsUPeriodic", &Adaptor3d_Surface::IsUPeriodic)
.def("IsVPeriodic", &Adaptor3d_Surface::IsVPeriodic)
.def("UPeriod", &Adaptor3d_Surface::UPeriod)
.def("VPeriod", &Adaptor3d_Surface::VPeriod)
.def("IsUClosed", &Adaptor3d_Surface::IsUClosed)
.def("IsVClosed", &Adaptor3d_Surface::IsVClosed)
.def("Value", &Adaptor3d_Surface::Value, "U"_a, "V"_a, OCP_RETURN_COPY)
.def("D0", &Adaptor3d_Surface::D0, "U"_a, "V"_a, "P"_a)
.def("D1", &Adaptor3d_Surface::D1, "U"_a, "V"_a, "P"_a, "D1U"_a, "D1V"_a)
.def("Plane", &Adaptor3d_Surface::Plane, OCP_RETURN_COPY)
.def("Cylinder", &Adaptor3d_Surface::Cylinder, OCP_RETURN_COPY)
.def("Cone", &Adaptor3d_Surface::Cone, OCP_RETURN_COPY)
.def("Sphere", &Adaptor3d_Surface::Sphere, OCP_RETURN_COPY);
}

View File

@@ -0,0 +1,22 @@
/*
OCP.BOPAlgo — boolean-operation options.
Only the glue enum: the app's pattern fuse sets BOPAlgo_GlueShift when it
knows the operands cannot intersect, which lets OCCT skip the intersection
stage entirely. It has to land with BRepAlgoAPI rather than later, since
SetGlue takes this type.
*/
#include "../common/occt_module.h"
#include <BOPAlgo_GlueEnum.hxx>
void register_BOPAlgo(nb::module_ &root) {
nb::module_ m = ocp_submodule(root, "BOPAlgo");
nb::enum_<BOPAlgo_GlueEnum>(m, "BOPAlgo_GlueEnum", nb::is_arithmetic())
.value("BOPAlgo_GlueOff", BOPAlgo_GlueOff)
.value("BOPAlgo_GlueShift", BOPAlgo_GlueShift)
.value("BOPAlgo_GlueFull", BOPAlgo_GlueFull)
.export_values();
}

View File

@@ -1,16 +1,22 @@
/*
OCP.BRep — builder plus the Inc 0 half of BRep_Tool.
OCP.BRep — the shape builder and BRep_Tool's query statics.
BRep_Tool::Surface / Curve return Geom handles and land with Inc 1, where
the Geom classes arrive; Triangulation is here because it is what the
tessellation path reads and what the handle spike exercises.
Surface/Curve hand back the face's or edge's *live* Geom handle when the
location is identity, and a transformed copy otherwise. The handle caster
wraps whichever it is without copying, so mutating the result mutates the
model — upstream behaves the same way, and the app only ever reads.
*/
#include "../common/occt_module.h"
#include "../common/occt_policies.h"
#include <nanobind/stl/tuple.h>
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <Geom2d_Curve.hxx>
#include <Geom_Curve.hxx>
#include <Geom_Surface.hxx>
#include <Poly_Triangulation.hxx>
#include <TopLoc_Location.hxx>
#include <TopoDS_Compound.hxx>
@@ -70,4 +76,34 @@ void register_BRep(nb::module_ &root) {
OCP_DEF_S(
cls, "IsClosed",
[](const TopoDS_Shape &S) { return BRep_Tool::IsClosed(S); }, "S"_a);
OCP_DEF_S(
cls, "Surface",
[](const TopoDS_Face &F) { return BRep_Tool::Surface(F); }, "F"_a);
OCP_DEF_S(
cls, "Surface",
[](const TopoDS_Face &F, TopLoc_Location &L) {
return BRep_Tool::Surface(F, L);
},
"F"_a, "L"_a);
// Curve reports the parameter range through two scalar out-parameters;
// upstream returns them alongside the handle, so a caller writes
// `curve, first, last = BRep_Tool.Curve_s(edge)`.
OCP_DEF_S(
cls, "Curve",
[](const TopoDS_Edge &E) {
Standard_Real first = 0.0, last = 0.0;
auto curve = BRep_Tool::Curve(E, first, last);
return std::make_tuple(curve, first, last);
},
"E"_a);
OCP_DEF_S(
cls, "CurveOnSurface",
[](const TopoDS_Edge &E, const TopoDS_Face &F) {
Standard_Real first = 0.0, last = 0.0;
auto curve = BRep_Tool::CurveOnSurface(E, F, first, last);
return std::make_tuple(curve, first, last);
},
"E"_a, "F"_a);
}

View File

@@ -0,0 +1,42 @@
/*
OCP.BRepAdaptor — adaptors over topology.
Constructors only: every method the app calls is a virtual declared on
Adaptor3d_Curve/Adaptor3d_Surface and bound there. These are the app's
single most-used query path — "what kind of surface is this face, and what
are its axis and radius" — behind reference inference, anchor scoring and
hole recognition.
*/
#include "../common/occt_module.h"
#include "../common/occt_transient.h"
#include <Adaptor3d_Curve.hxx>
#include <Adaptor3d_Surface.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <BRepAdaptor_Surface.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
void register_BRepAdaptor(nb::module_ &root) {
nb::module_ m = ocp_submodule(root, "BRepAdaptor");
nb::class_<BRepAdaptor_Curve, Adaptor3d_Curve>(m, "BRepAdaptor_Curve")
.def(ocp_new<BRepAdaptor_Curve>())
.def(ocp_new<BRepAdaptor_Curve, const TopoDS_Edge &>(), "E"_a)
.def(ocp_new<BRepAdaptor_Curve, const TopoDS_Edge &, const TopoDS_Face &>(),
"E"_a, "F"_a)
.def("Initialize",
nb::overload_cast<const TopoDS_Edge &>(&BRepAdaptor_Curve::Initialize),
"E"_a)
.def("Edge", &BRepAdaptor_Curve::Edge, nb::rv_policy::copy);
nb::class_<BRepAdaptor_Surface, Adaptor3d_Surface>(m, "BRepAdaptor_Surface")
.def(ocp_new<BRepAdaptor_Surface>())
.def(ocp_new<BRepAdaptor_Surface, const TopoDS_Face &,
const Standard_Boolean>(),
"F"_a, "R"_a = Standard_True)
.def("Initialize", &BRepAdaptor_Surface::Initialize, "F"_a,
"Restriction"_a = Standard_True)
.def("Face", &BRepAdaptor_Surface::Face, nb::rv_policy::copy);
}

View File

@@ -0,0 +1,117 @@
/*
OCP.BRepAlgoAPI — booleans and the splitter.
This is the one place where the binding deliberately refuses part of
upstream's surface: the two-argument constructors, which execute the
operation during construction. Every app call site also called Build(),
so the boolean ran twice and the first, destructive pass could mutate
inputs shared with the shape cache. Only the default constructor is bound;
operands go in through SetArguments/SetTools and the caller owns Build().
Section is the exception in form only: its operands arrive through
Init1/Init2 (Init2 takes a gp_Pln and builds the infinite plane face
itself), which are plain setters, so both are bound.
BRepAlgoAPI_Algo inherits BOPAlgo_Options *protected* and re-exports the
option setters with using-declarations, so there is no public upcast to
bind against — those go through lambdas on BuilderAlgo.
Build/Shape/Generated/Modified/IsDeleted all come from
BRepBuilderAPI_MakeShape. The history is the topological-naming substrate:
cad/topology/provenance.py reads it to decide which feature owns which
face, so it must be exact, and un-tracked sub-shapes must raise a catchable
Python exception rather than abort (the app wraps those calls in
try/except).
*/
#include "../common/occt_module.h"
#include "../common/occt_policies.h"
#include <BOPAlgo_GlueEnum.hxx>
#include <BRepAlgoAPI_BooleanOperation.hxx>
#include <BRepAlgoAPI_BuilderAlgo.hxx>
#include <BRepAlgoAPI_Common.hxx>
#include <BRepAlgoAPI_Cut.hxx>
#include <BRepAlgoAPI_Fuse.hxx>
#include <BRepAlgoAPI_Section.hxx>
#include <BRepAlgoAPI_Splitter.hxx>
#include <BRepBuilderAPI_MakeShape.hxx>
#include <TopTools_ListOfShape.hxx>
#include <TopoDS_Shape.hxx>
#include <gp_Pln.hxx>
void register_BRepAlgoAPI(nb::module_ &root) {
nb::module_ m = ocp_submodule(root, "BRepAlgoAPI");
// BRepAlgoAPI_Algo is skipped as a declared base: it adds nothing public
// of its own, and nanobind only needs an unambiguous upcast path.
nb::class_<BRepAlgoAPI_BuilderAlgo, BRepBuilderAPI_MakeShape>(
m, "BRepAlgoAPI_BuilderAlgo")
.def("SetArguments", &BRepAlgoAPI_BuilderAlgo::SetArguments, "theLS"_a)
.def("Arguments", &BRepAlgoAPI_BuilderAlgo::Arguments, OCP_RETURN_COPY)
.def("SetNonDestructive", &BRepAlgoAPI_BuilderAlgo::SetNonDestructive,
"theFlag"_a)
.def("SetGlue", &BRepAlgoAPI_BuilderAlgo::SetGlue, "theGlue"_a)
.def("HasModified", &BRepAlgoAPI_BuilderAlgo::HasModified)
.def("HasGenerated", &BRepAlgoAPI_BuilderAlgo::HasGenerated)
.def("HasDeleted", &BRepAlgoAPI_BuilderAlgo::HasDeleted)
// Inherited from the protected BOPAlgo_Options base through
// using-declarations, so they are reachable by name but not by
// member pointer.
.def(
"SetFuzzyValue",
[](BRepAlgoAPI_BuilderAlgo &self, Standard_Real v) {
self.SetFuzzyValue(v);
},
"theFuzz"_a)
.def(
"SetRunParallel",
[](BRepAlgoAPI_BuilderAlgo &self, Standard_Boolean f) {
self.SetRunParallel(f);
},
"theFlag"_a)
.def(
"SetUseOBB",
[](BRepAlgoAPI_BuilderAlgo &self, Standard_Boolean f) {
self.SetUseOBB(f);
},
"theUseOBB"_a);
nb::class_<BRepAlgoAPI_BooleanOperation, BRepAlgoAPI_BuilderAlgo>(
m, "BRepAlgoAPI_BooleanOperation")
.def("SetTools", &BRepAlgoAPI_BooleanOperation::SetTools, "theLS"_a)
.def("Tools", &BRepAlgoAPI_BooleanOperation::Tools, OCP_RETURN_COPY)
.def("Shape1", &BRepAlgoAPI_BooleanOperation::Shape1, OCP_RETURN_COPY)
.def("Shape2", &BRepAlgoAPI_BooleanOperation::Shape2, OCP_RETURN_COPY);
nb::class_<BRepAlgoAPI_Fuse, BRepAlgoAPI_BooleanOperation>(
m, "BRepAlgoAPI_Fuse")
.def(nb::init<>());
nb::class_<BRepAlgoAPI_Cut, BRepAlgoAPI_BooleanOperation>(m,
"BRepAlgoAPI_Cut")
.def(nb::init<>());
nb::class_<BRepAlgoAPI_Common, BRepAlgoAPI_BooleanOperation>(
m, "BRepAlgoAPI_Common")
.def(nb::init<>());
nb::class_<BRepAlgoAPI_Section, BRepAlgoAPI_BooleanOperation>(
m, "BRepAlgoAPI_Section")
.def(nb::init<>())
.def("Init1",
nb::overload_cast<const TopoDS_Shape &>(&BRepAlgoAPI_Section::Init1),
"S1"_a)
.def("Init2",
nb::overload_cast<const TopoDS_Shape &>(&BRepAlgoAPI_Section::Init2),
"S2"_a)
.def("Init2", nb::overload_cast<const gp_Pln &>(&BRepAlgoAPI_Section::Init2),
"Pl"_a)
.def("Approximation", &BRepAlgoAPI_Section::Approximation, "B"_a)
.def("ComputePCurveOn1", &BRepAlgoAPI_Section::ComputePCurveOn1, "B"_a)
.def("ComputePCurveOn2", &BRepAlgoAPI_Section::ComputePCurveOn2, "B"_a);
nb::class_<BRepAlgoAPI_Splitter, BRepAlgoAPI_BuilderAlgo>(
m, "BRepAlgoAPI_Splitter")
.def(nb::init<>())
.def("SetTools", &BRepAlgoAPI_Splitter::SetTools, "theLS"_a)
.def("Tools", &BRepAlgoAPI_Splitter::Tools, OCP_RETURN_COPY);
}

View File

@@ -0,0 +1,36 @@
/*
OCP.BRepBndLib — bounding box of a shape.
Only Add is used. ``useTriangulation`` matters to callers: with an
existing mesh it is both faster and tighter than the default, which
enlarges the box by the surfaces' own tolerance.
*/
#include "../common/occt_module.h"
#include "../common/occt_policies.h"
#include <BRepBndLib.hxx>
#include <Bnd_Box.hxx>
#include <TopoDS_Shape.hxx>
void register_BRepBndLib(nb::module_ &root) {
nb::module_ m = ocp_submodule(root, "BRepBndLib");
nb::class_<BRepBndLib> cls(m, "BRepBndLib");
OCP_DEF_S(
cls, "Add",
[](const TopoDS_Shape &S, Bnd_Box &B, Standard_Boolean useTriangulation) {
BRepBndLib::Add(S, B, useTriangulation);
},
"S"_a, "B"_a, "useTriangulation"_a = Standard_True, OCP_NOGIL);
OCP_DEF_S(
cls, "AddOptimal",
[](const TopoDS_Shape &S, Bnd_Box &B, Standard_Boolean useTriangulation,
Standard_Boolean useShapeTolerance) {
BRepBndLib::AddOptimal(S, B, useTriangulation, useShapeTolerance);
},
"S"_a, "B"_a, "useTriangulation"_a = Standard_True,
"useShapeTolerance"_a = Standard_False, OCP_NOGIL);
}

View File

@@ -0,0 +1,164 @@
/*
OCP.BRepBuilderAPI — topology construction, and the base class every other
maker in this binding inherits.
BRepBuilderAPI_MakeShape is where Build/Shape/Generated/Modified/IsDeleted
are declared, so binding them once here covers the booleans, the primitive
makers, the fillet/chamfer builders and the splitter through ordinary
virtual dispatch. That matters beyond tidiness: the app's provenance layer
(cad/topology/provenance.py) is deliberately duck-typed over "anything with
a history", and this is what makes every such builder answer it.
Generated/Modified return the builder's own list by reference in C++; they
are copied out here, so the Python list stays valid after the builder dies
and its elements follow the by-value sub-shape rule.
Build() takes a Message_ProgressRange the app never supplies; it is bound
argument-less, per the convention in adding-symbols.md.
*/
#include "../common/occt_module.h"
#include "../common/occt_policies.h"
#include "../common/occt_transient.h"
#include <BRepBuilderAPI_Command.hxx>
#include <BRepBuilderAPI_Copy.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepBuilderAPI_MakePolygon.hxx>
#include <BRepBuilderAPI_MakeShape.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
#include <BRepBuilderAPI_Sewing.hxx>
#include <BRepBuilderAPI_Transform.hxx>
#include <Geom2d_Curve.hxx>
#include <gp_Circ.hxx>
#include <gp_Lin.hxx>
#include <gp_Pln.hxx>
#include <gp_Pnt.hxx>
#include <gp_Trsf.hxx>
#include <Geom_Curve.hxx>
#include <Geom_Surface.hxx>
#include <TopTools_ListOfShape.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Wire.hxx>
void register_BRepBuilderAPI(nb::module_ &root) {
nb::module_ m = ocp_submodule(root, "BRepBuilderAPI");
// Abstract bases: registered for the shared surface, never constructed.
nb::class_<BRepBuilderAPI_Command>(m, "BRepBuilderAPI_Command")
.def("IsDone", &BRepBuilderAPI_Command::IsDone);
nb::class_<BRepBuilderAPI_MakeShape, BRepBuilderAPI_Command>(
m, "BRepBuilderAPI_MakeShape")
.def(
"Build",
[](BRepBuilderAPI_MakeShape &self) { self.Build(); }, OCP_NOGIL)
.def("Shape", &BRepBuilderAPI_MakeShape::Shape, OCP_RETURN_COPY)
.def("Generated", &BRepBuilderAPI_MakeShape::Generated, "S"_a,
OCP_RETURN_COPY)
.def("Modified", &BRepBuilderAPI_MakeShape::Modified, "S"_a,
OCP_RETURN_COPY)
.def("IsDeleted", &BRepBuilderAPI_MakeShape::IsDeleted, "S"_a);
// ------------------------------------------------------------ makers --
nb::class_<BRepBuilderAPI_MakeEdge, BRepBuilderAPI_MakeShape>(
m, "BRepBuilderAPI_MakeEdge")
.def(nb::init<const gp_Pnt &, const gp_Pnt &>(), "P1"_a, "P2"_a)
.def(nb::init<const gp_Circ &>(), "L"_a)
.def(nb::init<const gp_Lin &>(), "L"_a)
.def(nb::init<const opencascade::handle<Geom_Curve> &>(), "L"_a)
.def(nb::init<const opencascade::handle<Geom2d_Curve> &,
const opencascade::handle<Geom_Surface> &>(),
"L"_a, "S"_a)
.def(nb::init<const opencascade::handle<Geom2d_Curve> &,
const opencascade::handle<Geom_Surface> &,
const Standard_Real, const Standard_Real>(),
"L"_a, "S"_a, "p1"_a, "p2"_a)
.def("Edge", &BRepBuilderAPI_MakeEdge::Edge, OCP_RETURN_COPY);
nb::class_<BRepBuilderAPI_MakeWire, BRepBuilderAPI_MakeShape>(
m, "BRepBuilderAPI_MakeWire")
.def(nb::init<>())
.def(nb::init<const TopoDS_Edge &>(), "E"_a)
.def(nb::init<const TopoDS_Wire &>(), "W"_a)
.def("Add", nb::overload_cast<const TopoDS_Edge &>(
&BRepBuilderAPI_MakeWire::Add),
"E"_a)
.def("Add", nb::overload_cast<const TopoDS_Wire &>(
&BRepBuilderAPI_MakeWire::Add),
"W"_a)
.def("Add", nb::overload_cast<const TopTools_ListOfShape &>(
&BRepBuilderAPI_MakeWire::Add),
"L"_a)
.def("Wire", &BRepBuilderAPI_MakeWire::Wire, OCP_RETURN_COPY);
nb::class_<BRepBuilderAPI_MakeFace, BRepBuilderAPI_MakeShape>(
m, "BRepBuilderAPI_MakeFace")
.def(nb::init<const TopoDS_Face &>(), "F"_a)
.def(nb::init<const gp_Pln &>(), "P"_a)
.def(nb::init<const gp_Pln &, const Standard_Real, const Standard_Real,
const Standard_Real, const Standard_Real>(),
"P"_a, "UMin"_a, "UMax"_a, "VMin"_a, "VMax"_a)
.def(nb::init<const TopoDS_Wire &, const Standard_Boolean>(), "W"_a,
"OnlyPlane"_a = Standard_False)
.def(nb::init<const opencascade::handle<Geom_Surface> &,
const TopoDS_Wire &, const Standard_Boolean>(),
"S"_a, "W"_a, "Inside"_a = Standard_True)
.def("Add", &BRepBuilderAPI_MakeFace::Add, "W"_a)
.def("Face", &BRepBuilderAPI_MakeFace::Face, OCP_RETURN_COPY);
nb::class_<BRepBuilderAPI_MakePolygon, BRepBuilderAPI_MakeShape>(
m, "BRepBuilderAPI_MakePolygon")
.def(nb::init<>())
.def(nb::init<const gp_Pnt &, const gp_Pnt &>(), "P1"_a, "P2"_a)
.def(nb::init<const gp_Pnt &, const gp_Pnt &, const gp_Pnt &,
const Standard_Boolean>(),
"P1"_a, "P2"_a, "P3"_a, "Close"_a = Standard_False)
.def(nb::init<const gp_Pnt &, const gp_Pnt &, const gp_Pnt &,
const gp_Pnt &, const Standard_Boolean>(),
"P1"_a, "P2"_a, "P3"_a, "P4"_a, "Close"_a = Standard_False)
.def("Add", nb::overload_cast<const gp_Pnt &>(
&BRepBuilderAPI_MakePolygon::Add),
"P"_a)
.def("Added", &BRepBuilderAPI_MakePolygon::Added)
.def("Close", &BRepBuilderAPI_MakePolygon::Close)
.def("Wire", &BRepBuilderAPI_MakePolygon::Wire, OCP_RETURN_COPY);
nb::class_<BRepBuilderAPI_Transform, BRepBuilderAPI_MakeShape>(
m, "BRepBuilderAPI_Transform")
.def(nb::init<const gp_Trsf &>(), "T"_a)
.def(nb::init<const TopoDS_Shape &, const gp_Trsf &,
const Standard_Boolean, const Standard_Boolean>(),
"theShape"_a, "theTrsf"_a, "theCopyGeom"_a = Standard_False,
"theCopyMesh"_a = Standard_False, OCP_NOGIL)
.def("ModifiedShape", &BRepBuilderAPI_Transform::ModifiedShape, "S"_a,
OCP_RETURN_COPY);
nb::class_<BRepBuilderAPI_Copy, BRepBuilderAPI_MakeShape>(
m, "BRepBuilderAPI_Copy")
.def(nb::init<>())
.def(nb::init<const TopoDS_Shape &, const Standard_Boolean,
const Standard_Boolean>(),
"S"_a, "copyGeom"_a = Standard_True,
"copyMesh"_a = Standard_False, OCP_NOGIL);
// Sewing is a transient and not a MakeShape — it has its own result
// accessor rather than Shape().
nb::class_<BRepBuilderAPI_Sewing, Standard_Transient>(
m, "BRepBuilderAPI_Sewing")
.def(ocp_new<BRepBuilderAPI_Sewing, const Standard_Real,
const Standard_Boolean, const Standard_Boolean,
const Standard_Boolean, const Standard_Boolean>(),
"tolerance"_a = 1.0e-06, "option1"_a = Standard_True,
"option2"_a = Standard_True, "option3"_a = Standard_True,
"option4"_a = Standard_False)
.def("Add", &BRepBuilderAPI_Sewing::Add, "shape"_a)
.def(
"Perform", [](BRepBuilderAPI_Sewing &self) { self.Perform(); },
OCP_NOGIL)
.def("SewedShape", &BRepBuilderAPI_Sewing::SewedShape, OCP_RETURN_COPY);
}

View File

@@ -0,0 +1,73 @@
/*
OCP.BRepGProp — mass properties of a shape.
Three statics, all filling a GProp_GProps: LinearProperties (edge length),
SurfaceProperties (area) and VolumeProperties. Both eps overloads are
bound: the default quadrature is inaccurate on spline-bounded faces, and
the app's area readouts may move onto the eps form (see the app's
NOTEPAD). A test already depends on the 3-argument form.
SurfaceProperties is the single hottest kernel call in a rebuild — 94 % of
face_candidate_anchors — so the GIL is released here and n3xd_ocp.measure
offers the batched form.
*/
#include "../common/occt_module.h"
#include "../common/occt_policies.h"
#include <BRepGProp.hxx>
#include <GProp_GProps.hxx>
#include <TopoDS_Shape.hxx>
void register_BRepGProp(nb::module_ &root) {
nb::module_ m = ocp_submodule(root, "BRepGProp");
nb::class_<BRepGProp> cls(m, "BRepGProp");
OCP_DEF_S(
cls, "LinearProperties",
[](const TopoDS_Shape &S, GProp_GProps &LProps, Standard_Boolean SkipShared,
Standard_Boolean UseTriangulation) {
BRepGProp::LinearProperties(S, LProps, SkipShared, UseTriangulation);
},
"S"_a, "LProps"_a, "SkipShared"_a = Standard_False,
"UseTriangulation"_a = Standard_False, OCP_NOGIL);
OCP_DEF_S(
cls, "SurfaceProperties",
[](const TopoDS_Shape &S, GProp_GProps &SProps, Standard_Boolean SkipShared,
Standard_Boolean UseTriangulation) {
BRepGProp::SurfaceProperties(S, SProps, SkipShared, UseTriangulation);
},
"S"_a, "SProps"_a, "SkipShared"_a = Standard_False,
"UseTriangulation"_a = Standard_False, OCP_NOGIL);
OCP_DEF_S(
cls, "SurfaceProperties",
[](const TopoDS_Shape &S, GProp_GProps &SProps, Standard_Real Eps,
Standard_Boolean SkipShared) {
return BRepGProp::SurfaceProperties(S, SProps, Eps, SkipShared);
},
"S"_a, "SProps"_a, "Eps"_a, "SkipShared"_a = Standard_False, OCP_NOGIL);
OCP_DEF_S(
cls, "VolumeProperties",
[](const TopoDS_Shape &S, GProp_GProps &VProps, Standard_Boolean OnlyClosed,
Standard_Boolean SkipShared, Standard_Boolean UseTriangulation) {
BRepGProp::VolumeProperties(S, VProps, OnlyClosed, SkipShared,
UseTriangulation);
},
"S"_a, "VProps"_a, "OnlyClosed"_a = Standard_False,
"SkipShared"_a = Standard_False, "UseTriangulation"_a = Standard_False,
OCP_NOGIL);
OCP_DEF_S(
cls, "VolumeProperties",
[](const TopoDS_Shape &S, GProp_GProps &VProps, Standard_Real Eps,
Standard_Boolean OnlyClosed, Standard_Boolean SkipShared) {
return BRepGProp::VolumeProperties(S, VProps, Eps, OnlyClosed,
SkipShared);
},
"S"_a, "VProps"_a, "Eps"_a, "OnlyClosed"_a = Standard_False,
"SkipShared"_a = Standard_False, OCP_NOGIL);
}

View File

@@ -0,0 +1,35 @@
/*
OCP.BRepMesh — triangulation.
One class, always constructed in its executing form: meshing a shape has
no deferred API, and the result is written into the shape rather than
returned. The GIL is released for it — this is one of the longest single
kernel calls a rebuild makes, and the app already runs it with OCCT's own
parallel flag on.
In 7.9 BRepMesh_IncrementalMesh is a transient (via BRepMesh_DiscretRoot),
so its constructor goes through ocp_new.
*/
#include "../common/occt_module.h"
#include "../common/occt_policies.h"
#include "../common/occt_transient.h"
#include <BRepMesh_IncrementalMesh.hxx>
#include <TopoDS_Shape.hxx>
void register_BRepMesh(nb::module_ &root) {
nb::module_ m = ocp_submodule(root, "BRepMesh");
nb::class_<BRepMesh_IncrementalMesh, Standard_Transient>(
m, "BRepMesh_IncrementalMesh")
.def(ocp_new<BRepMesh_IncrementalMesh>())
.def(ocp_new<BRepMesh_IncrementalMesh, const TopoDS_Shape &,
const Standard_Real, const Standard_Boolean,
const Standard_Real, const Standard_Boolean>(),
"theShape"_a, "theLinDeflection"_a,
"isRelative"_a = Standard_False, "theAngDeflection"_a = 0.5,
"isInParallel"_a = Standard_False, OCP_NOGIL)
.def("IsDone", &BRepMesh_IncrementalMesh::IsDone)
.def("IsModified", &BRepMesh_IncrementalMesh::IsModified);
}

View File

@@ -0,0 +1,110 @@
/*
OCP.BRepPrimAPI — primitive solids and sweeps.
Every one of these is a BRepBuilderAPI_MakeShape, so Build/Shape and the
history come from there. MakePrism matters for history in particular: an
extrude's provenance is read off it exactly as a boolean's is.
These constructors do build their shape, and there is no deferred form to
prefer — unlike the BRepAlgoAPI booleans, whose two-argument constructors
duplicate an explicit Build(). They are bound as stock does.
MakeHalfSpace produces an infinite solid used as a clipping operand; its
result comes back through Solid(), not Shape().
*/
#include "../common/occt_module.h"
#include "../common/occt_policies.h"
#include <BRepBuilderAPI_MakeShape.hxx>
#include <BRepPrimAPI_MakeBox.hxx>
#include <BRepPrimAPI_MakeCone.hxx>
#include <BRepPrimAPI_MakeCylinder.hxx>
#include <BRepPrimAPI_MakeHalfSpace.hxx>
#include <BRepPrimAPI_MakePrism.hxx>
#include <BRepPrimAPI_MakeRevol.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Shell.hxx>
#include <gp_Ax1.hxx>
#include <gp_Ax2.hxx>
#include <gp_Pnt.hxx>
#include <gp_Vec.hxx>
#include <TopoDS_Shape.hxx>
void register_BRepPrimAPI(nb::module_ &root) {
nb::module_ m = ocp_submodule(root, "BRepPrimAPI");
nb::class_<BRepPrimAPI_MakeBox, BRepBuilderAPI_MakeShape>(
m, "BRepPrimAPI_MakeBox")
.def(nb::init<const Standard_Real, const Standard_Real,
const Standard_Real>(),
"dx"_a, "dy"_a, "dz"_a)
.def(nb::init<const gp_Pnt &, const Standard_Real, const Standard_Real,
const Standard_Real>(),
"P"_a, "dx"_a, "dy"_a, "dz"_a)
.def(nb::init<const gp_Pnt &, const gp_Pnt &>(), "P1"_a, "P2"_a)
.def(nb::init<const gp_Ax2 &, const Standard_Real, const Standard_Real,
const Standard_Real>(),
"Axes"_a, "dx"_a, "dy"_a, "dz"_a);
nb::class_<BRepPrimAPI_MakeCylinder, BRepBuilderAPI_MakeShape>(
m, "BRepPrimAPI_MakeCylinder")
.def(nb::init<const Standard_Real, const Standard_Real>(), "R"_a, "H"_a)
.def(nb::init<const Standard_Real, const Standard_Real,
const Standard_Real>(),
"R"_a, "H"_a, "Angle"_a)
.def(nb::init<const gp_Ax2 &, const Standard_Real,
const Standard_Real>(),
"Axes"_a, "R"_a, "H"_a)
.def(nb::init<const gp_Ax2 &, const Standard_Real, const Standard_Real,
const Standard_Real>(),
"Axes"_a, "R"_a, "H"_a, "Angle"_a);
nb::class_<BRepPrimAPI_MakeCone, BRepBuilderAPI_MakeShape>(
m, "BRepPrimAPI_MakeCone")
.def(nb::init<const Standard_Real, const Standard_Real,
const Standard_Real>(),
"R1"_a, "R2"_a, "H"_a)
.def(nb::init<const gp_Ax2 &, const Standard_Real, const Standard_Real,
const Standard_Real>(),
"Axes"_a, "R1"_a, "R2"_a, "H"_a);
nb::class_<BRepPrimAPI_MakeHalfSpace, BRepBuilderAPI_MakeShape>(
m, "BRepPrimAPI_MakeHalfSpace")
.def(nb::init<const TopoDS_Face &, const gp_Pnt &>(), "Face"_a,
"RefPnt"_a)
.def(nb::init<const TopoDS_Shell &, const gp_Pnt &>(), "Shell"_a,
"RefPnt"_a)
.def("Solid", &BRepPrimAPI_MakeHalfSpace::Solid, OCP_RETURN_COPY);
// Only the finite (gp_Vec) form is bound. The sibling overload takes a
// gp_Dir for a semi-infinite prism, and gp_Dir converts implicitly from
// gp_Vec — so binding both invites a call meant for one to land silently
// on the other, with valid but wrong geometry. The app builds finite
// prisms only.
nb::class_<BRepPrimAPI_MakePrism, BRepBuilderAPI_MakeShape>(
m, "BRepPrimAPI_MakePrism")
.def(nb::init<const TopoDS_Shape &, const gp_Vec &,
const Standard_Boolean, const Standard_Boolean>(),
"S"_a, "V"_a, "Copy"_a = Standard_False,
"Canonize"_a = Standard_True, OCP_NOGIL)
.def("FirstShape",
nb::overload_cast<>(&BRepPrimAPI_MakePrism::FirstShape),
OCP_RETURN_COPY)
.def("LastShape", nb::overload_cast<>(&BRepPrimAPI_MakePrism::LastShape),
OCP_RETURN_COPY);
nb::class_<BRepPrimAPI_MakeRevol, BRepBuilderAPI_MakeShape>(
m, "BRepPrimAPI_MakeRevol")
.def(nb::init<const TopoDS_Shape &, const gp_Ax1 &, const Standard_Real,
const Standard_Boolean>(),
"S"_a, "A"_a, "D"_a, "Copy"_a = Standard_False, OCP_NOGIL)
.def(nb::init<const TopoDS_Shape &, const gp_Ax1 &,
const Standard_Boolean>(),
"S"_a, "A"_a, "Copy"_a = Standard_False, OCP_NOGIL)
.def("FirstShape",
nb::overload_cast<>(&BRepPrimAPI_MakeRevol::FirstShape),
OCP_RETURN_COPY)
.def("LastShape", nb::overload_cast<>(&BRepPrimAPI_MakeRevol::LastShape),
OCP_RETURN_COPY);
}

54
src/modules/mod_Bnd.cpp Normal file
View File

@@ -0,0 +1,54 @@
/*
OCP.Bnd — axis-aligned bounding boxes.
Get() returns six scalar out-parameters as a tuple, which is how the app
unpacks it (`xmin, ymin, zmin, xmax, ymax, zmax = box.Get()`) and what
upstream OCP does. A void box raises from OCCT, so callers check IsVoid
first.
*/
#include "../common/occt_module.h"
#include "../common/occt_policies.h"
#include <nanobind/stl/tuple.h>
#include <Bnd_Box.hxx>
#include <gp_Pnt.hxx>
#include <gp_Trsf.hxx>
void register_Bnd(nb::module_ &root) {
nb::module_ m = ocp_submodule(root, "Bnd");
nb::class_<Bnd_Box>(m, "Bnd_Box")
.def(nb::init<>())
.def(nb::init<const gp_Pnt &, const gp_Pnt &>(), "theMin"_a, "theMax"_a)
.def("Get",
[](const Bnd_Box &self) {
Standard_Real xmin = 0.0, ymin = 0.0, zmin = 0.0;
Standard_Real xmax = 0.0, ymax = 0.0, zmax = 0.0;
self.Get(xmin, ymin, zmin, xmax, ymax, zmax);
return std::make_tuple(xmin, ymin, zmin, xmax, ymax, zmax);
})
.def("CornerMin", &Bnd_Box::CornerMin, OCP_RETURN_COPY)
.def("CornerMax", &Bnd_Box::CornerMax, OCP_RETURN_COPY)
.def("IsVoid", &Bnd_Box::IsVoid)
.def("SetVoid", &Bnd_Box::SetVoid)
.def("SetGap", &Bnd_Box::SetGap, "Tol"_a)
.def("GetGap", &Bnd_Box::GetGap)
.def("Add", nb::overload_cast<const Bnd_Box &>(&Bnd_Box::Add), "Other"_a)
.def("Add", nb::overload_cast<const gp_Pnt &>(&Bnd_Box::Add), "P"_a)
.def("Update", nb::overload_cast<const Standard_Real, const Standard_Real,
const Standard_Real, const Standard_Real,
const Standard_Real, const Standard_Real>(
&Bnd_Box::Update),
"aXmin"_a, "aYmin"_a, "aZmin"_a, "aXmax"_a, "aYmax"_a, "aZmax"_a)
.def("Enlarge", &Bnd_Box::Enlarge, "Tol"_a)
.def("IsOut", nb::overload_cast<const gp_Pnt &>(&Bnd_Box::IsOut,
nb::const_),
"P"_a)
.def("IsOut", nb::overload_cast<const Bnd_Box &>(&Bnd_Box::IsOut,
nb::const_),
"Other"_a)
.def("SquareExtent", &Bnd_Box::SquareExtent)
.def("Transformed", &Bnd_Box::Transformed, "T"_a, OCP_RETURN_COPY);
}

25
src/modules/mod_GC.cpp Normal file
View File

@@ -0,0 +1,25 @@
/*
OCP.GC — 3D geometry constructors.
One use: the sketch builder turns a three-point arc into a trimmed circle
before handing it to BRepBuilderAPI_MakeEdge.
*/
#include "../common/occt_module.h"
#include <GC_MakeArcOfCircle.hxx>
#include <gp_Circ.hxx>
#include <gp_Pnt.hxx>
void register_GC(nb::module_ &root) {
nb::module_ m = ocp_submodule(root, "GC");
nb::class_<GC_MakeArcOfCircle>(m, "GC_MakeArcOfCircle")
.def(nb::init<const gp_Pnt &, const gp_Pnt &, const gp_Pnt &>(), "P1"_a,
"P2"_a, "P3"_a)
.def(nb::init<const gp_Circ &, const gp_Pnt &, const gp_Pnt &,
const Standard_Boolean>(),
"Circ"_a, "P1"_a, "P2"_a, "Sense"_a)
.def("IsDone", &GC_MakeArcOfCircle::IsDone)
.def("Value", &GC_MakeArcOfCircle::Value);
}

57
src/modules/mod_GProp.cpp Normal file
View File

@@ -0,0 +1,57 @@
/*
OCP.GProp — the result object every mass measurement writes into.
BRepGProp fills a GProp_GProps; the app reads Mass() (which is length, area
or volume depending on which BRepGProp entry point ran) and CentreOfMass().
The principal-axis block is used once, by cad/measurement.py's inertia
readout.
OCCT reports the moments and radii through scalar out-parameters; those
become tuples here, matching upstream OCP. Object out-parameters stay
out-parameters (see BRep_Tool.Triangulation_s) — the distinction is that a
caller cannot pre-allocate a Standard_Real to be written through.
*/
#include "../common/occt_module.h"
#include "../common/occt_policies.h"
#include <nanobind/stl/tuple.h>
#include <GProp_GProps.hxx>
#include <GProp_PrincipalProps.hxx>
#include <gp_Pnt.hxx>
#include <gp_Vec.hxx>
void register_GProp(nb::module_ &root) {
nb::module_ m = ocp_submodule(root, "GProp");
nb::class_<GProp_PrincipalProps>(m, "GProp_PrincipalProps")
.def(nb::init<>())
.def("Moments",
[](const GProp_PrincipalProps &self) {
Standard_Real ixx = 0.0, iyy = 0.0, izz = 0.0;
self.Moments(ixx, iyy, izz);
return std::make_tuple(ixx, iyy, izz);
})
.def("RadiusOfGyration",
[](const GProp_PrincipalProps &self) {
Standard_Real rxx = 0.0, ryy = 0.0, rzz = 0.0;
self.RadiusOfGyration(rxx, ryy, rzz);
return std::make_tuple(rxx, ryy, rzz);
})
.def("FirstAxisOfInertia", &GProp_PrincipalProps::FirstAxisOfInertia,
OCP_RETURN_COPY)
.def("SecondAxisOfInertia", &GProp_PrincipalProps::SecondAxisOfInertia,
OCP_RETURN_COPY)
.def("ThirdAxisOfInertia", &GProp_PrincipalProps::ThirdAxisOfInertia,
OCP_RETURN_COPY);
nb::class_<GProp_GProps>(m, "GProp_GProps")
.def(nb::init<>())
.def(nb::init<const gp_Pnt &>(), "SLocation"_a)
.def("Mass", &GProp_GProps::Mass)
.def("CentreOfMass", &GProp_GProps::CentreOfMass, OCP_RETURN_COPY)
.def("PrincipalProperties", &GProp_GProps::PrincipalProperties,
OCP_RETURN_COPY)
.def("Add", &GProp_GProps::Add, "Item"_a, "Density"_a = 1.0);
}

87
src/modules/mod_Geom.cpp Normal file
View File

@@ -0,0 +1,87 @@
/*
OCP.Geom — the analytic curves and surfaces behind the topology.
The app imports only three of these, but it *receives* the two abstract
bases: BRep_Tool.Surface_s hands back a Handle(Geom_Surface), and
GC_MakeArcOfCircle a Handle(Geom_TrimmedCurve), both of which then travel
into BRepBuilderAPI_MakeEdge/MakeFace. So the bases have to be registered
for those returns to convert, and the concrete leaves for the constructors
the app calls.
Deliberately partial: the concrete subclasses OCCT may hand back
(Geom_Plane, Geom_Circle, ...) are not registered, so such a return arrives
as its static type, Geom_Surface. That is fine here — the app reads
surface *kinds* off BRepAdaptor_Surface, never off the Geom object, and no
call site does DownCast or isinstance on one. Add a leaf the day one does.
Surface_s returns the face's live surface when the location is identity, a
transformed copy otherwise; the handle caster wraps whatever OCCT gives
back without copying, which is upstream's behaviour too.
*/
#include "../common/occt_module.h"
#include "../common/occt_policies.h"
#include "../common/occt_transient.h"
#include <Geom_BSplineCurve.hxx>
#include <Geom_BSplineSurface.hxx>
#include <Geom_CylindricalSurface.hxx>
#include <Geom_OffsetSurface.hxx>
#include <Geom_Surface.hxx>
#include <Geom_TrimmedCurve.hxx>
#include <TColStd_Array1OfInteger.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <gp_Ax3.hxx>
#include <gp_Pnt.hxx>
void register_Geom(nb::module_ &root) {
nb::module_ m = ocp_submodule(root, "Geom");
// ------------------------------------------------------------ curves --
nb::class_<Geom_Curve, Standard_Transient>(m, "Geom_Curve")
.def("FirstParameter", &Geom_Curve::FirstParameter)
.def("LastParameter", &Geom_Curve::LastParameter)
.def("IsClosed", &Geom_Curve::IsClosed)
.def("IsPeriodic", &Geom_Curve::IsPeriodic)
.def("Value", &Geom_Curve::Value, "U"_a, OCP_RETURN_COPY);
nb::class_<Geom_TrimmedCurve, Geom_Curve>(m, "Geom_TrimmedCurve");
nb::class_<Geom_BSplineCurve, Geom_Curve>(m, "Geom_BSplineCurve")
.def(ocp_new<Geom_BSplineCurve, const TColgp_Array1OfPnt &,
const TColStd_Array1OfReal &,
const TColStd_Array1OfInteger &, const Standard_Integer,
const Standard_Boolean>(),
"Poles"_a, "Knots"_a, "Multiplicities"_a, "Degree"_a,
"Periodic"_a = Standard_False)
.def("Degree", &Geom_BSplineCurve::Degree)
.def("NbPoles", &Geom_BSplineCurve::NbPoles)
.def("NbKnots", &Geom_BSplineCurve::NbKnots);
// ---------------------------------------------------------- surfaces --
nb::class_<Geom_Surface, Standard_Transient>(m, "Geom_Surface")
.def("Value", &Geom_Surface::Value, "U"_a, "V"_a, OCP_RETURN_COPY)
.def("IsUPeriodic", &Geom_Surface::IsUPeriodic)
.def("IsVPeriodic", &Geom_Surface::IsVPeriodic)
.def("IsUClosed", &Geom_Surface::IsUClosed)
.def("IsVClosed", &Geom_Surface::IsVClosed);
nb::class_<Geom_BSplineSurface, Geom_Surface>(m, "Geom_BSplineSurface");
nb::class_<Geom_CylindricalSurface, Geom_Surface>(m,
"Geom_CylindricalSurface")
.def(ocp_new<Geom_CylindricalSurface, const gp_Ax3 &,
const Standard_Real>(),
"A3"_a, "Radius"_a)
.def("Radius", &Geom_CylindricalSurface::Radius);
nb::class_<Geom_OffsetSurface, Geom_Surface>(m, "Geom_OffsetSurface")
.def(ocp_new<Geom_OffsetSurface, const opencascade::handle<Geom_Surface> &,
const Standard_Real, const Standard_Boolean>(),
"S"_a, "Offset"_a, "isNotCheckC0"_a = Standard_False)
.def("Offset", &Geom_OffsetSurface::Offset)
.def("BasisSurface", &Geom_OffsetSurface::BasisSurface);
}

View File

@@ -0,0 +1,30 @@
/*
OCP.Geom2d — parametric-space curves.
Not imported by the app, but unavoidable: GCE2d_MakeLine/MakeSegment return
these, and BRepBuilderAPI_MakeEdge takes the Geom2d_Curve base when it
builds an edge on a surface (thread.py lays a helix out as a line in the
cylinder's UV space). Only registration matters — no method on them is
ever called.
The declared base is Standard_Transient, skipping Geom2d_Geometry: nanobind
needs an unambiguous public upcast, not the full chain.
*/
#include "../common/occt_module.h"
#include <Geom2d_Curve.hxx>
#include <Geom2d_Line.hxx>
#include <Geom2d_TrimmedCurve.hxx>
void register_Geom2d(nb::module_ &root) {
nb::module_ m = ocp_submodule(root, "Geom2d");
// Abstract: no constructor. Registered so handles to it convert at all.
nb::class_<Geom2d_Curve, Standard_Transient>(m, "Geom2d_Curve")
.def("FirstParameter", &Geom2d_Curve::FirstParameter)
.def("LastParameter", &Geom2d_Curve::LastParameter);
nb::class_<Geom2d_Line, Geom2d_Curve>(m, "Geom2d_Line");
nb::class_<Geom2d_TrimmedCurve, Geom2d_Curve>(m, "Geom2d_TrimmedCurve");
}

View File

@@ -0,0 +1,59 @@
/*
OCP.GeomAPI — point projection and surface fitting.
Both compute in their constructor and expose no deferred Build(), so they
are bound exactly as stock does. The no-executing-constructor rule targets
the BRepAlgoAPI booleans, where a deferred SetX/Build form exists and the
constructor silently duplicates it; it does not apply here (see
adding-symbols.md).
LowerDistanceParameters returns its two scalars as a tuple, which is how
the app unpacks it. ProjectPointOnSurf keeps the GIL: it is measured in
microseconds and runs inside per-face Python loops, where the release
handshake would cost more than the call.
*/
#include "../common/occt_module.h"
#include "../common/occt_policies.h"
#include <nanobind/stl/tuple.h>
#include <GeomAPI_PointsToBSplineSurface.hxx>
#include <GeomAPI_ProjectPointOnSurf.hxx>
#include <GeomAbs_Shape.hxx>
#include <Geom_BSplineSurface.hxx>
#include <Geom_Surface.hxx>
#include <gp_Pnt.hxx>
#include <TColgp_Array2OfPnt.hxx>
void register_GeomAPI(nb::module_ &root) {
nb::module_ m = ocp_submodule(root, "GeomAPI");
nb::class_<GeomAPI_ProjectPointOnSurf>(m, "GeomAPI_ProjectPointOnSurf")
// The Extrema_ExtAlgo overload is left out: binding it would drag in
// the Extrema enum only to carry a default the app never overrides,
// and an unregistered default argument fails at module-init time.
.def(nb::init<const gp_Pnt &, const opencascade::handle<Geom_Surface> &>(),
"P"_a, "Surface"_a)
.def("IsDone", &GeomAPI_ProjectPointOnSurf::IsDone)
.def("NbPoints", &GeomAPI_ProjectPointOnSurf::NbPoints)
.def("LowerDistance", &GeomAPI_ProjectPointOnSurf::LowerDistance)
.def("NearestPoint", &GeomAPI_ProjectPointOnSurf::NearestPoint,
OCP_RETURN_COPY)
.def("LowerDistanceParameters",
[](const GeomAPI_ProjectPointOnSurf &self) {
Standard_Real u = 0.0, v = 0.0;
self.LowerDistanceParameters(u, v);
return std::make_tuple(u, v);
});
nb::class_<GeomAPI_PointsToBSplineSurface>(m, "GeomAPI_PointsToBSplineSurface")
.def(nb::init<>())
.def(nb::init<const TColgp_Array2OfPnt &, const Standard_Integer,
const Standard_Integer, const GeomAbs_Shape,
const Standard_Real>(),
"Points"_a, "DegMin"_a = 3, "DegMax"_a = 8,
"Continuity"_a = GeomAbs_C2, "Tol3D"_a = 1.0e-3, OCP_NOGIL)
.def("IsDone", &GeomAPI_PointsToBSplineSurface::IsDone)
.def("Surface", &GeomAPI_PointsToBSplineSurface::Surface);
}

View File

@@ -0,0 +1,55 @@
/*
OCP.GeomAbs — the curve/surface type tags the adaptors report.
The app reads these off BRepAdaptor_Curve/Surface.GetType() to decide what
a face or edge *is* (plane, cylinder, circle, spline), which drives
reference inference, anchor scoring and hole recognition. Only the
continuity value GeomAbs_C2 is used as an input, by
GeomAPI_PointsToBSplineSurface.
*/
#include "../common/occt_module.h"
#include <GeomAbs_CurveType.hxx>
#include <GeomAbs_Shape.hxx>
#include <GeomAbs_SurfaceType.hxx>
void register_GeomAbs(nb::module_ &root) {
nb::module_ m = ocp_submodule(root, "GeomAbs");
nb::enum_<GeomAbs_CurveType>(m, "GeomAbs_CurveType", nb::is_arithmetic())
.value("GeomAbs_Line", GeomAbs_Line)
.value("GeomAbs_Circle", GeomAbs_Circle)
.value("GeomAbs_Ellipse", GeomAbs_Ellipse)
.value("GeomAbs_Hyperbola", GeomAbs_Hyperbola)
.value("GeomAbs_Parabola", GeomAbs_Parabola)
.value("GeomAbs_BezierCurve", GeomAbs_BezierCurve)
.value("GeomAbs_BSplineCurve", GeomAbs_BSplineCurve)
.value("GeomAbs_OffsetCurve", GeomAbs_OffsetCurve)
.value("GeomAbs_OtherCurve", GeomAbs_OtherCurve)
.export_values();
nb::enum_<GeomAbs_SurfaceType>(m, "GeomAbs_SurfaceType", nb::is_arithmetic())
.value("GeomAbs_Plane", GeomAbs_Plane)
.value("GeomAbs_Cylinder", GeomAbs_Cylinder)
.value("GeomAbs_Cone", GeomAbs_Cone)
.value("GeomAbs_Sphere", GeomAbs_Sphere)
.value("GeomAbs_Torus", GeomAbs_Torus)
.value("GeomAbs_BezierSurface", GeomAbs_BezierSurface)
.value("GeomAbs_BSplineSurface", GeomAbs_BSplineSurface)
.value("GeomAbs_SurfaceOfRevolution", GeomAbs_SurfaceOfRevolution)
.value("GeomAbs_SurfaceOfExtrusion", GeomAbs_SurfaceOfExtrusion)
.value("GeomAbs_OffsetSurface", GeomAbs_OffsetSurface)
.value("GeomAbs_OtherSurface", GeomAbs_OtherSurface)
.export_values();
nb::enum_<GeomAbs_Shape>(m, "GeomAbs_Shape", nb::is_arithmetic())
.value("GeomAbs_C0", GeomAbs_C0)
.value("GeomAbs_G1", GeomAbs_G1)
.value("GeomAbs_C1", GeomAbs_C1)
.value("GeomAbs_G2", GeomAbs_G2)
.value("GeomAbs_C2", GeomAbs_C2)
.value("GeomAbs_C3", GeomAbs_C3)
.value("GeomAbs_CN", GeomAbs_CN)
.export_values();
}

View File

@@ -0,0 +1,32 @@
/*
OCP.GeomLProp — local surface properties.
One use: text emboss reads the surface normal at the anchor's UV to decide
which way the glyph solid grows out of a curved face.
OCCT 8.0 supersedes this package with GeomProp/BRepProp (results come back
as structs carrying IsDefined flags instead of throwing). Only Normal()
is bound, so the port is a one-line move — see design.md's 8.0 watchlist.
*/
#include "../common/occt_module.h"
#include "../common/occt_policies.h"
#include <GeomLProp_SLProps.hxx>
#include <Geom_Surface.hxx>
#include <gp_Dir.hxx>
#include <gp_Pnt.hxx>
void register_GeomLProp(nb::module_ &root) {
nb::module_ m = ocp_submodule(root, "GeomLProp");
nb::class_<GeomLProp_SLProps>(m, "GeomLProp_SLProps")
.def(nb::init<const opencascade::handle<Geom_Surface> &, const Standard_Real,
const Standard_Real, const Standard_Integer,
const Standard_Real>(),
"S"_a, "U"_a, "V"_a, "N"_a, "Resolution"_a)
.def("Value", &GeomLProp_SLProps::Value, OCP_RETURN_COPY)
.def("Normal", &GeomLProp_SLProps::Normal, OCP_RETURN_COPY)
.def("IsNormalDefined", &GeomLProp_SLProps::IsNormalDefined)
.def("SetParameters", &GeomLProp_SLProps::SetParameters, "U"_a, "V"_a);
}

View File

@@ -0,0 +1,67 @@
/*
OCP.TColStd — the plain integer/real arrays a B-spline definition needs
(knots and multiplicities in sketch_builder/edges.py), plus the string
sequence the IGES reader fills with unit names.
NCollection's SetValue/Value are overloaded (const ref and rvalue), so they
are bound through lambdas rather than member pointers.
*/
#include "../common/occt_module.h"
#include "../common/occt_policies.h"
#include <TColStd_Array1OfInteger.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <TColStd_SequenceOfAsciiString.hxx>
namespace {
/// Bind one NCollection_Array1<T> instantiation with the app's surface.
template <typename A, typename T>
void bind_array1(nb::module_ &m, const char *name) {
nb::class_<A>(m, name)
.def(nb::init<const Standard_Integer, const Standard_Integer>(),
"theLower"_a, "theUpper"_a)
.def(
"SetValue",
[](A &self, Standard_Integer index, const T &value) {
self.SetValue(index, value);
},
"theIndex"_a, "theValue"_a)
.def(
"Value",
[](const A &self, Standard_Integer index) { return self.Value(index); },
"theIndex"_a)
.def("Length", &A::Length)
.def("Lower", &A::Lower)
.def("Upper", &A::Upper)
.def("__len__", &A::Length);
}
} // namespace
void register_TColStd(nb::module_ &root) {
nb::module_ m = ocp_submodule(root, "TColStd");
bind_array1<TColStd_Array1OfInteger, Standard_Integer>(
m, "TColStd_Array1OfInteger");
bind_array1<TColStd_Array1OfReal, Standard_Real>(m, "TColStd_Array1OfReal");
nb::class_<TColStd_SequenceOfAsciiString>(m, "TColStd_SequenceOfAsciiString")
.def(nb::init<>())
.def("Length", &TColStd_SequenceOfAsciiString::Length)
.def("IsEmpty", &TColStd_SequenceOfAsciiString::IsEmpty)
.def(
"Value",
[](const TColStd_SequenceOfAsciiString &self, Standard_Integer i) {
return self.Value(i);
},
"theIndex"_a)
.def(
"Append",
[](TColStd_SequenceOfAsciiString &self,
const TCollection_AsciiString &v) { self.Append(v); },
"theItem"_a)
.def("Clear", [](TColStd_SequenceOfAsciiString &self) { self.Clear(); })
.def("__len__", &TColStd_SequenceOfAsciiString::Length);
}

View File

@@ -0,0 +1,59 @@
/*
OCP.TColgp — point arrays.
Array1 carries B-spline poles (sketch_builder/edges.py); Array2 carries the
control grid GeomAPI_PointsToBSplineSurface fits a smooth surface through.
*/
#include "../common/occt_module.h"
#include <TColgp_Array1OfPnt.hxx>
#include <TColgp_Array2OfPnt.hxx>
#include <gp_Pnt.hxx>
void register_TColgp(nb::module_ &root) {
nb::module_ m = ocp_submodule(root, "TColgp");
nb::class_<TColgp_Array1OfPnt>(m, "TColgp_Array1OfPnt")
.def(nb::init<const Standard_Integer, const Standard_Integer>(),
"theLower"_a, "theUpper"_a)
.def(
"SetValue",
[](TColgp_Array1OfPnt &self, Standard_Integer i, const gp_Pnt &v) {
self.SetValue(i, v);
},
"theIndex"_a, "theValue"_a)
.def(
"Value",
[](const TColgp_Array1OfPnt &self, Standard_Integer i) {
return self.Value(i);
},
"theIndex"_a)
.def("Length", &TColgp_Array1OfPnt::Length)
.def("Lower", &TColgp_Array1OfPnt::Lower)
.def("Upper", &TColgp_Array1OfPnt::Upper)
.def("__len__", &TColgp_Array1OfPnt::Length);
nb::class_<TColgp_Array2OfPnt>(m, "TColgp_Array2OfPnt")
.def(nb::init<const Standard_Integer, const Standard_Integer,
const Standard_Integer, const Standard_Integer>(),
"theRowLower"_a, "theRowUpper"_a, "theColLower"_a, "theColUpper"_a)
.def(
"SetValue",
[](TColgp_Array2OfPnt &self, Standard_Integer row,
Standard_Integer col, const gp_Pnt &v) {
self.SetValue(row, col, v);
},
"theRow"_a, "theCol"_a, "theValue"_a)
.def(
"Value",
[](const TColgp_Array2OfPnt &self, Standard_Integer row,
Standard_Integer col) { return self.Value(row, col); },
"theRow"_a, "theCol"_a)
.def("RowLength", &TColgp_Array2OfPnt::RowLength)
.def("ColLength", &TColgp_Array2OfPnt::ColLength)
.def("LowerRow", &TColgp_Array2OfPnt::LowerRow)
.def("UpperRow", &TColgp_Array2OfPnt::UpperRow)
.def("LowerCol", &TColgp_Array2OfPnt::LowerCol)
.def("UpperCol", &TColgp_Array2OfPnt::UpperCol);
}

View File

@@ -0,0 +1,24 @@
/*
OCP.TCollection — OCCT's own string type.
Not imported by the app directly: it arrives as the element type of
TColStd_SequenceOfAsciiString, which the IGES reader fills with unit names
(`import_.py` reads them back through ToCString).
*/
#include "../common/occt_module.h"
#include <TCollection_AsciiString.hxx>
void register_TCollection(nb::module_ &root) {
nb::module_ m = ocp_submodule(root, "TCollection");
nb::class_<TCollection_AsciiString>(m, "TCollection_AsciiString")
.def(nb::init<>())
.def(nb::init<const Standard_CString>(), "message"_a)
.def("ToCString", &TCollection_AsciiString::ToCString)
.def("Length", &TCollection_AsciiString::Length)
.def("IsEmpty", &TCollection_AsciiString::IsEmpty)
.def("__len__", &TCollection_AsciiString::Length)
.def("__str__", &TCollection_AsciiString::ToCString);
}

View File

@@ -1,19 +1,33 @@
/*
OCP.gp — the Inc 0 subset (points, vectors, directions, axes, transforms).
OCP.gp — points, vectors, directions, axes, planes and transforms.
The rest of gp (gp_Ax2/Ax3/Pln/Circ/Lin/Pnt2d/Dir2d/Quaternion, which the
app also uses) lands with Inc 1, where the curve and surface classes that
consume them arrive.
The quadrics (gp_Cylinder/Cone/Sphere/Elips) are not imported by the app
directly; they arrive as return values of the adaptors' GetType() branches
(`BRepAdaptor_Surface(f).Cylinder().Radius()`), so they have to be
registered for those returns to convert at all.
*/
#include "../common/occt_module.h"
#include "../common/occt_policies.h"
#include <gp_Ax1.hxx>
#include <gp_Ax2.hxx>
#include <gp_Ax3.hxx>
#include <gp_Circ.hxx>
#include <gp_Cone.hxx>
#include <gp_Cylinder.hxx>
#include <gp_Dir.hxx>
#include <gp_Dir2d.hxx>
#include <gp_Elips.hxx>
#include <gp_Lin.hxx>
#include <gp_Pln.hxx>
#include <gp_Pnt.hxx>
#include <gp_Pnt2d.hxx>
#include <gp_Quaternion.hxx>
#include <gp_Sphere.hxx>
#include <gp_Trsf.hxx>
#include <gp_Vec.hxx>
#include <gp_Vec2d.hxx>
#include <gp_XYZ.hxx>
void register_gp(nb::module_ &root) {
@@ -81,6 +95,9 @@ void register_gp(nb::module_ &root) {
.def("Reversed", &gp_Vec::Reversed, OCP_RETURN_COPY)
.def("Multiplied", &gp_Vec::Multiplied, "Scalar"_a, OCP_RETURN_COPY)
.def("Angle", &gp_Vec::Angle, "Other"_a)
.def("Added", &gp_Vec::Added, "Other"_a, OCP_RETURN_COPY)
.def("Subtracted", &gp_Vec::Subtracted, "Right"_a, OCP_RETURN_COPY)
.def("Multiply", &gp_Vec::Multiply, "Scalar"_a)
.def("Transform", &gp_Vec::Transform, "T"_a)
.def("Transformed", &gp_Vec::Transformed, "T"_a, OCP_RETURN_COPY);
@@ -123,6 +140,9 @@ void register_gp(nb::module_ &root) {
nb::overload_cast<const gp_Ax1 &, Standard_Real>(
&gp_Trsf::SetRotation),
"A1"_a, "Ang"_a)
.def("SetRotation",
nb::overload_cast<const gp_Quaternion &>(&gp_Trsf::SetRotation),
"R"_a)
.def("SetScale", &gp_Trsf::SetScale, "P"_a, "S"_a)
.def("SetMirror", nb::overload_cast<const gp_Ax1 &>(&gp_Trsf::SetMirror),
"A1"_a)
@@ -135,4 +155,160 @@ void register_gp(nb::module_ &root) {
.def("Multiply", &gp_Trsf::Multiply, "T"_a)
.def("PreMultiply", &gp_Trsf::PreMultiply, "T"_a)
.def("Invert", &gp_Trsf::Invert);
nb::class_<gp_Quaternion>(m, "gp_Quaternion")
.def(nb::init<>())
// (x, y, z, w) — note the scalar comes *last*, which is the opposite
// of the (w, x, y, z) order most serialisations use.
.def(nb::init<Standard_Real, Standard_Real, Standard_Real,
Standard_Real>(),
"x"_a, "y"_a, "z"_a, "w"_a)
.def(nb::init<const gp_Vec &, Standard_Real>(), "theAxis"_a,
"theAngle"_a)
.def("X", &gp_Quaternion::X)
.def("Y", &gp_Quaternion::Y)
.def("Z", &gp_Quaternion::Z)
.def("W", &gp_Quaternion::W)
.def("Normalize", &gp_Quaternion::Normalize)
.def("Normalized", &gp_Quaternion::Normalized, OCP_RETURN_COPY)
.def("GetRotationAngle", &gp_Quaternion::GetRotationAngle);
// ---------------------------------------------------------------- 2D --
nb::class_<gp_Pnt2d>(m, "gp_Pnt2d")
.def(nb::init<>())
.def(nb::init<Standard_Real, Standard_Real>(), "Xp"_a, "Yp"_a)
.def("X", &gp_Pnt2d::X)
.def("Y", &gp_Pnt2d::Y)
.def("SetX", &gp_Pnt2d::SetX, "X"_a)
.def("SetY", &gp_Pnt2d::SetY, "Y"_a)
.def("Distance", &gp_Pnt2d::Distance, "Other"_a);
nb::class_<gp_Dir2d>(m, "gp_Dir2d")
.def(nb::init<>())
.def(nb::init<Standard_Real, Standard_Real>(), "Xv"_a, "Yv"_a)
.def("X", &gp_Dir2d::X)
.def("Y", &gp_Dir2d::Y)
.def("Angle", &gp_Dir2d::Angle, "Other"_a)
.def("Reversed", &gp_Dir2d::Reversed, OCP_RETURN_COPY);
nb::class_<gp_Vec2d>(m, "gp_Vec2d")
.def(nb::init<>())
.def(nb::init<Standard_Real, Standard_Real>(), "Xv"_a, "Yv"_a)
.def(nb::init<const gp_Dir2d &>(), "V"_a)
.def("X", &gp_Vec2d::X)
.def("Y", &gp_Vec2d::Y)
.def("Magnitude", &gp_Vec2d::Magnitude);
// -------------------------------------------------------------- axes --
nb::class_<gp_Ax2>(m, "gp_Ax2")
.def(nb::init<>())
.def(nb::init<const gp_Pnt &, const gp_Dir &>(), "P"_a, "V"_a)
.def(nb::init<const gp_Pnt &, const gp_Dir &, const gp_Dir &>(), "P"_a,
"N"_a, "Vx"_a)
.def("Location", &gp_Ax2::Location, OCP_RETURN_COPY)
.def("Direction", &gp_Ax2::Direction, OCP_RETURN_COPY)
.def("XDirection", &gp_Ax2::XDirection, OCP_RETURN_COPY)
.def("YDirection", &gp_Ax2::YDirection, OCP_RETURN_COPY)
.def("Axis", &gp_Ax2::Axis, OCP_RETURN_COPY)
.def("SetLocation", &gp_Ax2::SetLocation, "theP"_a)
.def("SetDirection", &gp_Ax2::SetDirection, "theV"_a)
.def("Rotate", &gp_Ax2::Rotate, "theA1"_a, "theAng"_a)
.def("Rotated", &gp_Ax2::Rotated, "theA1"_a, "theAng"_a,
OCP_RETURN_COPY)
.def("Transform", &gp_Ax2::Transform, "theT"_a)
.def("Transformed", &gp_Ax2::Transformed, "theT"_a, OCP_RETURN_COPY);
nb::class_<gp_Ax3>(m, "gp_Ax3")
.def(nb::init<>())
.def(nb::init<const gp_Ax2 &>(), "theA"_a)
.def(nb::init<const gp_Pnt &, const gp_Dir &>(), "theP"_a, "theN"_a)
.def(nb::init<const gp_Pnt &, const gp_Dir &, const gp_Dir &>(),
"theP"_a, "theN"_a, "theVx"_a)
.def("Location", &gp_Ax3::Location, OCP_RETURN_COPY)
.def("Direction", &gp_Ax3::Direction, OCP_RETURN_COPY)
.def("XDirection", &gp_Ax3::XDirection, OCP_RETURN_COPY)
.def("YDirection", &gp_Ax3::YDirection, OCP_RETURN_COPY)
.def("Axis", &gp_Ax3::Axis, OCP_RETURN_COPY)
.def("Ax2", &gp_Ax3::Ax2, OCP_RETURN_COPY)
.def("Direct", &gp_Ax3::Direct)
.def("SetLocation", &gp_Ax3::SetLocation, "theP"_a)
.def("SetDirection", &gp_Ax3::SetDirection, "theV"_a)
.def("Rotate", &gp_Ax3::Rotate, "theA1"_a, "theAng"_a)
.def("Rotated", &gp_Ax3::Rotated, "theA1"_a, "theAng"_a,
OCP_RETURN_COPY)
.def("Transform", &gp_Ax3::Transform, "theT"_a)
.def("Transformed", &gp_Ax3::Transformed, "theT"_a, OCP_RETURN_COPY);
// ------------------------------------------------- curves & quadrics --
nb::class_<gp_Lin>(m, "gp_Lin")
.def(nb::init<>())
.def(nb::init<const gp_Pnt &, const gp_Dir &>(), "theP"_a, "theV"_a)
.def(nb::init<const gp_Ax1 &>(), "theA1"_a)
.def("Location", &gp_Lin::Location, OCP_RETURN_COPY)
.def("Direction", &gp_Lin::Direction, OCP_RETURN_COPY)
.def("Position", &gp_Lin::Position, OCP_RETURN_COPY)
.def("Distance", nb::overload_cast<const gp_Pnt &>(&gp_Lin::Distance,
nb::const_),
"theP"_a);
nb::class_<gp_Circ>(m, "gp_Circ")
.def(nb::init<>())
.def(nb::init<const gp_Ax2 &, Standard_Real>(), "theA2"_a,
"theRadius"_a)
.def("Location", &gp_Circ::Location, OCP_RETURN_COPY)
.def("Axis", &gp_Circ::Axis, OCP_RETURN_COPY)
.def("Position", &gp_Circ::Position, OCP_RETURN_COPY)
.def("Radius", &gp_Circ::Radius);
nb::class_<gp_Elips>(m, "gp_Elips")
.def(nb::init<>())
.def("Location", &gp_Elips::Location, OCP_RETURN_COPY)
.def("Axis", &gp_Elips::Axis, OCP_RETURN_COPY)
.def("Position", &gp_Elips::Position, OCP_RETURN_COPY)
.def("MajorRadius", &gp_Elips::MajorRadius)
.def("MinorRadius", &gp_Elips::MinorRadius);
nb::class_<gp_Pln>(m, "gp_Pln")
.def(nb::init<>())
.def(nb::init<const gp_Pnt &, const gp_Dir &>(), "theP"_a, "theV"_a)
.def(nb::init<const gp_Ax3 &>(), "theA3"_a)
.def("Location", &gp_Pln::Location, OCP_RETURN_COPY)
.def("Axis", &gp_Pln::Axis, OCP_RETURN_COPY)
.def("Position", &gp_Pln::Position, OCP_RETURN_COPY)
.def("XAxis", &gp_Pln::XAxis, OCP_RETURN_COPY)
.def("YAxis", &gp_Pln::YAxis, OCP_RETURN_COPY)
.def("Distance", nb::overload_cast<const gp_Pnt &>(&gp_Pln::Distance,
nb::const_),
"theP"_a)
.def("Transform", &gp_Pln::Transform, "theT"_a)
.def("Transformed", &gp_Pln::Transformed, "theT"_a, OCP_RETURN_COPY);
nb::class_<gp_Cylinder>(m, "gp_Cylinder")
.def(nb::init<>())
.def(nb::init<const gp_Ax3 &, Standard_Real>(), "theA3"_a,
"theRadius"_a)
.def("Location", &gp_Cylinder::Location, OCP_RETURN_COPY)
.def("Axis", &gp_Cylinder::Axis, OCP_RETURN_COPY)
.def("Position", &gp_Cylinder::Position, OCP_RETURN_COPY)
.def("Radius", &gp_Cylinder::Radius);
nb::class_<gp_Cone>(m, "gp_Cone")
.def(nb::init<>())
.def("Location", &gp_Cone::Location, OCP_RETURN_COPY)
.def("Axis", &gp_Cone::Axis, OCP_RETURN_COPY)
.def("Position", &gp_Cone::Position, OCP_RETURN_COPY)
.def("Apex", &gp_Cone::Apex, OCP_RETURN_COPY)
.def("RefRadius", &gp_Cone::RefRadius)
.def("SemiAngle", &gp_Cone::SemiAngle);
nb::class_<gp_Sphere>(m, "gp_Sphere")
.def(nb::init<>())
.def(nb::init<const gp_Ax3 &, Standard_Real>(), "theA3"_a,
"theRadius"_a)
.def("Location", &gp_Sphere::Location, OCP_RETURN_COPY)
.def("Position", &gp_Sphere::Position, OCP_RETURN_COPY)
.def("Radius", &gp_Sphere::Radius);
}