Allow extruding from a datum plane to another face or plane, optionally with an offset

This commit is contained in:
jrheinlaender
2013-07-10 10:15:50 +02:00
committed by Stefan Tröger
parent fa020cf867
commit f1b5a6044d
16 changed files with 230 additions and 42 deletions

View File

@@ -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());