Toponaming/Part: cleanup FeatureExtrusion

This commit is contained in:
bgbsww
2024-03-18 09:08:34 -04:00
parent 946f8e9b0b
commit c75acb2d51
6 changed files with 155 additions and 218 deletions

View File

@@ -41,10 +41,14 @@
#include <Base/Console.h>
#include <Base/Exception.h>
#include <BRepClass3d_SolidClassifier.hxx>
#include <ShapeFix_Wire.hxx>
// #include <BRepLib_FindSurface.hxx>
#include "ExtrusionHelper.h"
#include "TopoShape.h"
#include "BRepOffsetAPI_MakeOffsetFix.h"
#include "Geometry.h"
using namespace Part;
@@ -478,138 +482,58 @@ void ExtrusionHelper::createTaperedPrismOffset(TopoDS_Wire sourceWire,
}
static TopoShape makEDraftUsingPipe(const std::vector<TopoShape> &_wires,
App::StringHasherRef hasher)
void ExtrusionHelper::makeElementDraft(const ExtrusionParameters& params,
const TopoShape& _shape,
std::vector<TopoShape>& drafts)
{
std::vector<TopoShape> shells;
std::vector<TopoShape> frontwires, backwires;
double distanceFwd = tan(params.taperAngleFwd) * params.lengthFwd;
double distanceRev = tan(params.taperAngleRev) * params.lengthRev;
if (_wires.size() < 2)
throw Base::CADKernelError("Not enough wire section");
std::vector<TopoShape> wires;
wires.reserve(_wires.size());
for (auto &wire : _wires) {
// Make a copy to work around OCCT bug on offset circular shapes
wires.push_back(wire.makECopy());
}
GeomLineSegment line;
Base::Vector3d pstart, pend;
wires.front().getCenterOfGravity(pstart);
gp_Pln pln;
if (wires.back().findPlane(pln)) {
auto dir = pln.Position().Direction();
auto base = pln.Location();
pend = pstart;
pend.ProjectToPlane(Base::Vector3d(base.X(), base.Y(), base.Z()),
Base::Vector3d(dir.X(), dir.Y(), dir.Z()));
} else
wires.back().getCenterOfGravity(pend);
line.setPoints(pstart, pend);
BRepBuilderAPI_MakeWire mkWire(TopoDS::Edge(line.toShape()));
BRepOffsetAPI_MakePipeShell mkPS(mkWire.Wire());
mkPS.SetTolerance(Precision::Confusion());
mkPS.SetTransitionMode(BRepBuilderAPI_Transformed);
mkPS.SetMode(false);
for (auto &wire : wires)
mkPS.Add(TopoDS::Wire(wire.getShape()));
if (!mkPS.IsReady())
throw Base::CADKernelError("Shape could not be built");
TopoShape result(0,hasher);
result.makEShape(mkPS,wires);
if (!mkPS.Shape().Closed()) {
// shell is not closed - use simulate to get the end wires
TopTools_ListOfShape sim;
mkPS.Simulate(2, sim);
TopoShape front(sim.First());
if(front.countSubShapes(TopAbs_EDGE)==wires.front().countSubShapes(TopAbs_EDGE)) {
front = wires.front();
front.setShape(sim.First(),false);
}else
front.Tag = -wires.front().Tag;
TopoShape back(sim.Last());
if(back.countSubShapes(TopAbs_EDGE)==wires.back().countSubShapes(TopAbs_EDGE)) {
back = wires.back();
back.setShape(sim.Last(),false);
}else
back.Tag = -wires.back().Tag;
// build the end faces, sew the shell and build the final solid
front = front.makEFace();
back = back.makEFace();
BRepBuilderAPI_Sewing sewer;
sewer.SetTolerance(Precision::Confusion());
sewer.Add(front.getShape());
sewer.Add(back.getShape());
sewer.Add(result.getShape());
sewer.Perform();
result = result.makEShape(sewer);
}
result = result.makESolid();
BRepClass3d_SolidClassifier SC(result.getShape());
SC.PerformInfinitePoint(Precision::Confusion());
if (SC.State() == TopAbs_IN) {
result.setShape(result.getShape().Reversed(),false);
}
return result;
}
void ExtrusionHelper::makEDraft(const ExtrusionParameters& params,
const TopoShape& _shape,
std::vector<TopoShape>& drafts,
App::StringHasherRef hasher)
{
double distanceFwd = tan(params.taperAngleFwd)*params.lengthFwd;
double distanceRev = tan(params.taperAngleRev)*params.lengthRev;
gp_Vec vecFwd = gp_Vec(params.dir)*params.lengthFwd;
gp_Vec vecRev = gp_Vec(params.dir.Reversed())*params.lengthRev;
gp_Vec vecFwd = gp_Vec(params.dir) * params.lengthFwd;
gp_Vec vecRev = gp_Vec(params.dir.Reversed()) * params.lengthRev;
bool bFwd = fabs(params.lengthFwd) > Precision::Confusion();
bool bRev = fabs(params.lengthRev) > Precision::Confusion();
bool bMid = !bFwd || !bRev || params.lengthFwd*params.lengthRev > 0.0; //include the source shape as loft section?
bool bMid = !bFwd || !bRev
|| params.lengthFwd * params.lengthRev > 0.0; // include the source shape as loft section?
TopoShape shape = _shape;
TopoShape sourceWire;
if (shape.isNull())
if (shape.isNull()) {
Standard_Failure::Raise("Not a valid shape");
}
if (params.solid && !shape.hasSubShape(TopAbs_FACE))
shape = shape.makEFace(nullptr, params.faceMakerClass.c_str());
if (params.solid && !shape.hasSubShape(TopAbs_FACE)) {
shape = shape.makeElementFace(nullptr, params.faceMakerClass.c_str());
}
if (shape.shapeType() == TopAbs_FACE) {
std::vector<TopoShape> wires;
TopoShape outerWire = shape.splitWires(&wires, TopoShape::ReorientForward);
if (outerWire.isNull())
if (outerWire.isNull()) {
Standard_Failure::Raise("Missing outer wire");
if (wires.empty())
}
if (wires.empty()) {
shape = outerWire;
}
else {
unsigned pos = drafts.size();
makEDraft(params, outerWire, drafts, hasher);
if (drafts.size() != pos+1)
makeElementDraft(params, outerWire, drafts);
if (drafts.size() != pos + 1) {
Standard_Failure::Raise("Failed to make drafted extrusion");
}
std::vector<TopoShape> inner;
TopoShape innerWires(0, hasher);
innerWires.makECompound(wires,"",false);
ExtrusionParameters copy = params;
copy.taperAngleFwd = params.innerTaperAngleFwd;
copy.taperAngleRev = params.innerTaperAngleRev;
makEDraft(copy, innerWires, inner, hasher);
if (inner.empty())
TopoShape innerWires(0);
innerWires.makeElementCompound(
wires,
"",
TopoShape::SingleShapeCompoundCreationPolicy::returnShape);
makeElementDraft(params, innerWires, inner);
if (inner.empty()) {
Standard_Failure::Raise("Failed to make drafted extrusion with inner hole");
}
inner.insert(inner.begin(), drafts.back());
drafts.back().makECut(inner);
drafts.back().makeElementCut(inner);
return;
}
}
@@ -625,8 +549,9 @@ void ExtrusionHelper::makEDraft(const ExtrusionParameters& params,
sourceWire.mapSubElement(shape);
}
else if (shape.shapeType() == TopAbs_COMPOUND) {
for(auto &s : shape.getSubTopoShapes())
makEDraft(params, s, drafts, hasher);
for (auto& s : shape.getSubTopoShapes()) {
makeElementDraft(params, s, drafts);
}
}
else {
Standard_Failure::Raise("Only a wire or a face is supported");
@@ -634,73 +559,48 @@ void ExtrusionHelper::makEDraft(const ExtrusionParameters& params,
if (!sourceWire.isNull()) {
std::vector<TopoShape> list_of_sections;
auto makeOffset = [&sourceWire](const gp_Vec& translation, double offset) -> TopoShape {
gp_Trsf mat;
mat.SetTranslation(translation);
TopoShape offsetShape(sourceWire.makETransform(mat,"RV"));
if (fabs(offset)>Precision::Confusion())
offsetShape = offsetShape.makEOffset2D(offset, TopoShape::JoinType::Intersection);
return offsetShape;
};
//first. add wire for reversed part of extrusion
if (bRev){
auto offsetShape = makeOffset(vecRev, distanceRev);
if (offsetShape.isNull())
Standard_Failure::Raise("Tapered shape is empty");
TopAbs_ShapeEnum type = offsetShape.getShape().ShapeType();
if (type == TopAbs_WIRE) {
list_of_sections.push_back(offsetShape);
}
else if (type == TopAbs_EDGE) {
list_of_sections.push_back(offsetShape.makEWires());
}
else {
Standard_Failure::Raise("Tapered shape type is not supported");
}
if (bRev) {
TopoDS_Wire offsetWire;
createTaperedPrismOffset(TopoDS::Wire(sourceWire.getShape()),
vecRev,
distanceRev,
false,
offsetWire);
list_of_sections.push_back(TopoShape(offsetWire, sourceWire.Tag));
}
//next. Add source wire as middle section. Order is important.
if (bMid){
// next. Add source wire as middle section. Order is important.
if (bMid) {
list_of_sections.push_back(sourceWire);
}
//finally. Forward extrusion offset wire.
if (bFwd){
auto offsetShape = makeOffset(vecFwd, distanceFwd);
if (offsetShape.isNull())
Standard_Failure::Raise("Tapered shape is empty");
TopAbs_ShapeEnum type = offsetShape.getShape().ShapeType();
if (type == TopAbs_WIRE) {
list_of_sections.push_back(offsetShape);
}
else if (type == TopAbs_EDGE) {
list_of_sections.push_back(offsetShape.makEWires());
}
else {
Standard_Failure::Raise("Tapered shape type is not supported");
}
// finally. Forward extrusion offset wire.
if (bFwd) {
TopoDS_Wire offsetWire;
createTaperedPrismOffset(TopoDS::Wire(sourceWire.getShape()),
vecFwd,
distanceFwd,
false,
offsetWire);
list_of_sections.push_back(TopoShape(offsetWire, sourceWire.Tag));
}
try {
#if defined(__GNUC__) && defined (FC_OS_LINUX)
#if defined(__GNUC__) && defined(FC_OS_LINUX)
Base::SignalException se;
#endif
if (params.usepipe) {
drafts.push_back(makEDraftUsingPipe(list_of_sections, hasher));
return;
// make loft
BRepOffsetAPI_ThruSections mkGenerator(params.solid ? Standard_True : Standard_False,
/*ruled=*/Standard_True);
for (auto& s : list_of_sections) {
mkGenerator.AddWire(TopoDS::Wire(s.getShape()));
}
//make loft
BRepOffsetAPI_ThruSections mkGenerator(
params.solid ? Standard_True : Standard_False, /*ruled=*/Standard_True);
for(auto &s : list_of_sections)
mkGenerator.AddWire(TopoDS::Wire(s.getShape()));
mkGenerator.Build();
drafts.push_back(TopoShape(0,hasher).makEShape(mkGenerator,list_of_sections));
drafts.push_back(TopoShape(0).makeElementShape(mkGenerator, list_of_sections));
}
catch (Standard_Failure &){
catch (Standard_Failure&) {
throw;
}
catch (...) {