Allow extruding from a datum plane to another face or plane, optionally with an offset
This commit is contained in:
committed by
Stefan Tröger
parent
0c16cb4cee
commit
12bf1d58f6
@@ -39,6 +39,9 @@
|
||||
# include <Precision.hxx>
|
||||
# include <BRepPrimAPI_MakeHalfSpace.hxx>
|
||||
# include <BRepAlgoAPI_Common.hxx>
|
||||
# include <BRepAdaptor_Surface.hxx>
|
||||
# include <gp_Pln.hxx>
|
||||
# include <GeomAPI_ProjectPointOnSurf.hxx>
|
||||
#endif
|
||||
|
||||
#include <Base/Exception.h>
|
||||
@@ -64,6 +67,7 @@ Pad::Pad()
|
||||
ADD_PROPERTY_TYPE(Length,(100.0),"Pad",App::Prop_None,"Pad length");
|
||||
ADD_PROPERTY_TYPE(Length2,(100.0),"Pad",App::Prop_None,"P");
|
||||
ADD_PROPERTY_TYPE(UpToFace,(0),"Pad",App::Prop_None,"Face where pad will end");
|
||||
ADD_PROPERTY(Offset,(0.0));
|
||||
}
|
||||
|
||||
short Pad::mustExecute() const
|
||||
@@ -155,12 +159,9 @@ App::DocumentObjectExecReturn *Pad::execute(void)
|
||||
sketchshape.Move(invObjLoc);
|
||||
|
||||
TopoDS_Shape prism;
|
||||
std::string method(Type.getValueAsString());
|
||||
std::string method(Type.getValueAsString());
|
||||
if (method == "UpToFirst" || method == "UpToLast" || method == "UpToFace") {
|
||||
// TODO: Write our own PrismMaker which does not depend on a solid base shape
|
||||
if (base.IsNull())
|
||||
return new App::DocumentObjectExecReturn("Pad: Extruding up to a face is only possible if the sketch is located on a face");
|
||||
// Note: This will return an unlimited planar face if support is a datum plane
|
||||
// Note: This will return an unlimited planar face if support is a datum plane
|
||||
TopoDS_Face supportface = getSupportFace();
|
||||
supportface.Move(invObjLoc);
|
||||
|
||||
@@ -173,27 +174,57 @@ App::DocumentObjectExecReturn *Pad::execute(void)
|
||||
getUpToFaceFromLinkSub(upToFace, UpToFace);
|
||||
upToFace.Move(invObjLoc);
|
||||
}
|
||||
getUpToFace(upToFace, base, supportface, sketchshape, method, dir);
|
||||
getUpToFace(upToFace, base, supportface, sketchshape, method, dir, Offset.getValue());
|
||||
|
||||
// A support object is always required and we need to use BRepFeat_MakePrism
|
||||
// Problem: For Pocket/UpToFirst (or an equivalent Pocket/UpToFace) the resulting shape is invalid
|
||||
// because the feature does not add any material. This only happens with the "2" option, though
|
||||
// Note: It might be possible to pass a shell or a compound containing multiple faces
|
||||
// as the Until parameter of Perform()
|
||||
// Note: Multiple independent wires are not supported, we should check for that and
|
||||
// warn the user
|
||||
// FIXME: If the support shape is not the previous solid in the tree, then there will be unexpected results
|
||||
// Check supportface for limits, otherwise Perform() throws an exception
|
||||
TopExp_Explorer Ex(supportface,TopAbs_WIRE);
|
||||
if (!Ex.More())
|
||||
supportface = TopoDS_Face();
|
||||
BRepFeat_MakePrism PrismMaker;
|
||||
PrismMaker.Init(base, sketchshape, supportface, dir, 2, 1);
|
||||
PrismMaker.Perform(upToFace);
|
||||
// TODO: Write our own PrismMaker which does not depend on a solid base shape
|
||||
if (base.IsNull()) {
|
||||
// Workaround because BRepFeat_MakePrism requires the base face located on a solid to be able to extrude up to a face
|
||||
// Handle special case of extruding up to a face or plane parallel to the base face
|
||||
BRepAdaptor_Surface adapt(upToFace);
|
||||
if (adapt.GetType() != GeomAbs_Plane)
|
||||
return new App::DocumentObjectExecReturn("Pad: Extruding up to a face or plane is only possible if the sketch is located on a face");
|
||||
|
||||
if (!PrismMaker.IsDone())
|
||||
return new App::DocumentObjectExecReturn("Pad: Up to face: Could not extrude the sketch!");
|
||||
prism = PrismMaker.Shape();
|
||||
double angle = dir.Angle(adapt.Plane().Axis().Direction());
|
||||
if (angle > Precision::Confusion())
|
||||
return new App::DocumentObjectExecReturn("Pad: Extruding up to a face is only possible if the sketch plane is parallel to it");
|
||||
|
||||
// Project basepoint of sketch onto the UpToFace to determine distance and direction
|
||||
gp_Pnt basePoint(SketchPos.getPosition().x, SketchPos.getPosition().y, SketchPos.getPosition().z);
|
||||
GeomAPI_ProjectPointOnSurf prj(basePoint, adapt.Surface().Surface());
|
||||
if (prj.NbPoints() != 1)
|
||||
return new App::DocumentObjectExecReturn("Pad: Extruding up to a face failed to find extrusion direction");
|
||||
// Distance
|
||||
double length = prj.Distance(1) + Offset.getValue();
|
||||
if (length < Precision::Confusion())
|
||||
return new App::DocumentObjectExecReturn("Pad: Extruding up to a face failed because of zero height");
|
||||
|
||||
// Direction (the distance is always positive)
|
||||
gp_Pnt prjP = prj.NearestPoint();
|
||||
dir = gp_Dir(gp_Vec(basePoint, prjP));
|
||||
dir.Transform(invObjLoc.Transformation());
|
||||
|
||||
generatePrism(prism, sketchshape, "Length", dir, length, 0.0, false, false);
|
||||
} else {
|
||||
// A support object is always required and we need to use BRepFeat_MakePrism
|
||||
// Problem: For Pocket/UpToFirst (or an equivalent Pocket/UpToFace) the resulting shape is invalid
|
||||
// because the feature does not add any material. This only happens with the "2" option, though
|
||||
// Note: It might be possible to pass a shell or a compound containing multiple faces
|
||||
// as the Until parameter of Perform()
|
||||
// Note: Multiple independent wires are not supported, we should check for that and
|
||||
// warn the user
|
||||
// FIXME: If the support shape is not the previous solid in the tree, then there will be unexpected results
|
||||
// Check supportface for limits, otherwise Perform() throws an exception
|
||||
TopExp_Explorer Ex(supportface,TopAbs_WIRE);
|
||||
if (!Ex.More())
|
||||
supportface = TopoDS_Face();
|
||||
BRepFeat_MakePrism PrismMaker;
|
||||
PrismMaker.Init(base, sketchshape, supportface, dir, 2, 1);
|
||||
PrismMaker.Perform(upToFace);
|
||||
|
||||
if (!PrismMaker.IsDone())
|
||||
return new App::DocumentObjectExecReturn("Pad: Up to face: Could not extrude the sketch!");
|
||||
prism = PrismMaker.Shape();
|
||||
}
|
||||
} else {
|
||||
generatePrism(prism, sketchshape, method, dir, L, L2,
|
||||
Midplane.getValue(), Reversed.getValue());
|
||||
|
||||
@@ -42,6 +42,7 @@ public:
|
||||
App::PropertyEnumeration Type;
|
||||
App::PropertyLength Length;
|
||||
App::PropertyLength Length2;
|
||||
App::PropertyFloat Offset;
|
||||
|
||||
/** @name methods override feature */
|
||||
//@{
|
||||
|
||||
@@ -62,6 +62,7 @@ Pocket::Pocket()
|
||||
Type.setEnums(TypeEnums);
|
||||
ADD_PROPERTY_TYPE(Length,(100.0),"Pocket",App::Prop_None,"Pocket length");
|
||||
ADD_PROPERTY_TYPE(UpToFace,(0),"Pocket",App::Prop_None,"Face where pocket will end");
|
||||
ADD_PROPERTY(Offset,(0.0));
|
||||
}
|
||||
|
||||
short Pocket::mustExecute() const
|
||||
@@ -150,7 +151,7 @@ App::DocumentObjectExecReturn *Pocket::execute(void)
|
||||
getUpToFaceFromLinkSub(upToFace, UpToFace);
|
||||
upToFace.Move(invObjLoc);
|
||||
}
|
||||
getUpToFace(upToFace, base, supportface, sketchshape, method, dir);
|
||||
getUpToFace(upToFace, base, supportface, sketchshape, method, dir, Offset.getValue());
|
||||
|
||||
// Special treatment because often the created stand-alone prism is invalid (empty) because
|
||||
// BRepFeat_MakePrism(..., 2, 1) is buggy
|
||||
|
||||
@@ -39,6 +39,7 @@ public:
|
||||
|
||||
App::PropertyEnumeration Type;
|
||||
App::PropertyLength Length;
|
||||
App::PropertyFloat Offset;
|
||||
|
||||
/** @name methods override feature */
|
||||
//@{
|
||||
|
||||
@@ -494,7 +494,8 @@ void SketchBased::getUpToFace(TopoDS_Face& upToFace,
|
||||
const TopoDS_Face& supportface,
|
||||
const TopoDS_Shape& sketchshape,
|
||||
const std::string& method,
|
||||
const gp_Dir& dir)
|
||||
const gp_Dir& dir,
|
||||
const double offset)
|
||||
{
|
||||
if ((method == "UpToLast") || (method == "UpToFirst")) {
|
||||
// Check for valid support object
|
||||
@@ -564,6 +565,18 @@ void SketchBased::getUpToFace(TopoDS_Face& upToFace,
|
||||
if (distSS.Value() < Precision::Confusion())
|
||||
throw Base::Exception("SketchBased: Up to face: Must not intersect sketch!");
|
||||
|
||||
// Move the face in the extrusion direction
|
||||
// TODO: For non-planar faces, we could consider offsetting the surface
|
||||
if (fabs(offset) > Precision::Confusion()) {
|
||||
if (adapt2.GetType() == GeomAbs_Plane) {
|
||||
gp_Trsf mov;
|
||||
mov.SetTranslation(offset * gp_Vec(dir));
|
||||
TopLoc_Location loc(mov);
|
||||
upToFace.Move(loc);
|
||||
} else {
|
||||
throw Base::Exception("SketchBased: Up to Face: Offset not supported yet for non-planar faces");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SketchBased::generatePrism(TopoDS_Shape& prism,
|
||||
|
||||
@@ -101,7 +101,8 @@ protected:
|
||||
const TopoDS_Face& supportface,
|
||||
const TopoDS_Shape& sketchshape,
|
||||
const std::string& method,
|
||||
const gp_Dir& dir);
|
||||
const gp_Dir& dir,
|
||||
const double offset);
|
||||
/**
|
||||
* Generate a linear prism
|
||||
* It will be a stand-alone solid created with BRepPrimAPI_MakePrism
|
||||
|
||||
Reference in New Issue
Block a user