From fe2660b4684b51100ccc19c7479d08f7ae507398 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 26 Aug 2018 13:22:35 +0200 Subject: [PATCH] issue #0003177: Part Design Pad should allow besides 'Up to face' something like 'Up to plane' as well --- src/Mod/PartDesign/App/FeaturePad.cpp | 43 ++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/src/Mod/PartDesign/App/FeaturePad.cpp b/src/Mod/PartDesign/App/FeaturePad.cpp index 8bd0de633c..71b398d691 100644 --- a/src/Mod/PartDesign/App/FeaturePad.cpp +++ b/src/Mod/PartDesign/App/FeaturePad.cpp @@ -42,7 +42,8 @@ # include # include # include -#include +# include +# include #endif #include @@ -152,6 +153,12 @@ App::DocumentObjectExecReturn *Pad::execute(void) // TODO: Write our own PrismMaker which does not depend on a solid base shape if (base.IsNull()) { + // This implementation suffers from some problems: + // * it explicitly checks for planes only but e.g. a B-spline may work too + // * The extracted surface passed to GeomAPI_ProjectPointOnSurf may lack of + // its placement and thus computes a wrong result + // * the direction computed by base and projection point must not be transformed +#if 0 // 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); @@ -176,6 +183,34 @@ App::DocumentObjectExecReturn *Pad::execute(void) gp_Pnt prjP = prj.NearestPoint(); dir = gp_Dir(gp_Vec(basePoint, prjP)); dir.Transform(invObjLoc.Transformation()); +#else + TopLoc_Location upToFaceLoc; + Handle(Geom_Surface) surf = BRep_Tool::Surface(upToFace, upToFaceLoc); + GeomLib_IsPlanarSurface checkSurface(surf); + if (surf.IsNull() || !checkSurface.IsPlanar()) + return new App::DocumentObjectExecReturn("Pad: Extruding up to a face or plane is only possible if the sketch is located on a face"); + + gp_Pln upToPlane = checkSurface.Plan().Transformed(upToFaceLoc); + gp_Dir planeNorm = upToPlane.Axis().Direction(); + gp_Pnt planeBase = upToPlane.Location(); + double angle = dir.Angle(planeNorm); + 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); + Standard_Real pn = planeBase.XYZ().Dot(planeNorm.XYZ()); + Standard_Real qn = basePoint.XYZ().Dot(planeNorm.XYZ()); + gp_Pnt projPoint = basePoint.Translated(planeNorm.XYZ().Multiplied(pn-qn)); + + // Distance + double length = projPoint.Distance(basePoint) + 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) + dir = gp_Dir(gp_Vec(basePoint, projPoint)); +#endif generatePrism(prism, sketchshape, "Length", dir, length, 0.0, false, false); } else { @@ -225,12 +260,12 @@ App::DocumentObjectExecReturn *Pad::execute(void) // lets check if the result is a solid if (solRes.IsNull()) return new App::DocumentObjectExecReturn("Pad: Resulting shape is not a solid"); - + int solidCount = countSolids(result); if (solidCount > 1) { return new App::DocumentObjectExecReturn("Pad: Result has multiple solids. This is not supported at this time."); } - + solRes = refineShapeIfActive(solRes); this->Shape.setValue(getSolid(solRes)); } else { @@ -238,7 +273,7 @@ App::DocumentObjectExecReturn *Pad::execute(void) if (solidCount > 1) { return new App::DocumentObjectExecReturn("Pad: Result has multiple solids. This is not supported at this time."); } - + this->Shape.setValue(getSolid(prism)); }