Topology and Geometry in Open CASCADE. Part 2


Vertex has a primary geometric representation which is a point in 3D space encoded as gp_Pnt. It may have other representations but they are virtually never used in practice.

Another important attribute of a vertex is its tolerance which indicates possible inaccuracy of its placement. Geometrical meaning of the vertex tolerance T is a sphere with a radius T centered in vertex’s point. This sphere must encompass curves ends of all edges connected at that point.

Let me elaborate a little bit on tolerances.

Unlike some other geometric libraries which have some global precision (e.g. as 1/1000th of the model bounding box dimension), Open CASCADE treats tolerances as local properties. As indicated in the diagram in Part1, tolerance is a field of any vertex, edge, or face instance. This approach helps to describe the model with higher accuracy in general. Look at the picture below:

Individual tolerances allow to specify local inaccuracies while leaving the rest of the model well defined. If you have to build your shape bottom up, the best approach is to specify the smallest valid tolerance. By default, it is Precision::Confusion() which is 1e-07.

In general some modeling algorithms are quite sensitive to tolerances, especially if they have to work with a single value to be specified by the user. For instance, importing a model from another 3D geometric kernel (via IGES or STEP formats, or directly from native format of other kernels or CAD systems), involves a global precision specified in a file header. The importer tries to be robust regardless of that value, no matter how coarse it is (e.g. it could that big so that some tiny faces are fully encompassed by its boundaries what would even violate the standard).

Another example is Sewing (stitching topologically disconnected faces into a shell). Gaps between faces can be quite different across the model. Specifying too small tolerance would leave too many disconnected faces, specifying too big upfront would connect too distant faces (maybe even implied too be disconnected by user intent, like tiny holes).

Coming back to vertices, let me mention about their orientation field. It does not have a direct geometric meaning, but by convention vertex with TopAbs_FORWARD orientation must match an edge’s end corresponding to the smaller parameter of its curve. Respectively a vertex with TopAbs_REVERSED – to the curve’s end with greater parameter. For instance, if you have an edge lying on a circular arc of radius 1 on plane Z=0 starting at point (1, 0, 0) and moving anti-clockwise (if to look in the direction opposite to Z axis) then its forward vertex will have a point (1, 0, 0) and reversed one – (0, 1, 0):

Building a vertex bottom-up
BRep_Builder is the tool that actually performs low-level operations.

gp_Pnt aPoint (100., 200., 300.);
BRep_Builder aBuilder;
TopoDS_Vertex aVertex;
aBuilder.MakeVertex (aVertex, aPoint, Precision::Confusion());
aVertex.Orientation (TopAbs_REVERSED);

There is a convenience class BRepBuilderAPI_MakeVertex which eventually uses BRep_Builder inside. So, if you have to construct topology bottom up make sure you are familiar with BRep_Builder.

Accessing vertex info
BRep_Tool is the tool that provides access to geometry of the topological entities. Most its methods are static.

Standard_Real aTolerance = BRep_Tool::Tolerance (aVertex);
gp_Pnt aPoint = BRep_Tool::Pnt (aVertex);

To be continued...


  1. Hi Roman,

    I have a question, you said one must use BRep_Builder to build the vertex as you shown above. Pardon my ignorance, when should then one use AIS_Point to display an interactive point? can one still use AIS_Point to display a point? I am bit confused with the use of BRep_Builder, I have a small application for sketching 2d geometries where I have not used BRep_Builder. I am completely new to CAD programming, so please be kind to me :)


  2. Hi Venu,
    BRep_Builder is a way to build a vertex.
    AIS_Point to display it. No confusion ;-).

    BRep_Builder is an underlying low-/medium-level way to build shapes bottom-up. As usual, there are higher level, convenience, API. For instance as follows:
    TopoDS_Vertex aV = BRepBuilderAPI_MakeVertex (gp_Pnt (x, y, z));
    It uses BRep_Builder internally but you don't see it.

  3. Aah, looked again at AIS_Point. Of course, it does not display a vertex (TopoDS_Vertex). It just displays an auxiliary point on the screen, i.e. has no relationship to your 3D model.
    AIS_Shape does display a vertex, like any other TopoDS_Shape.
    Sorry for initial misleading comment.

  4. Thanks Roman, greatly appreciate your effort and time you are putting to for people like me. One question, I kind of understand what you are saying but when I place/create an AIS_Point (or any AIS geometrical entity) is it not building it and then displaying it?

    In my small application, all my 2d geometrical quantities are AIS objects, so that I can change them interactively...if I am not building them, should be implementing a Brep builder? my ultimate goal is to have an application which can used to build CAD objects and then mesh them...please advice if I also have to implement Brep builder eventually...thanks again for your beautiful notes...I am learning a lot from your notes.



  5. Venu, if you compare with MVC(model-view-controller), TopoDS_Shape or OCAF is your model, and AIS is a mix of view and controller. So you may operate at AIS level (creating, visualizing and moving around some points) as long as you need, but if you eventually need a data to store/retrieve, create complex CAD model, mesh on it, etc you obviously need a model component. This is where TopoDS_Shape comes in. Again, BRep_Builder is a just a low-level tool to create shapes bottom up, there are higher level API methods to facilitate some pre-defined primitives.
    Hope this helps a bit.

  6. Thanks Roman...now it's getting clearer...I will study BrepBuilder from your notes and code. I guess with meshing in mind, I may have to implement that then..again, thank you for all your effort.



  7. Hi
    I just found about your notes on OCC.
    And I found them very helpful.
    I am trying to do some Numerical Computation
    and I need to access the individual patches (surfaces) an object is made from in the sense
    that I need to have a (u,v) parametrization of the surfaces. The actual model is an ACIS file and I am not sure using OCC can get me to what I need. Can you give me some adivice please ?


  8. Hi Davood,

    Glad to see you now on my blog.
    First off, to read ACIS-SAT file you will need to use CAD Exchanger SDK and its ACIS importer.
    Then you will need to explore faces (topological entities that bound surfaces) using Open CASCADE API. Doing so you can retrieve underlying surfaces and calculate 3D points using (u, v) coordinates. Each surface has a predefined parametrization – e.g. a plane is a parametrized in u and v along its X- and Y- axes respectively. Surface of revolution is parameterized in u along the rotation angle, and in v - along the generatrix curve, and so on. Alternatively you can project 3D points on surface to get (u,v) coordinates, etc. It’s all depends upon your needs.

    Here is a (pseudo-)code that would do this:

    //use CAD Exchanger to read-in the .sat file into Open CASCADE model
    ACIS_Reader aReader;
    Handle_Base_ShapeModel aModel;
    if (aReader.ReadFile ("myfile.sat") && aReader.Transfer (aModel)) {
    //iterate over model roots
    const Base_ShapeModel::ListOfHShapes& aRootL = aModel->Roots();
    Base_ShapeModel::ListOfHShapes::const_iterator anIt = aRootL.begin();
    for (; anIt != aRootL.end(); ++anIt) {
    Handle(TopoDS_HShape) aHShape = Handle(TopoDS_HShape)::DownCast (*anIt);
    if (!aHShape.IsNull()) {
    const TopoDS_Shape& aShape = aHShape->Shape();

    //iterate over faces of i-th root
    for (TopExp_Explorer anExp (aShape, TopAbs_FACE); anExp.More(); anExp.Next()) {
    const TopoDS_Face& aFace = TopoDS::Face (anExp.Current());
    Handle(Geom_Surface) aSurf = BRep_Tool::Surface (aFace);

    //do what you need with the surface
    if (aSurf->IsKind (STANDARD_TYPE ())) {
    Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast (aSurface);
    //do plane-specific stuff...
    } else if (aSurf->IsKind (STANDARD_TYPE (Geom_SphericalSurface))) {
    //do sphere-specific stuff...
    } else


  9. Obviously, the first if should read as :
    if (aSurf->IsKind (STANDARD_TYPE (Geom_Plane))) {
    Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast (aSurface);
    //do plane-specific stuff...

  10. Hi Roman,

    I am new to OpenCascade. I wanted to ask if it is possible to define the coordinates in a gp_Pnt function as variables and take their values from other classes?
    like gp_Pnt (x,y,z) and I am getting the values of x,y,z from other classes.