Files
ocp/src/modules/mod_gp.cpp
stroblme 01a5bcf188 10C Inc 3 + 4: I/O and text — the app's whole OCP surface is bound
138/138 symbols across 53 modules. New: IFSelect, Interface, XSControl,
IGESData, STEPControl, IGESControl, RWStl, Graphic3d, NCollection, StdPrs.

**The full app suite passes against this wheel: 1797 passed, 1 skipped — the
same result as the stock wheel**, run from the parity venv.

Getting there needed six methods that no static analysis could have found:
`inventory --check` only sees symbols reached through an import, so a method
called on an instance is invisible to it. The suite found them in one pass, and
one of them (gp_Vec.Reverse, which every outward-normal probe calls) accounted
for 311 of the 255 failing tests on its own. The others: gp_Trsf.SetMirror over
a plane and a point, Geom_Surface.D0, BRep_Builder.MakeFace from a
triangulation, MakePipeShell.SetMode with a fixed binormal, and MakeFace from a
surface plus tolerance.

Open question **S5 is settled: no**. The wheel does not need OCCT's share/
resources. test_inc3_io.py asserts no CSF_* variable is set and then round-trips
STEP and IGES, reading the declared units back off both — which is exactly the
resource-less container the question was about.

The XSTEP readers keep the GIL, amending the blanket "file readers and writers"
line in design.md's GIL policy. STEP and IGES traffic in process-global
Interface_Static state, the IGES reader is documented as not thread-safe, and
the app already serialises imports behind a lock — so holding it costs nothing
and removes a class of question. RWStl, which touches no global state, releases.

XSControl_Reader and IGESData are registered although the app imports neither:
they are the reader base both concrete readers inherit their transfer surface
from, and the model-to-global-section chain the IGES unit probe walks.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DfriM8XUkn7uYf5Dwe2xo6
2026-08-10 20:31:15 +02:00

320 lines
14 KiB
C++

/*
OCP.gp — points, vectors, directions, axes, planes and transforms.
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) {
nb::module_ m = ocp_submodule(root, "gp");
nb::enum_<gp_TrsfForm>(m, "gp_TrsfForm", nb::is_arithmetic())
.value("gp_Identity", gp_Identity)
.value("gp_Rotation", gp_Rotation)
.value("gp_Translation", gp_Translation)
.value("gp_PntMirror", gp_PntMirror)
.value("gp_Ax1Mirror", gp_Ax1Mirror)
.value("gp_Ax2Mirror", gp_Ax2Mirror)
.value("gp_Scale", gp_Scale)
.value("gp_CompoundTrsf", gp_CompoundTrsf)
.value("gp_Other", gp_Other)
.export_values();
nb::class_<gp_XYZ>(m, "gp_XYZ")
.def(nb::init<>())
.def(nb::init<Standard_Real, Standard_Real, Standard_Real>(), "X"_a,
"Y"_a, "Z"_a)
.def("X", &gp_XYZ::X)
.def("Y", &gp_XYZ::Y)
.def("Z", &gp_XYZ::Z);
nb::class_<gp_Pnt>(m, "gp_Pnt")
.def(nb::init<>())
.def(nb::init<Standard_Real, Standard_Real, Standard_Real>(), "Xp"_a,
"Yp"_a, "Zp"_a)
.def(nb::init<const gp_XYZ &>(), "Coord"_a)
.def("X", &gp_Pnt::X)
.def("Y", &gp_Pnt::Y)
.def("Z", &gp_Pnt::Z)
.def("SetX", &gp_Pnt::SetX, "X"_a)
.def("SetY", &gp_Pnt::SetY, "Y"_a)
.def("SetZ", &gp_Pnt::SetZ, "Z"_a)
.def("Coord", nb::overload_cast<>(&gp_Pnt::Coord, nb::const_),
OCP_RETURN_COPY)
.def("Distance", &gp_Pnt::Distance, "Other"_a)
.def("SquareDistance", &gp_Pnt::SquareDistance, "Other"_a)
.def("IsEqual", &gp_Pnt::IsEqual, "Other"_a, "LinearTolerance"_a)
.def("Transform", &gp_Pnt::Transform, "T"_a)
.def("Transformed", &gp_Pnt::Transformed, "T"_a, OCP_RETURN_COPY)
.def("Translate",
nb::overload_cast<const gp_Vec &>(&gp_Pnt::Translate), "V"_a)
.def("Translated",
nb::overload_cast<const gp_Vec &>(&gp_Pnt::Translated, nb::const_),
"V"_a, OCP_RETURN_COPY);
nb::class_<gp_Vec>(m, "gp_Vec")
.def(nb::init<>())
.def(nb::init<Standard_Real, Standard_Real, Standard_Real>(), "Xv"_a,
"Yv"_a, "Zv"_a)
.def(nb::init<const gp_Dir &>(), "V"_a)
.def(nb::init<const gp_Pnt &, const gp_Pnt &>(), "P1"_a, "P2"_a)
.def("X", &gp_Vec::X)
.def("Y", &gp_Vec::Y)
.def("Z", &gp_Vec::Z)
.def("Magnitude", &gp_Vec::Magnitude)
.def("SquareMagnitude", &gp_Vec::SquareMagnitude)
.def("Dot", &gp_Vec::Dot, "Other"_a)
.def("Crossed", &gp_Vec::Crossed, "Right"_a, OCP_RETURN_COPY)
.def("Normalize", &gp_Vec::Normalize)
.def("Normalized", &gp_Vec::Normalized, OCP_RETURN_COPY)
.def("Reverse", &gp_Vec::Reverse)
.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);
nb::class_<gp_Dir>(m, "gp_Dir")
.def(nb::init<>())
.def(nb::init<Standard_Real, Standard_Real, Standard_Real>(), "Xv"_a,
"Yv"_a, "Zv"_a)
.def(nb::init<const gp_Vec &>(), "V"_a)
.def("X", &gp_Dir::X)
.def("Y", &gp_Dir::Y)
.def("Z", &gp_Dir::Z)
.def("Dot", &gp_Dir::Dot, "Other"_a)
.def("Crossed", &gp_Dir::Crossed, "Right"_a, OCP_RETURN_COPY)
.def("Angle", &gp_Dir::Angle, "Other"_a)
.def("IsParallel", &gp_Dir::IsParallel, "Other"_a, "AngularTolerance"_a)
.def("Reversed", &gp_Dir::Reversed, OCP_RETURN_COPY)
.def("Reverse", &gp_Dir::Reverse)
.def("Transform", &gp_Dir::Transform, "T"_a)
.def("Transformed", &gp_Dir::Transformed, "T"_a, OCP_RETURN_COPY);
nb::class_<gp_Ax1>(m, "gp_Ax1")
.def(nb::init<>())
.def(nb::init<const gp_Pnt &, const gp_Dir &>(), "P"_a, "V"_a)
.def("Location", &gp_Ax1::Location, OCP_RETURN_COPY)
.def("Direction", &gp_Ax1::Direction, OCP_RETURN_COPY)
.def("SetLocation", &gp_Ax1::SetLocation, "P"_a)
.def("SetDirection", &gp_Ax1::SetDirection, "V"_a)
.def("Reversed", &gp_Ax1::Reversed, OCP_RETURN_COPY);
nb::class_<gp_Trsf>(m, "gp_Trsf")
.def(nb::init<>())
.def("SetTranslation",
nb::overload_cast<const gp_Vec &>(&gp_Trsf::SetTranslation),
"V"_a)
.def("SetTranslation",
nb::overload_cast<const gp_Pnt &, const gp_Pnt &>(
&gp_Trsf::SetTranslation),
"P1"_a, "P2"_a)
.def("SetRotation",
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)
.def("SetMirror", nb::overload_cast<const gp_Ax2 &>(&gp_Trsf::SetMirror),
"A2"_a)
.def("SetMirror", nb::overload_cast<const gp_Pnt &>(&gp_Trsf::SetMirror),
"P"_a)
.def("Form", &gp_Trsf::Form)
.def("ScaleFactor", &gp_Trsf::ScaleFactor)
.def("TranslationPart", &gp_Trsf::TranslationPart, OCP_RETURN_COPY)
.def("Value", &gp_Trsf::Value, "Row"_a, "Col"_a)
.def("Inverted", &gp_Trsf::Inverted, OCP_RETURN_COPY)
.def("Multiplied", &gp_Trsf::Multiplied, "T"_a, OCP_RETURN_COPY)
.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);
}