Part: Refactor TopoShape::splitWires (#23096)

This refactors TopoShape::splitWires method to be easier to follow and
use variable names that better describe the intent.
This commit is contained in:
Kacper Donat
2026-02-08 06:24:47 +01:00
committed by GitHub
parent fa97300ec6
commit 9dbf5ae94b
2 changed files with 43 additions and 45 deletions

View File

@@ -697,15 +697,16 @@ public:
/// Make both outer and inner wires reversed
ReorientReversed,
};
/** Return the outer and inner wires of a face
*
* @param inner: optional output of inner wires
* @param innerWiresOutput: optional output of inner wires
* @param reorient: wire reorientation, see SplitWireReorient
*
* @return Return the outer wire
*/
TopoShape splitWires(
std::vector<TopoShape>* inner = nullptr,
std::vector<TopoShape>* innerWiresOutput = nullptr,
SplitWireReorient reorient = Reorient
) const;

View File

@@ -5327,14 +5327,15 @@ std::vector<Data::MappedName> TopoShape::decodeElementComboName(
/**
* Reorient the outer and inner wires of the TopoShape
*
* @param inner If this is not a nullptr, then any inner wires processed will be returned in this
* vector.
* @param reorient One of NoReorient, Reorient ( Outer forward, inner reversed ),
* ReorientForward ( all forward ), or ReorientReversed ( all reversed )
* @param innerWiresOutput If this is not a nullptr, then any inner wires processed will be returned
* in this vector.
* @param reorient One of NoReorient, Reorient (Outer forward, inner reversed),
* ReorientForward (all forward), or ReorientReversed (all reversed)
*
* @return The outer wire, or an empty TopoShape if this isn't a Face, has no Face subShapes, or the
* outer wire isn't found.
*/
TopoShape TopoShape::splitWires(std::vector<TopoShape>* inner, SplitWireReorient reorient) const
TopoShape TopoShape::splitWires(std::vector<TopoShape>* innerWiresOutput, SplitWireReorient reorient) const
{
// ShapeAnalysis::OuterWire() is un-reliable for some reason. OCC source
// code shows it works by creating face using each wire, and then test using
@@ -5348,18 +5349,18 @@ TopoShape TopoShape::splitWires(std::vector<TopoShape>* inner, SplitWireReorient
// implemented using simple bound box checking. This should be a
// reliable method, especially so for a planar face.
TopoDS_Shape tmp;
TopoDS_Shape outerWire;
if (shapeType(true) == TopAbs_FACE) {
tmp = BRepTools::OuterWire(TopoDS::Face(_Shape));
outerWire = BRepTools::OuterWire(TopoDS::Face(_Shape));
}
else if (countSubShapes(TopAbs_FACE) == 1) {
tmp = BRepTools::OuterWire(TopoDS::Face(getSubShape(TopAbs_FACE, 1)));
outerWire = BRepTools::OuterWire(TopoDS::Face(getSubShape(TopAbs_FACE, 1)));
}
if (tmp.IsNull()) {
if (outerWire.IsNull()) {
return TopoShape {};
}
const auto& wires = getSubTopoShapes(TopAbs_WIRE);
auto it = wires.begin();
TopAbs_Orientation orientOuter, orientInner;
switch (reorient) {
@@ -5375,55 +5376,51 @@ TopoShape TopoShape::splitWires(std::vector<TopoShape>* inner, SplitWireReorient
break;
}
auto doReorient = [](TopoShape& s, TopAbs_Orientation orient) {
auto reorientIfNecessary = [reorient](TopoShape& shape, TopAbs_Orientation orient) {
if (reorient == NoReorient) {
return;
}
// Special case of single edge wire. Make sure the edge is in the
// required orientation. This is necessary because BRepFill_OffsetWire
// has special handling of circular edge offset, which seem to only
// respect the edge orientation and disregard the wire orientation. The
// orientation is used to determine whether to shrink or expand.
if (s.countSubShapes(TopAbs_EDGE) == 1) {
TopoDS_Shape e = s.getSubShape(TopAbs_EDGE, 1);
if (e.Orientation() == orient) {
if (s._Shape.Orientation() == orient) {
if (shape.countSubShapes(TopAbs_EDGE) == 1) {
TopoDS_Shape edge = shape.getSubShape(TopAbs_EDGE, 1);
if (edge.Orientation() == orient) {
if (shape._Shape.Orientation() == orient) {
return;
}
}
else {
e = e.Oriented(orient);
edge = edge.Oriented(orient);
}
BRepBuilderAPI_MakeWire mkWire(TopoDS::Edge(e));
s.setShape(mkWire.Shape(), false);
BRepBuilderAPI_MakeWire mkWire(TopoDS::Edge(edge));
shape.setShape(mkWire.Shape(), false);
}
else if (s._Shape.Orientation() != orient) {
s.setShape(s._Shape.Oriented(orient), false);
else if (shape._Shape.Orientation() != orient) {
shape.setShape(shape._Shape.Oriented(orient), false);
}
};
for (; it != wires.end(); ++it) {
auto& wire = *it;
if (wire.getShape().IsSame(tmp)) {
if (inner) {
for (++it; it != wires.end(); ++it) {
inner->push_back(*it);
if (reorient) {
doReorient(inner->back(), orientInner);
}
}
}
auto res = wire;
if (reorient) {
doReorient(res, orientOuter);
}
return res;
TopoShape outerWireResult {};
for (auto& wire : getSubTopoShapes(TopAbs_WIRE)) {
if (wire.getShape().IsSame(outerWire)) {
outerWireResult = wire;
reorientIfNecessary(outerWireResult, orientOuter);
continue;
}
if (inner) {
inner->push_back(wire);
if (reorient) {
doReorient(inner->back(), orientInner);
}
if (innerWiresOutput) {
innerWiresOutput->push_back(wire);
reorientIfNecessary(innerWiresOutput->back(), orientInner);
}
}
return TopoShape {};
return outerWireResult;
}
bool TopoShape::isLinearEdge() const