Toponaming/Part: Cleaning and tests for makeElementRevolve, makeElementPrism, makeElementPrismUntil
This commit is contained in:
@@ -3097,198 +3097,227 @@ TopoShape& TopoShape::makeElementLoft(const std::vector<TopoShape>& shapes,
|
||||
op);
|
||||
}
|
||||
|
||||
TopoShape &TopoShape::makeElementPrism(const TopoShape &base, const gp_Vec& vec, const char *op) {
|
||||
if(!op) op = Part::OpCodes::Extrude;
|
||||
if(base.isNull())
|
||||
FC_THROWM(NullShapeException, "Null shape");
|
||||
BRepPrimAPI_MakePrism mkPrism(base.getShape(), vec);
|
||||
return makeElementShape(mkPrism,base,op);
|
||||
}
|
||||
|
||||
TopoShape &TopoShape::makeElementPrismUntil(const TopoShape &_base,
|
||||
const TopoShape& profile,
|
||||
const TopoShape& supportFace,
|
||||
const TopoShape& __uptoface,
|
||||
const gp_Dir& direction,
|
||||
PrismMode Mode,
|
||||
Standard_Boolean checkLimits,
|
||||
const char *op)
|
||||
TopoShape& TopoShape::makeElementPrism(const TopoShape& base, const gp_Vec& vec, const char* op)
|
||||
{
|
||||
if(!op) op = Part::OpCodes::Prism;
|
||||
|
||||
BRepFeat_MakePrism PrismMaker;
|
||||
|
||||
TopoShape _uptoface(__uptoface);
|
||||
if (checkLimits && _uptoface.shapeType(true) == TopAbs_FACE
|
||||
&& !BRep_Tool::NaturalRestriction(TopoDS::Face(_uptoface.getShape()))) {
|
||||
// When using the face with BRepFeat_MakePrism::Perform(const TopoDS_Shape& Until)
|
||||
// then the algorithm expects that the 'NaturalRestriction' flag is set in order
|
||||
// to work as expected.
|
||||
BRep_Builder builder;
|
||||
_uptoface = _uptoface.makeElementCopy();
|
||||
builder.NaturalRestriction(TopoDS::Face(_uptoface.getShape()), Standard_True);
|
||||
if (!op) {
|
||||
op = Part::OpCodes::Extrude;
|
||||
}
|
||||
|
||||
TopoShape uptoface(_uptoface);
|
||||
TopoShape base(_base);
|
||||
|
||||
if (base.isNull()) {
|
||||
Mode = PrismMode::None;
|
||||
base = profile;
|
||||
FC_THROWM(NullShapeException, "Null shape");
|
||||
}
|
||||
|
||||
// Check whether the face has limits or not. Unlimited faces have no wire
|
||||
// Note: Datum planes are always unlimited
|
||||
if (checkLimits && uptoface.hasSubShape(TopAbs_WIRE)) {
|
||||
TopoDS_Face face = TopoDS::Face(uptoface.getShape());
|
||||
bool remove_limits = false;
|
||||
// Remove the limits of the upToFace so that the extrusion works even if profile is larger
|
||||
// than the upToFace
|
||||
for (auto &sketchface : profile.getSubTopoShapes(TopAbs_FACE)) {
|
||||
// Get outermost wire of sketch face
|
||||
TopoShape outerWire = sketchface.splitWires();
|
||||
BRepProj_Projection proj(TopoDS::Wire(outerWire.getShape()), face, direction);
|
||||
if (!proj.More() || !proj.Current().Closed()) {
|
||||
remove_limits = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// It must also be checked that all projected inner wires of the upToFace
|
||||
// lie outside the sketch shape. If this is not the case then the sketch
|
||||
// shape is not completely covered by the upToFace. See #0003141
|
||||
if (!remove_limits) {
|
||||
std::vector<TopoShape> wires;
|
||||
uptoface.splitWires(&wires);
|
||||
for (auto & w : wires) {
|
||||
BRepProj_Projection proj(TopoDS::Wire(w.getShape()), profile.getShape(), -direction);
|
||||
if (proj.More()) {
|
||||
remove_limits = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (remove_limits) {
|
||||
// Note: Using an unlimited face every time gives unnecessary failures for concave faces
|
||||
TopLoc_Location loc = face.Location();
|
||||
BRepAdaptor_Surface adapt(face, Standard_False);
|
||||
// use the placement of the adapter, not of the upToFace
|
||||
loc = TopLoc_Location(adapt.Trsf());
|
||||
BRepBuilderAPI_MakeFace mkFace(adapt.Surface().Surface()
|
||||
#if OCC_VERSION_HEX >= 0x060502
|
||||
, Precision::Confusion()
|
||||
#endif
|
||||
);
|
||||
if (!mkFace.IsDone())
|
||||
remove_limits = false;
|
||||
else
|
||||
uptoface.setShape(located(mkFace.Shape(),loc), false);
|
||||
}
|
||||
}
|
||||
|
||||
TopoShape uptofaceCopy = uptoface;
|
||||
bool checkBase = false;
|
||||
auto retry = [&]() {
|
||||
if (!uptoface.isSame(_uptoface)) {
|
||||
// retry using the original up to face in case unnecessary failure
|
||||
// due to removing the limits
|
||||
uptoface = _uptoface;
|
||||
return true;
|
||||
}
|
||||
if ((!_base.isNull() && base.isSame(_base))
|
||||
|| (_base.isNull() && base.isSame(profile))) {
|
||||
// It is unclear under exactly what condition extrude up to face
|
||||
// can fail. Either the support face or the up to face must be part
|
||||
// of the base, or maybe some thing else.
|
||||
//
|
||||
// To deal with it, we retry again by disregard the supplied base,
|
||||
// and use up to face to extrude our own base. Later on, use the
|
||||
// supplied base (i.e. _base) to calculate the final shape if the
|
||||
// mode is FuseWithBase or CutWithBase.
|
||||
checkBase = true;
|
||||
uptoface = uptofaceCopy;
|
||||
base.makeElementPrism(_uptoface, direction);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
std::vector<TopoShape> srcShapes;
|
||||
TopoShape result;
|
||||
for (;;) {
|
||||
try {
|
||||
result = base;
|
||||
|
||||
// We do not rely on BRepFeat_MakePrism to perform fuse or cut for
|
||||
// us because of its poor support of shape history.
|
||||
auto mode = PrismMode::None;
|
||||
|
||||
for (auto &face : profile.getSubTopoShapes(
|
||||
profile.hasSubShape(TopAbs_FACE)?TopAbs_FACE:TopAbs_WIRE)) {
|
||||
srcShapes.clear();
|
||||
if (!profile.isNull() && !result.findShape(profile.getShape()))
|
||||
srcShapes.push_back(profile);
|
||||
if (!supportFace.isNull() && !result.findShape(supportFace.getShape()))
|
||||
srcShapes.push_back(supportFace);
|
||||
|
||||
// DO NOT include uptoface for element mapping. Because OCCT
|
||||
// BRepFeat_MakePrism will report all top extruded face being
|
||||
// modified by the uptoface. If there are more than one face in
|
||||
// the profile, this will cause uncessary duplicated element
|
||||
// mapped name. And will also disrupte element history tracing
|
||||
// back to the profile sketch.
|
||||
//
|
||||
// if (!uptoface.isNull() && !this->findShape(uptoface.getShape()))
|
||||
// srcShapes.push_back(uptoface);
|
||||
|
||||
srcShapes.push_back(result);
|
||||
|
||||
PrismMaker.Init(result.getShape(), face.getShape(),
|
||||
TopoDS::Face(supportFace.getShape()), direction, mode, Standard_False);
|
||||
mode = PrismMode::FuseWithBase;
|
||||
|
||||
PrismMaker.Perform(uptoface.getShape());
|
||||
|
||||
if (!PrismMaker.IsDone() || PrismMaker.Shape().IsNull())
|
||||
FC_THROWM(Base::CADKernelError,"BRepFeat_MakePrism: extrusion failed");
|
||||
|
||||
result.makeElementShape(PrismMaker, srcShapes, uptoface, op);
|
||||
}
|
||||
break;
|
||||
} catch (Base::Exception &) {
|
||||
if (!retry()) throw;
|
||||
} catch (Standard_Failure &) {
|
||||
if (!retry()) throw;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_base.isNull() && Mode != PrismMode::None) {
|
||||
if (Mode == PrismMode::FuseWithBase)
|
||||
result.makeElementFuse({_base, result});
|
||||
else
|
||||
result.makeElementCut({_base, result});
|
||||
}
|
||||
|
||||
*this = result;
|
||||
return *this;
|
||||
BRepPrimAPI_MakePrism mkPrism(base.getShape(), vec);
|
||||
return makeElementShape(mkPrism, base, op);
|
||||
}
|
||||
|
||||
TopoShape &TopoShape::makeElementRevolve(const TopoShape &_base, const gp_Ax1& axis,
|
||||
double d, const char *face_maker, const char *op)
|
||||
// TODO: This code was transferred in Feb 2024 as part of the toponaming project, but appears to be
|
||||
// unused. It is potentially useful if debugged.
|
||||
//TopoShape& TopoShape::makeElementPrismUntil(const TopoShape& _base,
|
||||
// const TopoShape& profile,
|
||||
// const TopoShape& supportFace,
|
||||
// const TopoShape& __uptoface,
|
||||
// const gp_Dir& direction,
|
||||
// PrismMode Mode,
|
||||
// Standard_Boolean checkLimits,
|
||||
// const char* op)
|
||||
//{
|
||||
// if (!op) {
|
||||
// op = Part::OpCodes::Prism;
|
||||
// }
|
||||
//
|
||||
// BRepFeat_MakePrism PrismMaker;
|
||||
//
|
||||
// TopoShape _uptoface(__uptoface);
|
||||
// if (checkLimits && _uptoface.shapeType(true) == TopAbs_FACE
|
||||
// && !BRep_Tool::NaturalRestriction(TopoDS::Face(_uptoface.getShape()))) {
|
||||
// // When using the face with BRepFeat_MakePrism::Perform(const TopoDS_Shape& Until)
|
||||
// // then the algorithm expects that the 'NaturalRestriction' flag is set in order
|
||||
// // to work as expected.
|
||||
// BRep_Builder builder;
|
||||
// _uptoface = _uptoface.makeElementCopy();
|
||||
// builder.NaturalRestriction(TopoDS::Face(_uptoface.getShape()), Standard_True);
|
||||
// }
|
||||
//
|
||||
// TopoShape uptoface(_uptoface);
|
||||
// TopoShape base(_base);
|
||||
//
|
||||
// if (base.isNull()) {
|
||||
// Mode = PrismMode::None;
|
||||
// base = profile;
|
||||
// }
|
||||
//
|
||||
// // Check whether the face has limits or not. Unlimited faces have no wire
|
||||
// // Note: Datum planes are always unlimited
|
||||
// if (checkLimits && uptoface.hasSubShape(TopAbs_WIRE)) {
|
||||
// TopoDS_Face face = TopoDS::Face(uptoface.getShape());
|
||||
// bool remove_limits = false;
|
||||
// // Remove the limits of the upToFace so that the extrusion works even if profile is larger
|
||||
// // than the upToFace
|
||||
// for (auto& sketchface : profile.getSubTopoShapes(TopAbs_FACE)) {
|
||||
// // Get outermost wire of sketch face
|
||||
// TopoShape outerWire = sketchface.splitWires();
|
||||
// BRepProj_Projection proj(TopoDS::Wire(outerWire.getShape()), face, direction);
|
||||
// if (!proj.More() || !proj.Current().Closed()) {
|
||||
// remove_limits = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // It must also be checked that all projected inner wires of the upToFace
|
||||
// // lie outside the sketch shape. If this is not the case then the sketch
|
||||
// // shape is not completely covered by the upToFace. See #0003141
|
||||
// if (!remove_limits) {
|
||||
// std::vector<TopoShape> wires;
|
||||
// uptoface.splitWires(&wires);
|
||||
// for (auto& w : wires) {
|
||||
// BRepProj_Projection proj(TopoDS::Wire(w.getShape()),
|
||||
// profile.getShape(),
|
||||
// -direction);
|
||||
// if (proj.More()) {
|
||||
// remove_limits = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (remove_limits) {
|
||||
// // Note: Using an unlimited face every time gives unnecessary failures for concave faces
|
||||
// TopLoc_Location loc = face.Location();
|
||||
// BRepAdaptor_Surface adapt(face, Standard_False);
|
||||
// // use the placement of the adapter, not of the upToFace
|
||||
// loc = TopLoc_Location(adapt.Trsf());
|
||||
// BRepBuilderAPI_MakeFace mkFace(adapt.Surface().Surface(), Precision::Confusion());
|
||||
// if (!mkFace.IsDone()) {
|
||||
// remove_limits = false;
|
||||
// }
|
||||
// else {
|
||||
// uptoface.setShape(located(mkFace.Shape(), loc), false);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// TopoShape uptofaceCopy = uptoface;
|
||||
// bool checkBase = false;
|
||||
// auto retry = [&]() {
|
||||
// if (!uptoface.isSame(_uptoface)) {
|
||||
// // retry using the original up to face in case unnecessary failure
|
||||
// // due to removing the limits
|
||||
// uptoface = _uptoface;
|
||||
// return true;
|
||||
// }
|
||||
// if ((!_base.isNull() && base.isSame(_base)) || (_base.isNull() && base.isSame(profile))) {
|
||||
// // It is unclear under exactly what condition extrude up to face
|
||||
// // can fail. Either the support face or the up to face must be part
|
||||
// // of the base, or maybe some thing else.
|
||||
// //
|
||||
// // To deal with it, we retry again by disregard the supplied base,
|
||||
// // and use up to face to extrude our own base. Later on, use the
|
||||
// // supplied base (i.e. _base) to calculate the final shape if the
|
||||
// // mode is FuseWithBase or CutWithBase.
|
||||
// checkBase = true;
|
||||
// uptoface = uptofaceCopy;
|
||||
// base.makeElementPrism(_uptoface, direction);
|
||||
// return true;
|
||||
// }
|
||||
// return false;
|
||||
// };
|
||||
//
|
||||
// std::vector<TopoShape> srcShapes;
|
||||
// TopoShape result;
|
||||
// for (;;) {
|
||||
// try {
|
||||
// result = base;
|
||||
//
|
||||
// // We do not rely on BRepFeat_MakePrism to perform fuse or cut for
|
||||
// // us because of its poor support of shape history.
|
||||
// auto mode = PrismMode::None;
|
||||
//
|
||||
// for (auto& face : profile.getSubTopoShapes(
|
||||
// profile.hasSubShape(TopAbs_FACE) ? TopAbs_FACE : TopAbs_WIRE)) {
|
||||
// srcShapes.clear();
|
||||
// if (!profile.isNull() && !result.findShape(profile.getShape())) {
|
||||
// srcShapes.push_back(profile);
|
||||
// }
|
||||
// if (!supportFace.isNull() && !result.findShape(supportFace.getShape())) {
|
||||
// srcShapes.push_back(supportFace);
|
||||
// }
|
||||
//
|
||||
// // DO NOT include uptoface for element mapping. Because OCCT
|
||||
// // BRepFeat_MakePrism will report all top extruded face being
|
||||
// // modified by the uptoface. If there are more than one face in
|
||||
// // the profile, this will cause uncessary duplicated element
|
||||
// // mapped name. And will also disrupte element history tracing
|
||||
// // back to the profile sketch.
|
||||
// //
|
||||
// // if (!uptoface.isNull() && !this->findShape(uptoface.getShape()))
|
||||
// // srcShapes.push_back(uptoface);
|
||||
//
|
||||
// srcShapes.push_back(result);
|
||||
//
|
||||
// PrismMaker.Init(result.getShape(),
|
||||
// face.getShape(),
|
||||
// TopoDS::Face(supportFace.getShape()),
|
||||
// direction,
|
||||
// mode,
|
||||
// Standard_False);
|
||||
// mode = PrismMode::FuseWithBase;
|
||||
//
|
||||
// PrismMaker.Perform(uptoface.getShape());
|
||||
//
|
||||
// if (!PrismMaker.IsDone() || PrismMaker.Shape().IsNull()) {
|
||||
// FC_THROWM(Base::CADKernelError, "BRepFeat_MakePrism: extrusion failed");
|
||||
// }
|
||||
//
|
||||
// result.makeElementShape(PrismMaker, srcShapes, uptoface, op);
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// catch (Base::Exception&) {
|
||||
// if (!retry()) {
|
||||
// throw;
|
||||
// }
|
||||
// }
|
||||
// catch (Standard_Failure&) {
|
||||
// if (!retry()) {
|
||||
// throw;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (!_base.isNull() && Mode != PrismMode::None) {
|
||||
// if (Mode == PrismMode::FuseWithBase) {
|
||||
// result.makeElementFuse({_base, result});
|
||||
// }
|
||||
// else {
|
||||
// result.makeElementCut({_base, result});
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// *this = result;
|
||||
// return *this;
|
||||
//}
|
||||
|
||||
TopoShape& TopoShape::makeElementRevolve(const TopoShape& _base,
|
||||
const gp_Ax1& axis,
|
||||
double d,
|
||||
const char* face_maker,
|
||||
const char* op)
|
||||
{
|
||||
if(!op) op = Part::OpCodes::Revolve;
|
||||
if (!op) {
|
||||
op = Part::OpCodes::Revolve;
|
||||
}
|
||||
|
||||
TopoShape base(_base);
|
||||
if(base.isNull())
|
||||
if (base.isNull()) {
|
||||
FC_THROWM(NullShapeException, "Null shape");
|
||||
if(face_maker && !base.hasSubShape(TopAbs_FACE)) {
|
||||
if(!base.hasSubShape(TopAbs_WIRE))
|
||||
base = base.makeElementWires();
|
||||
base = base.makeElementFace(nullptr,face_maker, nullptr);
|
||||
}
|
||||
BRepPrimAPI_MakeRevol mkRevol(base.getShape(), axis,d);
|
||||
return makeElementShape(mkRevol,base,op);
|
||||
if (face_maker && !base.hasSubShape(TopAbs_FACE)) {
|
||||
if (!base.hasSubShape(TopAbs_WIRE)) {
|
||||
base = base.makeElementWires();
|
||||
}
|
||||
base = base.makeElementFace(nullptr, face_maker, nullptr);
|
||||
}
|
||||
BRepPrimAPI_MakeRevol mkRevol(base.getShape(), axis, d);
|
||||
return makeElementShape(mkRevol, base, op);
|
||||
}
|
||||
|
||||
TopoShape& TopoShape::makeElementDraft(const TopoShape& shape,
|
||||
|
||||
Reference in New Issue
Block a user