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

@@ -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);
}