Table of Contents

Geometry

OCCT separates exact geometry from topology: gp has the math values (points, vectors, axes, transformations), Geom the curves and surfaces shapes are made of. Everything here is independent of shapes; Topology builds on it.

flowchart LR
    gp["gp: values<br/>gp_Pnt, gp_Vec, gp_Dir, gp_Ax2, gp_Trsf"]
    geom["Geom / Geom2d: handles<br/>Geom_Circle, Geom_BSplineCurve, Geom_Plane"]
    adaptor["Adaptors<br/>GeomAdaptor_Curve, BRepAdaptor_Surface"]
    algo["Algorithms<br/>GeomAPI, GCPnts, Extrema"]
    gp -->|define| geom
    geom -->|wrapped by| adaptor
    adaptor -->|evaluated by| algo
    geom --> algo

Values: gp

gp types are C# structs with OCCT's memory layout: no native allocation, copied on assignment. Their methods and operators run OCCT's code.

var p = new gp_Pnt(1, 2, 3);
var q = new gp_Pnt(4, 6, 3);
var distance = p.Distance(q); // 5

var along = new gp_Vec(p, q); // from p to q
var up = new gp_Vec(0, 0, 1);
var normal = along ^ up;                 // ^ is the cross product
var halfway = p.Translated(along * 0.5); // Translated returns a new point, p stays

var x = new gp_Dir(1, 0, 0);              // a direction is always unit length
var angle = x.Angle(new gp_Dir(0, 1, 0)); // π/2

OCCT's naming convention holds throughout: a verb changes the object (Translate, Rotate, Normalize), its participle returns a changed copy (Translated, Rotated, Normalized).

var point = new gp_Pnt(1, 1, 1);
var copy = point; // a copy: gp types are C# structs
copy.SetX(5);     // changes the copy only

point.Translate(new gp_Vec(1, 0, 0));                   // Translate changes point itself...
var translated = point.Translated(new gp_Vec(1, 0, 0)); // ...Translated returns a new one
Note

Since gp types are structs, var copy = point copies. Mutating methods on a readonly field or a property's result change a temporary copy; assign the result of the participle form instead.

Type Holds
gp_Pnt, gp_Vec, gp_Dir a point, a vector, a unit vector (normalized on construction)
gp_Ax1 a point and a direction: an axis of rotation
gp_Ax2, gp_Ax3 a right-handed (Ax3: either-handed) coordinate system
gp_Trsf, gp_GTrsf a rigid transformation with uniform scale, a general affine one
gp_Lin, gp_Circ, gp_Pln, gp_Cylinder elementary curves and surfaces as values
gp_Pnt2d, gp_Vec2d, ... the same in 2D, for curves on surfaces

Transformations

gp_Trsf composes with *, applied right to left like OCCT's Multiplied:

var rotation = new gp_Trsf();
rotation.SetRotation(new gp_Ax1(new gp_Pnt(0, 0, 0), new gp_Dir(0, 0, 1)),
                     Math.PI / 2); // 90° about Z

var shift = new gp_Trsf();
shift.SetTranslation(new gp_Vec(10, 0, 0));

var both = shift * rotation;                       // rotate, then shift
var moved = new gp_Pnt(1, 0, 0).Transformed(both); // (10, 1, 0)

Shapes take transformations through locations, see Modeling.

Curves and surfaces: Geom

Geom types are OCCT transients: reference-counted, shared, and referred to through Handle(T), which is just T in C#. Each is a parametric function: Value(u) for curves, Value(u, v) for surfaces.

flowchart LR
    geometry[Geom_Geometry] --- curve[Geom_Curve]
    geometry --- surface[Geom_Surface]
    curve --- line[Geom_Line]
    curve --- conic[Geom_Conic]
    conic --- circle[Geom_Circle]
    conic --- ellipse["Geom_Ellipse<br/>Geom_Hyperbola, Geom_Parabola"]
    curve --- bounded[Geom_BoundedCurve]
    bounded --- bspline[Geom_BSplineCurve]
    bounded --- bezier[Geom_BezierCurve]
    bounded --- trimmed[Geom_TrimmedCurve]
    curve --- offset[Geom_OffsetCurve]
    surface --- elementary[Geom_ElementarySurface]
    elementary --- plane[Geom_Plane]
    elementary --- revolution["Geom_CylindricalSurface<br/>Geom_ConicalSurface<br/>Geom_SphericalSurface<br/>Geom_ToroidalSurface"]
    surface --- swept["Geom_SweptSurface<br/>Geom_SurfaceOfLinearExtrusion<br/>Geom_SurfaceOfRevolution"]
    surface --- offsetSurface[Geom_OffsetSurface]
    surface --- boundedSurface[Geom_BoundedSurface]
    boundedSurface --- bsplineSurface[Geom_BSplineSurface]
    boundedSurface --- bezierSurface[Geom_BezierSurface]
    boundedSurface --- rectangular[Geom_RectangularTrimmedSurface]
// a circle of radius 10 in the XY plane, and a B-spline through four points
Geom_Curve circle = new Geom_Circle(new gp_Ax2(new gp_Pnt(0, 0, 0), new gp_Dir(0, 0, 1)), 10);
var points = new TColgp_Array1OfPnt([
  new gp_Pnt(0, 0, 0), new gp_Pnt(10, 5, 0), new gp_Pnt(20, 0, 0), new gp_Pnt(30, 5, 0)
]);
Geom_BSplineCurve spline = new GeomAPI_PointsToBSpline(points).Curve();

// a point and a derivative on the circle, at a quarter turn
var atQuarter = circle.Value(Math.PI / 2); // (0, 10, 0)
var d1 = circle.EvalD1(Math.PI / 2);       // OCCT 8: the point and first derivative together
var tangent = d1.D1;                       // (-10, 0, 0)

// lengths come from an adaptor, which algorithms take instead of the curve
var length = GCPnts_AbscissaPoint.Length(new GeomAdaptor_Curve(circle)); // 2π·10

OCCT 8's EvalD1 to EvalD3 return the point with its derivatives as one plain struct (Geom_Curve_ResD1 and so on) with public fields; EvalD0 returns the point.

Handles and casts

A C# cast never reaches the C++ object: a Geom_Curve that is a circle in C++ is a Geom_Curve proxy in C#. DownCast asks OCCT, like Handle(Geom_Circle)::DownCast:

Geom_Curve curve = new Geom_Circle(new gp_Ax2(), 10); // a Handle(Geom_Curve) in C++
var circle = Geom_Circle.DownCast(curve);             // the circle, or null
var line = Geom_Line.DownCast(curve);                 // null: it isn't a line
var radius = circle?.Radius();

Building curves

To get Use
a circle, arc, line segment from points GC_MakeCircle, GC_MakeArcOfCircle, GC_MakeSegment (.Value())
a B-spline approximating points GeomAPI_PointsToBSpline
a B-spline through points, with tangents GeomAPI_Interpolate
a B-spline surface through a grid GeomAPI_PointsToBSplineSurface
a curve's length, points at even spacing GCPnts_AbscissaPoint, GCPnts_UniformAbscissa
the 2D curve of a 3D curve on a plane GeomAPI.To2d

Projection and extrema

Geom_Curve circle = new Geom_Circle(new gp_Ax2(), 10);
var projection = new GeomAPI_ProjectPointOnCurve(new gp_Pnt(20, 0, 5), circle);
var nearest = projection.NearestPoint(); // (10, 0, 0)
var gap = projection.LowerDistance();    // √(10² + 5²)

GeomAPI_ProjectPointOnSurf, GeomAPI_ExtremaCurveCurve and GeomAPI_IntCS (curve-surface intersection) work the same way: construct, check the number of results (NbPoints(), NbExtrema()), read them numbered from 1.

Invalid input

Constructors check their arguments and throw:

Action zero = () => new gp_Dir(0, 0, 0); // OCCT raises Standard_ConstructionError

See Errors.