PartDesign: Modeling features work with faces

-Rename Sketchbased to ProfileBased to show new behavior
-Adopt ProfileBased to make the relevant helper functions work with faces too
-Adopt features for unified use of helper functions
-Adopt commands to allow face selection
This commit is contained in:
Stefan Tröger 2016-01-20 07:11:59 +01:00
parent 7dea66872e
commit f712f5e4ac
26 changed files with 417 additions and 203 deletions

View File

@ -87,7 +87,7 @@ PyMODINIT_FUNC init_PartDesign()
PartDesign::Solid ::init();
PartDesign::DressUp ::init();
PartDesign::FeatureAddSub ::init();
PartDesign::SketchBased ::init();
PartDesign::ProfileBased ::init();
PartDesign::Transformed ::init();
PartDesign::Mirrored ::init();
PartDesign::LinearPattern ::init();

View File

@ -49,7 +49,7 @@ using namespace PartDesign;
namespace PartDesign {
PROPERTY_SOURCE(PartDesign::Groove, PartDesign::SketchBased)
PROPERTY_SOURCE(PartDesign::Groove, PartDesign::ProfileBased)
Groove::Groove()
{
@ -69,7 +69,7 @@ short Groove::mustExecute() const
Base.isTouched() ||
Angle.isTouched())
return 1;
return SketchBased::mustExecute();
return ProfileBased::mustExecute();
}
App::DocumentObjectExecReturn *Groove::execute(void)
@ -86,9 +86,9 @@ App::DocumentObjectExecReturn *Groove::execute(void)
if (Reversed.getValue() && !Midplane.getValue())
angle *= (-1.0);
std::vector<TopoDS_Wire> wires;
TopoDS_Shape sketchshape;
try {
wires = getSketchWires();
sketchshape = getVerifiedFace();
} catch (const Base::Exception& e) {
return new App::DocumentObjectExecReturn(e.what());
}
@ -110,7 +110,6 @@ App::DocumentObjectExecReturn *Groove::execute(void)
gp_Dir dir(v.x,v.y,v.z);
try {
TopoDS_Shape sketchshape = makeFace(wires);
if (sketchshape.IsNull())
return new App::DocumentObjectExecReturn("Creating a face from sketch failed");
@ -177,7 +176,7 @@ App::DocumentObjectExecReturn *Groove::execute(void)
bool Groove::suggestReversed(void)
{
updateAxis();
return SketchBased::getReversedAngle(Base.getValue(), Axis.getValue()) > 0.0;
return ProfileBased::getReversedAngle(Base.getValue(), Axis.getValue()) > 0.0;
}
void Groove::updateAxis(void)

View File

@ -30,7 +30,7 @@
namespace PartDesign
{
class PartDesignExport Groove : public SketchBased
class PartDesignExport Groove : public ProfileBased
{
PROPERTY_HEADER(PartDesign::Groove);

View File

@ -52,7 +52,7 @@ const char* Hole::TypeEnums[] = {"Dimension","UpToLast","UpToFirst",NULL};
const char* Hole::HoleTypeEnums[]= {"Simple","Counterbore","Countersunk",NULL};
const char* Hole::ThreadEnums[] = {"None","Metric","MetricFine",NULL};
PROPERTY_SOURCE(PartDesign::Hole, PartDesign::SketchBased)
PROPERTY_SOURCE(PartDesign::Hole, PartDesign::ProfileBased)
Hole::Hole()
{

View File

@ -30,7 +30,7 @@
namespace PartDesign
{
class PartDesignExport Hole : public SketchBased
class PartDesignExport Hole : public ProfileBased
{
PROPERTY_HEADER(PartDesign::Hole);

View File

@ -49,7 +49,7 @@
using namespace PartDesign;
PROPERTY_SOURCE(PartDesign::Loft, PartDesign::SketchBased)
PROPERTY_SOURCE(PartDesign::Loft, PartDesign::ProfileBased)
Loft::Loft()
{
@ -68,7 +68,7 @@ short Loft::mustExecute() const
if (Closed.isTouched())
return 1;
return SketchBased::mustExecute();
return ProfileBased::mustExecute();
}
App::DocumentObjectExecReturn *Loft::execute(void)
@ -76,12 +76,12 @@ App::DocumentObjectExecReturn *Loft::execute(void)
std::vector<TopoDS_Wire> wires;
try {
wires = getSketchWires();
wires = getProfileWires();
} catch (const Base::Exception& e) {
return new App::DocumentObjectExecReturn(e.what());
}
TopoDS_Shape sketchshape = makeFace(wires);
TopoDS_Shape sketchshape = getVerifiedFace();
if (sketchshape.IsNull())
return new App::DocumentObjectExecReturn("Loft: Creating a face from sketch failed");
@ -145,7 +145,7 @@ App::DocumentObjectExecReturn *Loft::execute(void)
}
//build the top and bottom face, sew the shell and build the final solid
TopoDS_Shape front = makeFace(wires);
TopoDS_Shape front = getVerifiedFace();
front.Move(invObjLoc);
std::vector<TopoDS_Wire> backwires;
for(std::vector<TopoDS_Wire>& wires : wiresections)
@ -213,7 +213,7 @@ App::DocumentObjectExecReturn *Loft::execute(void)
return App::DocumentObject::StdReturn;
return SketchBased::execute();
return ProfileBased::execute();
}
catch (Standard_Failure) {
Handle_Standard_Failure e = Standard_Failure::Caught();

View File

@ -33,7 +33,7 @@
namespace PartDesign
{
class PartDesignExport Loft : public SketchBased
class PartDesignExport Loft : public ProfileBased
{
PROPERTY_HEADER(PartDesign::Loft);

View File

@ -42,6 +42,7 @@
# include <BRepAdaptor_Surface.hxx>
# include <gp_Pln.hxx>
# include <GeomAPI_ProjectPointOnSurf.hxx>
#include <BRepLProp_SLProps.hxx>
#endif
#include <Base/Exception.h>
@ -58,7 +59,7 @@ using namespace PartDesign;
const char* Pad::TypeEnums[]= {"Length","UpToLast","UpToFirst","UpToFace","TwoLengths",NULL};
PROPERTY_SOURCE(PartDesign::Pad, PartDesign::SketchBased)
PROPERTY_SOURCE(PartDesign::Pad, PartDesign::ProfileBased)
Pad::Pad()
{
@ -83,7 +84,7 @@ short Pad::mustExecute() const
Offset.isTouched() ||
UpToFace.isTouched())
return 1;
return SketchBased::mustExecute();
return ProfileBased::mustExecute();
}
App::DocumentObjectExecReturn *Pad::execute(void)
@ -96,11 +97,11 @@ App::DocumentObjectExecReturn *Pad::execute(void)
if ((std::string(Type.getValueAsString()) == "TwoLengths") && (L < Precision::Confusion()))
return new App::DocumentObjectExecReturn("Second length of pad too small");
Part::Part2DObject* sketch = 0;
std::vector<TopoDS_Wire> wires;
Part::Feature* obj = 0;
TopoDS_Shape sketchshape;
try {
sketch = getVerifiedSketch();
wires = getSketchWires();
obj = getVerifiedObject();
sketchshape = getVerifiedFace();
} catch (const Base::Exception& e) {
return new App::DocumentObjectExecReturn(e.what());
}
@ -115,10 +116,8 @@ App::DocumentObjectExecReturn *Pad::execute(void)
// get the Sketch plane
Base::Placement SketchPos = sketch->Placement.getValue();
Base::Rotation SketchOrientation = SketchPos.getRotation();
Base::Vector3d SketchVector(0,0,1);
SketchOrientation.multVec(SketchVector,SketchVector);
Base::Placement SketchPos = obj->Placement.getValue();
Base::Vector3d SketchVector = getProfileNormal();
try {
this->positionByPrevious();
@ -129,7 +128,6 @@ App::DocumentObjectExecReturn *Pad::execute(void)
gp_Dir dir(SketchVector.x,SketchVector.y,SketchVector.z);
dir.Transform(invObjLoc.Transformation());
TopoDS_Shape sketchshape = makeFace(wires);
if (sketchshape.IsNull())
return new App::DocumentObjectExecReturn("Pad: Creating a face from sketch failed");
sketchshape.Move(invObjLoc);
@ -214,6 +212,8 @@ App::DocumentObjectExecReturn *Pad::execute(void)
this->AddSubShape.setValue(prism);
if (!base.IsNull()) {
// auto obj = getDocument()->addObject("Part::Feature", "prism");
// static_cast<Part::Feature*>(obj)->Shape.setValue(prism);
// Let's call algorithm computing a fuse operation:
BRepAlgoAPI_Fuse mkFuse(base, prism);
// Let's check if the fusion has been successful

View File

@ -33,7 +33,7 @@
namespace PartDesign
{
class PartDesignExport Pad : public SketchBased
class PartDesignExport Pad : public ProfileBased
{
PROPERTY_HEADER(PartDesign::Pad);

View File

@ -76,7 +76,7 @@ const char* Pipe::ModeEnums[] = {"Standart", "Fixed", "Frenet", "Auxillery", "Bi
const char* Pipe::TransformEnums[] = {"Constant", "Multisection", "Linear", "S-shape", "Interpolation", NULL};
PROPERTY_SOURCE(PartDesign::Pipe, PartDesign::SketchBased)
PROPERTY_SOURCE(PartDesign::Pipe, PartDesign::ProfileBased)
Pipe::Pipe()
{
@ -106,7 +106,7 @@ short Pipe::mustExecute() const
return 1;
if (Transition.isTouched())
return 1;
return SketchBased::mustExecute();
return ProfileBased::mustExecute();
}
App::DocumentObjectExecReturn *Pipe::execute(void)
@ -114,14 +114,24 @@ App::DocumentObjectExecReturn *Pipe::execute(void)
std::vector<TopoDS_Wire> wires;
try {
wires = getSketchWires();
wires = getProfileWires();
} catch (const Base::Exception& e) {
return new App::DocumentObjectExecReturn(e.what());
}
TopoDS_Shape sketchshape = makeFace(wires);
TopoDS_Shape sketchshape = getVerifiedFace();
if (sketchshape.IsNull())
return new App::DocumentObjectExecReturn("Pipe: Creating a face from sketch failed");
return new App::DocumentObjectExecReturn("Pipe: No valid sketch or face as first section");
else {
//TODO: currently we only allow planar faces. the reason for this is that with other faces in front, we could
//not use the current simulate approach and build the start and end face from the wires. As the shell
//beginns always at the spine and not the profile, the sketchshape cannot be used directly as front face.
//We would need a method to translate the frontshape to match the shell starting position somehow...
TopoDS_Face face = TopoDS::Face(sketchshape);
BRepAdaptor_Surface adapt(face);
if(adapt.GetType() != GeomAbs_Plane)
return new App::DocumentObjectExecReturn("Pipe: Only planar faces supportet");
}
// if the Base property has a valid shape, fuse the pipe into it
TopoDS_Shape base;
@ -310,7 +320,7 @@ App::DocumentObjectExecReturn *Pipe::execute(void)
return App::DocumentObject::StdReturn;
return SketchBased::execute();
return ProfileBased::execute();
}
catch (Standard_Failure) {
Handle_Standard_Failure e = Standard_Failure::Caught();

View File

@ -31,7 +31,7 @@
namespace PartDesign
{
class PartDesignExport Pipe : public SketchBased
class PartDesignExport Pipe : public ProfileBased
{
PROPERTY_HEADER(PartDesign::Pad);

View File

@ -54,7 +54,7 @@ using namespace PartDesign;
const char* Pocket::TypeEnums[]= {"Length","ThroughAll","UpToFirst","UpToFace",NULL};
PROPERTY_SOURCE(PartDesign::Pocket, PartDesign::SketchBased)
PROPERTY_SOURCE(PartDesign::Pocket, PartDesign::ProfileBased)
Pocket::Pocket()
{
@ -77,7 +77,7 @@ short Pocket::mustExecute() const
Offset.isTouched() ||
UpToFace.isTouched())
return 1;
return SketchBased::mustExecute();
return ProfileBased::mustExecute();
}
App::DocumentObjectExecReturn *Pocket::execute(void)
@ -93,11 +93,11 @@ App::DocumentObjectExecReturn *Pocket::execute(void)
if ((std::string(Type.getValueAsString()) == "Length") && (L < Precision::Confusion()))
return new App::DocumentObjectExecReturn("Pocket: Length of pocket too small");
Part::Part2DObject* sketch = 0;
std::vector<TopoDS_Wire> wires;
Part::Feature* obj = 0;
TopoDS_Face face;
try {
sketch = getVerifiedSketch();
wires = getSketchWires();
obj = getVerifiedObject();
face = getVerifiedFace();
} catch (const Base::Exception& e) {
return new App::DocumentObjectExecReturn(e.what());
}
@ -111,10 +111,8 @@ App::DocumentObjectExecReturn *Pocket::execute(void)
}
// get the Sketch plane
Base::Placement SketchPos = sketch->Placement.getValue();
Base::Rotation SketchOrientation = SketchPos.getRotation();
Base::Vector3d SketchVector(0,0,1);
SketchOrientation.multVec(SketchVector,SketchVector);
Base::Placement SketchPos = obj->Placement.getValue();
Base::Vector3d SketchVector = getProfileNormal();
// turn around for pockets
SketchVector *= -1;
@ -128,10 +126,9 @@ App::DocumentObjectExecReturn *Pocket::execute(void)
gp_Dir dir(SketchVector.x,SketchVector.y,SketchVector.z);
dir.Transform(invObjLoc.Transformation());
TopoDS_Shape sketchshape = makeFace(wires);
if (sketchshape.IsNull())
if (face.IsNull())
return new App::DocumentObjectExecReturn("Pocket: Creating a face from sketch failed");
sketchshape.Move(invObjLoc);
face.Move(invObjLoc);
std::string method(Type.getValueAsString());
if (method == "UpToFirst" || method == "UpToFace") {
@ -151,7 +148,7 @@ App::DocumentObjectExecReturn *Pocket::execute(void)
getUpToFaceFromLinkSub(upToFace, UpToFace);
upToFace.Move(invObjLoc);
}
getUpToFace(upToFace, base, supportface, sketchshape, method, dir, Offset.getValue());
getUpToFace(upToFace, base, supportface, face, method, dir, Offset.getValue());
// BRepFeat_MakePrism(..., 2, 1) in combination with PerForm(upToFace) is buggy when the
// prism that is being created is contained completely inside the base solid
@ -164,7 +161,7 @@ App::DocumentObjectExecReturn *Pocket::execute(void)
if (!Ex.More())
supportface = TopoDS_Face();
BRepFeat_MakePrism PrismMaker;
PrismMaker.Init(base, sketchshape, supportface, dir, 0, 1);
PrismMaker.Init(base, face, supportface, dir, 0, 1);
PrismMaker.Perform(upToFace);
if (!PrismMaker.IsDone())
@ -181,7 +178,7 @@ App::DocumentObjectExecReturn *Pocket::execute(void)
this->Shape.setValue(prism);
} else {
TopoDS_Shape prism;
generatePrism(prism, sketchshape, method, dir, L, 0.0,
generatePrism(prism, face, method, dir, L, 0.0,
Midplane.getValue(), Reversed.getValue());
if (prism.IsNull())
return new App::DocumentObjectExecReturn("Pocket: Resulting shape is empty");

View File

@ -30,7 +30,7 @@
namespace PartDesign
{
class PartDesignExport Pocket : public SketchBased
class PartDesignExport Pocket : public ProfileBased
{
PROPERTY_HEADER(PartDesign::Pocket);

View File

@ -49,7 +49,7 @@ using namespace PartDesign;
namespace PartDesign {
PROPERTY_SOURCE(PartDesign::Revolution, PartDesign::SketchBased)
PROPERTY_SOURCE(PartDesign::Revolution, PartDesign::ProfileBased)
Revolution::Revolution()
{
@ -69,7 +69,7 @@ short Revolution::mustExecute() const
Base.isTouched() ||
Angle.isTouched())
return 1;
return SketchBased::mustExecute();
return ProfileBased::mustExecute();
}
App::DocumentObjectExecReturn *Revolution::execute(void)
@ -86,9 +86,9 @@ App::DocumentObjectExecReturn *Revolution::execute(void)
if (Reversed.getValue() && !Midplane.getValue())
angle *= (-1.0);
std::vector<TopoDS_Wire> wires;
TopoDS_Shape sketchshape;
try {
wires = getSketchWires();
sketchshape = getVerifiedFace();
} catch (const Base::Exception& e) {
return new App::DocumentObjectExecReturn(e.what());
}
@ -112,7 +112,6 @@ App::DocumentObjectExecReturn *Revolution::execute(void)
gp_Dir dir(v.x,v.y,v.z);
try {
TopoDS_Shape sketchshape = makeFace(wires);
if (sketchshape.IsNull())
return new App::DocumentObjectExecReturn("Creating a face from sketch failed");
@ -177,7 +176,7 @@ App::DocumentObjectExecReturn *Revolution::execute(void)
bool Revolution::suggestReversed(void)
{
updateAxis();
return SketchBased::getReversedAngle(Base.getValue(), Axis.getValue()) < 0.0;
return ProfileBased::getReversedAngle(Base.getValue(), Axis.getValue()) < 0.0;
}
void Revolution::updateAxis(void)

View File

@ -30,7 +30,7 @@
namespace PartDesign
{
class PartDesignExport Revolution : public SketchBased
class PartDesignExport Revolution : public ProfileBased
{
PROPERTY_HEADER(PartDesign::Revolution);

View File

@ -66,11 +66,16 @@
#include <BRepExtrema_DistShapeShape.hxx>
#include <TopExp.hxx>
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
#include <BRepLProp_SLProps.hxx>
#include <BRepGProp_Face.hxx>
#include <Base/Exception.h>
#include <Base/Parameter.h>
#include <Base/Reader.h>
#include <Base/Console.h>
#include <App/Application.h>
#include <App/OriginFeature.h>
#include <App/Document.h>
#include <Mod/Part/App/modelRefine.h>
#include "FeatureSketchBased.h"
#include "DatumPlane.h"
@ -79,7 +84,7 @@
using namespace PartDesign;
// sort bounding boxes according to diagonal length
class SketchBased::Wire_Compare : public std::binary_function<const TopoDS_Wire&,
class ProfileBased::Wire_Compare : public std::binary_function<const TopoDS_Wire&,
const TopoDS_Wire&, bool> {
public:
bool operator() (const TopoDS_Wire& w1, const TopoDS_Wire& w2)
@ -99,19 +104,19 @@ public:
}
};
PROPERTY_SOURCE(PartDesign::SketchBased, PartDesign::FeatureAddSub)
PROPERTY_SOURCE(PartDesign::ProfileBased, PartDesign::FeatureAddSub)
SketchBased::SketchBased()
ProfileBased::ProfileBased()
{
ADD_PROPERTY_TYPE(Sketch,(0),"SketchBased", App::Prop_None, "Reference to sketch");
ADD_PROPERTY_TYPE(Profile,(0),"SketchBased", App::Prop_None, "Reference to sketch");
ADD_PROPERTY_TYPE(Midplane,(0),"SketchBased", App::Prop_None, "Extrude symmetric to sketch face");
ADD_PROPERTY_TYPE(Reversed, (0),"SketchBased", App::Prop_None, "Reverse extrusion direction");
ADD_PROPERTY_TYPE(UpToFace,(0),"SketchBased",(App::PropertyType)(App::Prop_None),"Face where feature will end");
}
short SketchBased::mustExecute() const
short ProfileBased::mustExecute() const
{
if (Sketch.isTouched() ||
if (Profile.isTouched() ||
Midplane.isTouched() ||
Reversed.isTouched() ||
UpToFace.isTouched())
@ -119,7 +124,7 @@ short SketchBased::mustExecute() const
return PartDesign::FeatureAddSub::mustExecute();
}
void SketchBased::positionByPrevious(void)
void ProfileBased::positionByPrevious(void)
{
Part::Feature* feat = getBaseObject(/* silent = */ true);
if (feat) {
@ -136,7 +141,7 @@ void SketchBased::positionByPrevious(void)
}
}
void SketchBased::transformPlacement(const Base::Placement &transform)
void ProfileBased::transformPlacement(const Base::Placement &transform)
{
Part::Feature* feat = getBaseObject(/* silent = */ true);
if (feat) {
@ -148,8 +153,8 @@ void SketchBased::transformPlacement(const Base::Placement &transform)
positionByPrevious();
}
Part::Part2DObject* SketchBased::getVerifiedSketch(bool silent) const {
App::DocumentObject* result = Sketch.getValue();
Part::Part2DObject* ProfileBased::getVerifiedSketch(bool silent) const {
App::DocumentObject* result = Profile.getValue();
const char* err = nullptr;
if (!result) {
@ -166,10 +171,78 @@ Part::Part2DObject* SketchBased::getVerifiedSketch(bool silent) const {
return static_cast<Part::Part2DObject*>(result);
}
std::vector<TopoDS_Wire> SketchBased::getSketchWires() const {
Part::Feature* ProfileBased::getVerifiedObject(bool silent) const {
App::DocumentObject* result = Profile.getValue();
const char* err = nullptr;
if (!result) {
err = "No object linked";
} else {
if (!result->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId()))
err = "Linked object is not a Sketch, Part2DObject or Feature";
}
if (!silent && err) {
throw Base::Exception (err);
}
return static_cast<Part::Feature*>(result);
}
TopoDS_Face ProfileBased::getVerifiedFace(bool silent) const {
App::DocumentObject* result = Profile.getValue();
const char* err = nullptr;
if (!result) {
err = "No profile linked";
} else {
if (result->getTypeId().isDerivedFrom(Part::Part2DObject::getClassTypeId())) {
auto wires = getProfileWires();
return TopoDS::Face(makeFace(wires));
}
else if(result->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
if(Profile.getSubValues().empty())
err = "Linked object has no subshape specified";
else {
const TopoShape& shape = Profile.getValue<Part::Feature*>()->Shape.getShape();
TopoDS_Shape sub = shape.getSubShape(Profile.getSubValues()[0].c_str());
if(sub.ShapeType() == TopAbs_FACE)
return TopoDS::Face(sub);
else if(sub.ShapeType() == TopAbs_WIRE) {
auto wire = TopoDS::Wire(sub);
if(!wire.Closed())
err = "Linked wire is not closed";
else {
BRepBuilderAPI_MakeFace mk(wire);
mk.Build();
return TopoDS::Face(mk.Shape());
}
}
else
err = "Linked Subshape cannot be used";
}
}
else
err = "Linked object is neither Sketch, Part2DObject or Part::Feature";
}
if (!silent && err) {
throw Base::Exception (err);
}
return TopoDS_Face();
}
std::vector<TopoDS_Wire> ProfileBased::getProfileWires() const {
std::vector<TopoDS_Wire> result;
TopoDS_Shape shape = getVerifiedSketch()->Shape.getShape()._Shape;
TopoDS_Shape shape = getVerifiedFace();
if (shape.IsNull())
throw Base::Exception("Linked shape object is empty");
@ -195,7 +268,7 @@ std::vector<TopoDS_Wire> SketchBased::getSketchWires() const {
// Note: We cannot return a reference, because it will become Null.
// Not clear where, because we check for IsNull() here, but as soon as it is passed out of
// this method, it becomes null!
const TopoDS_Face SketchBased::getSupportFace() const {
const TopoDS_Face ProfileBased::getSupportFace() const {
const Part::Part2DObject* sketch = getVerifiedSketch();
if (sketch->MapMode.getValue() == Attacher::mmFlatFace && sketch->Support.getValue()) {
const auto &Support = sketch->Support;
@ -229,15 +302,15 @@ const TopoDS_Face SketchBased::getSupportFace() const {
}
int SketchBased::getSketchAxisCount(void) const
int ProfileBased::getSketchAxisCount(void) const
{
Part::Part2DObject *sketch = static_cast<Part::Part2DObject*>(Sketch.getValue());
Part::Part2DObject *sketch = static_cast<Part::Part2DObject*>(Profile.getValue());
if (!sketch)
return -1; // the link to the sketch is lost
return sketch->getAxisCount();
}
Part::Feature *SketchBased::getBaseObject(bool silent) const
Part::Feature *ProfileBased::getBaseObject(bool silent) const
{
// Test the base's class feature.
Part::Feature *rv = Feature::getBaseObject(/* silent = */ true);
@ -245,13 +318,17 @@ Part::Feature *SketchBased::getBaseObject(bool silent) const
return rv;
}
// getVerifiedSketch() may throw it's own exception if fail
Part::Part2DObject* sketch = getVerifiedSketch(silent);
// getVerifiedObject() may throw it's own exception if fail
Part::Feature* obj = getVerifiedObject(silent);
if (!sketch) {
if(!obj)
return nullptr;
}
if (!obj->isDerivedFrom(Part::Part2DObject::getClassTypeId()))
return obj;
//due to former test we know we have a 2d object
Part::Part2DObject* sketch = getVerifiedSketch(silent);
const char* err = nullptr;
App::DocumentObject* spt = sketch->Support.getValue();
@ -272,17 +349,17 @@ Part::Feature *SketchBased::getBaseObject(bool silent) const
return rv;
}
void SketchBased::onChanged(const App::Property* prop)
void ProfileBased::onChanged(const App::Property* prop)
{
if (prop == &Sketch) {
if (prop == &Profile) {
// if attached to a sketch then mark it as read-only
this->Placement.setStatus(App::Property::ReadOnly, Sketch.getValue() != 0);
this->Placement.setStatus(App::Property::ReadOnly, Profile.getValue() != 0);
}
FeatureAddSub::onChanged(prop);
}
bool SketchBased::isInside(const TopoDS_Wire& wire1, const TopoDS_Wire& wire2) const
bool ProfileBased::isInside(const TopoDS_Wire& wire1, const TopoDS_Wire& wire2) const
{
Bnd_Box box1;
BRepBndLib::Add(wire1, box1);
@ -323,7 +400,7 @@ bool SketchBased::isInside(const TopoDS_Wire& wire1, const TopoDS_Wire& wire2) c
return false;
}
TopoDS_Face SketchBased::validateFace(const TopoDS_Face& face) const
TopoDS_Face ProfileBased::validateFace(const TopoDS_Face& face) const
{
BRepCheck_Analyzer aChecker(face);
if (!aChecker.IsValid()) {
@ -367,7 +444,7 @@ TopoDS_Face SketchBased::validateFace(const TopoDS_Face& face) const
return face;
}
TopoDS_Shape SketchBased::makeFace(std::list<TopoDS_Wire>& wires) const
TopoDS_Shape ProfileBased::makeFace(std::list<TopoDS_Wire>& wires) const
{
BRepBuilderAPI_MakeFace mkFace(wires.front());
const TopoDS_Face& face = mkFace.Face();
@ -399,7 +476,7 @@ TopoDS_Shape SketchBased::makeFace(std::list<TopoDS_Wire>& wires) const
return validateFace(mkFace.Face());
}
TopoDS_Shape SketchBased::makeFace(const std::vector<TopoDS_Wire>& w) const
TopoDS_Shape ProfileBased::makeFace(const std::vector<TopoDS_Wire>& w) const
{
if (w.empty())
return TopoDS_Shape();
@ -472,7 +549,7 @@ TopoDS_Shape SketchBased::makeFace(const std::vector<TopoDS_Wire>& w) const
}
}
void SketchBased::getUpToFaceFromLinkSub(TopoDS_Face& upToFace,
void ProfileBased::getUpToFaceFromLinkSub(TopoDS_Face& upToFace,
const App::PropertyLinkSub& refFace)
{
App::DocumentObject* ref = refFace.getValue();
@ -503,7 +580,7 @@ void SketchBased::getUpToFaceFromLinkSub(TopoDS_Face& upToFace,
throw Base::Exception("SketchBased: Up to face: Failed to extract face");
}
void SketchBased::getUpToFace(TopoDS_Face& upToFace,
void ProfileBased::getUpToFace(TopoDS_Face& upToFace,
const TopoDS_Shape& support,
const TopoDS_Face& supportface,
const TopoDS_Shape& sketchshape,
@ -593,7 +670,7 @@ void SketchBased::getUpToFace(TopoDS_Face& upToFace,
}
}
void SketchBased::generatePrism(TopoDS_Shape& prism,
void ProfileBased::generatePrism(TopoDS_Shape& prism,
const TopoDS_Shape& sketchshape,
const std::string& method,
const gp_Dir& dir,
@ -639,7 +716,7 @@ void SketchBased::generatePrism(TopoDS_Shape& prism,
}
const bool SketchBased::checkWireInsideFace(const TopoDS_Wire& wire, const TopoDS_Face& face,
const bool ProfileBased::checkWireInsideFace(const TopoDS_Wire& wire, const TopoDS_Face& face,
const gp_Dir& dir) {
// Project wire onto the face (face, not surface! So limits of face apply)
// FIXME: The results of BRepProj_Projection do not seem to be very stable. Sometimes they return no result
@ -650,7 +727,7 @@ const bool SketchBased::checkWireInsideFace(const TopoDS_Wire& wire, const TopoD
return (proj.More() && proj.Current().Closed());
}
const bool SketchBased::checkLineCrossesFace(const gp_Lin &line, const TopoDS_Face &face)
const bool ProfileBased::checkLineCrossesFace(const gp_Lin &line, const TopoDS_Face &face)
{
#if 1
BRepBuilderAPI_MakeEdge mkEdge(line);
@ -800,7 +877,7 @@ const bool SketchBased::checkLineCrossesFace(const gp_Lin &line, const TopoDS_Fa
#endif
}
void SketchBased::remapSupportShape(const TopoDS_Shape& newShape)
void ProfileBased::remapSupportShape(const TopoDS_Shape& newShape)
{
TopTools_IndexedMapOfShape faceMap;
TopExp::MapShapes(newShape, TopAbs_FACE, faceMap);
@ -911,7 +988,7 @@ struct gp_Pnt_Less : public std::binary_function<const gp_Pnt&,
};
}
bool SketchBased::isQuasiEqual(const TopoDS_Shape& s1, const TopoDS_Shape& s2) const
bool ProfileBased::isQuasiEqual(const TopoDS_Shape& s1, const TopoDS_Shape& s2) const
{
if (s1.ShapeType() != s2.ShapeType())
return false;
@ -947,7 +1024,7 @@ bool SketchBased::isQuasiEqual(const TopoDS_Shape& s1, const TopoDS_Shape& s2) c
return true;
}
bool SketchBased::isEqualGeometry(const TopoDS_Shape& s1, const TopoDS_Shape& s2) const
bool ProfileBased::isEqualGeometry(const TopoDS_Shape& s1, const TopoDS_Shape& s2) const
{
if (s1.ShapeType() == TopAbs_FACE && s2.ShapeType() == TopAbs_FACE) {
BRepAdaptor_Surface a1(TopoDS::Face(s1));
@ -974,7 +1051,7 @@ bool SketchBased::isEqualGeometry(const TopoDS_Shape& s1, const TopoDS_Shape& s2
return false;
}
bool SketchBased::isParallelPlane(const TopoDS_Shape& s1, const TopoDS_Shape& s2) const
bool ProfileBased::isParallelPlane(const TopoDS_Shape& s1, const TopoDS_Shape& s2) const
{
if (s1.ShapeType() == TopAbs_FACE && s2.ShapeType() == TopAbs_FACE) {
BRepAdaptor_Surface a1(TopoDS::Face(s1));
@ -993,12 +1070,11 @@ bool SketchBased::isParallelPlane(const TopoDS_Shape& s1, const TopoDS_Shape& s2
}
const double SketchBased::getReversedAngle(const Base::Vector3d &b, const Base::Vector3d &v)
const double ProfileBased::getReversedAngle(const Base::Vector3d &b, const Base::Vector3d &v)
{
try {
Part::Part2DObject* sketch = getVerifiedSketch();
std::vector<TopoDS_Wire> wires = getSketchWires();
TopoDS_Shape sketchshape = makeFace(wires);
Part::Feature* obj = getVerifiedObject();
TopoDS_Shape sketchshape = getVerifiedFace();
// get centre of gravity of the sketch face
GProp_GProps props;
@ -1010,7 +1086,7 @@ const double SketchBased::getReversedAngle(const Base::Vector3d &b, const Base::
// get cross product of projection direction with revolve axis direction
Base::Vector3d cross = v % perp_dir;
// get sketch vector pointing away from support material
Base::Placement SketchPos = sketch->Placement.getValue();
Base::Placement SketchPos = obj->Placement.getValue();
Base::Rotation SketchOrientation = SketchPos.getRotation();
Base::Vector3d SketchNormal(0,0,1);
SketchOrientation.multVec(SketchNormal,SketchNormal);
@ -1022,7 +1098,7 @@ const double SketchBased::getReversedAngle(const Base::Vector3d &b, const Base::
}
}
void SketchBased::getAxis(const App::DocumentObject *pcReferenceAxis, const std::vector<std::string> &subReferenceAxis,
void ProfileBased::getAxis(const App::DocumentObject *pcReferenceAxis, const std::vector<std::string> &subReferenceAxis,
Base::Vector3d& base, Base::Vector3d& dir)
{
dir = Base::Vector3d(0,0,0); // If unchanged signals that no valid axis was found
@ -1116,7 +1192,7 @@ void SketchBased::getAxis(const App::DocumentObject *pcReferenceAxis, const std:
throw Base::Exception("Rotation axis reference is invalid");
}
TopoDS_Shape SketchBased::refineShapeIfActive(const TopoDS_Shape& oldShape) const
TopoDS_Shape ProfileBased::refineShapeIfActive(const TopoDS_Shape& oldShape) const
{
Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter()
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/PartDesign");
@ -1128,3 +1204,88 @@ TopoDS_Shape SketchBased::refineShapeIfActive(const TopoDS_Shape& oldShape) cons
return oldShape;
}
Base::Vector3d ProfileBased::getProfileNormal() const {
Base::Vector3d SketchVector(0,0,1);
auto obj = getVerifiedObject(true);
if(!obj)
return SketchVector;
// get the Sketch plane
if(obj->isDerivedFrom(Part::Part2DObject::getClassTypeId())) {
Base::Placement SketchPos = obj->Placement.getValue();
Base::Rotation SketchOrientation = SketchPos.getRotation();
SketchOrientation.multVec(SketchVector,SketchVector);
}
else {
TopoDS_Face face = getVerifiedFace(true);
BRepAdaptor_Surface adapt(face);
double u = adapt.FirstUParameter() + (adapt.LastUParameter() - adapt.FirstUParameter())/2.;
double v = adapt.FirstVParameter() + (adapt.LastVParameter() - adapt.FirstVParameter())/2.;
BRepLProp_SLProps prop(adapt,u,v,2,Precision::Confusion());
if(prop.IsNormalDefined()) {
gp_Pnt pnt; gp_Vec vec;
// handles the orientation state of the shape
BRepGProp_Face(face).Normal(u,v,pnt,vec);
SketchVector = Base::Vector3d(vec.X(), vec.Y(), vec.Z());
}
}
return SketchVector;
}
void ProfileBased::Restore(Base::XMLReader& reader) {
reader.readElement("Properties");
int Cnt = reader.getAttributeAsInteger("Count");
for (int i=0 ;i<Cnt ;i++) {
reader.readElement("Property");
const char* PropName = reader.getAttribute("name");
const char* TypeName = reader.getAttribute("type");
App::Property* prop = getPropertyByName(PropName);
// NOTE: We must also check the type of the current property because a
// subclass of PropertyContainer might change the type of a property but
// not its name. In this case we would force to read-in a wrong property
// type and the behaviour would be undefined.
try {
//check if we load the old sketch property
if(!prop && (strcmp("Sketch", PropName) == 0) && (strcmp("App::PropertyLink", TypeName) == 0)) {
std::vector<std::string> vec;
// read my element
reader.readElement("Link");
// get the value of my attribute
std::string name = reader.getAttribute("value");
if (name != "") {
App::Document* document = getDocument();
DocumentObject* object = document ? document->getObject(name.c_str()) : 0;
Profile.setValue(object, vec);
}
else {
Profile.setValue(0, vec);
}
}
else if (prop && strcmp(prop->getTypeId().getName(), TypeName) == 0)
prop->Restore(reader);
}
catch (const Base::XMLParseException&) {
throw; // re-throw
}
catch (const Base::Exception &e) {
Base::Console().Error("%s\n", e.what());
}
catch (const std::exception &e) {
Base::Console().Error("%s\n", e.what());
}
catch (const char* e) {
Base::Console().Error("%s\n", e);
}
reader.readEndElement("Property");
}
reader.readEndElement("Properties");
}

View File

@ -37,16 +37,16 @@ class gp_Lin;
namespace PartDesign
{
class PartDesignExport SketchBased : public PartDesign::FeatureAddSub
class PartDesignExport ProfileBased : public PartDesign::FeatureAddSub
{
PROPERTY_HEADER(PartDesign::SketchBased);
public:
SketchBased();
ProfileBased();
// Common properties for all sketch based features
/// Sketch used to create this feature
App::PropertyLink Sketch;
/// Profile used to create this feature
App::PropertyLinkSub Profile;
/// Reverse extrusion direction
App::PropertyBool Reversed;
/// Make extrusion symmetric to sketch plane
@ -68,31 +68,46 @@ public:
virtual void transformPlacement(const Base::Placement &transform);
/**
* Verifies the linked Sketch object
* @param silent if sketch property is malformed and the parameter is true
* Verifies the linked Profile and returns it if it is a valid 2D object
* @param silent if profile property is malformed and the parameter is true
* silently returns nullptr, otherwice throw a Base::Exception.
* Default is false.
*/
Part::Part2DObject* getVerifiedSketch(bool silent=false) const;
/**
* Verifies the linked Profile and returns it if it is a valid object
* @param silent if profile property is malformed and the parameter is true
* silently returns nullptr, otherwice throw a Base::Exception.
* Default is false.
*/
Part::Feature* getVerifiedObject(bool silent=false) const;
/**
* Verifies the linked Object and returns the shape used as profile
* @param silent if profile property is malformed and the parameter is true
* silently returns nullptr, otherwice throw a Base::Exception.
* Default is false.
*/
TopoDS_Face getVerifiedFace(bool silent = false) const;
/// Returns the wires the sketch is composed of
std::vector<TopoDS_Wire> getSketchWires() const;
std::vector<TopoDS_Wire> getProfileWires() const;
/// Returns the face of the sketch support (if any)
const TopoDS_Face getSupportFace() const;
Base::Vector3d getProfileNormal() const;
/// retrieves the number of axes in the linked sketch (defined as construction lines)
int getSketchAxisCount(void) const;
virtual Part::Feature* getBaseObject(bool silent=false) const;
//backwards compatibility: profile property was renamed and has different type now
virtual void Restore(Base::XMLReader& reader);
protected:
void onChanged(const App::Property* prop);
TopoDS_Face validateFace(const TopoDS_Face&) const;
TopoDS_Shape makeFace(const std::vector<TopoDS_Wire>&) const;
TopoDS_Shape makeFace(std::list<TopoDS_Wire>&) const; // for internal use only
bool isInside(const TopoDS_Wire&, const TopoDS_Wire&) const;
bool isParallelPlane(const TopoDS_Shape&, const TopoDS_Shape&) const;
bool isEqualGeometry(const TopoDS_Shape&, const TopoDS_Shape&) const;
bool isQuasiEqual(const TopoDS_Shape&, const TopoDS_Shape&) const;
void remapSupportShape(const TopoDS_Shape&);
TopoDS_Shape refineShapeIfActive(const TopoDS_Shape&) const;
@ -136,6 +151,17 @@ protected:
/// get Axis from ReferenceAxis
void getAxis(const App::DocumentObject* pcReferenceAxis, const std::vector<std::string>& subReferenceAxis,
Base::Vector3d& base, Base::Vector3d& dir);
TopoDS_Shape makeFace(const std::vector<TopoDS_Wire>&) const;
private:
void onChanged(const App::Property* prop);
TopoDS_Face validateFace(const TopoDS_Face&) const;
TopoDS_Shape makeFace(std::list<TopoDS_Wire>&) const; // for internal use only
bool isInside(const TopoDS_Wire&, const TopoDS_Wire&) const;
bool isParallelPlane(const TopoDS_Shape&, const TopoDS_Shape&) const;
bool isEqualGeometry(const TopoDS_Shape&, const TopoDS_Shape&) const;
bool isQuasiEqual(const TopoDS_Shape&, const TopoDS_Shape&) const;
};
} //namespace PartDesign

View File

@ -103,8 +103,8 @@ Part::Feature* Transformed::getBaseObject(bool silent) const {
App::DocumentObject* Transformed::getSketchObject() const
{
std::vector<DocumentObject*> originals = Originals.getValues();
if (!originals.empty() && originals.front()->getTypeId().isDerivedFrom(PartDesign::SketchBased::getClassTypeId())) {
return (static_cast<PartDesign::SketchBased*>(originals.front()))->getVerifiedSketch();
if (!originals.empty() && originals.front()->getTypeId().isDerivedFrom(PartDesign::ProfileBased::getClassTypeId())) {
return (static_cast<PartDesign::ProfileBased*>(originals.front()))->getVerifiedSketch();
}
else if (!originals.empty() && originals.front()->getTypeId().isDerivedFrom(PartDesign::FeatureAddSub::getClassTypeId())) {
return NULL;

View File

@ -612,11 +612,11 @@ void finishFeature(const Gui::Command* cmd, const std::string& FeatName,
}
//===========================================================================
// Common utility functions for SketchBased features
// Common utility functions for ProfileBased features
//===========================================================================
// Take a list of Part2DObjects and classify them for creating a
// SketchBased feature. FirstFreeSketch is the first free sketch in the same body
// ProfileBased feature. FirstFreeSketch is the first free sketch in the same body
// or sketches.end() if non available. The returned number is the amount of free sketches
const unsigned validateSketches(std::vector<App::DocumentObject*>& sketches,
std::vector<PartDesignGui::TaskFeaturePick::featureStatus>& status,
@ -705,9 +705,42 @@ const unsigned validateSketches(std::vector<App::DocumentObject*>& sketches,
return freeSketches;
}
void prepareSketchBased(Gui::Command* cmd, const std::string& which,
boost::function<void (Part::Part2DObject*, std::string)> func)
void prepareProfileBased(Gui::Command* cmd, const std::string& which,
boost::function<void (Part::Feature*, std::string)> func)
{
auto base_worker = [which, cmd, func](App::DocumentObject* feature, std::string sub) {
if(!feature || !feature->isDerivedFrom(Part::Feature::getClassTypeId()))
return;
std::string FeatName = cmd->getUniqueObjectName(which.c_str());
Gui::Command::openCommand((std::string("Make ") + which).c_str());
Gui::Command::doCommand(Gui::Command::Doc,"App.activeDocument().addObject(\"PartDesign::%s\",\"%s\")",
which.c_str(), FeatName.c_str());
if(feature->isDerivedFrom(Part::Part2DObject::getClassTypeId())) {
Gui::Command::doCommand(Gui::Command::Doc,"App.activeDocument().%s.Profile = App.activeDocument().%s",
FeatName.c_str(), feature->getNameInDocument());
}
else {
Gui::Command::doCommand(Gui::Command::Doc,"App.activeDocument().%s.Profile = (App.activeDocument().%s, [\"%s\"])",
FeatName.c_str(), feature->getNameInDocument(), sub.c_str());
}
func(static_cast<Part::Feature*>(feature), FeatName);
};
//if a profie is selected we can make our life easy and fast
auto selection = cmd->getSelection().getSelectionEx();
if(!selection.empty() && selection.front().hasSubNames()) {
base_worker(selection.front().getObject(), selection.front().getSubNames().front());
return;
}
//no face profile was selected, do he extended sketch logic
bool bNoSketchWasSelected = false;
// Get a valid sketch from the user
// First check selections
@ -734,26 +767,12 @@ void prepareSketchBased(Gui::Command* cmd, const std::string& which,
return true;
};
auto worker = [which, cmd, func](std::vector<App::DocumentObject*> features) {
if(features.empty())
return;
auto sketch_worker = [&](std::vector<App::DocumentObject*> features) {
auto firstValidSketch = features.begin();
Part::Part2DObject* sketch = static_cast<Part::Part2DObject*>(*firstValidSketch);
std::string FeatName = cmd->getUniqueObjectName(which.c_str());
Gui::Command::openCommand((std::string("Make ") + which).c_str());
Gui::Command::doCommand(Gui::Command::Doc,"App.activeDocument().addObject(\"PartDesign::%s\",\"%s\")",
which.c_str(), FeatName.c_str());
Gui::Command::doCommand(Gui::Command::Doc,"App.activeDocument().%s.Sketch = App.activeDocument().%s",
FeatName.c_str(), sketch->getNameInDocument());
func(sketch, FeatName);
base_worker(features.front(), "");
};
//if there is a sketch selected which is from annother body or part we need to bring up the
//pick task dialog to decide how those are handled
bool ext = std::find_if( status.begin(), status.end(),
@ -814,7 +833,7 @@ void prepareSketchBased(Gui::Command* cmd, const std::string& which,
Gui::Control().closeDialog();
Gui::Selection().clearSelection();
pickDlg = new PartDesignGui::TaskDlgFeaturePick(sketches, status, accepter, worker);
pickDlg = new PartDesignGui::TaskDlgFeaturePick(sketches, status, accepter, sketch_worker);
if(!bNoSketchWasSelected && ext)
pickDlg->showExternal(true);
@ -827,14 +846,15 @@ void prepareSketchBased(Gui::Command* cmd, const std::string& which,
else
theSketch.push_back(*firstFreeSketch);
worker(theSketch);
sketch_worker(theSketch);
}
}
void finishSketchBased(const Gui::Command* cmd, const Part::Part2DObject* sketch, const std::string& FeatName)
void finishProfileBased(const Gui::Command* cmd, const Part::Feature* sketch, const std::string& FeatName)
{
cmd->doCommand(cmd->Gui,"Gui.activeDocument().hide(\"%s\")", sketch->getNameInDocument());
if(sketch && sketch->isDerivedFrom(Part::Part2DObject::getClassTypeId()))
cmd->doCommand(cmd->Gui,"Gui.activeDocument().hide(\"%s\")", sketch->getNameInDocument());
finishFeature(cmd, FeatName);
}
@ -858,26 +878,28 @@ CmdPartDesignPad::CmdPartDesignPad()
void CmdPartDesignPad::activated(int iMsg)
{
Gui::Command* cmd = this;
auto worker = [cmd](Part::Part2DObject* sketch, std::string FeatName) {
auto worker = [cmd](Part::Feature* profile, std::string FeatName) {
if (FeatName.empty()) return;
// specific parameters for Pad
Gui::Command::doCommand(Doc,"App.activeDocument().%s.Length = 10.0",FeatName.c_str());
App::DocumentObjectGroup* grp = sketch->getGroup();
App::DocumentObjectGroup* grp = profile->getGroup();
if (grp) {
Gui::Command::doCommand(Doc,"App.activeDocument().%s.addObject(App.activeDocument().%s)"
,grp->getNameInDocument(),FeatName.c_str());
Gui::Command::doCommand(Doc,"App.activeDocument().%s.removeObject(App.activeDocument().%s)"
,grp->getNameInDocument(),sketch->getNameInDocument());
if(profile->isDerivedFrom(Part::Part2DObject::getClassTypeId()))
Gui::Command::doCommand(Doc,"App.activeDocument().%s.removeObject(App.activeDocument().%s)"
,grp->getNameInDocument(), profile->getNameInDocument());
}
Gui::Command::updateActive();
finishSketchBased(cmd, sketch, FeatName);
Part::Part2DObject* sketch = dynamic_cast<Part::Part2DObject*>(profile);
finishProfileBased(cmd, sketch, FeatName);
cmd->adjustCameraPosition();
};
prepareSketchBased(this, "Pad", worker);
prepareProfileBased(this, "Pad", worker);
}
bool CmdPartDesignPad::isActive(void)
@ -905,16 +927,16 @@ CmdPartDesignPocket::CmdPartDesignPocket()
void CmdPartDesignPocket::activated(int iMsg)
{
Gui::Command* cmd = this;
auto worker = [cmd](Part::Part2DObject* sketch, std::string FeatName) {
auto worker = [cmd](Part::Feature* sketch, std::string FeatName) {
if (FeatName.empty()) return;
Gui::Command::doCommand(Doc,"App.activeDocument().%s.Length = 5.0",FeatName.c_str());
finishSketchBased(cmd, sketch, FeatName);
finishProfileBased(cmd, sketch, FeatName);
cmd->adjustCameraPosition();
};
prepareSketchBased(this, "Pocket", worker);
prepareProfileBased(this, "Pocket", worker);
}
bool CmdPartDesignPocket::isActive(void)
@ -942,7 +964,7 @@ CmdPartDesignRevolution::CmdPartDesignRevolution()
void CmdPartDesignRevolution::activated(int iMsg)
{
Gui::Command* cmd = this;
auto worker = [cmd](Part::Part2DObject* sketch, std::string FeatName) {
auto worker = [cmd](Part::Feature* sketch, std::string FeatName) {
if (FeatName.empty()) return;
@ -953,11 +975,11 @@ void CmdPartDesignRevolution::activated(int iMsg)
if (pcRevolution && pcRevolution->suggestReversed())
Gui::Command::doCommand(Doc,"App.activeDocument().%s.Reversed = 1",FeatName.c_str());
finishSketchBased(cmd, sketch, FeatName);
finishProfileBased(cmd, sketch, FeatName);
cmd->adjustCameraPosition();
};
prepareSketchBased(this, "Revolution", worker);
prepareProfileBased(this, "Revolution", worker);
}
bool CmdPartDesignRevolution::isActive(void)
@ -985,7 +1007,7 @@ CmdPartDesignGroove::CmdPartDesignGroove()
void CmdPartDesignGroove::activated(int iMsg)
{
Gui::Command* cmd = this;
auto worker = [cmd](Part::Part2DObject* sketch, std::string FeatName) {
auto worker = [cmd](Part::Feature* sketch, std::string FeatName) {
if (FeatName.empty()) return;
@ -996,11 +1018,11 @@ void CmdPartDesignGroove::activated(int iMsg)
if (pcGroove && pcGroove->suggestReversed())
Gui::Command::doCommand(Doc,"App.activeDocument().%s.Reversed = 1",FeatName.c_str());
finishSketchBased(cmd, sketch, FeatName);
finishProfileBased(cmd, sketch, FeatName);
cmd->adjustCameraPosition();
};
prepareSketchBased(this, "Groove", worker);
prepareProfileBased(this, "Groove", worker);
}
bool CmdPartDesignGroove::isActive(void)
@ -1028,18 +1050,18 @@ CmdPartDesignAdditivePipe::CmdPartDesignAdditivePipe()
void CmdPartDesignAdditivePipe::activated(int iMsg)
{
Gui::Command* cmd = this;
auto worker = [cmd](Part::Part2DObject* sketch, std::string FeatName) {
auto worker = [cmd](Part::Feature* sketch, std::string FeatName) {
if (FeatName.empty()) return;
// specific parameters for pipe
Gui::Command::updateActive();
finishSketchBased(cmd, sketch, FeatName);
finishProfileBased(cmd, sketch, FeatName);
cmd->adjustCameraPosition();
};
prepareSketchBased(this, "AdditivePipe", worker);
prepareProfileBased(this, "AdditivePipe", worker);
}
bool CmdPartDesignAdditivePipe::isActive(void)
@ -1068,18 +1090,18 @@ CmdPartDesignSubtractivePipe::CmdPartDesignSubtractivePipe()
void CmdPartDesignSubtractivePipe::activated(int iMsg)
{
Gui::Command* cmd = this;
auto worker = [cmd](Part::Part2DObject* sketch, std::string FeatName) {
auto worker = [cmd](Part::Feature* sketch, std::string FeatName) {
if (FeatName.empty()) return;
// specific parameters for pipe
Gui::Command::updateActive();
finishSketchBased(cmd, sketch, FeatName);
finishProfileBased(cmd, sketch, FeatName);
cmd->adjustCameraPosition();
};
prepareSketchBased(this, "SubtractivePipe", worker);
prepareProfileBased(this, "SubtractivePipe", worker);
}
bool CmdPartDesignSubtractivePipe::isActive(void)
@ -1108,18 +1130,18 @@ CmdPartDesignAdditiveLoft::CmdPartDesignAdditiveLoft()
void CmdPartDesignAdditiveLoft::activated(int iMsg)
{
Gui::Command* cmd = this;
auto worker = [cmd](Part::Part2DObject* sketch, std::string FeatName) {
auto worker = [cmd](Part::Feature* sketch, std::string FeatName) {
if (FeatName.empty()) return;
// specific parameters for pipe
Gui::Command::updateActive();
finishSketchBased(cmd, sketch, FeatName);
finishProfileBased(cmd, sketch, FeatName);
cmd->adjustCameraPosition();
};
prepareSketchBased(this, "AdditiveLoft", worker);
prepareProfileBased(this, "AdditiveLoft", worker);
}
bool CmdPartDesignAdditiveLoft::isActive(void)
@ -1148,18 +1170,18 @@ CmdPartDesignSubtractiveLoft::CmdPartDesignSubtractiveLoft()
void CmdPartDesignSubtractiveLoft::activated(int iMsg)
{
Gui::Command* cmd = this;
auto worker = [cmd](Part::Part2DObject* sketch, std::string FeatName) {
auto worker = [cmd](Part::Feature* sketch, std::string FeatName) {
if (FeatName.empty()) return;
// specific parameters for pipe
Gui::Command::updateActive();
finishSketchBased(cmd, sketch, FeatName);
finishProfileBased(cmd, sketch, FeatName);
cmd->adjustCameraPosition();
};
prepareSketchBased(this, "SubtractiveLoft", worker);
prepareProfileBased(this, "SubtractiveLoft", worker);
}
bool CmdPartDesignSubtractiveLoft::isActive(void)
@ -1523,8 +1545,8 @@ void CmdPartDesignMirrored::activated(int iMsg)
if (features.empty())
return;
if(features.front()->isDerivedFrom(PartDesign::SketchBased::getClassTypeId())) {
Part::Part2DObject *sketch = (static_cast<PartDesign::SketchBased*>(features.front()))->getVerifiedSketch(/* silent =*/ true);
if(features.front()->isDerivedFrom(PartDesign::ProfileBased::getClassTypeId())) {
Part::Part2DObject *sketch = (static_cast<PartDesign::ProfileBased*>(features.front()))->getVerifiedSketch(/* silent =*/ true);
if (sketch)
Gui::Command::doCommand(Doc,"App.activeDocument().%s.MirrorPlane = (App.activeDocument().%s, [\"V_Axis\"])",
FeatName.c_str(), sketch->getNameInDocument());
@ -1571,8 +1593,8 @@ void CmdPartDesignLinearPattern::activated(int iMsg)
if (features.empty())
return;
if(features.front()->isDerivedFrom(PartDesign::SketchBased::getClassTypeId())) {
Part::Part2DObject *sketch = (static_cast<PartDesign::SketchBased*>(features.front()))->getVerifiedSketch(/* silent =*/ true);
if(features.front()->isDerivedFrom(PartDesign::ProfileBased::getClassTypeId())) {
Part::Part2DObject *sketch = (static_cast<PartDesign::ProfileBased*>(features.front()))->getVerifiedSketch(/* silent =*/ true);
if (sketch)
doCommand(Doc,"App.activeDocument().%s.Direction = (App.activeDocument().%s, [\"H_Axis\"])",
FeatName.c_str(), sketch->getNameInDocument());
@ -1621,8 +1643,8 @@ void CmdPartDesignPolarPattern::activated(int iMsg)
if (features.empty())
return;
if(features.front()->isDerivedFrom(PartDesign::SketchBased::getClassTypeId())) {
Part::Part2DObject *sketch = (static_cast<PartDesign::SketchBased*>(features.front()))->getVerifiedSketch(/* silent =*/ true);
if(features.front()->isDerivedFrom(PartDesign::ProfileBased::getClassTypeId())) {
Part::Part2DObject *sketch = (static_cast<PartDesign::ProfileBased*>(features.front()))->getVerifiedSketch(/* silent =*/ true);
if (sketch)
doCommand(Doc,"App.activeDocument().%s.Axis = (App.activeDocument().%s, [\"N_Axis\"])",
FeatName.c_str(), sketch->getNameInDocument());

View File

@ -373,9 +373,9 @@ void CmdPartDesignMigrate::activated(int iMsg)
// Fill the body with features
for ( auto feature: *chainIt ) {
if ( feature->isDerivedFrom ( PartDesign::SketchBased::getClassTypeId() ) ) {
if ( feature->isDerivedFrom ( PartDesign::ProfileBased::getClassTypeId() ) ) {
// add the sketch and also reroute it if needed
PartDesign::SketchBased *sketchBased = static_cast<PartDesign::SketchBased *> ( feature );
PartDesign::ProfileBased *sketchBased = static_cast<PartDesign::ProfileBased *> ( feature );
Part::Part2DObject *sketch = sketchBased->getVerifiedSketch( /*silent =*/ true);
if ( sketch ) {
doCommand ( Doc,"App.activeDocument().%s.addFeature(App.activeDocument().%s)",

View File

@ -86,7 +86,7 @@ TaskRevolutionParameters::TaskRevolutionParameters(PartDesignGui::ViewProvider*
ui->checkBoxReversed->blockSignals(true);
//bind property mirrors
PartDesign::SketchBased* pcFeat = static_cast<PartDesign::SketchBased*>(vp->getObject());
PartDesign::ProfileBased* pcFeat = static_cast<PartDesign::ProfileBased*>(vp->getObject());
if (pcFeat->isDerivedFrom(PartDesign::Revolution::getClassTypeId())) {
PartDesign::Revolution* rev = static_cast<PartDesign::Revolution*>(vp->getObject());
this->propAngle = &(rev->Angle);
@ -114,7 +114,7 @@ TaskRevolutionParameters::TaskRevolutionParameters(PartDesignGui::ViewProvider*
ui->checkBoxMidplane->setChecked(mirrored);
ui->checkBoxReversed->setChecked(reversed);
PartDesign::SketchBased* sketchBased = static_cast<PartDesign::SketchBased*>(vp->getObject());
PartDesign::ProfileBased* sketchBased = static_cast<PartDesign::ProfileBased*>(vp->getObject());
// TODO This is quite ugly better redo it (2015-11-02, Fat-Zer)
if ( sketchBased->isDerivedFrom(PartDesign::Revolution::getClassTypeId() ) ) {
ui->revolveAngle->bind(static_cast<PartDesign::Revolution *> ( sketchBased )->Angle);
@ -161,8 +161,8 @@ void TaskRevolutionParameters::fillAxisCombo(bool forceRefill)
this->axesInList.clear();
//add sketch axes
PartDesign::SketchBased* pcFeat = static_cast<PartDesign::Revolution*>(vp->getObject());
Part::Part2DObject* pcSketch = static_cast<Part::Part2DObject*>(pcFeat->Sketch.getValue());
PartDesign::ProfileBased* pcFeat = static_cast<PartDesign::Revolution*>(vp->getObject());
Part::Part2DObject* pcSketch = static_cast<Part::Part2DObject*>(pcFeat->Profile.getValue());
if (pcSketch){
addAxisToCombo(pcSketch,"V_Axis",QObject::tr("Vertical sketch axis"));
addAxisToCombo(pcSketch,"H_Axis",QObject::tr("Horizontal sketch axis"));
@ -268,7 +268,7 @@ void TaskRevolutionParameters::onAxisChanged(int num)
{
if (blockUpdate)
return;
PartDesign::SketchBased* pcRevolution = static_cast<PartDesign::SketchBased*>(vp->getObject());
PartDesign::ProfileBased* pcRevolution = static_cast<PartDesign::ProfileBased*>(vp->getObject());
if(axesInList.size() == 0)
return;
@ -338,7 +338,7 @@ void TaskRevolutionParameters::getReferenceAxis(App::DocumentObject*& obj, std::
if(lnk.getValue() == 0){
throw Base::Exception("Still in reference selection mode; reference wasn't selected yet");
} else {
PartDesign::SketchBased* pcRevolution = static_cast<PartDesign::SketchBased*>(vp->getObject());
PartDesign::ProfileBased* pcRevolution = static_cast<PartDesign::ProfileBased*>(vp->getObject());
if (! pcRevolution->getDocument()->isIn(lnk.getValue())){
throw Base::Exception("Object was deleted");
return;

View File

@ -68,7 +68,7 @@ TaskSketchBasedParameters::TaskSketchBasedParameters(PartDesignGui::ViewProvider
const QString TaskSketchBasedParameters::onAddSelection(const Gui::SelectionChanges& msg)
{
// Note: The validity checking has already been done in ReferenceSelection.cpp
PartDesign::SketchBased* pcSketchBased = static_cast<PartDesign::SketchBased*>(vp->getObject());
PartDesign::ProfileBased* pcSketchBased = static_cast<PartDesign::ProfileBased*>(vp->getObject());
App::DocumentObject* selObj = pcSketchBased->getDocument()->getObject(msg.pObjectName);
if (selObj == pcSketchBased)
return QString::fromAscii("");
@ -94,7 +94,7 @@ const QString TaskSketchBasedParameters::onAddSelection(const Gui::SelectionChan
void TaskSketchBasedParameters::onSelectReference(const bool pressed, const bool edge, const bool face, const bool planar) {
// Note: Even if there is no solid, App::Plane and Part::Datum can still be selected
PartDesign::SketchBased* pcSketchBased = static_cast<PartDesign::SketchBased*>(vp->getObject());
PartDesign::ProfileBased* pcSketchBased = static_cast<PartDesign::ProfileBased*>(vp->getObject());
// The solid this feature will be fused to
App::DocumentObject* prevSolid = pcSketchBased->getBaseObject( /* silent =*/ true );
@ -163,7 +163,7 @@ const QByteArray TaskSketchBasedParameters::onFaceName(const QString& text)
ss << "Face" << faceId;
std::vector<std::string> upToFaces(1,ss.str());
PartDesign::SketchBased* pcSketchBased = static_cast<PartDesign::SketchBased*>(vp->getObject());
PartDesign::ProfileBased* pcSketchBased = static_cast<PartDesign::ProfileBased*>(vp->getObject());
pcSketchBased->UpToFace.setValue(obj, upToFaces);
recomputeFeature();
@ -210,11 +210,11 @@ bool TaskDlgSketchBasedParameters::accept() {
// Make sure the feature is what we are expecting
// Should be fine but you never know...
if ( !feature->getTypeId().isDerivedFrom(PartDesign::SketchBased::getClassTypeId()) ) {
if ( !feature->getTypeId().isDerivedFrom(PartDesign::ProfileBased::getClassTypeId()) ) {
throw Base::Exception("Bad object processed in the sketch based dialog.");
}
App::DocumentObject* sketch = static_cast<PartDesign::SketchBased*>(feature)->Sketch.getValue();
App::DocumentObject* sketch = static_cast<PartDesign::ProfileBased*>(feature)->Profile.getValue();
if (sketch) {
Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().hide(\"%s\")", sketch->getNameInDocument());
@ -225,9 +225,9 @@ bool TaskDlgSketchBasedParameters::accept() {
bool TaskDlgSketchBasedParameters::reject()
{
PartDesign::SketchBased* pcSketchBased = static_cast<PartDesign::SketchBased*>(vp->getObject());
PartDesign::ProfileBased* pcSketchBased = static_cast<PartDesign::ProfileBased*>(vp->getObject());
// get the Sketch
Sketcher::SketchObject *pcSketch = static_cast<Sketcher::SketchObject*>(pcSketchBased->Sketch.getValue());
Sketcher::SketchObject *pcSketch = static_cast<Sketcher::SketchObject*>(pcSketchBased->Profile.getValue());
bool rv;
// rv should be true anyway but to be on the safe side dur to thurver changes better respect it.

View File

@ -45,7 +45,7 @@ ViewProviderHole::~ViewProviderHole()
std::vector<App::DocumentObject*> ViewProviderHole::claimChildren(void)const
{
std::vector<App::DocumentObject*> temp;
temp.push_back(static_cast<PartDesign::Pad*>(getObject())->Sketch.getValue());
temp.push_back(static_cast<PartDesign::Pad*>(getObject())->Profile.getValue());
return temp;
}

View File

@ -55,7 +55,7 @@ ViewProviderLoft::~ViewProviderLoft()
std::vector<App::DocumentObject*> ViewProviderLoft::claimChildren(void)const
{
std::vector<App::DocumentObject*> temp;
App::DocumentObject* sketch = static_cast<PartDesign::Loft*>(getObject())->Sketch.getValue();
App::DocumentObject* sketch = static_cast<PartDesign::Loft*>(getObject())->Profile.getValue();
if (sketch != NULL)
temp.push_back(sketch);

View File

@ -55,7 +55,7 @@ ViewProviderPipe::~ViewProviderPipe()
std::vector<App::DocumentObject*> ViewProviderPipe::claimChildren(void)const
{
std::vector<App::DocumentObject*> temp;
App::DocumentObject* sketch = static_cast<PartDesign::Pipe*>(getObject())->Sketch.getValue();
App::DocumentObject* sketch = static_cast<PartDesign::Pipe*>(getObject())->Profile.getValue();
if (sketch != NULL)
temp.push_back(sketch);

View File

@ -50,8 +50,8 @@ ViewProviderSketchBased::~ViewProviderSketchBased()
std::vector<App::DocumentObject*> ViewProviderSketchBased::claimChildren(void) const {
std::vector<App::DocumentObject*> temp;
App::DocumentObject* sketch = static_cast<PartDesign::SketchBased*>(getObject())->Sketch.getValue();
if (sketch != NULL)
App::DocumentObject* sketch = static_cast<PartDesign::ProfileBased*>(getObject())->Profile.getValue();
if (sketch != NULL && sketch->isDerivedFrom(Part::Part2DObject::getClassTypeId()))
temp.push_back(sketch);
return temp;
@ -59,12 +59,12 @@ std::vector<App::DocumentObject*> ViewProviderSketchBased::claimChildren(void) c
bool ViewProviderSketchBased::onDelete(const std::vector<std::string> &s) {
PartDesign::SketchBased* feature = static_cast<PartDesign::SketchBased*>(getObject());
PartDesign::ProfileBased* feature = static_cast<PartDesign::ProfileBased*>(getObject());
// get the Sketch
Sketcher::SketchObject *pcSketch = 0;
if (feature->Sketch.getValue())
pcSketch = static_cast<Sketcher::SketchObject*>(feature->Sketch.getValue());
if (feature->Profile.getValue())
pcSketch = static_cast<Sketcher::SketchObject*>(feature->Profile.getValue());
// if abort command deleted the object the sketch is visible again
if (pcSketch && Gui::Application::Instance->getViewProvider(pcSketch))