Transfer FeatureHole code
This commit is contained in:
@@ -1882,30 +1882,77 @@ App::DocumentObjectExecReturn* Hole::execute()
|
||||
// we reuse the name protoHole (only now it is threaded)
|
||||
protoHole = mkFuse.Shape();
|
||||
}
|
||||
std::vector<TopoShape> holes;
|
||||
auto compound = findHoles(holes, profileshape, protoHole);
|
||||
|
||||
TopoDS_Compound holes = findHoles(profileshape.getShape(), protoHole);
|
||||
this->AddSubShape.setValue(holes);
|
||||
TopoShape result(0,getDocument()->getStringHasher());
|
||||
|
||||
// For some reason it is faster to do the cut through a BooleanOperation.
|
||||
BRepAlgoAPI_Cut mkBool(base.getShape(), holes);
|
||||
if (!mkBool.IsDone()) {
|
||||
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Boolean operation failed"));
|
||||
}
|
||||
TopoDS_Shape result = mkBool.Shape();
|
||||
// set the subtractive shape property for later usage in e.g. pattern
|
||||
this->AddSubShape.setValue(compound);
|
||||
if (isRecomputePaused())
|
||||
return App::DocumentObject::StdReturn;
|
||||
|
||||
|
||||
// We have to get the solids (fuse sometimes creates compounds)
|
||||
base = getSolid(result);
|
||||
if (base.isNull())
|
||||
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Resulting shape is not a solid"));
|
||||
base = refineShapeIfActive(base);
|
||||
|
||||
if (!isSingleSolidRuleSatisfied(base.getShape())) {
|
||||
return new App::DocumentObjectExecReturn(
|
||||
QT_TRANSLATE_NOOP("Exception", "Result has multiple solids: that is not currently supported."));
|
||||
if (base.isNull()) {
|
||||
Shape.setValue(compound);
|
||||
return App::DocumentObject::StdReturn;
|
||||
}
|
||||
|
||||
this->Shape.setValue(base);
|
||||
// First try cuting with compound which will be faster as it is done in
|
||||
// parallel
|
||||
bool retry = true;
|
||||
const char *maker;
|
||||
switch (getAddSubType()) {
|
||||
case Additive:
|
||||
maker = Part::OpCodes::Fuse;
|
||||
break;
|
||||
case Intersecting:
|
||||
maker = Part::OpCodes::Common;
|
||||
break;
|
||||
default:
|
||||
maker = Part::OpCodes::Cut;
|
||||
}
|
||||
try {
|
||||
if (base.isNull())
|
||||
result = compound;
|
||||
else
|
||||
result.makEBoolean(maker, {base,compound});
|
||||
result = getSolid(result);
|
||||
retry = false;
|
||||
} catch (Standard_Failure & e) {
|
||||
FC_WARN(getFullName() << ": boolean operation with compound failed ("
|
||||
<< e.GetMessageString() << "), retry...");
|
||||
} catch (Base::Exception & e) {
|
||||
FC_WARN(getFullName() << ": boolean operation with compound failed ("
|
||||
<< e.what() << "), retry...");
|
||||
}
|
||||
|
||||
if (retry) {
|
||||
int i = 0;
|
||||
for (auto & hole : holes) {
|
||||
++i;
|
||||
try {
|
||||
result.makEBoolean(maker, {base,hole});
|
||||
} catch (Standard_Failure &) {
|
||||
std::string msg(QT_TRANSLATE_NOOP("Exception", "Boolean operation failed on profile Edge"));
|
||||
msg += std::to_string(i);
|
||||
return new App::DocumentObjectExecReturn(msg.c_str());
|
||||
} catch (Base::Exception &e) {
|
||||
e.ReportException();
|
||||
std::string msg(QT_TRANSLATE_NOOP("Exception", "Boolean operataion failed on profile Edge"));
|
||||
msg += std::to_string(i);
|
||||
return new App::DocumentObjectExecReturn(msg.c_str());
|
||||
}
|
||||
base = getSolid(result);
|
||||
if (base.isNull()) {
|
||||
std::string msg(QT_TRANSLATE_NOOP("Exception", "Boolean operataion produced non-solid on profile Edge"));
|
||||
msg += std::to_string(i);
|
||||
return new App::DocumentObjectExecReturn(msg.c_str());
|
||||
}
|
||||
}
|
||||
result = base;
|
||||
}
|
||||
|
||||
this->Shape.setValue(result);
|
||||
|
||||
return App::DocumentObject::StdReturn;
|
||||
}
|
||||
@@ -1979,54 +2026,43 @@ gp_Vec Hole::computePerpendicular(const gp_Vec& zDir) const
|
||||
xDir.Normalize();
|
||||
return xDir;
|
||||
}
|
||||
|
||||
TopoDS_Compound Hole::findHoles(const TopoDS_Shape& profileshape,
|
||||
const TopoDS_Shape& protohole) const
|
||||
TopoShape Hole::findHoles(std::vector<TopoShape> &holes,
|
||||
const TopoShape& profileshape,
|
||||
const TopoDS_Shape& protoHole) const
|
||||
{
|
||||
BRep_Builder builder;
|
||||
TopoDS_Compound holes;
|
||||
builder.MakeCompound(holes);
|
||||
TopTools_IndexedMapOfShape edgeMap;
|
||||
TopExp::MapShapes(profileshape, TopAbs_EDGE, edgeMap);
|
||||
std::vector<gp_Pnt> holePointsList;
|
||||
for (int i = 1; i <= edgeMap.Extent(); i++) {
|
||||
bool dupCenter = false;
|
||||
TopoShape result(0,getDocument()->getStringHasher());
|
||||
|
||||
int i = 0;
|
||||
for(const auto &profileEdge : profileshape.getSubTopoShapes(TopAbs_EDGE)) {
|
||||
++i;
|
||||
Standard_Real c_start;
|
||||
Standard_Real c_end;
|
||||
TopoDS_Edge edge = TopoDS::Edge(edgeMap(i));
|
||||
TopoDS_Edge edge = TopoDS::Edge(profileEdge.getShape());
|
||||
Handle(Geom_Curve) c = BRep_Tool::Curve(edge, c_start, c_end);
|
||||
|
||||
// Circle?
|
||||
if (c.IsNull() || c->DynamicType() != STANDARD_TYPE(Geom_Circle)) {
|
||||
if (c->DynamicType() != STANDARD_TYPE(Geom_Circle))
|
||||
continue;
|
||||
}
|
||||
|
||||
Handle(Geom_Circle) circle = Handle(Geom_Circle)::DownCast(c);
|
||||
gp_Pnt loc = circle->Axis().Location();
|
||||
|
||||
for (auto holePoint : holePointsList) {
|
||||
if (holePoint.IsEqual(loc, Precision::Confusion())) {
|
||||
Base::Console().Log(
|
||||
"PartDesign_Hole - There is a duplicate circle/curve center at %.2f : %.2f "
|
||||
": %.2f therefore not passing parameter\n",
|
||||
loc.X(),
|
||||
loc.Y(),
|
||||
loc.Z());
|
||||
dupCenter = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dupCenter) {
|
||||
holePointsList.push_back(loc);
|
||||
gp_Trsf localSketchTransformation;
|
||||
localSketchTransformation.SetTranslation(gp_Pnt(0, 0, 0), loc);
|
||||
TopoDS_Shape copy = protohole;
|
||||
copy.Move(localSketchTransformation);
|
||||
builder.Add(holes, copy);
|
||||
}
|
||||
gp_Trsf localSketchTransformation;
|
||||
localSketchTransformation.SetTranslation( gp_Pnt( 0, 0, 0 ),
|
||||
gp_Pnt(loc.X(), loc.Y(), loc.Z()) );
|
||||
|
||||
Part::ShapeMapper mapper;
|
||||
mapper.populate(true, profileEdge, TopoShape(protoHole).getSubTopoShapes(TopAbs_FACE));
|
||||
|
||||
TopoShape hole(-getID(), getDocument()->getStringHasher());
|
||||
hole.makESHAPE(protoHole, mapper, {profileEdge});
|
||||
|
||||
// transform and generate element map.
|
||||
hole = hole.makETransform(localSketchTransformation);
|
||||
holes.push_back(hole);
|
||||
}
|
||||
|
||||
return holes;
|
||||
return TopoShape().makECompound(holes);
|
||||
}
|
||||
|
||||
TopoDS_Shape Hole::makeThread(const gp_Vec& xDir, const gp_Vec& zDir, double length)
|
||||
|
||||
@@ -224,7 +224,7 @@ private:
|
||||
void rotateToNormal(const gp_Dir& helixAxis, const gp_Dir& normalAxis, TopoDS_Shape& helixShape) const;
|
||||
gp_Vec computePerpendicular(const gp_Vec&) const;
|
||||
TopoDS_Shape makeThread(const gp_Vec&, const gp_Vec&, double);
|
||||
TopoDS_Compound findHoles(const TopoDS_Shape& profileshape, const TopoDS_Shape& protohole) const;
|
||||
TopoShape findHoles(std::vector<TopoShape> &holes, const TopoShape& profileshape, const TopoDS_Shape& protohole) const;
|
||||
|
||||
// helpers for nlohmann json
|
||||
friend void from_json(const nlohmann::json &j, CounterBoreDimension &t);
|
||||
|
||||
Reference in New Issue
Block a user