Hide menu
Loading...
Searching...
No Matches
exploring/brep_topology/main.cxx

Refer to the B-Rep Topology Exploration Example.

// ****************************************************************************
// $Id$
//
// Copyright (C) 2008-2014, Roman Lygin. All rights reserved.
// Copyright (C) 2014-2025, CADEX. All rights reserved.
//
// This file is part of the Manufacturing Toolkit software.
//
// You may use this file under the terms of the BSD license as follows:
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// ****************************************************************************
#include <cadex/LicenseManager_Activate.h>
#include <cadex/ModelData/Body.hxx>
#include <cadex/ModelData/Edge.hxx>
#include <cadex/ModelData/Face.hxx>
#include <cadex/ModelData/Model.hxx>
#include <cadex/ModelData/ModelElementVisitor.hxx>
#include <cadex/ModelData/ModelReader.hxx>
#include <cadex/ModelData/Part.hxx>
#include <cadex/ModelData/Shape.hxx>
#include <cadex/ModelData/SheetBody.hxx>
#include <cadex/ModelData/Shell.hxx>
#include <cadex/ModelData/SolidBody.hxx>
#include <cadex/ModelData/Vertex.hxx>
#include <cadex/ModelData/Wire.hxx>
#include <cadex/ModelData/WireframeBody.hxx>
#include <iostream>
#include <unordered_set>
#include "../../mtk_license.cxx"
using namespace std;
using namespace cadex;
// Define which level of equality we need in shape comparing
// Shapes comparison includes three components: entity, location and orientation
// There are two ways to compare shapes while using ShapeHashers: IsEqual() and IsSame()
// Two shapes are Equal if all three equivalence parts are identical for both shapes
// Two shapes are Same if all equivalence parts are identical except orientation
// Hence the difference between two ShapeHashes is what comparison method we need
#define ShapesOrientationIsUsed 0
#if ShapesOrientationIsUsed
// Use Oriented- ShapeHash and ShapeEqual if you want to consider orientation of shape in hash computing
typedef ModelData::OrientedShapeHash HasherType;
typedef ModelData::OrientedShapeEqual EqualerType;
#else
// Use Unoriented- ShapeHash and ShapeEqual if shape orientation is negligible
typedef ModelData::UnorientedShapeHash HasherType;
typedef ModelData::UnorientedShapeEqual EqualerType;
#endif
// Set to collect unique shapes from model
typedef unordered_set<ModelData::Shape, HasherType, EqualerType> ShapeSetType;
// Visits directly each part and calls B-Rep bodies exploring if a part has one
class PartBRepVisitor : public ModelData::ModelElementVoidVisitor
{
public:
PartBRepVisitor() : myNestingLevel (0)
{}
void PrintUniqueShapesCount()
{
cout << endl << "Total unique shapes count: " << myShapeSet.size() << endl;
}
protected:
void operator() (const ModelData::Part& thePart) override
{
cout << "Part = \"" << thePart.Name() << "\"" << endl;
const auto& aBodies = thePart.Bodies();
if (!aBodies.empty()) {
ExploreBRep (aBodies);
}
}
private:
void ExploreBRep (const std::vector<ModelData::Body>& theBodies)
{
myNestingLevel++;
// Iterate over bodies
for (size_t i = 0; i < theBodies.size(); ++i) {
const auto& aBody = theBodies[i];
PrintTabulation();
cout << "Body " << i << " " << PrintBodyType (aBody) << endl;
for (ModelData::ShapeIterator j (aBody); j.HasNext();) {
const ModelData::Shape& aShape = j.Next();
ExploreShape (aShape);
}
}
myNestingLevel--;
}
// Recursive iterating over the Shape untill reaching vertices
void ExploreShape (const ModelData::Shape theShape)
{
myShapeSet.insert (theShape);
++myNestingLevel;
ModelData::ShapeIterator aShapeIt (theShape);
while (aShapeIt.HasNext()) {
const ModelData::Shape& aShape = aShapeIt.Next();
PrintShapeInfo (aShape);
ExploreShape (aShape);
}
--myNestingLevel;
}
// Returns body type name
string PrintBodyType (const ModelData::Body& theBody)
{
if (theBody.IsOfType<ModelData::SheetBody>()) {
return "Sheet";
} else if (theBody.IsOfType<ModelData::SolidBody>()) {
return "Solid";
} else if (theBody.IsOfType<ModelData::WireframeBody>()) {
return "Wireframe";
}
return "Undefined";
}
// Returns shape type name and prints shape info in some cases
void PrintShapeInfo (const ModelData::Shape& theShape)
{
PrintTabulation();
switch (theShape.Type()) {
case ModelData::ShapeType::Solid:
cout << "Solid";
break;
case ModelData::ShapeType::Shell:
cout << "Shell";
break;
case ModelData::ShapeType::Wire:
cout << "Wire";
PrintWireInfo (ModelData::Wire::Cast (theShape));
break;
case ModelData::ShapeType::Face:
cout << "Face";
PrintFaceInfo (ModelData::Face::Cast (theShape));
break;
case ModelData::ShapeType::Edge:
cout << "Edge";
PrintEdgeInfo (ModelData::Edge::Cast (theShape));
break;
case ModelData::ShapeType::Vertex:
cout << "Vertex";
PrintVertexInfo (ModelData::Vertex::Cast (theShape));
break;
default:
cout << "Undefined";
break;
}
cout << endl;
}
void PrintWireInfo (const ModelData::Wire& theWire)
{
++myNestingLevel;
PrintOrientation (theWire.Orientation());
--myNestingLevel;
}
void PrintFaceInfo (const ModelData::Face& theFace)
{
++myNestingLevel;
PrintOrientation (theFace.Orientation());
cout << endl;
Geom::Surface aSurface = theFace.Surface();
PrintTabulation();
cout << "Surface: " << PrintSurfaceType (aSurface);
--myNestingLevel;
}
const char* PrintSurfaceType (const Geom::Surface& theSurface)
{
switch (theSurface.Type()) {
case Geom::SurfaceType::Plane:
return "Plane";
case Geom::SurfaceType::Cylinder:
return "Cylinder";
case Geom::SurfaceType::Cone:
return "Cone";
case Geom::SurfaceType::Sphere:
return "Sphere";
case Geom::SurfaceType::Torus:
return "Torus";
case Geom::SurfaceType::LinearExtrusion:
return "LinearExtrusion";
case Geom::SurfaceType::Revolution:
return "Revolution";
case Geom::SurfaceType::Bezier:
return "Bezier";
case Geom::SurfaceType::BSpline:
return "BSpline";
case Geom::SurfaceType::Offset:
return "Offset";
default:
break;
}
return "Undefined";
}
void PrintEdgeInfo (const ModelData::Edge& theEdge)
{
++myNestingLevel;
if (theEdge.IsDegenerated()) {
cout << "(Degenerated)";
}
PrintOrientation (theEdge.Orientation());
cout << "Tolerance = " << theEdge.Tolerance();
if (!theEdge.IsDegenerated()) {
double aFirstParam, aLastParam;
Geom::Curve aCurve = theEdge.Curve (aFirstParam, aLastParam);
cout << endl;
PrintTabulation();
cout << "Curve: " << PrintCurvetype (aCurve);
}
--myNestingLevel;
}
const char* PrintCurvetype (const Geom::Curve& theCurve)
{
switch (theCurve.Type()) {
case Geom::CurveType::Line:
return "Line";
case Geom::CurveType::Circle:
return "Circle";
case Geom::CurveType::Ellipse:
return "Ellipse";
case Geom::CurveType::Hyperbola:
return "Hyperbola";
case Geom::CurveType::Parabola:
return "Parabola";
case Geom::CurveType::Bezier:
return "Bezier";
case Geom::CurveType::BSpline:
return "BSpline";
case Geom::CurveType::Offset:
return "Offset";
default:
break;
}
return "Undefined";
}
void PrintVertexInfo (const ModelData::Vertex& theVertex)
{
PrintOrientation (theVertex.Orientation());
cout << "Tolerance = " << theVertex.Tolerance();
}
static void PrintOrientation (const ModelData::ShapeOrientation& theOrientation)
{
cout << "Orientation = ";
switch (theOrientation) {
case ModelData::ShapeOrientation::Forward:
cout << "Forward";
break;
case ModelData::ShapeOrientation::Reversed:
cout << "Reversed";
break;
default:
cout << "Undefined";
break;
}
cout << "; ";
}
void PrintTabulation()
{
for (size_t i = 0; i < myNestingLevel; ++i) {
cout << "- ";
}
}
size_t myNestingLevel;
ShapeSetType myShapeSet;
};
int main (int argc, char* argv[])
{
auto aKey = MTKLicenseKey::Value();
// Activate the license (aKey must be defined in mtk_license.cxx)
if (!CADExLicense_Activate (aKey)) {
cerr << "Failed to activate Manufacturing Toolkit license." << endl;
return 1;
}
// Get the input
if (argc != 2) {
cerr << "Usage: " << argv[0] << " <input_file>, where:" << endl;
cerr << " <input_file> is a name of the file to be read" << endl;
return 1;
}
const char* aSource = argv[1];
if (!ModelData::ModelReader().Read (aSource, aModel)) {
cerr << "Failed to read the file " << aSource << endl;
return 1;
}
// Explore B-Rep representation of model parts
PartBRepVisitor aVisitor;
aModel.Accept (aVisitor);
aVisitor.PrintUniqueShapesCount();
return 0;
}
Base class for 3D curves.
Definition Curve.hxx:39
CurveType Type() const
Definition Curve.cxx:434
Base class for geometrical surfaces.
Definition Surface.hxx:40
SurfaceType Type() const
Returns a surface type.
Definition Surface.cxx:495
Provides a base body class.
Definition Body.hxx:30
Defines an edge.
Definition Edge.hxx:33
Geom::Curve Curve(double &theFirstParameter, double &theLastParameter) const
Returns edge 3D curve and its limits.
Definition Edge.cxx:408
double Tolerance() const
Returns edge tolerance.
Definition Edge.cxx:682
bool IsDegenerated() const
Returns true if the edge is degenerated.
Definition Edge.cxx:689
Defines a topological face.
Definition Face.hxx:33
Geom::Surface Surface() const
Returns underlying surface.
Definition Face.cxx:324
UTF16String Name() const
Returns a name.
Definition ModelElement.cxx:55
Element visitor with empty implementation.
Definition ModelElementVisitor.hxx:64
Provides MTK data model.
Definition Model.hxx:40
void Accept(ModelElementVisitor &theVisitor) const
Accepts a visitor.
Definition Model.cxx:274
Reads STEP and native format.
Definition ModelReader.hxx:33
Compares shapes using 'IsEqual' relationship.
Definition Shape.hxx:93
Hasher for Shape using 'IsEqual' relationship.
Definition Shape.hxx:81
Defines a leaf node in the scene graph hiearchy.
Definition Part.hxx:34
Base class of topological shapes.
Definition Shape.hxx:38
ShapeOrientation Orientation() const
Returns orientation flag.
Definition Shape.cxx:271
ShapeType Type() const
Returns a shape type. For a null object returns Undefined.
Definition Shape.cxx:259
Iterates over subshapes in a shape.
Definition ShapeIterator.hxx:32
Provides a sheet body composed of faces and shells.
Definition SheetBody.hxx:34
Provides a solid body composed of solids.
Definition SolidBody.hxx:30
Compares shapes using 'IsSame' relationship.
Definition Shape.hxx:87
Hasher for Shape using 'IsSame' relationship.
Definition Shape.hxx:75
Defines topological vertex.
Definition Vertex.hxx:30
double Tolerance() const
Returns vertex tolerance.
Definition Vertex.cxx:117
Defines a connected set of edges.
Definition Wire.hxx:32
Provides a wireframe body composed of edges and wires.
Definition WireframeBody.hxx:34
ShapeOrientation
Defines shape orientation.
Definition ShapeOrientation.hxx:27
Contains classes, namespaces, enums, types, and global functions related to Manufacturing Toolkit.
Definition LicenseManager_LicenseError.hxx:30