PartDesign: transfer Datums to become AttachableObjects
Crude and quick, needs cleanup.
This commit is contained in:
parent
40592e6055
commit
9e440b955c
|
@ -67,16 +67,12 @@
|
|||
#endif
|
||||
|
||||
using namespace Part;
|
||||
using namespace Attacher;
|
||||
|
||||
PROPERTY_SOURCE_ABSTRACT(Part::Datum, Part::Feature)
|
||||
PROPERTY_SOURCE_ABSTRACT(Part::Datum, Part::AttachableObject)
|
||||
|
||||
Datum::Datum(void)
|
||||
{
|
||||
ADD_PROPERTY_TYPE(References,(0,0),"References",(App::PropertyType)(App::Prop_None),"References defining the datum feature");
|
||||
ADD_PROPERTY(Offset,(0.0));
|
||||
ADD_PROPERTY(Offset2,(0.0));
|
||||
ADD_PROPERTY(Offset3,(0.0));
|
||||
ADD_PROPERTY(Angle,(0.0));
|
||||
touch();
|
||||
}
|
||||
|
||||
|
@ -86,20 +82,19 @@ Datum::~Datum()
|
|||
|
||||
void Datum::onChanged (const App::Property* prop)
|
||||
{
|
||||
Part::Feature::onChanged(prop);
|
||||
AttachableObject::onChanged(prop);
|
||||
}
|
||||
|
||||
App::DocumentObjectExecReturn *Datum::execute(void)
|
||||
{
|
||||
References.touch();
|
||||
return StdReturn;
|
||||
return AttachableObject::execute();
|
||||
}
|
||||
|
||||
void Datum::onDocumentRestored()
|
||||
{
|
||||
// This seems to be the only way to make the ViewProvider display the datum feature
|
||||
References.touch();
|
||||
Part::Feature::onDocumentRestored();
|
||||
Support.touch();
|
||||
AttachableObject::onDocumentRestored();
|
||||
}
|
||||
|
||||
TopoDS_Shape Datum::getShape() const
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <App/PropertyLinks.h>
|
||||
|
||||
#include "PartFeature.h"
|
||||
#include "AttachableObject.h"
|
||||
|
||||
namespace Part
|
||||
{
|
||||
|
@ -35,7 +36,7 @@ namespace Part
|
|||
// This generic class is defined here so that the Sketcher module can access datum features
|
||||
// without creating a dependency on PartDesign
|
||||
|
||||
class PartExport Datum : public Part::Feature
|
||||
class PartExport Datum : public Part::AttachableObject
|
||||
{
|
||||
PROPERTY_HEADER(Part::Datum);
|
||||
|
||||
|
@ -44,35 +45,18 @@ public:
|
|||
virtual ~Datum();
|
||||
//short mustExecute();
|
||||
|
||||
/// The references defining the datum object, e.g. three planes for a point, two planes for a line
|
||||
App::PropertyLinkSubList References;
|
||||
/// Offsets and angle for defining planes
|
||||
App::PropertyFloat Offset;
|
||||
App::PropertyFloat Offset2;
|
||||
App::PropertyFloat Offset3;
|
||||
App::PropertyFloat Angle;
|
||||
|
||||
/// recalculate the feature
|
||||
App::DocumentObjectExecReturn *execute(void);
|
||||
|
||||
/// returns the type name of the view provider
|
||||
virtual const char* getViewProviderName(void) const = 0;
|
||||
|
||||
virtual const std::set<QString> getHint() const = 0;
|
||||
|
||||
/// Return the number of offset values that make sense for the current reference combination
|
||||
virtual const int offsetsAllowed() const = 0;
|
||||
|
||||
/// Return a shape including Placement representing the datum feature
|
||||
TopoDS_Shape getShape() const;
|
||||
|
||||
protected:
|
||||
void onChanged (const App::Property* prop);
|
||||
void onDocumentRestored();
|
||||
|
||||
protected:
|
||||
std::multiset<QString> refTypes;
|
||||
|
||||
};
|
||||
|
||||
} //namespace Part
|
||||
|
|
|
@ -140,8 +140,4 @@ PyMODINIT_FUNC init_PartDesign()
|
|||
PartDesign::AdditiveWedge ::init();
|
||||
PartDesign::SubtractiveWedge ::init();
|
||||
|
||||
PartDesign::Point ::initHints();
|
||||
PartDesign::Line ::initHints();
|
||||
PartDesign::Plane ::initHints();
|
||||
PartDesign::CoordinateSystem ::initHints();
|
||||
}
|
||||
|
|
|
@ -53,233 +53,21 @@
|
|||
|
||||
using namespace PartDesign;
|
||||
|
||||
// Note: We don't distinguish between e.g. datum lines and edges here
|
||||
#define PLANE QObject::tr("DPLANE")
|
||||
#define CYLINDER QObject::tr("DCYLINDER")
|
||||
#define LINE QObject::tr("DLINE")
|
||||
#define POINT QObject::tr("DPOINT")
|
||||
#define ANGLE QObject::tr("Angle")
|
||||
#define CS QObject::tr("DCOORDINATESYSTEM")
|
||||
#define DONE QObject::tr("Done")
|
||||
|
||||
std::map<std::multiset<QString>, std::set<QString> > CoordinateSystem::hints = std::map<std::multiset<QString>, std::set<QString> >();
|
||||
|
||||
void CoordinateSystem::initHints()
|
||||
{
|
||||
std::set<QString> Done;
|
||||
Done.insert(QObject::tr("Done"));
|
||||
|
||||
std::multiset<QString> key;
|
||||
std::set<QString> value;
|
||||
|
||||
//Point first ----------------------
|
||||
key.insert(POINT);
|
||||
value.insert(PLANE);
|
||||
value.insert(LINE);
|
||||
value.insert(POINT);
|
||||
value.insert(DONE);
|
||||
hints[key] = value;
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(POINT);
|
||||
key.insert(PLANE);
|
||||
value.insert(LINE);
|
||||
value.insert(POINT);
|
||||
value.insert(DONE);
|
||||
hints[key] = value;
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(POINT);
|
||||
key.insert(PLANE);
|
||||
key.insert(LINE);
|
||||
hints[key] = Done;
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(POINT);
|
||||
key.insert(PLANE);
|
||||
key.insert(POINT);
|
||||
hints[key] = Done;
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(POINT);
|
||||
key.insert(LINE);
|
||||
value.insert(PLANE);
|
||||
value.insert(LINE);
|
||||
value.insert(POINT);
|
||||
value.insert(DONE);
|
||||
hints[key] = value;
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(POINT);
|
||||
key.insert(LINE);
|
||||
key.insert(PLANE);
|
||||
hints[key] = Done;
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(POINT);
|
||||
key.insert(LINE);
|
||||
key.insert(LINE);
|
||||
hints[key] = Done;
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(POINT);
|
||||
key.insert(LINE);
|
||||
key.insert(POINT);
|
||||
hints[key] = Done;
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(POINT);
|
||||
key.insert(POINT);
|
||||
value.insert(PLANE);
|
||||
value.insert(LINE);
|
||||
value.insert(POINT);
|
||||
value.insert(DONE);
|
||||
hints[key] = value;
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(POINT);
|
||||
key.insert(POINT);
|
||||
key.insert(PLANE);
|
||||
hints[key] = Done;
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(POINT);
|
||||
key.insert(POINT);
|
||||
key.insert(LINE);
|
||||
hints[key] = Done;
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(POINT);
|
||||
key.insert(POINT);
|
||||
key.insert(POINT);
|
||||
hints[key] = Done;
|
||||
|
||||
//Plane First -------------------------
|
||||
key.clear(); value.clear();
|
||||
key.insert(PLANE);
|
||||
value.insert(LINE);
|
||||
value.insert(POINT);
|
||||
value.insert(DONE);
|
||||
hints[key] = value;
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(PLANE);
|
||||
key.insert(LINE);
|
||||
value.insert(POINT);
|
||||
value.insert(DONE);
|
||||
hints[key] = value;
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(PLANE);
|
||||
key.insert(LINE);
|
||||
key.insert(POINT);
|
||||
hints[key] = Done;
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(PLANE);
|
||||
key.insert(POINT);
|
||||
value.insert(LINE);
|
||||
value.insert(POINT);
|
||||
value.insert(DONE);
|
||||
hints[key] = value;
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(PLANE);
|
||||
key.insert(POINT);
|
||||
key.insert(LINE);
|
||||
hints[key] = Done;
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(PLANE);
|
||||
key.insert(POINT);
|
||||
key.insert(POINT);
|
||||
hints[key] = Done;
|
||||
|
||||
|
||||
//Line First -------------------------
|
||||
key.clear(); value.clear();
|
||||
key.insert(LINE);
|
||||
value.insert(PLANE);
|
||||
value.insert(LINE);
|
||||
value.insert(POINT);
|
||||
value.insert(DONE);
|
||||
hints[key] = value;
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(LINE);
|
||||
key.insert(PLANE);
|
||||
value.insert(POINT);
|
||||
value.insert(DONE);
|
||||
hints[key] = value;
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(LINE);
|
||||
key.insert(PLANE);
|
||||
key.insert(POINT);
|
||||
hints[key] = Done;
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(LINE);
|
||||
key.insert(LINE);
|
||||
value.insert(POINT);
|
||||
value.insert(DONE);
|
||||
hints[key] = value;
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(LINE);
|
||||
key.insert(LINE);
|
||||
key.insert(POINT);
|
||||
hints[key] = Done;
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(LINE);
|
||||
key.insert(POINT);
|
||||
value.insert(PLANE);
|
||||
value.insert(LINE);
|
||||
value.insert(POINT);
|
||||
value.insert(DONE);
|
||||
hints[key] = value;
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(LINE);
|
||||
key.insert(POINT);
|
||||
key.insert(PLANE);
|
||||
hints[key] = Done;
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(LINE);
|
||||
key.insert(POINT);
|
||||
key.insert(POINT);
|
||||
hints[key] = Done;
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(LINE);
|
||||
key.insert(PLANE);
|
||||
key.insert(POINT);
|
||||
hints[key] = Done;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
||||
#define GP_POINT(p) \
|
||||
gp_Pnt(p[0], p[1], p[2])
|
||||
|
||||
#define GP_DIR(p) \
|
||||
gp_Dir(p[0], p[1], p[2])
|
||||
|
||||
|
||||
PROPERTY_SOURCE(PartDesign::CoordinateSystem, Part::Datum)
|
||||
|
||||
CoordinateSystem::CoordinateSystem()
|
||||
{
|
||||
this->setAttacher(new AttachEngine3D);
|
||||
// Create a shape, which will be used by the Sketcher. Them main function is to avoid a dependency of
|
||||
// Sketcher on the PartDesign module
|
||||
BRepBuilderAPI_MakeFace builder(gp_Pln(gp_Pnt(0,0,0), gp_Dir(0,0,1)));
|
||||
if (!builder.IsDone())
|
||||
return;
|
||||
Shape.setValue(builder.Shape());
|
||||
|
||||
References.touch();
|
||||
}
|
||||
|
||||
CoordinateSystem::~CoordinateSystem()
|
||||
|
@ -288,304 +76,9 @@ CoordinateSystem::~CoordinateSystem()
|
|||
|
||||
void CoordinateSystem::onChanged(const App::Property *prop)
|
||||
{
|
||||
if ((prop == &References) || (prop == &Offset) || (prop == &Offset2) || (prop == &Offset3)) {
|
||||
|
||||
Base::Placement plm;
|
||||
const std::vector<App::DocumentObject*>& refs = References.getValues();
|
||||
const std::vector<std::string>& subrefs = References.getSubValues();
|
||||
|
||||
if (refs.size() != subrefs.size())
|
||||
throw Base::Exception("Size of references and subreferences do not match");
|
||||
|
||||
refTypes.clear();
|
||||
for (int r = 0; r < refs.size(); r++)
|
||||
refTypes.insert(getRefType(refs[r], subrefs[r]));
|
||||
|
||||
std::set<QString> hint = getHint();
|
||||
if (refs.size() != 0 && !(hint.find(QObject::tr("Done")) != hint.end()))
|
||||
throw Base::Exception("Can not build coordinate system from given references"); // incomplete references
|
||||
|
||||
//build the placement from the references
|
||||
bool plane = false, line1 = false, line2 = false, point1 = false, point2=false, point3=false;
|
||||
gp_Pln pln;
|
||||
gp_Lin lin1, lin2;
|
||||
gp_Pnt p1, p2, p3;
|
||||
|
||||
int count = 0;
|
||||
for(int i = 0; i < refs.size(); i++) {
|
||||
|
||||
if (refs[i]->getTypeId().isDerivedFrom(PartDesign::Point::getClassTypeId())) {
|
||||
PartDesign::Point* p = static_cast<PartDesign::Point*>(refs[i]);
|
||||
if(!point1) {
|
||||
p1 = GP_POINT(p->getPoint());
|
||||
point1=true;
|
||||
} else if(!point2) {
|
||||
p2 = GP_POINT(p->getPoint());
|
||||
point2=true;
|
||||
} else if(!point3) {
|
||||
p3 = GP_POINT(p->getPoint());
|
||||
point3=true;
|
||||
}
|
||||
else
|
||||
throw Base::Exception("Too many points in coordinate system references"); //too much points selected
|
||||
}
|
||||
else if (refs[i]->getTypeId().isDerivedFrom(PartDesign::Plane::getClassTypeId())) {
|
||||
PartDesign::Plane* p = static_cast<PartDesign::Plane*>(refs[i]);
|
||||
if(!plane) {
|
||||
pln = gp_Pln(GP_POINT(p->getBasePoint()), GP_DIR(p->getNormal()));
|
||||
plane=true;
|
||||
}
|
||||
else
|
||||
throw Base::Exception("Too many planes in coordinate syste references");
|
||||
} else if (refs[i]->getTypeId().isDerivedFrom(App::Plane::getClassTypeId())) {
|
||||
App::Plane* p = static_cast<App::Plane*>(refs[i]);
|
||||
if(!plane) {
|
||||
gp_Pnt base(0,0,0);
|
||||
gp_Dir dir(0,0,1);
|
||||
if (strcmp(p->PlaneType.getValue(), App::Part::BaseplaneTypes[0]) == 0)
|
||||
dir = gp_Dir(0,0,1);
|
||||
else if (strcmp(p->PlaneType.getValue(), App::Part::BaseplaneTypes[1]) == 0)
|
||||
dir = gp_Dir(0,1,0);
|
||||
else if (strcmp(p->PlaneType.getValue(), App::Part::BaseplaneTypes[2]) == 0)
|
||||
dir = gp_Dir(1,0,0);
|
||||
|
||||
pln = gp_Pln(base, dir);
|
||||
plane=true;
|
||||
}
|
||||
else
|
||||
throw Base::Exception("Too many planes in coordinate syste references"); //too much planes selected
|
||||
}
|
||||
else if (refs[i]->getTypeId().isDerivedFrom(PartDesign::Line::getClassTypeId())) {
|
||||
PartDesign::Line* p = static_cast<PartDesign::Line*>(refs[i]);
|
||||
if(!line1) {
|
||||
lin1 = gp_Lin(GP_POINT(p->getBasePoint()), GP_DIR(p->getDirection()));
|
||||
line1 = true;
|
||||
}
|
||||
else if(!line2) {
|
||||
lin2 = gp_Lin(GP_POINT(p->getBasePoint()), GP_DIR(p->getDirection()));
|
||||
line2 = true;
|
||||
}
|
||||
else
|
||||
throw Base::Exception("Too many lines in coordinate syste references");; //too much lines selected
|
||||
|
||||
} else if (refs[i]->getTypeId().isDerivedFrom(App::Line::getClassTypeId())) {
|
||||
App::Line* p = static_cast<App::Line*>(refs[i]);
|
||||
gp_Pnt base(0,0,0);
|
||||
gp_Dir dir(0,0,1);
|
||||
if (strcmp(p->LineType.getValue(), App::Part::BaselineTypes[0]) == 0)
|
||||
dir = gp_Dir(1,0,0);
|
||||
else if (strcmp(p->LineType.getValue(), App::Part::BaselineTypes[1]) == 0)
|
||||
dir = gp_Dir(0,1,0);
|
||||
else if (strcmp(p->LineType.getValue(), App::Part::BaselineTypes[2]) == 0)
|
||||
dir = gp_Dir(0,0,1);
|
||||
|
||||
if(!line1) {
|
||||
lin1 = gp_Lin(base, dir);
|
||||
line1=true;
|
||||
}
|
||||
else if(!line2) {
|
||||
lin2 = gp_Lin(base, dir);
|
||||
line2=true;
|
||||
}
|
||||
else
|
||||
throw Base::Exception("Too many lines in coordinate syste references");
|
||||
}
|
||||
else if (refs[i]->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
|
||||
Part::Feature* feature = static_cast<Part::Feature*>(refs[i]);
|
||||
const TopoDS_Shape& sh = feature->Shape.getValue();
|
||||
if (sh.IsNull())
|
||||
throw Base::Exception("Invalid shape in reference");
|
||||
// Get subshape
|
||||
TopoDS_Shape subshape = feature->Shape.getShape().getSubShape(subrefs[i].c_str());
|
||||
if (subshape.IsNull())
|
||||
throw Base::Exception("Reference has Null shape");
|
||||
|
||||
if (subshape.ShapeType() == TopAbs_VERTEX) {
|
||||
TopoDS_Vertex v = TopoDS::Vertex(subshape);
|
||||
|
||||
if(!point1) {
|
||||
p1 = BRep_Tool::Pnt(v);
|
||||
point1=true;
|
||||
} else if(!point2) {
|
||||
p2 = BRep_Tool::Pnt(v);
|
||||
point2=true;
|
||||
} else if(!point3) {
|
||||
p3 = BRep_Tool::Pnt(v);
|
||||
point3=true;
|
||||
}
|
||||
else
|
||||
throw Base::Exception("Too many points in coordinate system references");
|
||||
}
|
||||
else if (subshape.ShapeType() == TopAbs_EDGE) {
|
||||
TopoDS_Edge e = TopoDS::Edge(subshape);
|
||||
BRepAdaptor_Curve adapt(e);
|
||||
if (adapt.GetType() != GeomAbs_Line)
|
||||
throw Base::Exception("Only straight edges are supported");
|
||||
|
||||
if(!line1) {
|
||||
lin1 = adapt.Line();
|
||||
line1=true;
|
||||
}
|
||||
else if(!line2) {
|
||||
lin2 = adapt.Line();
|
||||
line2=true;
|
||||
}
|
||||
else
|
||||
throw Base::Exception("Too many lines in coordinate system references");
|
||||
|
||||
} else if (subshape.ShapeType() == TopAbs_FACE) {
|
||||
TopoDS_Face f = TopoDS::Face(subshape);
|
||||
BRepAdaptor_Surface adapt(f);
|
||||
if (adapt.GetType() == GeomAbs_Plane) {
|
||||
// Ensure that the front and back of the plane corresponds with the face's idea of front and back
|
||||
bool reverse = (f.Orientation() == TopAbs_REVERSED);
|
||||
gp_Pln pl = adapt.Plane();
|
||||
gp_Dir d = pl.Axis().Direction();
|
||||
const gp_Pnt& p = pl.Location();
|
||||
if (reverse) d.Reverse();
|
||||
|
||||
if(!plane) {
|
||||
pln = gp_Pln(p, d);
|
||||
plane = true;
|
||||
}
|
||||
else
|
||||
throw Base::Exception("Too many planes in coordinate system references");
|
||||
|
||||
} else {
|
||||
throw Base::Exception("Only planar faces allowed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
count++;
|
||||
};
|
||||
|
||||
gp_Ax3 ax;
|
||||
if(point1) {
|
||||
|
||||
if(plane) {
|
||||
if(!pln.Contains(p1, Precision::Confusion()))
|
||||
throw Base::Exception("Point must lie on plane");
|
||||
|
||||
if(point2) {
|
||||
if(!pln.Contains(p2, Precision::Confusion()))
|
||||
throw Base::Exception("Point must lie on plane");
|
||||
|
||||
if(p1.Distance(p2) < Precision::Confusion())
|
||||
throw Base::Exception("Point must not be coincident");
|
||||
|
||||
ax = gp_Ax3(p1, pln.Axis().Direction(), gp_Dir((p2.XYZ()-p1.XYZ())));
|
||||
}
|
||||
else if(line1) {
|
||||
if(!pln.Contains(lin1, Precision::Confusion(), Precision::Confusion()))
|
||||
throw Base::Exception("Line must lie on plane");
|
||||
|
||||
if(line2)
|
||||
throw Base::Exception("Two lines and a plain are not supportet");
|
||||
|
||||
ax = gp_Ax3(p1, pln.Axis().Direction(), lin1.Direction());
|
||||
}
|
||||
else {
|
||||
ax = gp_Ax3(p1, pln.Axis().Direction(), pln.XAxis().Direction());
|
||||
}
|
||||
}
|
||||
else if(line1) {
|
||||
|
||||
if(point2) {
|
||||
if(!gp_Lin(p1, lin1.Direction()).Contains(p2, Precision::Confusion()))
|
||||
throw Base::Exception("Second Point must not lie on z-axis");
|
||||
|
||||
if(p1.Distance(p2) < Precision::Confusion())
|
||||
throw Base::Exception("Points must not be coincident");
|
||||
|
||||
ax = gp_Ax3(p1, lin1.Direction(), gp_Dir((p2.XYZ()-p1.XYZ())));
|
||||
}
|
||||
else if(line2) {
|
||||
if(lin2.Angle(lin1)<Precision::Angular())
|
||||
return;
|
||||
|
||||
ax = gp_Ax3(p1, lin1.Direction(), lin2.Direction());
|
||||
}
|
||||
else
|
||||
ax = gp_Ax3(p1, lin1.Direction());
|
||||
}
|
||||
else if(point2) {
|
||||
|
||||
if(p1.Distance(p2) < Precision::Confusion())
|
||||
throw Base::Exception("Points must not be coincident");
|
||||
|
||||
if(point3) {
|
||||
if(p1.Distance(p3) < 2*Precision::Confusion())
|
||||
throw Base::Exception("Points must not be coincident");
|
||||
|
||||
ax = gp_Ax3(p1, gp_Dir((p2.XYZ()-p1.XYZ())), gp_Dir((p3.XYZ()-p2.XYZ())));
|
||||
}
|
||||
else {
|
||||
ax = gp_Ax3(p1, gp_Dir((p2.XYZ()-p1.XYZ())));
|
||||
}
|
||||
}
|
||||
else
|
||||
ax = gp_Ax3(p1, gp_Dir(0,0,1), gp_Dir(1,0,0));
|
||||
}
|
||||
else if(plane) {
|
||||
|
||||
if(line1) {
|
||||
if(!pln.Contains(lin1, Precision::Confusion(), Precision::Confusion()))
|
||||
throw Base::Exception("Line must lie on plane");
|
||||
|
||||
ax = gp_Ax3(pln.Location(), pln.Axis().Direction(), lin1.Direction());
|
||||
}
|
||||
else {
|
||||
ax = gp_Ax3(pln.Location(), pln.Axis().Direction(), pln.XAxis().Direction());
|
||||
}
|
||||
}
|
||||
else if(line1) {
|
||||
|
||||
if(line2) {
|
||||
if(! (fabs(lin1.Angle(lin2) - M_PI/2.0) < Precision::Angular()) )
|
||||
throw Base::Exception("Lines must be perpendicular");
|
||||
ax = gp_Ax3(lin1.Location(), lin1.Direction(), lin2.Direction());
|
||||
}
|
||||
else
|
||||
ax = gp_Ax3(lin1.Location(), lin1.Direction());
|
||||
}
|
||||
|
||||
//build the placement
|
||||
gp_Trsf trans;
|
||||
trans.SetTransformation(ax);
|
||||
trans.Invert();
|
||||
gp_XYZ p = trans.TranslationPart();
|
||||
gp_Quaternion q = trans.GetRotation();
|
||||
plm = Base::Placement(Base::Vector3d(p.X(), p.Y(), p.Z()), Base::Rotation(q.X(), q.Y(), q.Z(), q.W()));
|
||||
|
||||
//add the offsets
|
||||
Base::Vector3d o1;
|
||||
plm.getRotation().multVec(Base::Vector3d(1,0,0), o1);
|
||||
Base::Vector3d o2;
|
||||
plm.getRotation().multVec(Base::Vector3d(0,1,0), o2);
|
||||
Base::Vector3d o3;
|
||||
plm.getRotation().multVec(Base::Vector3d(0,0,1), o3);
|
||||
plm.move(Offset.getValue()*o1+Offset2.getValue()*o2+Offset3.getValue()*o3);
|
||||
|
||||
Placement.setValue(plm);
|
||||
}
|
||||
Part::Datum::onChanged(prop);
|
||||
}
|
||||
|
||||
|
||||
const std::set<QString> CoordinateSystem::getHint() const
|
||||
{
|
||||
if (hints.find(refTypes) != hints.end())
|
||||
return hints[refTypes];
|
||||
else
|
||||
return std::set<QString>();
|
||||
}
|
||||
|
||||
const int CoordinateSystem::offsetsAllowed() const
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
Base::Vector3d CoordinateSystem::getXAxis()
|
||||
{
|
||||
Base::Rotation rot = Placement.getValue().getRotation();
|
||||
|
|
|
@ -43,10 +43,6 @@ public:
|
|||
return "PartDesignGui::ViewProviderDatumCoordinateSystem";
|
||||
}
|
||||
|
||||
static void initHints();
|
||||
const std::set<QString> getHint() const;
|
||||
const int offsetsAllowed() const;
|
||||
|
||||
Base::Vector3d getXAxis();
|
||||
Base::Vector3d getYAxis();
|
||||
Base::Vector3d getZAxis();
|
||||
|
@ -54,9 +50,6 @@ public:
|
|||
protected:
|
||||
virtual void onChanged(const App::Property* prop);
|
||||
|
||||
private:
|
||||
// Hints on what further references are required/possible on this feature for a given set of references
|
||||
static std::map<std::multiset<QString>, std::set<QString> > hints;
|
||||
};
|
||||
|
||||
} //namespace PartDesign
|
||||
|
|
|
@ -70,74 +70,19 @@
|
|||
#include <Base/Tools.h>
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Exception.h>
|
||||
#include "Mod/Part/App/PrimitiveFeature.h"
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
using namespace PartDesign;
|
||||
|
||||
// Note: We don't distinguish between e.g. datum lines and edges here
|
||||
#define PLANE QObject::tr("DPLANE")
|
||||
#define LINE QObject::tr("DLINE")
|
||||
#define CIRCLE QObject::tr("DCIRCLE")
|
||||
#define POINT QObject::tr("DPOINT")
|
||||
#define ANGLE QObject::tr("Angle")
|
||||
|
||||
std::map<std::multiset<QString>, std::set<QString> > Line::hints = std::map<std::multiset<QString>, std::set<QString> >();
|
||||
|
||||
void Line::initHints()
|
||||
{
|
||||
std::set<QString> DONE;
|
||||
DONE.insert(QObject::tr("Done"));
|
||||
|
||||
std::multiset<QString> key;
|
||||
std::set<QString> value;
|
||||
key.insert(LINE);
|
||||
hints[key] = DONE; // LINE -> DONE. Line from another line or edge
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(CIRCLE);
|
||||
hints[key] = DONE; // CIRCLE -> DONE. Line from center of circle or arc or axis of cylinder or cylinder segment
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(POINT);
|
||||
value.insert(POINT);
|
||||
hints[key] = value; // POINT -> POINT
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(POINT); key.insert(POINT);
|
||||
hints[key] = DONE; // {POINT, POINT} -> DONE. Line from two points or vertices
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(PLANE);
|
||||
value.insert(PLANE);
|
||||
value.insert(LINE);
|
||||
hints[key] = value; // PLANE -> LINE or PLANE
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(PLANE); key.insert(PLANE);
|
||||
hints[key] = DONE; // {PLANE, PLANE} -> DONE. Line from two planes or faces
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(PLANE); key.insert(LINE);
|
||||
value.insert(LINE);
|
||||
hints[key] = value; // {PLANE, LINE} -> LINE
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(PLANE); key.insert(LINE); key.insert(LINE);
|
||||
hints[key] = DONE; // {PLANE, LINE, LINE} -> DONE. Line from plane with distance (default zero) to two lines
|
||||
|
||||
key.clear(); value.clear();
|
||||
value.insert(POINT); value.insert(LINE); value.insert(PLANE);
|
||||
hints[key] = value;
|
||||
}
|
||||
using namespace Attacher;
|
||||
|
||||
PROPERTY_SOURCE(PartDesign::Line, Part::Datum)
|
||||
|
||||
Line::Line()
|
||||
{
|
||||
this->setAttacher(new AttachEngineLine);
|
||||
// Create a shape, which will be used by the Sketcher. Them main function is to avoid a dependency of
|
||||
// Sketcher on the PartDesign module
|
||||
BRepBuilderAPI_MakeEdge builder(gp_Lin(gp_Pnt(0,0,0), gp_Dir(0,0,1)));
|
||||
|
@ -145,7 +90,7 @@ Line::Line()
|
|||
return;
|
||||
Shape.setValue(builder.Shape());
|
||||
|
||||
References.touch();
|
||||
Support.touch();
|
||||
}
|
||||
|
||||
Line::~Line()
|
||||
|
@ -154,274 +99,9 @@ Line::~Line()
|
|||
|
||||
void Line::onChanged(const App::Property *prop)
|
||||
{
|
||||
if ((prop == &References) || (prop == &Offset) || (prop == &Offset2)) {
|
||||
refTypes.clear();
|
||||
std::vector<App::DocumentObject*> refs = References.getValues();
|
||||
std::vector<std::string> refnames = References.getSubValues();
|
||||
if (refs.size() != refnames.size())
|
||||
throw Base::Exception("Reference Missmatch");
|
||||
|
||||
for (int r = 0; r < refs.size(); r++)
|
||||
refTypes.insert(getRefType(refs[r], refnames[r]));
|
||||
|
||||
std::set<QString> hint = getHint();
|
||||
if (!((hint.size() == 1) && (hint.find(QObject::tr("Done")) != hint.end())))
|
||||
return; // incomplete references
|
||||
|
||||
// Extract the geometry of the references
|
||||
Base::Vector3d* base = NULL;
|
||||
Base::Vector3d* direction = NULL;
|
||||
Base::Vector3d* p1 = NULL;
|
||||
Base::Vector3d* p2 = NULL;
|
||||
gp_Lin* line = NULL;
|
||||
gp_Circ* circle = NULL;
|
||||
Handle_Geom_Surface s1 = NULL;
|
||||
Handle_Geom_Surface s2 = NULL;
|
||||
Handle_Geom_Surface s3 = NULL;
|
||||
|
||||
for (int i = 0; i < refs.size(); i++) {
|
||||
if (refs[i]->getTypeId().isDerivedFrom(PartDesign::Point::getClassTypeId())) {
|
||||
PartDesign::Point* p = static_cast<PartDesign::Point*>(refs[i]);
|
||||
if (p1 == NULL)
|
||||
p1 = new Base::Vector3d (p->getPoint());
|
||||
else
|
||||
p2 = new Base::Vector3d (p->getPoint());
|
||||
} else if (refs[i]->getTypeId().isDerivedFrom(PartDesign::Line::getClassTypeId())) {
|
||||
PartDesign::Line* l = static_cast<PartDesign::Line*>(refs[i]);
|
||||
if (s1.IsNull()) {
|
||||
base = new Base::Vector3d (l->getBasePoint());
|
||||
direction = new Base::Vector3d (l->getDirection());
|
||||
} else {
|
||||
// Create plane through line normal to s1
|
||||
Handle_Geom_Plane pl = Handle_Geom_Plane::DownCast(s1);
|
||||
if (pl.IsNull())
|
||||
return; // Non-planar first surface
|
||||
gp_Dir ldir = gp_Dir(l->getDirection().x, l->getDirection().y, l->getDirection().z);
|
||||
gp_Dir normal = ldir.Crossed(pl->Axis().Direction());
|
||||
double offset1 = Offset.getValue();
|
||||
double offset2 = Offset2.getValue();
|
||||
gp_Pnt base = gp_Pnt(l->getBasePoint().x, l->getBasePoint().y, l->getBasePoint().z);
|
||||
if (s2.IsNull()) {
|
||||
base.Translate(offset1 * normal);
|
||||
s2 = new Geom_Plane(base, normal);
|
||||
} else {
|
||||
base.Translate(offset2 * normal);
|
||||
s3 = new Geom_Plane(base, normal);
|
||||
}
|
||||
}
|
||||
} else if (refs[i]->getTypeId().isDerivedFrom(App::Line::getClassTypeId())) {
|
||||
App::Line* l = static_cast<App::Line*>(refs[i]);
|
||||
gp_Dir ldir;
|
||||
if (strcmp(l->LineType.getValue(), App::Part::BaselineTypes[0]) == 0)
|
||||
ldir = gp_Dir(1,0,0);
|
||||
else if (strcmp(l->LineType.getValue(), App::Part::BaselineTypes[1]) == 0)
|
||||
ldir = gp_Dir(0,1,0);
|
||||
else if (strcmp(l->LineType.getValue(), App::Part::BaselineTypes[2]) == 0)
|
||||
ldir = gp_Dir(0,0,1);
|
||||
|
||||
if (s1.IsNull()) {
|
||||
base = new Base::Vector3d (0,0,0);
|
||||
direction = new Base::Vector3d (ldir.X(), ldir.Y(), ldir.Z());
|
||||
} else {
|
||||
// Create plane through line normal to s1
|
||||
Handle_Geom_Plane pl = Handle_Geom_Plane::DownCast(s1);
|
||||
if (pl.IsNull())
|
||||
throw Base::Exception("Non-planar first surface"); // Non-planar first surface
|
||||
gp_Dir normal = ldir.Crossed(pl->Axis().Direction());
|
||||
double offset1 = Offset.getValue();
|
||||
double offset2 = Offset2.getValue();
|
||||
gp_Pnt base = gp_Pnt(0,0,0);
|
||||
if (s2.IsNull()) {
|
||||
base.Translate(offset1 * normal);
|
||||
s2 = new Geom_Plane(base, normal);
|
||||
} else {
|
||||
base.Translate(offset2 * normal);
|
||||
s3 = new Geom_Plane(base, normal);
|
||||
}
|
||||
}
|
||||
|
||||
}else if (refs[i]->getTypeId().isDerivedFrom(PartDesign::Plane::getClassTypeId())) {
|
||||
PartDesign::Plane* p = static_cast<PartDesign::Plane*>(refs[i]);
|
||||
Base::Vector3d base = p->getBasePoint();
|
||||
Base::Vector3d normal = p->getNormal();
|
||||
double offset1 = Offset.getValue();
|
||||
double offset2 = Offset2.getValue();
|
||||
|
||||
if (s1.IsNull()) {
|
||||
base += normal * offset1;
|
||||
s1 = new Geom_Plane(gp_Pnt(base.x, base.y, base.z), gp_Dir(normal.x, normal.y, normal.z));
|
||||
} else {
|
||||
base += normal * offset2;
|
||||
s2 = new Geom_Plane(gp_Pnt(base.x, base.y, base.z), gp_Dir(normal.x, normal.y, normal.z));
|
||||
}
|
||||
} else if (refs[i]->getTypeId().isDerivedFrom(App::Plane::getClassTypeId())) {
|
||||
App::Plane* p = static_cast<App::Plane*>(refs[i]);
|
||||
// Note: We only handle the three base planes here
|
||||
gp_Pnt base(0,0,0);
|
||||
gp_Dir normal;
|
||||
if (strcmp(p->PlaneType.getValue(), App::Part::BaseplaneTypes[0]) == 0)
|
||||
normal = gp_Dir(0,0,1);
|
||||
else if (strcmp(p->PlaneType.getValue(), App::Part::BaseplaneTypes[2]) == 0)
|
||||
normal = gp_Dir(1,0,0);
|
||||
else if (strcmp(p->PlaneType.getValue(), App::Part::BaseplaneTypes[1]) == 0)
|
||||
normal = gp_Dir(0,1,0);
|
||||
|
||||
double offset1 = Offset.getValue();
|
||||
double offset2 = Offset2.getValue();
|
||||
|
||||
if (s1.IsNull()) {
|
||||
base = gp_Pnt(normal.X() * offset1, normal.Y() * offset1, normal.Z() * offset1);
|
||||
s1 = new Geom_Plane(base, normal);
|
||||
} else {
|
||||
base = gp_Pnt(normal.X() * offset2, normal.Y() * offset2, normal.Z() * offset2);
|
||||
s2 = new Geom_Plane(base, normal);
|
||||
}
|
||||
} else if (refs[i]->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
|
||||
Part::Feature* feature = static_cast<Part::Feature*>(refs[i]);
|
||||
const TopoDS_Shape& sh = feature->Shape.getValue();
|
||||
if (sh.IsNull())
|
||||
return; // "PartDesign::Line: Reference has NULL shape"
|
||||
// Get subshape
|
||||
TopoDS_Shape subshape = feature->Shape.getShape().getSubShape(refnames[i].c_str());
|
||||
if (subshape.IsNull())
|
||||
return; // "PartDesign::Line: Reference has NULL subshape";
|
||||
|
||||
if (subshape.ShapeType() == TopAbs_VERTEX) {
|
||||
TopoDS_Vertex v = TopoDS::Vertex(subshape);
|
||||
gp_Pnt p = BRep_Tool::Pnt(v);
|
||||
if (p1 == NULL)
|
||||
p1 = new Base::Vector3d(p.X(), p.Y(), p.Z());
|
||||
else
|
||||
p2 = new Base::Vector3d(p.X(), p.Y(), p.Z());
|
||||
} else if (subshape.ShapeType() == TopAbs_EDGE) {
|
||||
TopoDS_Edge e = TopoDS::Edge(subshape);
|
||||
BRepAdaptor_Curve adapt(e);
|
||||
if (adapt.GetType() == GeomAbs_Circle) {
|
||||
circle = new gp_Circ(adapt.Circle());
|
||||
} else if (adapt.GetType() == GeomAbs_Line) {
|
||||
if (s1.IsNull()) {
|
||||
line = new gp_Lin(adapt.Line());
|
||||
} else {
|
||||
// Create plane through line normal to s1
|
||||
Handle_Geom_Plane pl = Handle_Geom_Plane::DownCast(s1);
|
||||
if (pl.IsNull())
|
||||
return; // Non-planar first surface
|
||||
gp_Dir normal = adapt.Line().Direction().Crossed(pl->Axis().Direction());
|
||||
double offset1 = Offset.getValue();
|
||||
double offset2 = Offset2.getValue();
|
||||
gp_Pnt base = adapt.Line().Location();
|
||||
if (s2.IsNull()) {
|
||||
base.Translate(offset1 * normal);
|
||||
s2 = new Geom_Plane(base, normal);
|
||||
} else {
|
||||
base.Translate(offset2 * normal);
|
||||
s3 = new Geom_Plane(base, normal);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return; // Non-linear edge
|
||||
}
|
||||
} else if (subshape.ShapeType() == TopAbs_FACE) {
|
||||
TopoDS_Face f = TopoDS::Face(subshape);
|
||||
double offset1 = Offset.getValue();
|
||||
double offset2 = Offset2.getValue();
|
||||
BRepAdaptor_Surface adapt(f);
|
||||
|
||||
if (s1.IsNull()) {
|
||||
if (adapt.GetType() == GeomAbs_Cylinder) {
|
||||
circle = new gp_Circ(gp_Ax2(adapt.Cylinder().Location(), adapt.Cylinder().Axis().Direction()),
|
||||
adapt.Cylinder().Radius());
|
||||
} else if (adapt.GetType() == GeomAbs_Plane) {
|
||||
gp_Trsf mov;
|
||||
mov.SetTranslation(offset1 * gp_Vec(adapt.Plane().Axis().Direction()));
|
||||
TopLoc_Location loc(mov);
|
||||
f.Move(loc);
|
||||
}
|
||||
s1 = BRep_Tool::Surface(f);
|
||||
} else {
|
||||
if (adapt.GetType() == GeomAbs_Plane) {
|
||||
gp_Trsf mov;
|
||||
mov.SetTranslation(offset2 * gp_Vec(adapt.Plane().Axis().Direction()));
|
||||
TopLoc_Location loc(mov);
|
||||
f.Move(loc);
|
||||
}
|
||||
s2 = BRep_Tool::Surface(f);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return; //"PartDesign::Point: Invalid reference type"
|
||||
}
|
||||
}
|
||||
|
||||
if ((base != NULL) && (direction != NULL)) {
|
||||
// Line from other datum line. Nothing to be done
|
||||
} else if ((p1 != NULL) && (p2 != NULL)) {
|
||||
// Line from two points
|
||||
base = new Base::Vector3d(*p1);
|
||||
direction = new Base::Vector3d(*p2 - *p1);
|
||||
} else if (line != NULL) {
|
||||
// Line from gp_lin
|
||||
base = new Base::Vector3d(line->Location().X(), line->Location().Y(), line->Location().Z());
|
||||
direction = new Base::Vector3d(line->Direction().X(), line->Direction().Y(), line->Direction().Z());
|
||||
} else if (circle != NULL) {
|
||||
// Line from center of circle or cylinder
|
||||
gp_Pnt centre = circle->Axis().Location();
|
||||
base = new Base::Vector3d(centre.X(), centre.Y(), centre.Z());
|
||||
gp_Dir dir = circle->Axis().Direction();
|
||||
direction = new Base::Vector3d(dir.X(), dir.Y(), dir.Z());
|
||||
} else if (!s1.IsNull() && !s2.IsNull()) {
|
||||
if (!s3.IsNull())
|
||||
s1 = s3; // Line from a plane and two lines/edges
|
||||
// Line from two surfaces
|
||||
GeomAPI_IntSS intersectorSS(s1, s2, Precision::Confusion());
|
||||
if (!intersectorSS.IsDone() || (intersectorSS.NbLines() == 0))
|
||||
throw Base::Exception("Intersection of surfaces failed");
|
||||
if (intersectorSS.NbLines() > 1)
|
||||
Base::Console().Warning("More than one intersection curve for datum line from surfaces\n");
|
||||
Handle_Geom_Line l = Handle_Geom_Line::DownCast(intersectorSS.Line(1));
|
||||
if (l.IsNull())
|
||||
return; // non-linear intersection curve
|
||||
gp_Lin lin = l->Lin();
|
||||
base = new Base::Vector3d(lin.Location().X(), lin.Location().Y(), lin.Location().Z());
|
||||
direction = new Base::Vector3d(lin.Direction().X(), lin.Direction().Y(), lin.Direction().Z());
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
Placement.setValue(Base::Placement(*base, Base::Rotation(Base::Vector3d(0,0,1), *direction)));
|
||||
|
||||
delete base;
|
||||
delete direction;
|
||||
if (p1 != NULL) delete p1;
|
||||
if (p2 != NULL) delete p2;
|
||||
if (line != NULL) delete line;
|
||||
if (circle != NULL) delete circle;
|
||||
}
|
||||
|
||||
Part::Datum::onChanged(prop);
|
||||
}
|
||||
|
||||
const std::set<QString> Line::getHint() const
|
||||
{
|
||||
if (hints.find(refTypes) != hints.end())
|
||||
return hints[refTypes];
|
||||
else
|
||||
return std::set<QString>();
|
||||
}
|
||||
|
||||
const int Line::offsetsAllowed() const
|
||||
{
|
||||
int planes = 0;
|
||||
int lines = 0;
|
||||
for (std::multiset<QString>::const_iterator r = refTypes.begin(); r != refTypes.end(); r++) {
|
||||
if (*r == PLANE) planes++;
|
||||
if (*r == LINE) lines++;
|
||||
}
|
||||
if (lines == 0) return planes;
|
||||
if ((planes == 1) && (lines == 2)) return 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Base::Vector3d Line::getBasePoint() const
|
||||
{
|
||||
return Placement.getValue().getPosition();
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <App/PropertyLinks.h>
|
||||
#include <App/GeoFeature.h>
|
||||
#include <Mod/Part/App/DatumFeature.h>
|
||||
#include <Mod/Part/App/AttachableObject.h>
|
||||
|
||||
namespace PartDesign
|
||||
{
|
||||
|
@ -44,19 +45,12 @@ public:
|
|||
return "PartDesignGui::ViewProviderDatumLine";
|
||||
}
|
||||
|
||||
static void initHints();
|
||||
const std::set<QString> getHint() const;
|
||||
const int offsetsAllowed() const;
|
||||
|
||||
Base::Vector3d getBasePoint() const;
|
||||
Base::Vector3d getDirection() const;
|
||||
|
||||
protected:
|
||||
virtual void onChanged(const App::Property* prop);
|
||||
|
||||
private:
|
||||
// Hints on what further references are required/possible on this feature for a given set of references
|
||||
static std::map<std::multiset<QString>, std::set<QString> > hints;
|
||||
};
|
||||
|
||||
} //namespace PartDesign
|
||||
|
|
|
@ -68,88 +68,13 @@
|
|||
#include <Base/Tools.h>
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Exception.h>
|
||||
#include "Mod/Part/App/PrimitiveFeature.h"
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
using namespace PartDesign;
|
||||
|
||||
// Note: We don't distinguish between e.g. datum lines and edges here
|
||||
#define PLANE QObject::tr("DPLANE")
|
||||
#define CYLINDER QObject::tr("DCYLINDER")
|
||||
#define LINE QObject::tr("DLINE")
|
||||
#define POINT QObject::tr("DPOINT")
|
||||
#define ANGLE QObject::tr("Angle")
|
||||
|
||||
std::map<std::multiset<QString>, std::set<QString> > Plane::hints = std::map<std::multiset<QString>, std::set<QString> >();
|
||||
|
||||
void Plane::initHints()
|
||||
{
|
||||
std::set<QString> DONE;
|
||||
DONE.insert(QObject::tr("Done"));
|
||||
|
||||
std::multiset<QString> key;
|
||||
std::set<QString> value;
|
||||
key.insert(PLANE);
|
||||
hints[key] = DONE; // PLANE -> DONE. Plane from another plane or face
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(POINT);
|
||||
value.insert(POINT); value.insert(LINE);
|
||||
hints[key] = value; // POINT -> POINT or LINE
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(POINT); key.insert(LINE);
|
||||
hints[key] = DONE; // {POINT, LINE} -> DONE. Plane from point/vertex and line/edge
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(POINT); key.insert(POINT);
|
||||
value.insert(POINT);
|
||||
hints[key] = value; // {POINT, POINT} -> POINT
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(POINT); key.insert(POINT); key.insert(POINT);
|
||||
hints[key] = DONE; // {POINT, POINT, POINT} -> DONE. Plane from 3 points or vertices
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(LINE);
|
||||
value.insert(POINT); value.insert(PLANE); value.insert(ANGLE);
|
||||
hints[key] = value; // LINE -> POINT or PLANE or ANGLE
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(PLANE); key.insert(LINE);
|
||||
value.insert(ANGLE);
|
||||
hints[key] = value; // {PLANE, LINE} -> ANGLE
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(PLANE); key.insert(ANGLE);
|
||||
value.insert(LINE);
|
||||
hints[key] = value; // {PLANE, ANGLE} -> LINE
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(ANGLE); key.insert(LINE);
|
||||
value.insert(PLANE);
|
||||
hints[key] = value; // {ANGLE, LINE} -> PLANE
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(LINE); key.insert(PLANE); key.insert(ANGLE);
|
||||
hints[key] = DONE; // {LINE, PLANE, ANGLE} -> DONE. Plane through line with angle to other plane
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(CYLINDER);
|
||||
value.insert(PLANE);
|
||||
hints[key] = value; // CYLINDER -> PLANE
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(CYLINDER); key.insert(PLANE);
|
||||
hints[key] = DONE; // {CYLINDER, PLANE} -> DONE. Plane tangential to cylinder and normal to other plane
|
||||
|
||||
key.clear(); value.clear();
|
||||
value.insert(POINT); value.insert(LINE); value.insert(PLANE); value.insert(ANGLE);
|
||||
hints[key] = value;
|
||||
}
|
||||
using namespace Attacher;
|
||||
|
||||
// ============================================================================
|
||||
|
||||
|
@ -157,6 +82,7 @@ PROPERTY_SOURCE(PartDesign::Plane, Part::Datum)
|
|||
|
||||
Plane::Plane()
|
||||
{
|
||||
this->setAttacher(new AttachEngine3D);
|
||||
// Create a shape, which will be used by the Sketcher. Them main function is to avoid a dependency of
|
||||
// Sketcher on the PartDesign module
|
||||
BRepBuilderAPI_MakeFace builder(gp_Pln(gp_Pnt(0,0,0), gp_Dir(0,0,1)));
|
||||
|
@ -164,7 +90,6 @@ Plane::Plane()
|
|||
return;
|
||||
Shape.setValue(builder.Shape());
|
||||
|
||||
References.touch();
|
||||
}
|
||||
|
||||
Plane::~Plane()
|
||||
|
@ -173,217 +98,9 @@ Plane::~Plane()
|
|||
|
||||
void Plane::onChanged(const App::Property *prop)
|
||||
{
|
||||
if (prop == &Angle) {
|
||||
// Zero value counts as angle not defined
|
||||
if (fabs(Angle.getValue()) > Precision::Confusion())
|
||||
refTypes.insert(ANGLE);
|
||||
else
|
||||
refTypes.erase(ANGLE);
|
||||
}
|
||||
|
||||
if ((prop == &References) || (prop == &Offset)) {
|
||||
refTypes.clear();
|
||||
std::vector<App::DocumentObject*> refs = References.getValues();
|
||||
std::vector<std::string> refnames = References.getSubValues();
|
||||
|
||||
for (int r = 0; r < refs.size(); r++) {
|
||||
const Part::Feature* ref = static_cast<const Part::Feature*>(refs[r]);
|
||||
if ((ref != NULL) && ref->Shape.getValue().IsNull())
|
||||
continue; // This can happen while a document is being restored from a file
|
||||
refTypes.insert(getRefType(refs[r], refnames[r]));
|
||||
}
|
||||
|
||||
if (fabs(Angle.getValue()) > Precision::Confusion())
|
||||
refTypes.insert(ANGLE);
|
||||
|
||||
std::set<QString> hint = getHint();
|
||||
if (!((hint.size() == 1) && (hint.find(QObject::tr("Done")) != hint.end())))
|
||||
return; // incomplete references
|
||||
|
||||
// Extract the geometry of the references
|
||||
Base::Vector3d* p1 = NULL;
|
||||
Base::Vector3d* p2 = NULL;
|
||||
Base::Vector3d* p3 = NULL;
|
||||
Base::Vector3d* normal = NULL;
|
||||
gp_Lin* line = NULL;
|
||||
gp_Cylinder* cyl = NULL;
|
||||
|
||||
for (int i = 0; i < refs.size(); i++) {
|
||||
if (refs[i]->getTypeId().isDerivedFrom(PartDesign::Point::getClassTypeId())) {
|
||||
PartDesign::Point* p = static_cast<PartDesign::Point*>(refs[i]);
|
||||
if (p1 == NULL)
|
||||
p1 = new Base::Vector3d (p->getPoint());
|
||||
else if (p2 == NULL)
|
||||
p2 = new Base::Vector3d (p->getPoint());
|
||||
else
|
||||
p3 = new Base::Vector3d (p->getPoint());
|
||||
} else if (refs[i]->getTypeId().isDerivedFrom(PartDesign::Line::getClassTypeId())) {
|
||||
PartDesign::Line* l = static_cast<PartDesign::Line*>(refs[i]);
|
||||
Base::Vector3d base = l->getBasePoint();
|
||||
Base::Vector3d dir = l->getDirection();
|
||||
line = new gp_Lin(gp_Pnt(base.x, base.y, base.z), gp_Dir(dir.x, dir.y, dir.z));
|
||||
} else if (refs[i]->getTypeId().isDerivedFrom(App::Line::getClassTypeId())) {
|
||||
App::Line* l = static_cast<App::Line*>(refs[i]);
|
||||
Base::Vector3d base = Base::Vector3d(0,0,0);
|
||||
gp_Dir dir;
|
||||
if (strcmp(l->LineType.getValue(), App::Part::BaselineTypes[0]) == 0)
|
||||
dir = gp_Dir(1,0,0);
|
||||
else if (strcmp(l->LineType.getValue(), App::Part::BaselineTypes[1]) == 0)
|
||||
dir = gp_Dir(0,1,0);
|
||||
else if (strcmp(l->LineType.getValue(), App::Part::BaselineTypes[2]) == 0)
|
||||
dir = gp_Dir(0,0,1);
|
||||
line = new gp_Lin(gp_Pnt(base.x, base.y, base.z), gp_Dir(dir.X(), dir.Y(), dir.Z()));
|
||||
} else if (refs[i]->getTypeId().isDerivedFrom(PartDesign::Plane::getClassTypeId())) {
|
||||
PartDesign::Plane* p = static_cast<PartDesign::Plane*>(refs[i]);
|
||||
p1 = new Base::Vector3d(p->getBasePoint());
|
||||
normal = new Base::Vector3d(p->getNormal());
|
||||
} else if (refs[i]->getTypeId().isDerivedFrom(App::Plane::getClassTypeId())) {
|
||||
App::Plane* p = static_cast<App::Plane*>(refs[i]);
|
||||
// Note: We only handle the three base planes here
|
||||
p1 = new Base::Vector3d(0,0,0);
|
||||
normal = new Base::Vector3d;
|
||||
if (strcmp(p->PlaneType.getValue(), App::Part::BaseplaneTypes[0]) == 0)
|
||||
*normal = Base::Vector3d(0,0,1);
|
||||
else if (strcmp(p->PlaneType.getValue(), App::Part::BaseplaneTypes[1]) == 0)
|
||||
*normal = Base::Vector3d(0,1,0);
|
||||
else if (strcmp(p->PlaneType.getValue(), App::Part::BaseplaneTypes[2]) == 0)
|
||||
*normal = Base::Vector3d(1,0,0);
|
||||
} else if (refs[i]->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
|
||||
Part::Feature* feature = static_cast<Part::Feature*>(refs[i]);
|
||||
const TopoDS_Shape& sh = feature->Shape.getValue();
|
||||
if (sh.IsNull())
|
||||
return; // "PartDesign::Plane: Reference has NULL shape"
|
||||
// Get subshape
|
||||
TopoDS_Shape subshape = feature->Shape.getShape().getSubShape(refnames[i].c_str());
|
||||
if (subshape.IsNull())
|
||||
return; // "PartDesign::Plane: Reference has NULL subshape";
|
||||
|
||||
if (subshape.ShapeType() == TopAbs_VERTEX) {
|
||||
TopoDS_Vertex v = TopoDS::Vertex(subshape);
|
||||
gp_Pnt p = BRep_Tool::Pnt(v);
|
||||
if (p1 == NULL)
|
||||
p1 = new Base::Vector3d(p.X(), p.Y(), p.Z());
|
||||
else if (p2 == NULL)
|
||||
p2 = new Base::Vector3d(p.X(), p.Y(), p.Z());
|
||||
else
|
||||
p3 = new Base::Vector3d(p.X(), p.Y(), p.Z());
|
||||
} else if (subshape.ShapeType() == TopAbs_EDGE) {
|
||||
TopoDS_Edge e = TopoDS::Edge(subshape);
|
||||
BRepAdaptor_Curve adapt(e);
|
||||
if (adapt.GetType() != GeomAbs_Line)
|
||||
return; // Non-linear edge
|
||||
line = new gp_Lin(adapt.Line());
|
||||
} else if (subshape.ShapeType() == TopAbs_FACE) {
|
||||
TopoDS_Face f = TopoDS::Face(subshape);
|
||||
BRepAdaptor_Surface adapt(f);
|
||||
if (adapt.GetType() == GeomAbs_Plane) {
|
||||
// Ensure that the front and back of the plane corresponds with the face's idea of front and back
|
||||
bool reverse = (f.Orientation() == TopAbs_REVERSED);
|
||||
gp_Pln plane = adapt.Plane();
|
||||
if (!plane.Direct()) {
|
||||
// toggle if plane has a left-handed coordinate system
|
||||
plane.UReverse();
|
||||
reverse = !reverse;
|
||||
}
|
||||
gp_Dir d = adapt.Plane().Axis().Direction();
|
||||
if (reverse) d.Reverse();
|
||||
|
||||
// Ensure that the position of the placement corresponds to what the face would yield in
|
||||
// Part2DObject::positionBySupport()
|
||||
Base::Vector3d pos = feature->Placement.getValue().getPosition();
|
||||
gp_Pnt gp_pos(pos.x,pos.y,pos.z);
|
||||
Handle (Geom_Plane) gPlane = new Geom_Plane(plane);
|
||||
GeomAPI_ProjectPointOnSurf projector(gp_pos,gPlane);
|
||||
gp_Pnt b = projector.NearestPoint();
|
||||
|
||||
p1 = new Base::Vector3d(b.X(), b.Y(), b.Z());
|
||||
normal = new Base::Vector3d(d.X(), d.Y(), d.Z());
|
||||
} else if (adapt.GetType() == GeomAbs_Cylinder) {
|
||||
cyl = new gp_Cylinder(adapt.Cylinder());
|
||||
} else {
|
||||
return; // invalid surface type
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return; //"PartDesign::Plane: Invalid reference type"
|
||||
}
|
||||
}
|
||||
|
||||
if ((line != NULL) && (normal != NULL) && (p1 != NULL) && (fabs(Angle.getValue()) > Precision::Confusion())) {
|
||||
// plane from line, plane, and angle to plane
|
||||
*normal = normal->Normalize();
|
||||
gp_Pnt p = line->Location();
|
||||
*p1 = Base::Vector3d(p.X(), p.Y(), p.Z());
|
||||
gp_Dir dir = line->Direction();
|
||||
Base::Rotation rot(Base::Vector3d(dir.X(), dir.Y(), dir.Z()), Angle.getValue() / 180.0 * M_PI);
|
||||
rot.multVec(*normal, *normal);
|
||||
} else if ((cyl != NULL) && (normal != NULL)) {
|
||||
// Plane tangential to cylinder and parallel to other plane
|
||||
gp_Dir dir(normal->x, normal->y, normal->z);
|
||||
Handle_Geom_Curve normalLine = new Geom_Line(cyl->Location(), dir);
|
||||
Handle_Geom_Surface cylinder = new Geom_CylindricalSurface(*cyl);
|
||||
|
||||
// Intersect a line through the base point of the cylinder and normal to the plane with the cylinder itself
|
||||
GeomAPI_IntCS intersector(normalLine, cylinder);
|
||||
if (!intersector.IsDone() || (intersector.NbPoints() == 0))
|
||||
throw Base::Exception("Curve - Surface intersection failed");
|
||||
if (intersector.NbPoints() > 1)
|
||||
Base::Console().Warning("More than one intersection point for datum plane from cylinder and plane\n");
|
||||
|
||||
gp_Pnt inter = intersector.Point(1);
|
||||
p1 = new Base::Vector3d(inter.X(), inter.Y(), inter.Z());
|
||||
// TODO: Allow to control which side of the cylinder the plane is created on - there are always two possibilities
|
||||
} else if ((p1 != NULL) && (normal != NULL)) {
|
||||
// plane from other plane. Nothing to be done
|
||||
} else if ((p1 != NULL) && (p2 != NULL) && (p3 != NULL)) {
|
||||
// Plane from three points
|
||||
Base::Vector3d vec1 = *p2 - *p1;
|
||||
Base::Vector3d vec2 = *p3 - *p1;
|
||||
normal = new Base::Vector3d(vec1 % vec2);
|
||||
} else if ((line != NULL) && (p1 != NULL)) {
|
||||
// Plane from point and line
|
||||
p2 = new Base::Vector3d(line->Location().X(), line->Location().Y(), line->Location().Z());
|
||||
gp_Pnt p(line->Location().X() + line->Direction().X(), line->Location().Y() + line->Direction().Y(), line->Location().Z() + line->Direction().Z());
|
||||
p3 = new Base::Vector3d(p.X(), p.Y(), p.Z());
|
||||
Base::Vector3d vec1 = *p2 - *p1;
|
||||
Base::Vector3d vec2 = *p3 - *p1;
|
||||
normal = new Base::Vector3d(vec1 % vec2);
|
||||
} else {
|
||||
throw Base::Exception("Unvalid references");
|
||||
}
|
||||
|
||||
*normal = normal->Normalize();
|
||||
|
||||
if (fabs(Offset.getValue()) > Precision::Confusion())
|
||||
*p1 += Offset.getValue() * *normal;
|
||||
|
||||
Placement.setValue(Base::Placement(*p1,Base::Rotation(Base::Vector3d(0,0,1), *normal)));
|
||||
|
||||
delete p1;
|
||||
delete normal;
|
||||
if (p2 != NULL) delete p2;
|
||||
if (p3 != NULL) delete p3;
|
||||
if (line != NULL) delete line;
|
||||
if (cyl != NULL) delete cyl;
|
||||
}
|
||||
|
||||
Part::Datum::onChanged(prop);
|
||||
}
|
||||
|
||||
|
||||
const std::set<QString> Plane::getHint() const
|
||||
{
|
||||
if (hints.find(refTypes) != hints.end())
|
||||
return hints[refTypes];
|
||||
else
|
||||
return std::set<QString>();
|
||||
}
|
||||
|
||||
const int Plane::offsetsAllowed() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
Base::Vector3d Plane::getBasePoint()
|
||||
{
|
||||
return Placement.getValue().getPosition();
|
||||
|
|
|
@ -43,19 +43,11 @@ public:
|
|||
return "PartDesignGui::ViewProviderDatumPlane";
|
||||
}
|
||||
|
||||
static void initHints();
|
||||
const std::set<QString> getHint() const;
|
||||
const int offsetsAllowed() const;
|
||||
|
||||
Base::Vector3d getBasePoint();
|
||||
Base::Vector3d getNormal();
|
||||
|
||||
protected:
|
||||
virtual void onChanged(const App::Property* prop);
|
||||
|
||||
private:
|
||||
// Hints on what further references are required/possible on this feature for a given set of references
|
||||
static std::map<std::multiset<QString>, std::set<QString> > hints;
|
||||
};
|
||||
|
||||
} //namespace PartDesign
|
||||
|
|
|
@ -76,78 +76,19 @@
|
|||
|
||||
using namespace PartDesign;
|
||||
|
||||
// Note: We don't distinguish between e.g. datum lines and edges here
|
||||
#define PLANE QObject::tr("DPLANE")
|
||||
#define CYLINDER QObject::tr("DCYLINDER")
|
||||
#define LINE QObject::tr("DLINE")
|
||||
#define POINT QObject::tr("DPOINT")
|
||||
#define CIRCLE QObject::tr("DCIRCLE")
|
||||
#define ANGLE QObject::tr("Angle")
|
||||
|
||||
// ================================ Initialize the hints =====================
|
||||
|
||||
std::map<std::multiset<QString>, std::set<QString> > Point::hints = std::map<std::multiset<QString>, std::set<QString> >();
|
||||
|
||||
void Point::initHints()
|
||||
{
|
||||
std::set<QString> DONE;
|
||||
DONE.insert(QObject::tr("Done"));
|
||||
|
||||
std::multiset<QString> key;
|
||||
std::set<QString> value;
|
||||
key.insert(POINT);
|
||||
hints[key] = DONE; // POINT -> DONE. Point from another point or vertex
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(CIRCLE);
|
||||
hints[key] = DONE; // CIRCLE -> DONE. Point from center of circle or arc
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(LINE);
|
||||
value.insert(LINE); value.insert(PLANE);
|
||||
hints[key] = value; // LINE -> LINE or PLANE
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(LINE); key.insert(LINE);
|
||||
hints[key] = DONE; // {LINE, LINE} -> DONE. Point from two lines or edges
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(LINE); key.insert(PLANE);
|
||||
hints[key] = DONE; // {LINE, PLANE} -> DONE. Point from line and plane
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(PLANE);
|
||||
value.insert(PLANE); value.insert(LINE);
|
||||
hints[key] = value; // PLANE -> PLANE or LINE
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(PLANE); key.insert(PLANE);
|
||||
value.insert(PLANE);
|
||||
hints[key] = value; // {PLANE, PLANE} -> PLANE
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(PLANE); key.insert(PLANE); key.insert(PLANE);
|
||||
hints[key] = DONE; // {PLANE, PLANE, PLANE} -> DONE. Point from three planes
|
||||
|
||||
key.clear(); value.clear();
|
||||
value.insert(POINT); value.insert(LINE); value.insert(PLANE);
|
||||
hints[key] = value;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
||||
PROPERTY_SOURCE(PartDesign::Point, Part::Datum)
|
||||
|
||||
Point::Point()
|
||||
{
|
||||
this->setAttacher(new AttachEnginePoint);
|
||||
// Create a shape, which will be used by the Sketcher. Them main function is to avoid a dependency of
|
||||
// Sketcher on the PartDesign module
|
||||
BRepBuilderAPI_MakeVertex builder(gp_Pnt(0,0,0));
|
||||
if (!builder.IsDone())
|
||||
return;
|
||||
Shape.setValue(builder.Shape());
|
||||
|
||||
References.touch();
|
||||
}
|
||||
|
||||
Point::~Point()
|
||||
|
@ -156,223 +97,6 @@ Point::~Point()
|
|||
|
||||
void Point::onChanged(const App::Property* prop)
|
||||
{
|
||||
if ((prop == &References) || (prop == &Offset) || (prop == &Offset2) || (prop == &Offset3)) {
|
||||
refTypes.clear();
|
||||
std::vector<App::DocumentObject*> refs = References.getValues();
|
||||
std::vector<std::string> refnames = References.getSubValues();
|
||||
|
||||
for (int r = 0; r < refs.size(); r++)
|
||||
refTypes.insert(getRefType(refs[r], refnames[r]));
|
||||
|
||||
std::set<QString> hint = getHint();
|
||||
if (!((hint.size() == 1) && (hint.find(QObject::tr("Done")) != hint.end())))
|
||||
return; // incomplete references
|
||||
|
||||
// Extract the geometry of the references
|
||||
Base::Vector3d* point = NULL;
|
||||
Handle_Geom_Curve c1 = NULL;
|
||||
Handle_Geom_Curve c2 = NULL;
|
||||
Handle_Geom_Surface s1 = NULL;
|
||||
Handle_Geom_Surface s2 = NULL;
|
||||
Handle_Geom_Surface s3 = NULL;
|
||||
gp_Circ* circle = NULL;
|
||||
|
||||
for (int i = 0; i < refs.size(); i++) {
|
||||
if (refs[i]->getTypeId().isDerivedFrom(PartDesign::Point::getClassTypeId())) {
|
||||
PartDesign::Point* p = static_cast<PartDesign::Point*>(refs[i]);
|
||||
point = new Base::Vector3d (p->getPoint());
|
||||
} else if (refs[i]->getTypeId().isDerivedFrom(PartDesign::Line::getClassTypeId())) {
|
||||
PartDesign::Line* l = static_cast<PartDesign::Line*>(refs[i]);
|
||||
Base::Vector3d base = l->getBasePoint();
|
||||
Base::Vector3d dir = l->getDirection();
|
||||
if (c1.IsNull())
|
||||
c1 = new Geom_Line(gp_Pnt(base.x, base.y, base.z), gp_Dir(dir.x, dir.y, dir.z));
|
||||
else
|
||||
c2 = new Geom_Line(gp_Pnt(base.x, base.y, base.z), gp_Dir(dir.x, dir.y, dir.z));
|
||||
} else if (refs[i]->getTypeId().isDerivedFrom(PartDesign::Plane::getClassTypeId())) {
|
||||
PartDesign::Plane* p = static_cast<PartDesign::Plane*>(refs[i]);
|
||||
Base::Vector3d base = p->getBasePoint();
|
||||
Base::Vector3d normal = p->getNormal();
|
||||
if (s1.IsNull())
|
||||
s1 = new Geom_Plane(gp_Pnt(base.x, base.y, base.z), gp_Dir(normal.x, normal.y, normal.z));
|
||||
else if (s2.IsNull())
|
||||
s2 = new Geom_Plane(gp_Pnt(base.x, base.y, base.z), gp_Dir(normal.x, normal.y, normal.z));
|
||||
else
|
||||
s3 = new Geom_Plane(gp_Pnt(base.x, base.y, base.z), gp_Dir(normal.x, normal.y, normal.z));
|
||||
|
||||
} else if (refs[i]->getTypeId().isDerivedFrom(App::Line::getClassTypeId())) {
|
||||
App::Line* l = static_cast<App::Line*>(refs[i]);
|
||||
// Note: We only handle the three base planes here
|
||||
gp_Pnt base(0,0,0);
|
||||
gp_Dir normal;
|
||||
if (strcmp(l->LineType.getValue(), App::Part::BaselineTypes[0]) == 0)
|
||||
normal = gp_Dir(1,0,0);
|
||||
else if (strcmp(l->LineType.getValue(), App::Part::BaselineTypes[1]) == 0)
|
||||
normal = gp_Dir(0,1,0);
|
||||
else if (strcmp(l->LineType.getValue(), App::Part::BaselineTypes[2]) == 0)
|
||||
normal = gp_Dir(0,0,1);
|
||||
|
||||
if (s1.IsNull())
|
||||
c1 = new Geom_Line(base, normal);
|
||||
else if (s2.IsNull())
|
||||
c2 = new Geom_Line(base, normal);
|
||||
|
||||
} else if (refs[i]->getTypeId().isDerivedFrom(App::Plane::getClassTypeId())) {
|
||||
App::Plane* p = static_cast<App::Plane*>(refs[i]);
|
||||
// Note: We only handle the three base planes here
|
||||
gp_Pnt base(0,0,0);
|
||||
gp_Dir normal;
|
||||
if (strcmp(p->PlaneType.getValue(), App::Part::BaseplaneTypes[0]) == 0)
|
||||
normal = gp_Dir(0,0,1);
|
||||
else if (strcmp(p->PlaneType.getValue(), App::Part::BaseplaneTypes[2]) == 0)
|
||||
normal = gp_Dir(1,0,0);
|
||||
else if (strcmp(p->PlaneType.getValue(), App::Part::BaseplaneTypes[1]) == 0)
|
||||
normal = gp_Dir(0,1,0);
|
||||
|
||||
if (s1.IsNull())
|
||||
s1 = new Geom_Plane(base, normal);
|
||||
else if (s2.IsNull())
|
||||
s2 = new Geom_Plane(base, normal);
|
||||
else
|
||||
s3 = new Geom_Plane(base, normal);
|
||||
} else if (refs[i]->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
|
||||
Part::Feature* feature = static_cast<Part::Feature*>(refs[i]);
|
||||
const TopoDS_Shape& sh = feature->Shape.getValue();
|
||||
if (sh.IsNull())
|
||||
return; // "PartDesign::Point: Reference has NULL shape"
|
||||
// Get subshape
|
||||
TopoDS_Shape subshape = feature->Shape.getShape().getSubShape(refnames[i].c_str());
|
||||
if (subshape.IsNull())
|
||||
return; // "PartDesign::Point: Reference has NULL subshape";
|
||||
|
||||
if (subshape.ShapeType() == TopAbs_VERTEX) {
|
||||
TopoDS_Vertex v = TopoDS::Vertex(subshape);
|
||||
gp_Pnt p = BRep_Tool::Pnt(v);
|
||||
point = new Base::Vector3d(p.X(), p.Y(), p.Z());
|
||||
} else if (subshape.ShapeType() == TopAbs_EDGE) {
|
||||
TopoDS_Edge e = TopoDS::Edge(subshape);
|
||||
BRepAdaptor_Curve adapt(e);
|
||||
if (adapt.GetType() == GeomAbs_Circle) {
|
||||
circle = new gp_Circ(adapt.Circle());
|
||||
} else {
|
||||
Standard_Real first, last;
|
||||
if (c1.IsNull())
|
||||
c1 = BRep_Tool::Curve(e, first, last);
|
||||
else
|
||||
c2 = BRep_Tool::Curve(e, first, last);
|
||||
}
|
||||
} else if (subshape.ShapeType() == TopAbs_FACE) {
|
||||
TopoDS_Face f = TopoDS::Face(subshape);
|
||||
double offset1 = Offset.getValue();
|
||||
double offset2 = Offset2.getValue();
|
||||
double offset3 = Offset3.getValue();
|
||||
BRepAdaptor_Surface adapt(f);
|
||||
|
||||
if (s1.IsNull()) {
|
||||
if (adapt.GetType() == GeomAbs_Plane) {
|
||||
gp_Trsf mov;
|
||||
mov.SetTranslation(offset1 * gp_Vec(adapt.Plane().Axis().Direction()));
|
||||
TopLoc_Location loc(mov);
|
||||
f.Move(loc);
|
||||
}
|
||||
s1 = BRep_Tool::Surface(f);
|
||||
} else if (s2.IsNull()) {
|
||||
if (adapt.GetType() == GeomAbs_Plane) {
|
||||
gp_Trsf mov;
|
||||
mov.SetTranslation(offset2 * gp_Vec(adapt.Plane().Axis().Direction()));
|
||||
TopLoc_Location loc(mov);
|
||||
f.Move(loc);
|
||||
}
|
||||
s2 = BRep_Tool::Surface(f);
|
||||
} else {
|
||||
if (adapt.GetType() == GeomAbs_Plane) {
|
||||
gp_Trsf mov;
|
||||
mov.SetTranslation(offset3 * gp_Vec(adapt.Plane().Axis().Direction()));
|
||||
TopLoc_Location loc(mov);
|
||||
f.Move(loc);
|
||||
}
|
||||
s3 = BRep_Tool::Surface(f);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return; //"PartDesign::Point: Invalid reference type"
|
||||
}
|
||||
}
|
||||
|
||||
if (point != NULL) {
|
||||
// Point from vertex or other point. Nothing to be done
|
||||
} else if (circle != NULL) {
|
||||
// Point from center of circle (or arc)
|
||||
gp_Pnt centre = circle->Axis().Location();
|
||||
point = new Base::Vector3d(centre.X(), centre.Y(), centre.Z());
|
||||
} else if (!c1.IsNull()) {
|
||||
if (!c2.IsNull()) {
|
||||
// Point from intersection of two curves
|
||||
GeomAPI_ExtremaCurveCurve intersector(c1, c2);
|
||||
if ((intersector.LowerDistance() > Precision::Confusion()) || (intersector.NbExtrema() == 0))
|
||||
throw Base::Exception("Curve-Curve intersection failed"); // No intersection
|
||||
// Note: We don't check for multiple intersection points
|
||||
gp_Pnt p, p2;
|
||||
intersector.Points(1, p, p2);
|
||||
|
||||
// Apply offset if the curves are linear (meaning they define a plane that contains them both)
|
||||
if ((c1->DynamicType() == STANDARD_TYPE(Geom_Line)) && (c2->DynamicType() == STANDARD_TYPE(Geom_Line))) {
|
||||
// Get translation vectors
|
||||
Handle_Geom_Line lin1 = Handle_Geom_Line::DownCast(c1);
|
||||
Handle_Geom_Line lin2 = Handle_Geom_Line::DownCast(c2);
|
||||
gp_Dir normal = lin1->Lin().Direction().Crossed(lin2->Lin().Direction()); // normal of the plane
|
||||
gp_Dir trans1 = normal.Crossed(lin1->Lin().Direction());
|
||||
gp_Dir trans2 = normal.Crossed(lin2->Lin().Direction());
|
||||
double offset1 = Offset.getValue();
|
||||
double offset2 = Offset2.getValue();
|
||||
c1->Translate(offset1 * gp_Vec(trans1));
|
||||
c2->Translate(offset2 * gp_Vec(trans2));
|
||||
// Intersect again
|
||||
intersector = GeomAPI_ExtremaCurveCurve(c1, c2);
|
||||
if ((intersector.LowerDistance() > Precision::Confusion()) || (intersector.NbExtrema() == 0))
|
||||
throw Base::Exception("Curve-Curve intersection failed"); // No intersection
|
||||
// Note: We don't check for multiple intersection points
|
||||
intersector.Points(1, p, p2);
|
||||
}
|
||||
|
||||
point = new Base::Vector3d(p.X(), p.Y(), p.Z());
|
||||
} else if (!s1.IsNull()) {
|
||||
GeomAPI_IntCS intersector(c1, s1);
|
||||
if (!intersector.IsDone() || (intersector.NbPoints() == 0))
|
||||
throw Base::Exception("Curve-Surface intersection failed");
|
||||
if (intersector.NbPoints() > 1)
|
||||
Base::Console().Warning("More than one intersection point for datum point from curve and surface\n");
|
||||
|
||||
gp_Pnt p = intersector.Point(1);
|
||||
point = new Base::Vector3d(p.X(), p.Y(), p.Z());
|
||||
} else
|
||||
return;
|
||||
} else if (!s1.IsNull() && !s2.IsNull() && !s3.IsNull()) {
|
||||
GeomAPI_IntSS intersectorSS(s1, s2, Precision::Confusion());
|
||||
if (!intersectorSS.IsDone() || (intersectorSS.NbLines() == 0))
|
||||
return;
|
||||
if (intersectorSS.NbLines() > 1)
|
||||
Base::Console().Warning("More than one intersection line for datum point from surfaces\n");
|
||||
Handle_Geom_Curve line = intersectorSS.Line(1);
|
||||
|
||||
GeomAPI_IntCS intersector(line, s3);
|
||||
if (!intersector.IsDone() || (intersector.NbPoints() == 0))
|
||||
return;
|
||||
if (intersector.NbPoints() > 1)
|
||||
Base::Console().Warning("More than one intersection point for datum point from surfaces\n");
|
||||
|
||||
gp_Pnt p = intersector.Point(1);
|
||||
point = new Base::Vector3d(p.X(), p.Y(), p.Z());
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
Placement.setValue(Base::Placement(*point, Base::Rotation()));
|
||||
|
||||
delete point;
|
||||
if (circle != NULL) delete circle;
|
||||
}
|
||||
|
||||
Part::Datum::onChanged(prop);
|
||||
}
|
||||
|
||||
|
@ -380,73 +104,3 @@ Base::Vector3d Point::getPoint()
|
|||
{
|
||||
return Placement.getValue().getPosition();
|
||||
}
|
||||
|
||||
|
||||
const std::set<QString> Point::getHint() const
|
||||
{
|
||||
if (hints.find(refTypes) != hints.end())
|
||||
return hints[refTypes];
|
||||
else
|
||||
return std::set<QString>();
|
||||
}
|
||||
|
||||
const int Point::offsetsAllowed() const
|
||||
{
|
||||
int numlines = 0, numplanes = 0;
|
||||
for (std::multiset<QString>::const_iterator r = refTypes.begin(); r != refTypes.end(); r++) {
|
||||
if (*r == LINE) numlines++;
|
||||
else if (*r == PLANE) numplanes++;
|
||||
}
|
||||
|
||||
if (numlines == 2) return 2; // Special case: Two intersecting lines. TODO: Check for co-planarity
|
||||
return numplanes;
|
||||
}
|
||||
|
||||
|
||||
namespace PartDesign {
|
||||
|
||||
const QString getRefType(const App::DocumentObject* obj, const std::string& subname)
|
||||
{
|
||||
Base::Type type = obj->getTypeId();
|
||||
|
||||
if ((type == App::Plane::getClassTypeId()) || (type == PartDesign::Plane::getClassTypeId()))
|
||||
return PLANE;
|
||||
else if ((type == App::Line::getClassTypeId()) || (type == PartDesign::Line::getClassTypeId()))
|
||||
return LINE;
|
||||
else if (type == PartDesign::Point::getClassTypeId())
|
||||
return POINT;
|
||||
else if (type.isDerivedFrom(Part::Feature::getClassTypeId())) {
|
||||
const Part::Feature* feature = static_cast<const Part::Feature*>(obj);
|
||||
const Part::TopoShape& topShape = feature->Shape.getShape();
|
||||
if (topShape.isNull())
|
||||
return QString::fromAscii("EMPTYSHAPE"); // Can happen on file loading
|
||||
|
||||
if (subname.size() > 4 && subname.substr(0,4) == "Face") {
|
||||
TopoDS_Shape face = topShape.getSubShape(subname.c_str());
|
||||
if (face.IsNull() || (face.ShapeType() != TopAbs_FACE))
|
||||
throw Base::Exception("Part::Datum::getRefType(): No valid subshape could be extracted");
|
||||
BRepAdaptor_Surface adapt(TopoDS::Face(face));
|
||||
if (adapt.GetType() == GeomAbs_Plane)
|
||||
return PLANE;
|
||||
else if (adapt.GetType() == GeomAbs_Cylinder)
|
||||
return CYLINDER;
|
||||
else
|
||||
throw Base::Exception("Part::Datum::getRefType(): Only planar and cylindrical faces are allowed");
|
||||
} else if (subname.size() > 4 && subname.substr(0,4) == "Edge") {
|
||||
TopoDS_Shape edge = topShape.getSubShape(subname.c_str());
|
||||
if (edge.IsNull() || (edge.ShapeType() != TopAbs_EDGE))
|
||||
throw Base::Exception("Part::Datum::getRefType(): No valid subshape could be extracted");
|
||||
BRepAdaptor_Curve adapt(TopoDS::Edge(edge));
|
||||
if (adapt.GetType() == GeomAbs_Circle)
|
||||
return CIRCLE;
|
||||
else // We don't check for other types yet
|
||||
return LINE;
|
||||
} else if (subname.size() > 6 && subname.substr(0,6) == "Vertex") {
|
||||
return POINT;
|
||||
}
|
||||
}
|
||||
|
||||
throw Base::Exception("Part::Datum::getRefType(): Illegal object type");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -44,24 +44,12 @@ public:
|
|||
return "PartDesignGui::ViewProviderDatumPoint";
|
||||
}
|
||||
|
||||
static void initHints();
|
||||
const std::set<QString> getHint() const;
|
||||
const int offsetsAllowed() const;
|
||||
|
||||
Base::Vector3d getPoint();
|
||||
|
||||
protected:
|
||||
virtual void onChanged(const App::Property* prop);
|
||||
|
||||
private:
|
||||
// Hints on what further references are required/possible on this feature for a given set of references
|
||||
static std::map<std::multiset<QString>, std::set<QString> > hints;
|
||||
};
|
||||
|
||||
// This has to be declared somewhere... a good place would be Part::Datum but since the code requires
|
||||
// access to PartDesign::Point etc. that's not possible
|
||||
const QString getRefType(const App::DocumentObject* obj, const std::string& subname);
|
||||
|
||||
} //namespace PartDesign
|
||||
|
||||
|
||||
|
|
|
@ -599,9 +599,10 @@ void CmdPartDesignPlane::activated(int iMsg)
|
|||
openCommand("Create a datum plane");
|
||||
doCommand(Doc,"App.activeDocument().addObject('PartDesign::Plane','%s')",FeatName.c_str());
|
||||
if (refStr.length() > 0)
|
||||
doCommand(Doc,"App.activeDocument().%s.References = %s",FeatName.c_str(),refStr.toStdString().c_str());
|
||||
doCommand(Doc,"App.activeDocument().%s.Offset = 0.0",FeatName.c_str());
|
||||
doCommand(Doc,"App.activeDocument().%s.Angle = 0.0",FeatName.c_str());
|
||||
doCommand(Doc,"App.activeDocument().%s.Support = %s",FeatName.c_str(),refStr.toStdString().c_str());
|
||||
Datum* pcDatum = static_cast<Datum*>(getDocument()->getObject(FeatName.c_str()));
|
||||
eSuggestResult msg;
|
||||
pcDatum->MapMode.setValue(pcDatum->attacher().listMapModes(msg));
|
||||
doCommand(Doc,"App.activeDocument().%s.addFeature(App.activeDocument().%s)",
|
||||
pcActiveBody->getNameInDocument(), FeatName.c_str());
|
||||
doCommand(Gui,"App.activeDocument().recompute()"); // recompute the feature based on its references
|
||||
|
@ -643,7 +644,10 @@ void CmdPartDesignLine::activated(int iMsg)
|
|||
openCommand("Create a datum line");
|
||||
doCommand(Doc,"App.activeDocument().addObject('PartDesign::Line','%s')",FeatName.c_str());
|
||||
if (refStr.length() > 0)
|
||||
doCommand(Doc,"App.activeDocument().%s.References = %s",FeatName.c_str(),refStr.toStdString().c_str());
|
||||
doCommand(Doc,"App.activeDocument().%s.Support = %s",FeatName.c_str(),refStr.toStdString().c_str());
|
||||
Datum* pcDatum = static_cast<Datum*>(getDocument()->getObject(FeatName.c_str()));
|
||||
eSuggestResult msg;
|
||||
pcDatum->MapMode.setValue(pcDatum->attacher().listMapModes(msg));
|
||||
doCommand(Doc,"App.activeDocument().%s.addFeature(App.activeDocument().%s)",
|
||||
pcActiveBody->getNameInDocument(), FeatName.c_str());
|
||||
doCommand(Gui,"App.activeDocument().recompute()"); // recompute the feature based on its references
|
||||
|
@ -685,12 +689,14 @@ void CmdPartDesignPoint::activated(int iMsg)
|
|||
openCommand("Create a datum point");
|
||||
doCommand(Doc,"App.activeDocument().addObject('PartDesign::Point','%s')",FeatName.c_str());
|
||||
if (refStr.length() > 0)
|
||||
doCommand(Doc,"App.activeDocument().%s.References = %s",FeatName.c_str(),refStr.toStdString().c_str());
|
||||
doCommand(Doc,"App.activeDocument().%s.Support = %s",FeatName.c_str(),refStr.toStdString().c_str());
|
||||
Datum* pcDatum = static_cast<Datum*>(getDocument()->getObject(FeatName.c_str()));
|
||||
eSuggestResult msg;
|
||||
pcDatum->MapMode.setValue(pcDatum->attacher().listMapModes(msg));
|
||||
doCommand(Doc,"App.activeDocument().%s.addFeature(App.activeDocument().%s)",
|
||||
pcActiveBody->getNameInDocument(), FeatName.c_str());
|
||||
doCommand(Gui,"App.activeDocument().recompute()"); // recompute the feature based on its references
|
||||
doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str());
|
||||
|
||||
}
|
||||
|
||||
bool CmdPartDesignPoint::isActive(void)
|
||||
|
@ -886,7 +892,7 @@ void CmdPartDesignNewSketch::activated(int iMsg)
|
|||
App::Plane* plane = static_cast<App::Plane*>(features.front());
|
||||
std::string FeatName = getUniqueObjectName("Sketch");
|
||||
std::string supportString = std::string("(App.activeDocument().") + plane->getNameInDocument() +
|
||||
", ['" + (false ? "back" : "front") + "'])";
|
||||
", [''])";
|
||||
|
||||
Gui::Command::openCommand("Create a new Sketch");
|
||||
Gui::Command::doCommand(Doc,"App.activeDocument().addObject('Sketcher::SketchObject','%s')",FeatName.c_str());
|
||||
|
|
Loading…
Reference in New Issue
Block a user