BRepPrimAPI_MakeRevol -> no wire/edges in result shape... Why?

Guys, i produce BRepPrimAPI_MakeRevol of simple rect profile and after i can't find any normal wires/edges data inside shape entity, why? In case of BRepPrimAPI_MakePrism -> all ok, but BRepPrimAPI_MakeRevol doesn't work properly for wires/edges...

I do:
BRepPrimAPI_MakeRevol -> shape
...

uint32_t c1 = 0;
for (TopExp_Explorer ex0(shape, TopAbs_WIRE); ex0.More(); ex0.Next())
{
TopoDS_Wire wire = TopoDS::Wire(ex0.Current());
std::cout << "=========WIRE: " << c1++ << std::endl;
int c2 = 0;
for (TopExp_Explorer ex1(wire, TopAbs_EDGE); ex1.More(); ex1.Next())
{
std::cout << "+++++++EDGE: " << c2++ << std::endl;
TopoDS_Edge edge = TopoDS::Edge(ex1.Current());
for (TopExp_Explorer ex2(edge, TopAbs_VERTEX); ex2.More(); ex2.Next())
{
TopoDS_Vertex vertex = TopoDS::Vertex(ex2.Current());
gp_Pnt p = BRep_Tool::Pnt(vertex);
std::cout << "\t" << p.X() << " " << p.Y() << " " << p.Z() << std::endl;
}
}
}

and result looks like crap... No desired circular edges... Hmm, any ideas?

=========WIRE: 0
+++++++EDGE: 0
-100 0 200
-100 0 200
+++++++EDGE: 1
100 0 200
100 0 200
+++++++EDGE: 2
-100 0 200
100 0 200
+++++++EDGE: 3
-100 0 200
100 0 200
=========WIRE: 1
+++++++EDGE: 0
-100 0 100
-100 0 100
=========WIRE: 2
+++++++EDGE: 0
-100 0 200
-100 0 200
=========WIRE: 3
+++++++EDGE: 0
100 0 100
100 0 100
+++++++EDGE: 1
-100 0 100
-100 0 100
+++++++EDGE: 2
100 0 100
-100 0 100
+++++++EDGE: 3
100 0 100
-100 0 100
=========WIRE: 4
+++++++EDGE: 0
100 0 200
100 0 200
=========WIRE: 5
+++++++EDGE: 0
100 0 100
100 0 100

Attachments: 
Dmitrii Pasukhin's picture

Hello, unfortunately, I'm not very familiar with the BRepPrimAPI_MakeRevol function. However, I think your result is valid.

As far as I can see, you have received a surface of revolution. The faces built using this type of surface have natural boundaries and do not require any additional boundaries such as wires.

Best regards, Dmitrii

Caleb Smith's picture

Well, i guess i have to additionally rotate my vertices of sketch profile by BRepPrimAPI_MakeRevol to get edges. I'll try it now and let you know what happens.

Caleb Smith's picture

It looks like a bug, nothing works. Vertices also don't rotate around axis to form edges... I do this:

int ccc = 0;
std::unordered_map<glm::dvec3, TopoDS_Vertex> ds;
for (TopExp_Explorer ex0(face, TopAbs_VERTEX); ex0.More(); ex0.Next())
{
TopoDS_Vertex vertex = TopoDS::Vertex(ex0.Current());
gp_Pnt p = BRep_Tool::Pnt(vertex);
ccc++;
glm::dvec3 dp(p.X(), p.Y(), p.Z());
ds.insert({ dp, vertex });
}

int vc = 0;
for (auto& it : ds)
{
BRepPrimAPI_MakeRevol revolve(it.second, revAxis, Standard_True);
if (!revolve.IsDone())
return false;
TopoDS_Shape revEdge = revolve.Shape();

TopAbs_ShapeEnum revEdgeType = revEdge.ShapeType();

int ec = 0;
//std::vector<glm::dvec3> edgeVertices;
for (TopExp_Explorer ex0(revEdge, TopAbs_VERTEX); ex0.More(); ex0.Next())
{
TopoDS_Vertex vertex = TopoDS::Vertex(ex0.Current());
gp_Pnt p = BRep_Tool::Pnt(vertex);
glm::dvec3 dp(p.X(), p.Y(), p.Z());
//edgeVertices.emplace_back(dp);

std::cout << "ROTATED VERTEX#" << vc << " DOT#" << ec << "\t:" << dp.x << " " << dp.y << " " << dp.z << std::endl;
ec++;
}

vc++;
}

and taking:
ROTATED VERTEX#0 DOT#0 :100 0 100
ROTATED VERTEX#0 DOT#1 :100 0 100
ROTATED VERTEX#1 DOT#0 :-100 0 200
ROTATED VERTEX#1 DOT#1 :-100 0 200
ROTATED VERTEX#2 DOT#0 :-100 0 100
ROTATED VERTEX#2 DOT#1 :-100 0 100
ROTATED VERTEX#3 DOT#0 :100 0 200
ROTATED VERTEX#3 DOT#1 :100 0 200

Look at attached image

Attachments: 
Dmitrii Pasukhin's picture

Im very interested on type if Edge curve, that generated.

Can you share result brep file after generation? You can just Write TopoDS_Shape into file using follow code:

 Handle(DEBRepCascade_ConfigurationNode) aNode = new DEBRepCascade_ConfigurationNode();
 // You can modify export setting by aNode->InternalParameters
 Handle(DE_Provider) aProvider = aNode->BuildProvider();
 aProvider->Write("Path",aShape);

Im interested in full result and rotating of vertexes. Can you share types of generated edges? It looks like a circle. If it is a circle, you be able to recieve a point on curve by getting value from pereodic (for example aCircle->Value(Pi))

Best regards, Dmitrii.

Caleb Smith's picture

ok, look at my revovle-dump files, i don't understand them :)

Dmitrii Pasukhin's picture

I was right. It is a circle. Now you be able to recieve a "gp_Pnt aPont = aCurve->Value(M_PI)"; or any other pereodic values.

Circle shareds one vertex for start and end with different orientation. So, as a result you recieve a start and end point in the same place.

Draw[3]> dump res


*********** Dump of res *************
Shape : 2, FORWARD

Dump of 2 TShapes

-----------------

Flags : Free, Modified, Checked, Orientable, Closed, Infinite, Convex, Locked

TShape # 1 : EDGE      11010000 00000251E1F6F390
    +2 -2
    Tolerance : 1e-07
     same parametrisation of curves
     same range on curves
    - Curve 3D : 1, range : 0 6.28318530717959

TShape # 2 : VERTEX    01011010 00000251E1F71700

    Tolerance : 1e-07
    - Point 3D : -100, 0, 100


 -------
Dump of 0 Curve2ds
 -------


 -------
Dump of 1 Curves
 -------

   1 : Circle
  Center :-100, 0, 0
  Axis   :-1, 0, 0
  XAxis  :0, 0, 1
  YAxis  :0, 1, -0
  Radius :100

 -------
Dump of 0 Polygon3Ds
 -------
 -------
Dump of 0 PolygonOnTriangulations
 -------

 -------
Dump of 0 surfaces
 -------

 -------
Dump of 0 Triangulations
 -------



 -------
 Dump of 0 Locations
 -------

Best regards, Dmitrii.

Caleb Smith's picture

"Circle shareds one vertex for start and end with different orientation. So, as a result you recieve a start and end point in the same place."
Aha!! Now I begin to understand :) Thank's man, but how to convert WIRE to CURVE?

Here is "shape" -> full revolve result, now i scan it for a wires...
for (TopExp_Explorer ex0(shape, TopAbs_WIRE); ex0.More(); ex0.Next())
{
TopoDS_Wire wire = TopoDS::Wire(ex0.Current());
//1) how to get aCurve from wire?
//2) and how to check "is wire a circle-curve or simple segment"?
gp_Pnt aPont = aCurve->Value(M_PI);
}

Dmitrii Pasukhin's picture

To get a Handle(Geom_Curve) from a TopoDS_Edge that is contained in a TopoDS_Wire, you need to first extract the TopoDS_Edge from the TopoDS_Wire and then get the Handle(Geom_Curve) from the TopoDS_Edge.

Here is an example code to get a Handle(Geom_Curve) from a TopoDS_Edge that is contained in a TopoDS_Wire:

// Get the TopoDS_Wire aWire
TopoDS_Wire aWire = ...;

// Iterate over all the edges in the wire
for (TopExp_Explorer expWireEdges(aWire, TopAbs_EDGE); expWireEdges.More(); expWireEdges.Next())
{
    // Get the TopoDS_Edge from the wire
    TopoDS_Edge anEdge = TopoDS::Edge(expWireEdges.Current());

    // Get the Handle(Geom_Curve) from the TopoDS_Edge
    Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge);
    // Use the Handle(Geom_Curve) here
}

Best regards, Dmitrii.

Caleb Smith's picture

"Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge);"
Wow, cool, so easy, but how to determinate is aCurve a circle or simple segment or spline or something else?
I mean, if aCurve is just a segment, i don't need to interpolate it by aCurve->Value(M_PI)...

Dmitrii Pasukhin's picture
// Get the TopoDS_Edge anEdge
TopoDS_Edge anEdge = ...;

// Get the curve from the TopoDS_Edge
Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge);

// Determine the type of curve
if(aCurve->DynamicType() == STANDARD_TYPE(Geom_Line))
{
    // Curve is a line
}
else if(aCurve->DynamicType() == STANDARD_TYPE(Geom_Circle))
{
    // Curve is a circle
}
else if(aCurve->DynamicType() == STANDARD_TYPE(Geom_Ellipse))
{
    // Curve is an ellipse
}
else if(aCurve->DynamicType() == STANDARD_TYPE(Geom_Hyperbola))
{
    // Curve is a hyperbola
}
else if(aCurve->DynamicType() == STANDARD_TYPE(Geom_Parabola))
{
    // Curve is a parabola
}
else if(aCurve->DynamicType() == STANDARD_TYPE(Geom_BezierCurve))
{
    // Curve is a Bezier curve
}
else if(aCurve->DynamicType() == STANDARD_TYPE(Geom_BSplineCurve))
{
    // Curve is a BSpline curve
}
Caleb Smith's picture

Ohh man, thank you very much! Your OCCT level - THE GOD! :-)

Last question:
In OCCT paradigm, Handle(Geom_Curve) -> self destroying smart pointer, which will deleted out of scope, right?

Dmitrii Pasukhin's picture

Yes, but it has a little different from std::shared_pointer or other std smart pointeres. It it the same with boost::intrusive_ptr

In any case, as you said, the Handle object will be destroyed as soon as it's no longer needed.

Regarding Geom_Curve, it can be a simple curve, as described earlier, but in some cases it can also be a Handle(Geom_TrimmedCurve), which has additional UV limitations and a basic simple curve that you might need.

Best regards, Dmitrii.

Caleb Smith's picture

I made it! But how to exclude base profile from existing wires in revolve resulting shape? 

Dmitrii Pasukhin's picture

It is possible only in visualization part to disable render edge.

Unfortunatelly, I don't know the Vis API.

Best regards, Dmitrii.

Caleb Smith's picture

I don't use built-in OCCT visualizer, I write my own render on Vulkan API.
Thanks again for help, I will find solution myself, most likely i just need to compare wires with the base profile and if it matches completely, exclude it.

Caleb Smith's picture

Thank you more buddy!