内容发布更新时间 : 2024/12/23 5:01:50星期一 下面是文章的全部内容请认真阅读。
own face orientation. That is, if you need to use edge pcurves you should rather use:
TopExp_Explorer aFaceExp (myFace.Oriented (TopAbs_FORWARD), TopAbs_EDGE);(same to forward and different to reversed added by lxh) for (; aFaceExp.More(); aFaceExp.Next()) {
const TopoDS_Edge& anEdge = TopoDS::Edge (aFaceExp.Current()); }
This exception becomes understandable if you try to understand the details. Let's construct a face bottom-up:
Handle(Geom_Surface) aSurf = new Geom_Plane (gp::XOY());
//anti-clockwise circles if to look from surface normal
Handle(Geom_Curve) anExtC = new Geom_Circle (gp::XOY(), 10.); Handle(Geom_Curve) anIntC = new Geom_Circle (gp::XOY(), 5.); TopoDS_Edge anExtE = BRepBuilderAPI_MakeEdge (anExtC); TopoDS_Edge anIntE = BRepBuilderAPI_MakeEdge (anExtC); TopoDS_Wire anExtW = BRepBuilderAPI_MakeWire (anExtE); TopoDS_Wire anIntW = BRepBuilderAPI_MakeWire (anIntE); BRep_Builder aB; TopoDS_Face aFace;
aB.MakeFace (aFace, aSurf, Precision::Confusion()); aB.Update (aFace, aSurf); aB.Add (aFace, anExtW);
aB.Add (aFace, anIntW.Reversed()); //material should lie on the right of the inner wire
aFace has a forward orientation (default). Let's explore its edges and pcurves. Though we did not explicitly add them, recall (see Part 3) that for planes they can be computed on the fly:
void TraversePCurves (const TopoDS_Face& theFace) {
TopExp_Explorer anExp (theFace, TopAbs_EDGE); for (; anExp.More(); anExp.Next()) {
const TopoDS_Edge& anEdge = TopoDS::Edge (anExp.Current()); Standard_Real aF, aL;
Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface (anEdge, theFace, aF, aL); } }
Returned pcurves will be as shown below (material will be on the left of red
16
and on the right of blue).
Everything is correct. Now imagine we reverse the face and explore again:
TopoDS_Face aRFace = TopoDS::Face (aFace.Reversed()); TraversePCurves (aRFace);
What will we see ? All the edges will be extracted with opposite orientations and respectively their pcurves will mean that material is beyond an external wire and within an internal wire. This is clearly wrong, though original aRFace is perfectly correct. Recall Part4 that a face orientation just shows face logical orientation regarding its underlying surface. In our case aRFace will be just aFace with a normal {0, 0, -1}.
Thus, the only way out is to do the following:
TopExp_Explorer anExp (theFace.Oriented (TopAbs_FORWARD), TopAbs_EDGE);
This will ensure that edges will show orientation regarding surface (not face!) normal. I made exact same comment in Part 4. Open CASCADE algorithms take care of this particular case, make sure so do you.
Hope orientation is now also a well swallowed bit of an elephant we have been eating in this series. I think we are almost done with it. There are a few tiny bones to pick, and unless you are still hungry we will finish it in the last post to follow. Bon appetite ;-)
17
To be continued...
Topology and Geometry in Open CASCADE. Part 6
Continued...
Back references
As you likely noticed using OpenCASCADE or analyzing the diagram in Part1, shapes refer to their sub-shapes and not the other way round. This is
understandable as the same (sub-)shape can belong to multiple parent shapes. For instance, any shared edge will belong to at least two faces.
However it is sometimes needed to trace parent shape back from a child. To do this use TopExp::MapShapesAndAncestors().
TopTools_IndexedDataMapOfShapeListOfShape anEFsMap;
TopExp::MapShapesAndAncestors (myShape, TopAbs_EDGE, TopAbs_FACE, anEFsMap);
The code above fills out a map of parent faces for each edge in myShape. If myShape is a solid box, each edge will map to 2 faces. If you explore the same box into faces and try to fill out edge's ancestors in context of each face, then obviously the map will contain a single face for each edge – that very face you are currently in.
Adaptors
Some Open CASCADE algorithms can work on objects representing a curve. However they provide an API that does not accept Geom_Curve but rather Adaptor3d_Curve. For instance, Extrema does so what enables its use in intersection, projection and other algorithms both on geometrical curves (Geom_Curve) and topological edges (TopoDS_Edge). Other examples – calculation of lengths, or surface areas. This approach is known as Adapter pattern.
GeomAdaptor3d_Curve subclasses Adaptor3d_Curve to ‘adapt' Geom_Curve, BRepAdaptor_Curve to TopoDS_Edge, BRepAdaptor_CompCurve to TopoDS_Wire. There are similar classes for 2D curves and surfaces.
So you could write the following to measure lengths of a curve and an edge:
Handle(Geom_Curve) aCurve = ...;
Standard_Real aCurveLen = GCPoints_AbscissaPoints::Length (GeomAdaptor_Curve (aCurve));
TopoDS_Edge anEdge = ...;
Standard_Real anEdgeLen = GCPoints_AbscissaPoints::Length
18
(BRepAdaptor_Curve (anEdge));
Conclusion
So, this has been a long story about fundamental concepts of Open CASCADE. Hope you are now more familiar with them and understand what geometry and topology are. As a first step, make yourself correctly use the terms – curve or edge, surface or face, point or vertex. This will help you and people reading your questions clearly distinguish if you mean geometry or topology. Once you have started using correct definitions and keeping in mind their distinctions, part of your problems may simply go away.
That's it! Full up with this elephant ;-) ?
19