[Part] Extrusion: taper nested wires properly

addendum to commit 2d6bcba90

Now also wires nested by more than one level are supported.
The possible nesting is infinite.
This commit is contained in:
Uwe
2022-01-30 05:52:43 +01:00
parent 7cc5cc8d74
commit b339cd4624
2 changed files with 111 additions and 42 deletions

View File

@@ -416,7 +416,7 @@ void Extrusion::makeDraft(const ExtrusionParameters& params, const TopoDS_Shape&
for (auto itInner = resultPrisms.begin(); itInner != resultPrisms.end(); ++itInner) {
if (itOuter == itInner)
continue;
// get center of mass of first shape
// get MomentOfInertia of first shape
BRepGProp::VolumeProperties(*itInner, tempProperties);
momentOfInertiaInitial = tempProperties.MomentOfInertia(gp_Ax1(gp_Pnt(), params.dir));
BRepAlgoAPI_Cut mkCut(*itInner, *itOuter);
@@ -442,6 +442,13 @@ void Extrusion::makeDraft(const ExtrusionParameters& params, const TopoDS_Shape&
The first input one will now be taken as outer one.\n");
}
// we can have the case of nested inner wires, therefore check for inner wires in inner wires
// these will become outer ones, inner of inner of inner reamin inner and so on
if (numInnerWires > 1) {
std::vector<bool> toCheck = isInnerWire; // all inner wires need to be checked
checkInnerWires(isInnerWire, params, toCheck, true, resultPrisms);
}
// at first create offset wires for the reversed part of extrusion
// it is important that these wires are the first loft section
if (bRev) {
@@ -539,51 +546,41 @@ void Extrusion::makeDraft(const ExtrusionParameters& params, const TopoDS_Shape&
if (params.solid) {
// we only need to cut if we have inner wires
if (numInnerWires > 0) {
TopoDS_Shape result;
BRep_Builder builder;
TopoDS_Compound compOuter;
TopoDS_Shape outerCutShape;
// when there is more than one outer wire make a compound of the outer shells
rows = 0;
if ((numWires - numInnerWires) > 1) {
builder.MakeCompound(compOuter);
for (auto it = shells.begin(); it != shells.end(); ++it) {
if (!isInnerWire[rows])
builder.Add(compOuter, *it);
++rows;
// we take every outer wire prism and cut subsequently all inner wires prisms from it
// every resulting shape is the final drafted extrusion shape
std::vector<bool>::iterator isInnerWireIterator = isInnerWire.begin();
std::vector<bool>::iterator isInnerWireIteratorLoop;
for (auto itOuter = shells.begin(); itOuter != shells.end(); ++itOuter) {
if (*isInnerWireIterator == true) {
++isInnerWireIterator;
continue;
}
outerCutShape = compOuter;
}
else { // take the shell directly without a compound
for (auto it = shells.begin(); it != shells.end(); ++it) {
if (!isInnerWire[rows]) {
outerCutShape = *it;
break;
isInnerWireIteratorLoop = isInnerWire.begin();
for (auto itInner = shells.begin(); itInner != shells.end(); ++itInner) {
if (itOuter == itInner || *isInnerWireIteratorLoop == false) {
++isInnerWireIteratorLoop;
continue;
}
++rows;
// get MomentOfInertia of first shape
BRepGProp::VolumeProperties(*itInner, tempProperties);
momentOfInertiaInitial = tempProperties.MomentOfInertia(gp_Ax1(gp_Pnt(), params.dir));
BRepAlgoAPI_Cut mkCut(*itOuter, *itInner);
if (!mkCut.IsDone())
Standard_Failure::Raise("Extrusion: Final cut out failed");
BRepGProp::VolumeProperties(mkCut.Shape(), tempProperties);
momentOfInertiaFinal = tempProperties.MomentOfInertia(gp_Ax1(gp_Pnt(), params.dir));
// if the whole shape was cut away the resulting shape is not Null but its MomentOfInertia is 0.0
// therefore we have a valid cut if the MomentOfInertia is not zero and changed
if ((momentOfInertiaInitial != momentOfInertiaFinal)
&& (momentOfInertiaFinal > Precision::Confusion())) {
// immediately update the outer shape since more inner wire prism might cut it
*itOuter = mkCut.Shape();
}
++isInnerWireIteratorLoop;
}
drafts.push_back(*itOuter);
++isInnerWireIterator;
}
// now the compound of the inner, no matter if we only have one inner
TopoDS_Compound compInner;
builder.MakeCompound(compInner);
rows = 0;
for (auto it = shells.begin(); it != shells.end(); ++it) {
if (isInnerWire[rows])
builder.Add(compInner, *it);
++rows;
}
// cut the inner from the outer
BRepAlgoAPI_Cut mkCutFinal(outerCutShape, compInner);
if (!mkCutFinal.IsDone())
Standard_Failure::Raise("Extrusion: Cut of inner structures failed");
result = mkCutFinal.Shape();
// de-assemble the result to return every solid independently
for (TopoDS_Iterator anExp(result); anExp.More(); anExp.Next()) {
if (anExp.Value().ShapeType() == TopAbs_SOLID)
drafts.push_back(anExp.Value());
}
if (drafts.empty()) // should never happen, we already checked the success of the cut of solids
Standard_Failure::Raise("Extrusion: The extrusion result is no solid shape");
} else
// we already have the results
for (auto it = shells.begin(); it != shells.end(); ++it)
@@ -609,6 +606,75 @@ void Extrusion::makeDraft(const ExtrusionParameters& params, const TopoDS_Shape&
}
}
void Extrusion::checkInnerWires (std::vector<bool>& isInnerWire, const ExtrusionParameters& params,
std::vector<bool>& checklist, bool forInner, std::vector<TopoDS_Shape> prisms)
{
GProp_GProps tempProperties;
Standard_Real momentOfInertiaInitial;
Standard_Real momentOfInertiaFinal;
int numCheckWires = 0;
std::vector<bool>::iterator isInnerWireIterator = isInnerWire.begin();
std::vector<bool>::iterator toCheckIterator = checklist.begin();
// create an array with false used later to store what can be cancelled from the checklist
std::vector<bool> toDisable;
for (auto numChecks : checklist)
toDisable.push_back(false);
int outer = -1;
// we cut every prism to be checked from the other to be checked ones
// if nothing happens, a prism can be cancelled from the checklist
for (auto itOuter = prisms.begin(); itOuter != prisms.end(); ++itOuter) {
++outer;
if (*toCheckIterator == false) {
++isInnerWireIterator;
++toCheckIterator;
continue;
}
auto toCheckIteratorInner = checklist.begin();
bool saveIsInnerWireIterator = *isInnerWireIterator;
for (auto itInner = prisms.begin(); itInner != prisms.end(); ++itInner) {
if (itOuter == itInner || *toCheckIteratorInner == false) {
++toCheckIteratorInner;
continue;
}
// get MomentOfInertia of first shape
BRepGProp::VolumeProperties(*itInner, tempProperties);
momentOfInertiaInitial = tempProperties.MomentOfInertia(gp_Ax1(gp_Pnt(), params.dir));
BRepAlgoAPI_Cut mkCut(*itInner, *itOuter);
if (!mkCut.IsDone())
Standard_Failure::Raise("Extrusion: Cut out failed");
BRepGProp::VolumeProperties(mkCut.Shape(), tempProperties);
momentOfInertiaFinal = tempProperties.MomentOfInertia(gp_Ax1(gp_Pnt(), params.dir));
// if the whole shape was cut away the resulting shape is not Null but its MomentOfInertia is 0.0
// therefore we have an inner wire if the MomentOfInertia is not zero and changed
if ((momentOfInertiaInitial != momentOfInertiaFinal)
&& (momentOfInertiaFinal > Precision::Confusion())) {
*isInnerWireIterator = !forInner;
++numCheckWires;
*toCheckIterator = true;
break;
}
++toCheckIteratorInner;
}
if (saveIsInnerWireIterator == *isInnerWireIterator)
// nothing was changed and we can remove it from the list to be checked
// but we cannot do this before the foor loop was fully run
toDisable[outer] = true;
++isInnerWireIterator;
++toCheckIterator;
}
// cancel prisms from the checklist whose wire state did not change
size_t i = 0;
for (auto disable : toDisable) {
if (disable)
checklist[i] = false;
++i;
}
// recursively call the function until all wires are checked
if (numCheckWires > 1)
checkInnerWires(isInnerWire, params, checklist, !forInner, prisms);
};
void Extrusion::createTaperedPrismOffset(TopoDS_Wire sourceWire,
const gp_Vec& translation,
double offset,

View File

@@ -123,6 +123,9 @@ public: //mode enumerations
protected:
static void makeDraft(const ExtrusionParameters& params, const TopoDS_Shape&, std::list<TopoDS_Shape>&);
static void checkInnerWires(std::vector<bool>& isInnerWire, const ExtrusionParameters& params,
std::vector<bool>& checklist, bool forInner, std::vector<TopoDS_Shape> prisms);
static void createTaperedPrismOffset(TopoDS_Wire sourceWire,
const gp_Vec& translation,
double offset,