How to fix C error ‘unknown type name bool’

Problem:

You have C code like

bool mybool;

but when you try to compile it you see an error message like

main.c: In function ‘main’:
main.c:3:5: error: unknown type name ‘bool’; did you mean ‘_Bool’?
     bool mybool;
     ^~~~
     _Bool

Solution:

Add

#include <stdbool.h>

at the top of the source file where the error occured.

The reason for this error is that bool is not a standard type in C (like int or char) but only in stdbool.h.

Posted by Uli Köhler in C/C++, GCC errors

How to fix C error ‘NULL undeclared’

Problem:

You have C code like

char* ptr = NULL;

but when you try to compile it you see an error message like

main.c: In function ‘main’:
main.c:3:17: error: ‘NULL’ undeclared (first use in this function)
     void* ptr = NULL;
                 ^~~~
main.c:3:17: note: each undeclared identifier is reported only once for each function it appears in

Solution:

Add

#include <stddef.h>

at the top of the source file where the error occured.

The reason for this error is that NULL is not defined in C itself but only in stddef.h.

Posted by Uli Köhler in C/C++, GCC errors

How to get length of curve in OpenCASCADE

OCCUtils provides a convenience function to get the length of a curve in OpenCASCADE:

#include <occutils/Curve.hxx>

using namespace OCCUtils;

GeomAdaptor_Curve curve = /* ... */;

double length = Curve::Length(curve);

You can call it with GeomAdaptor_Curve or Geom_TrimmedCurve. While you can also call it with Handle(Geom_Curve), this is usually not what you want to do, since Geom_Curve typically describes an infinite curve (like an infinitely long line) and doesn’t know about which section of the curve is actually use (GeomAdaptor_Curve and Geom_TrimmedCurve both have the required Umin/Umax information stored).

In case you need to do it manually (without OCCUtils), use this snippet:

#include <GCPnts_AbscissaPoint.hxx>

GeomAdaptor_Curve curve = /* ... */;

GCPnts_AbscissaPoint::Length(curve);

For a Geom_TrimmedCurve, you need to convert it to a GeomAdaptor_Curve first. See How to convert Geom_TrimmedCurve to GeomAdaptor_Curve in OpenCASCADE for details on how to do that.

Posted by Uli Köhler in C/C++, OpenCASCADE

How to convert Geom_TrimmedCurve to GeomAdaptor_Curve in OpenCASCADE

OCCUtils provides a conveniece function to convert a Geom_TrimmedCurve to a GeomAdaptor_Curve:

#include <occutils/Curve.hxx>

using namespace OCCUtils;

Geom_TrimmedCurve input = /* ... */;

GeomAdaptor_Curve result = Curve::FromTrimmedCurve(input);

If you want to do it manually, use this snippet:

Geom_TrimmedCurve input = /* ... */;

GeomAdaptor_Curve result(
    input.BasisCurve(), input.FirstParameter(), input.LastParameter()
);
Posted by Uli Köhler in C/C++, OpenCASCADE

How to check if two gp_Pnt coincide in OpenCASCADE

If you have two points in OpenCASCADE:

gp_Pnt p1 = /* ... */;
gp_Pnt p2 = /* ... */;

you can’t just use == to check if they coincide in stock OpenCASCADE. However, OCCUtils provides operator== and operator!= for gp_Pnt among other types:

#include <occutils/Equality.hxx>

bool areTheyCoincident = p1 == p2;

If you can’t use OCCUtils, this is the way to check if they are coincident:

if (p1.Distance(p2) <= Precision::Confusion()) {
    // p1 coincides with p2
}

or alternatively:

if (p1.IsEqual(p2, Precision::Confusion())) {
    // p1 coincides with p2
}

The reason for this is that even though two points may represent the same point in space, depending on how you compute their coordinates exactly, their cartesian X/Y/Z coordinates might not be exactly identical. This is always the case with floating-point arithmetic, that’s the type of math computers use. Don’t confuse floating-point arithmetic with exact arithmetic which you have learnt in school or university.

The solution for this issue is to define a very small tolerance – any objects that have a distance less than that tolerance are considered equal.

In OpenCASCADE, Precision::Confusion() in the standard tolerance value for this.

My OCCUtils library provides

Posted by Uli Köhler in C/C++, OpenCASCADE

How to create TopoDS_Edge from to gp_Pnt in OpenCASCADE

OCCUtils provides a conveniece function for creating a TopoDS_Edge between two points (i.e. a straight line):

#include <occutils/Edge.hxx>

using namespace OCCUtils;

gp_Pnt p1 = /* ... */;
gp_Pnt p2 = /* ... */;

TopoDS_Edge edge = Edge::FromPoints(p1, p2);

In case you want to do it manually (i.e. without OCCUtils), use this snippet

TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(p1, p2).Edge();

but be aware that you also have to handle the case of p1 == p2 i.e.

if (p1.Distance(p2) <= Precision::Confusion()) {
    // Don't try to create an Edge in this case
}

OCCUtil’s Edge::FromPoints handles this case by returning TopoDS_Edge() i.e. a TopoDS_Edge where edge.IsNull() == true.

Posted by Uli Köhler in C/C++, OpenCASCADE

How to fix boost::program_options “error: ‘po’ has not been declared”

If you want to compile your C++ project using boost::program_options but you see error messages like

/home/uli/myProject/main.cpp:28:5: error: ‘po’ has not been declared
     po::notify (vm);

you are missing this declaration which you need to place directly after #include <boost/program_options.hpp>:

namespace po = boost::program_options;

This declares po as an alias for the boost::program_options namespace, because writing po::variables_map is much easier to read than boost::program_options::variables_map and using namespace boost::program_options might cause some name collisions with other functions.

Posted by Uli Köhler in Boost, C/C++

How to add boost::program_options to your CMake build

Simply add these lines to the end of your CMakeLists.txt and replace myTarget by the name of your build target (usually the first argument to add_executable(...) or add_library(...)):

# Include boost
find_package( Boost 1.30 COMPONENTS program_options REQUIRED )
target_include_directories( myTarget PRIVATE ${Boost_INCLUDE_DIR})
target_link_libraries( myTarget ${Boost_LIBRARIES} )

If you have multiple targets, copy & paste the last two lines for each target.

If you need a specific version of boost, replace 1.30 by the minimum version you need.

Posted by Uli Köhler in Boost, C/C++, CMake

How to create TopoDS_Wire from TopoDS_Edge(s) in OpenCASCADE

OCCUtils provides easy-to-use conveniece functions to convert multiple TopoDS_Edges to a TopoDS_Wire:

#include <occutils/Wire.hxx>

using namespace OCCUtils;

TopoDS_Wire& wire = Wire::FromEdges({edge1, edge2})

You can also pass a std::vector<TopoDS_Edge> to Wire::FromEdges().

If you want to do it manually without using OCCUtils, you can use BRepLib_MakeWire like this:

BRepLib_MakeWire wireMaker;
wireMaker.Add(edge1);
wireMaker.Add(edge2);
TopoDS_Wire wire = wireMaker.Wire();
Posted by Uli Köhler in C/C++, OpenCASCADE

How to export colored STEP files in OpenCASCADE

OCCUtils provides an easy way of exporting a STEP with colored elements:

#include <occutils/ExtendedSTEP.hxx>
#include <occutils/Primitive.hxx>

TopoDS_Shape cube = Primitive::MakeCube(5 /* mm */);

STEP::ExtendedSTEPExporter stepExporter;
stepExporter.AddShapeWithColor(cube, Quantity_NOC_RED);
stepExporter.Write("ColoredCube.step");

The resulting STEP file looks like this:

You can also add non-colored shapes:

stepExporter.AddShape(myShape);

Doing it without OCCUtils is possible but might make your life miserable since it’s rather hard to get to work correctly.

Here’s a minimal example:

// Get global application
Handle(TDocStd_Application) application = XCAFApp_Application::GetApplication();
// Create document
Handle(TDocStd_Document) document;
application->NewDocument("MDTV-XCAF", document);
// Get shape & color tools
Handle(XCAFDoc_ShapeTool) shapeTool = XCAFDoc_DocumentTool::ShapeTool(document->Main());
Handle(XCAFDoc_ColorTool) colorTool = XCAFDoc_DocumentTool::ColorTool(document->Main());
// Create shape
// IMPORTANT: DO NOT use shapeTool->AddShape(TopoDS_Shape)!
// This WILL NOT PRESERVE the color!
TDF_Label partLabel = shapeTool->NewShape();
shapeTool->SetShape(partLabel, filletedBody);

//TDF_Label redColor = colorTool->AddColor();
colorTool->SetColor(partLabel, Quantity_NOC_RED, XCAFDoc_ColorGen);

STEPCAFControl_Writer writer;
writer.SetColorMode(true);
writer.Perform(document, "ColoredShape.step");

What colors can you use?

Either define the Quantity_Color yourself using RGB values (from 0.0 to 1.0) like this:

Quantity_Color red(1.0 /* R */, 0.0 /* G */, 0.0 /* B */, Quantity_TypeOfColor::Quantity_TOC_RGB);

alternatively you can do the same in the HSL colorspace:

Quantity_Color brownishOrange(1.0 /* H */, 0.5 /* L */, 0.5 /* S */, Quantity_TypeOfColor::Quantity_TOC_HLS);

or you can use the predefined colors in the Quantity_NameOfColor enum – see Overview of all standard colors available in OpenCASCADE for a table of all available colors.

Posted by Uli Köhler in C/C++, OpenCASCADE

How to return NaN in C++

Since C++11 returning NaN as double is as simple as

#include <cmath>

return std::nan("");

In case you want to return a float use

#include <cmath>

return std::nanf("");

In the rare case of a long double use

#include <cmath>

return std::nan("");

 

Posted by Uli Köhler in C/C++

How to check if float or double is NaN in C++

Checking for NaN is simple since C++11:

#include <numeric>

bool isNaN = std::isnan(myNumber);

See the std::isnan docs for reference.

You can also use the C99 function isnan from <cmath>:

#include <cmath>

bool isNaN = isnan(myDouble);

 

Posted by Uli Köhler in C/C++

How to iterate TopTools_IndexedMapOfShape

In OpenCASCADE, you can get e.g. a list of edges for a TopoDS_Shape using

TopTools_IndexedMapOfShape edges;
TopExp::MapShapes (shape, TopAbs_EDGE, edges);

How can you iterate edges?

The easiest way is to use indexing like this:

for (size_t i = 1; i <= edges.Extent(); i++) {
    TopoDS_Shape& edge = edges(i);
    /* ... */
}

If you want to get the TopoDS_Edge from the TopoDS_Shape in the above example, use TopoDS::Edge(edge) inside the loop.

Posted by Uli Köhler in C/C++, OpenCASCADE

How to fuse TopoDS_Shapes in OpenCASCADE (boolean AND)

The OCCUtils library provides an easy way to fuse two shapes in OpenCASCADE.

First, let’s generate a box and a cylinder using OCCUtil’s primitive generation functions:

#include <occutils/Primitive.hxx>

using namespace OCCUtils;
  
TopoDS_Shape solid1 = Primitive::MakeBox(18 /* X */, 8 /* Y */, 14 /* Z */,
    Primitive::CenterX | Primitive::CenterY);

TopoDS_Shape solid2 = Primitive::MakeCylinder(5 /* d */, 35 /* L */,
    Primitivs::Orientation::Z,
    Primitive::CenterD);

Now we can fuse the primitives using this snippet:

#include <occutils/Boolean.hxx>

using namespace OCCUtils;

TopoDS_Shape fused = Boolean::Fuse({solid1, solid2});

Boolean::Fuse() can take a number of different argument types. In this example, we’are using a std::initializer_list (this is the curly-bracket syntax) – but it can also take a TopTools_ListOfShape or a std::vector<TopoDS_Shape> (and also most other STL- or non-STL containers).

If you want to perform a fuse without using OCCUtils, you might be tempted to use this syntax:

BRepAlgoAPI_Fuse fuse(solid1, solid2);
fuse.Build();
TopoDS_Shape result = fuse.Shape();

However, the BRepAlgoAPI_Fuse(TopoDS, TopoDS) constructor is deprecated and should therefore not be used. Instead, the following syntax should be used:

// Configure fuse
BRepAlgoAPI_Fuse fuse;
fuse.SetArguments(arguments);
fuse.SetTools(tools);
// Run fuse
fuse.Build();
TopoDS_Shape shape = fuse.Shape(); // Raises NotDone if not done.

where arguments and tools are two TopTools_ListOfShape instances. For other boolean algorithms like BRepAlgoAPI_Cut (boolean difference) the two have distinct meanings, but for BRepAlgoAPI_Fuse it’s just important that both arguments and tools have at least one element each!

You can use ListUtils::SplitIntoHeadAndTail from OCCUtils to generate a std::pair of lists (arguments and tools), with arguments having one element and tools having the rest like this:

auto toolsAndArgs = ListUtils::SplitIntoHeadAndTail(shapes, 1);
auto tools = toolsAndArgs.first;
auto arguments = toolsAndArgs.second;

However, if you use ListUtils::SplitIntoHeadAndTail(), you can just use Boolean::Fuse() right away.

Posted by Uli Köhler in C/C++, OpenCASCADE

How to export STEP file in OpenCASCADE

My OCCUtils library provides a super-easy way of exporting your TopoDS_Shape to a STEP AP203 file:

#include <occutils/STEPExport.hxx>

using namespace OCCUtils;

TopoDS_Shape myShape = /* ... */;
STEP::ExportSTEP(myShape, "myShape.step");

In case you want to do it manually, it’s much more complicated to do right, but here are the basic steps to do it:

STEPControl_Writer writer;
writer.Transfer(shape, STEPControl_AsIs);
writer.Write(filename.c_str());

The full STEP::ExportSTEP code from OCCUtils is:

if (shape.IsNull () == true) {
    throw new invalid_argument("Can't export null shape to STEP");
}

STEPControl_Writer writer;
Interface_Static::SetCVal ("xstep.cascade.unit", unit.c_str());
Interface_Static::SetCVal ("write.step.unit", unit.c_str ());
Interface_Static::SetIVal ("write.step.nonmanifold", 1);
// "Transfer" = convert
IFSelect_ReturnStatus transferStatus = writer.Transfer(shape, STEPControl_AsIs);

if (transferStatus != IFSelect_RetDone) {
    throw std::logic_error ("Error while transferring shape to STEP");
}
// Write transferred structure to STEP file
IFSelect_ReturnStatus writeStatus = writer.Write(filename.c_str());

// Return previous locale
if (writeStatus != IFSelect_RetDone)
{
    throw std::logic_error ("Error while writing transferred shape to STEP file");
}

 

Posted by Uli Köhler in C/C++, OpenCASCADE

How to create a Cylinder TopoDS_Solid in OpenCASCADE

Also see How to create a Box TopoDS_Solid in OpenCASCADE and How to create a Cube TopoDS_Solid in OpenCASCADE

Using my OCCUtils library, you can easily create a cylinder of user-defined diameter and length:

#include <occutils/Primitive.hxx>

using namespace OCCUtils;

TopoDS_Solid myCube = Primitive::MakeCylinder(5.0 /* mm diameter */, 25.0 /* mm length */);

You can also define the orientation of the cylinder using Primites::Orientation::X, Primites::Orientation::Y or Primites::Orientation::Z:

#include <occutils/Primitive.hxx>
#include <vector>

using namespace OCCUtils;

TopoDS_Solid myCube = Primitive::MakeCylinder(5.0 /* mm diameter */,
    25.0 /* mm length */, Primitive::Orientation::X);

You can also center this cylinder on the length axis. The origin point (default: (0,0,0)) always lies on the cylinder’s main axis (i.e. along its length.

#include <occutils/Primitive.hxx>
#include <vector>

using namespace OCCUtils;

/*
 * Make a cube that is centered on the X- and Y axes
 */
TopoDS_Solid myCube = Primitive::MakeCylinder(5.0 /* mm diameter */, 25.0 /* mm length */,
    Primitive::Orientation::X,
    Primitive::CenterL);

Also you can use a specific point of origin as the third argument (gp_Pnt).

If you want to do it manually without OCCUtils, have a look at the OCC class BRepPrimAPI_MakeBox which you can use like this:

gp_Ax2 ax = /* Define origin point and direction of the cylinder here */;
BRepPrimAPI_MakeCylinder cyl(ax, diameter / 2.0, length);
cyl.Build();
TopoDS_Solid mySolid = cyl.Solid();

In this case, you have to center the object manually by computing the correct point of origin. In OCCUtils this is done using

// Compute offsets based on centering
if(center & CenterX) {
    origin.SetX(origin.X() - xSize / 2.0);
}
if(center & CenterY) {
    origin.SetY(origin.Y() - ySize / 2.0);
}
if(center & CenterZ) {
    origin.SetZ(origin.Z() - zSize / 2.0);
}

 

Posted by Uli Köhler in C/C++, OpenCASCADE

How to create a Box TopoDS_Solid in OpenCASCADE

Also see How to create a Cube TopoDS_Solid in OpenCASCADE and How to create a Cylinder TopoDS_Solid in OpenCASCADE

Using my OCCUtils library, you can easily create a box of user-defined dimensions:

#include <occutils/Primitive.hxx>
#include <vector>

using namespace OCCUtils;

TopoDS_Solid myCube = Primitive::MakeBox(5.0 /* X size */, 7.0 /* Y size */, 9.0 /* Z size */);

You can also center this box on one or more axes (if not centered in any axis, one of the corners is going to be on thre origin point):

#include <occutils/Primitive.hxx>
#include <vector>

using namespace OCCUtils;

/*
 * Make a box that is centered on the X- and Y axes
 */
TopoDS_Solid myCube = Primitive::MakeBox(5.0, 7.0, 9.0
    Primitive::CenterX | Primitive::CenterY);

Also you can use a specific point of origin as the third argument (gp_Pnt).

If you want to do it manually without OCCUtils, have a look at the OCC class BRepPrimAPI_MakeBox which you can use like this:

BRepPrimAPI_MakeBox box(origin, xSize, ySize, zSize);
box.Build();
TopoDS_Solid mySolid = box.Solid();

In this case, you have to center the object manually by computing the correct point of origin. In OCCUtils this is done using

// Compute offsets based on centering
if(center & CenterX) {
    origin.SetX(origin.X() - xSize / 2.0);
}
if(center & CenterY) {
    origin.SetY(origin.Y() - ySize / 2.0);
}
if(center & CenterZ) {
    origin.SetZ(origin.Z() - zSize / 2.0);
}

 

Posted by Uli Köhler in C/C++, OpenCASCADE

How to create a Cube TopoDS_Solid in OpenCASCADE

Also see How to create a Box TopoDS_Solid in OpenCASCADE and How to create a Cylinder TopoDS_Solid in OpenCASCADE

Using my OCCUtils library, you can easily create a cube of user-defined dimensions:

#include <occutils/Primitive.hxx>

using namespace OCCUtils;

TopoDS_Solid myCube = Primitive::MakeCube(5.0 /* mm side length */);

You can also center this cube on one or more axes (if not centered in any axis, one of the corners is going to be on thre origin point):

#include <occutils/Primitive.hxx>

using namespace OCCUtils;

/*
 * Make a cube that is centered on the X- and Y axes
 */
TopoDS_Solid myCube = Primitive::MakeCube(5.0 /* mm side length */,
    Primitive::CenterX | Primitive::CenterY);

Also you can use a specific point of origin as the third argument (gp_Pnt).

If you want to do it manually without OCCUtils, have a look at the OCC class BRepPrimAPI_MakeBox which you can use like this:

BRepPrimAPI_MakeBox box(origin, size, size, size);
box.Build();
TopoDS_Solid mySolid = box.Solid();

In this case, you have to center the object manually by computing the correct point of origin. In OCCUtils this is done using

// Compute offsets based on centering
if(center & CenterX) {
    origin.SetX(origin.X() - xSize / 2.0);
}
if(center & CenterY) {
    origin.SetY(origin.Y() - ySize / 2.0);
}
if(center & CenterZ) {
    origin.SetZ(origin.Z() - zSize / 2.0);
}

 

Posted by Uli Köhler in C/C++, OpenCASCADE