Moved generic Datum class to Part module to avoid Sketcher dependency on PartDesign

This commit is contained in:
jrheinlaender 2013-05-03 20:27:25 +04:30 committed by Stefan Tröger
parent 20ba1983a4
commit 5b3d5e6bd8
36 changed files with 6297 additions and 1314 deletions

View File

@ -91,6 +91,7 @@
#include "BRepOffsetAPI_MakePipeShellPy.h" #include "BRepOffsetAPI_MakePipeShellPy.h"
#include "PartFeaturePy.h" #include "PartFeaturePy.h"
#include "PropertyGeometryList.h" #include "PropertyGeometryList.h"
#include "DatumFeature.h"
namespace Part { namespace Part {
extern PyObject* initModule(); extern PyObject* initModule();
@ -301,7 +302,7 @@ PyMODINIT_FUNC initPart()
Part::GeomTrimmedSurface ::init(); Part::GeomTrimmedSurface ::init();
Part::GeomSurfaceOfRevolution ::init(); Part::GeomSurfaceOfRevolution ::init();
Part::GeomSurfaceOfExtrusion ::init(); Part::GeomSurfaceOfExtrusion ::init();
Part::Datum ::init();
IGESControl_Controller::Init(); IGESControl_Controller::Init();
STEPControl_Controller::Init(); STEPControl_Controller::Init();

View File

@ -137,6 +137,8 @@ SET(Features_SRCS
CustomFeature.h CustomFeature.h
BodyBase.h BodyBase.h
BodyBase.cpp BodyBase.cpp
DatumFeature.cpp
DatumFeature.h
) )
SOURCE_GROUP("Features" FILES ${Features_SRCS}) SOURCE_GROUP("Features" FILES ${Features_SRCS})

View File

@ -0,0 +1,103 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <cfloat>
# include <BRepLib.hxx>
# include <BRepBuilderAPI_MakeEdge.hxx>
# include <BRepBuilderAPI_MakeFace.hxx>
# include <BRepBuilderAPI_MakeVertex.hxx>
# include <BRepBuilderAPI_MakeWire.hxx>
# include <BRepBuilderAPI_GTransform.hxx>
# include <BRep_Tool.hxx>
# include <gp_GTrsf.hxx>
# include <gp_Lin.hxx>
# include <gp_Pln.hxx>
# include <Geom_Line.hxx>
# include <Geom_Plane.hxx>
# include <Geom2d_Line.hxx>
# include <Handle_Geom_Curve.hxx>
# include <Handle_Geom_Surface.hxx>
# include <Handle_Geom_Plane.hxx>
# include <Handle_Geom2d_Line.hxx>
# include <GeomAPI_IntCS.hxx>
# include <GeomAPI_IntSS.hxx>
# include <GeomAPI_ExtremaCurveCurve.hxx>
# include <Precision.hxx>
# include <Standard_Real.hxx>
# include <TopoDS.hxx>
# include <TopoDS_Vertex.hxx>
# include <TopoDS_Edge.hxx>
# include <TopoDS_Face.hxx>
# include <BRepAdaptor_Curve.hxx>
# include <BRepAdaptor_Surface.hxx>
# include <Standard_Version.hxx>
#endif
#include <QObject>
#include <App/Plane.h>
#include "DatumFeature.h"
#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 Part;
PROPERTY_SOURCE_ABSTRACT(Part::Datum, Part::Feature)
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(Angle,(0.0));
touch();
}
Datum::~Datum()
{
}
void Datum::onChanged (const App::Property* prop)
{
Part::Feature::onChanged(prop);
}
App::DocumentObjectExecReturn *Datum::execute(void)
{
References.touch();
return StdReturn;
}
void Datum::onDocumentRestored()
{
// This seems to be the only way to make the ViewProvider display the datum feature
References.touch();
Part::Feature::onDocumentRestored();
}

View File

@ -0,0 +1,75 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef PART_DATUMFEATURE_H
#define PART_DATUMFEATURE_H
#include <QString>
#include <App/PropertyLinks.h>
#include "PartFeature.h"
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
{
PROPERTY_HEADER(Part::Datum);
public:
Datum();
virtual ~Datum();
/// The references defining the datum object, e.g. three planes for a point, two planes for a line
App::PropertyLinkSubList References;
/// Offset and angle for defining planes
App::PropertyFloat Offset;
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() = 0;
/// Return a shape representing the datum feature
//virtual const TopoDS_Shape getShape() const = 0;
protected:
void onChanged (const App::Property* prop);
void onDocumentRestored();
protected:
std::multiset<QString> refTypes;
};
} //namespace Part
#endif // PART_DATUMFEATURE_H

View File

@ -48,6 +48,7 @@
#include <App/Plane.h> #include <App/Plane.h>
#include "Part2DObject.h" #include "Part2DObject.h"
#include "Geometry.h" #include "Geometry.h"
#include "DatumFeature.h"
#include <App/FeaturePythonPyImp.h> #include <App/FeaturePythonPyImp.h>
#include "Part2DObjectPy.h" #include "Part2DObjectPy.h"
@ -96,7 +97,7 @@ void Part2DObject::positionBySupport(void)
// Set placement identical to the way it used to be done in the Sketcher::SketchOrientationDialog // Set placement identical to the way it used to be done in the Sketcher::SketchOrientationDialog
if (dir == Base::Vector3d(0,0,1)) { if (dir == Base::Vector3d(0,0,1)) {
Place = Base::Placement(Base::Vector3d(0,0,0),Base::Rotation(Reverse ? -1.0 : 0.0,0.0,0.0,0.0)); Place = Base::Placement(Base::Vector3d(0,0,0),Base::Rotation(Reverse ? -1.0 : 0.0, 0.0,0.0,0.0));
} else if (dir == Base::Vector3d(0,1,0)) { } else if (dir == Base::Vector3d(0,1,0)) {
if (Reverse) if (Reverse)
Place = Base::Placement(Base::Vector3d(0,0,0),Base::Rotation(Base::Vector3d(0,sqrt(2.0)/2.0,sqrt(2.0)/2.0),M_PI)); Place = Base::Placement(Base::Vector3d(0,0,0),Base::Rotation(Base::Vector3d(0,sqrt(2.0)/2.0,sqrt(2.0)/2.0),M_PI));
@ -111,6 +112,18 @@ void Part2DObject::positionBySupport(void)
Place.getRotation().multVec(Base::Vector3d(0,0,1),dir); Place.getRotation().multVec(Base::Vector3d(0,0,1),dir);
Base::Vector3d pos = Place.getPosition(); Base::Vector3d pos = Place.getPosition();
plane = gp_Pln(gp_Pnt(pos.x, pos.y, pos.z), gp_Dir(dir.x, dir.y, dir.z)); plane = gp_Pln(gp_Pnt(pos.x, pos.y, pos.z), gp_Dir(dir.x, dir.y, dir.z));
} else if (support->getTypeId() == Part::Datum::getClassTypeId()) {
Part::Datum* pcDatum = static_cast<Part::Datum*>(support);
TopoDS_Shape plane = pcDatum->Shape.getValue();
if (plane.ShapeType() != TopAbs_FACE)
return;
BRepAdaptor_Surface adapt(TopoDS::Face(plane));
if (adapt.GetType() != GeomAbs_Plane)
return;
gp_Pln pl = adapt.Plane();
Base::Vector3d pos(pl.Location().X(), pl.Location().Y(), pl.Location().Z());
Base::Vector3d normal(pl.Axis().Direction().X(), pl.Axis().Direction().Y(), pl.Axis().Direction().Z());
this->Placement.setValue(Base::Placement(pos, Base::Rotation(Base::Vector3d(0,0,1), normal)));
} else { } else {
Part::Feature *part = static_cast<Part::Feature*>(support); Part::Feature *part = static_cast<Part::Feature*>(support);
if (!part || !part->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) if (!part || !part->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId()))

View File

@ -49,7 +49,9 @@
#include "FeatureScaled.h" #include "FeatureScaled.h"
#include "FeatureMultiTransform.h" #include "FeatureMultiTransform.h"
#include "FeatureHole.h" #include "FeatureHole.h"
#include "DatumFeature.h" #include "DatumPlane.h"
#include "DatumLine.h"
#include "DatumPoint.h"
namespace PartDesign { namespace PartDesign {
extern PyObject* initModule(); extern PyObject* initModule();
@ -97,7 +99,6 @@ PyMODINIT_FUNC init_PartDesign()
PartDesign::Groove ::init(); PartDesign::Groove ::init();
PartDesign::Chamfer ::init(); PartDesign::Chamfer ::init();
PartDesign::Draft ::init(); PartDesign::Draft ::init();
PartDesign::Datum ::init();
PartDesign::Plane ::init(); PartDesign::Plane ::init();
PartDesign::Line ::init(); PartDesign::Line ::init();
PartDesign::Point ::init(); PartDesign::Point ::init();

View File

@ -28,14 +28,14 @@
#include <Base/Placement.h> #include <Base/Placement.h>
#include "Feature.h" #include "Feature.h"
#include "DatumFeature.h"
#include "Body.h" #include "Body.h"
#include "BodyPy.h" #include "BodyPy.h"
#include "FeatureSketchBased.h"
#include <App/Application.h> #include <App/Application.h>
#include <App/Document.h> #include <App/Document.h>
#include <Base/Console.h> #include <Base/Console.h>
#include "FeatureSketchBased.h" #include <Mod/Part/App/DatumFeature.h>
using namespace PartDesign; using namespace PartDesign;
@ -192,7 +192,7 @@ const bool Body::isAllowed(const App::DocumentObject* f)
return false; return false;
return (f->getTypeId().isDerivedFrom(PartDesign::Feature::getClassTypeId()) || return (f->getTypeId().isDerivedFrom(PartDesign::Feature::getClassTypeId()) ||
f->getTypeId().isDerivedFrom(PartDesign::Datum::getClassTypeId()) || f->getTypeId().isDerivedFrom(Part::Datum::getClassTypeId()) ||
f->getTypeId().isDerivedFrom(Part::Part2DObject::getClassTypeId())); f->getTypeId().isDerivedFrom(Part::Part2DObject::getClassTypeId()));
} }
@ -214,7 +214,6 @@ Body* Body::findBodyOf(const App::DocumentObject* f)
void Body::addFeature(App::DocumentObject *feature) void Body::addFeature(App::DocumentObject *feature)
{ {
// Set the BaseFeature property // Set the BaseFeature property
// Note: This is not strictly necessary for Datum features
if (feature->getTypeId().isDerivedFrom(PartDesign::Feature::getClassTypeId())) { if (feature->getTypeId().isDerivedFrom(PartDesign::Feature::getClassTypeId())) {
App::DocumentObject* prevSolidFeature = getPrevSolidFeature(NULL, true); App::DocumentObject* prevSolidFeature = getPrevSolidFeature(NULL, true);
if (prevSolidFeature != NULL) if (prevSolidFeature != NULL)

View File

@ -91,13 +91,13 @@ public:
/** /**
* Return true if the given feature is a solid feature allowed in a Body. Currently this is only valid * Return true if the given feature is a solid feature allowed in a Body. Currently this is only valid
* for features derived from PartDesign::Feature * for features derived from PartDesign::Feature
* Return false if the given feature is a Sketch or a PartDesign::Datum feature * Return false if the given feature is a Sketch or a Part::Datum feature
*/ */
static const bool isSolidFeature(const App::DocumentObject* f); static const bool isSolidFeature(const App::DocumentObject* f);
/** /**
* Return true if the given feature is allowed in a Body. Currently allowed are * Return true if the given feature is allowed in a Body. Currently allowed are
* all features derived from PartDesign::Feature and PartDesign::Datum and sketches * all features derived from PartDesign::Feature and Part::Datum and sketches
*/ */
static const bool isAllowed(const App::DocumentObject* f); static const bool isAllowed(const App::DocumentObject* f);

View File

@ -3,7 +3,6 @@
#include "Mod/Part/App/Part2DObject.h" #include "Mod/Part/App/Part2DObject.h"
#include "Mod/PartDesign/App/Body.h" #include "Mod/PartDesign/App/Body.h"
#include "Mod/PartDesign/App/DatumFeature.h"
// inclusion of the generated files (generated out of ItemPy.xml) // inclusion of the generated files (generated out of ItemPy.xml)
#include "BodyPy.h" #include "BodyPy.h"

View File

@ -39,8 +39,12 @@ SET(Features_SRCS
SOURCE_GROUP("Features" FILES ${Features_SRCS}) SOURCE_GROUP("Features" FILES ${Features_SRCS})
SET(DatumFeatures_SRCS SET(DatumFeatures_SRCS
DatumFeature.cpp DatumPlane.cpp
DatumFeature.h DatumPlane.h
DatumLine.cpp
DatumLine.h
DatumPoint.cpp
DatumPoint.h
) )
SOURCE_GROUP("DatumFeatures" FILES ${DatumFeatures_SRCS}) SOURCE_GROUP("DatumFeatures" FILES ${DatumFeatures_SRCS})

View File

@ -1,763 +0,0 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <cfloat>
# include <BRepLib.hxx>
# include <BRepBuilderAPI_MakeEdge.hxx>
# include <BRepBuilderAPI_MakeFace.hxx>
# include <BRepBuilderAPI_MakeVertex.hxx>
# include <BRepBuilderAPI_MakeWire.hxx>
# include <BRepBuilderAPI_GTransform.hxx>
# include <BRep_Tool.hxx>
# include <gp_GTrsf.hxx>
# include <gp_Lin.hxx>
# include <gp_Pln.hxx>
# include <Geom_Line.hxx>
# include <Geom_Plane.hxx>
# include <Geom2d_Line.hxx>
# include <Handle_Geom_Curve.hxx>
# include <Handle_Geom_Surface.hxx>
# include <Handle_Geom_Plane.hxx>
# include <Handle_Geom2d_Line.hxx>
# include <GeomAPI_IntCS.hxx>
# include <GeomAPI_IntSS.hxx>
# include <GeomAPI_ExtremaCurveCurve.hxx>
# include <Precision.hxx>
# include <Standard_Real.hxx>
# include <TopoDS.hxx>
# include <TopoDS_Vertex.hxx>
# include <TopoDS_Edge.hxx>
# include <TopoDS_Face.hxx>
# include <BRepAdaptor_Curve.hxx>
# include <BRepAdaptor_Surface.hxx>
# include <Standard_Version.hxx>
#endif
#include <QObject>
#include <App/Plane.h>
#include "DatumFeature.h"
#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;
PROPERTY_SOURCE_ABSTRACT(PartDesign::Datum, App::GeoFeature)
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(Angle,(0.0));
touch();
}
Datum::~Datum()
{
}
App::DocumentObjectExecReturn *Datum::execute(void)
{
References.touch();
return StdReturn;
}
// Note: We don't distinguish between e.g. datum lines and edges here
#define PLANE QObject::tr("DPLANE")
#define LINE QObject::tr("DLINE")
#define POINT QObject::tr("DPOINT")
#define ANGLE QObject::tr("Angle")
void Datum::onChanged(const App::Property* prop)
{
if (prop == &References) {
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]));
if (fabs(Angle.getValue()) > Precision::Confusion())
refTypes.insert(ANGLE);
} else if (prop == &Angle) {
// Zero value counts as angle not defined
if (fabs(Angle.getValue()) > Precision::Confusion())
refTypes.insert(ANGLE);
else
refTypes.erase(ANGLE);
}
App::GeoFeature::onChanged(prop);
}
void Datum::onDocumentRestored()
{
// This seems to be the only way to make the ViewProvider display the datum feature
References.touch();
App::GeoFeature::onDocumentRestored();
}
const QString Datum::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 == PartDesign::Line::getClassTypeId())
return LINE;
else if (type == PartDesign::Point::getClassTypeId())
return POINT;
else if (type.isDerivedFrom(Part::Feature::getClassTypeId())) {
// Note: For now, only planar references are possible
if (subname.size() > 4 && subname.substr(0,4) == "Face")
return PLANE;
else if (subname.size() > 4 && subname.substr(0,4) == "Edge")
return LINE;
else if (subname.size() > 6 && subname.substr(0,6) == "Vertex")
return POINT;
}
throw Base::Exception("PartDesign::Datum::getRefType(): Illegal object type");
}
// ================================ 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(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;
}
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(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);
hints[key] = value; // PLANE -> 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();
value.insert(POINT); value.insert(LINE); value.insert(PLANE);
hints[key] = value;
}
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();
value.insert(POINT); value.insert(LINE); value.insert(PLANE); value.insert(ANGLE);
hints[key] = value;
}
// ============================================================================
PROPERTY_SOURCE(PartDesign::Point, PartDesign::Datum)
Point::Point()
{
ADD_PROPERTY_TYPE(_Point,(Base::Vector3d(0,0,0)),"DatumPoint",
App::PropertyType(App::Prop_ReadOnly|App::Prop_Output),
"Coordinates of the datum point");
}
Point::~Point()
{
}
void Point::onChanged(const App::Property* prop)
{
Datum::onChanged(prop);
if (prop == &References) {
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
std::vector<App::DocumentObject*> refs = References.getValues();
std::vector<std::string> refnames = References.getSubValues();
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;
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->_Point.getValue());
} else if (refs[i]->getTypeId().isDerivedFrom(PartDesign::Line::getClassTypeId())) {
PartDesign::Line* l = static_cast<PartDesign::Line*>(refs[i]);
Base::Vector3d base = l->_Base.getValue();
Base::Vector3d dir = l->_Direction.getValue();
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->_Base.getValue();
Base::Vector3d normal = p->_Normal.getValue();
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::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->getNameInDocument(), "BaseplaneXY") == 0)
normal = gp_Dir(0,0,1);
else if (strcmp(p->getNameInDocument(), "BaseplaneYZ") == 0)
normal = gp_Dir(1,0,0);
else if (strcmp(p->getNameInDocument(), "BaseplaneXZ") == 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);
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);
if (s1.IsNull())
s1 = BRep_Tool::Surface(f);
else if (s2.IsNull())
s2 = BRep_Tool::Surface(f);
else
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 (!c1.IsNull()) {
if (!c2.IsNull()) {
// Point from intersection of two curves
GeomAPI_ExtremaCurveCurve intersector(c1, c2);
if ((intersector.LowerDistance() > Precision::Confusion()) || (intersector.NbExtrema() == 0))
return; // No intersection
// Note: We don't check for multiple intersection points
gp_Pnt p, p2;
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))
return;
if (intersector.NbPoints() > 1)
Base::Console().Warning("More than one intersection point for datum point from curve and surface");
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");
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");
gp_Pnt p = intersector.Point(1);
point = new Base::Vector3d(p.X(), p.Y(), p.Z());
} else {
return;
}
_Point.setValue(*point);
_Point.touch(); // This triggers ViewProvider::updateData()
delete point;
}
}
const std::set<QString> Point::getHint()
{
if (hints.find(refTypes) != hints.end())
return hints[refTypes];
else
return std::set<QString>();
}
PROPERTY_SOURCE(PartDesign::Line, PartDesign::Datum)
Line::Line()
{
ADD_PROPERTY_TYPE(_Base,(Base::Vector3d(0,0,0)),"DatumLine",
App::PropertyType(App::Prop_ReadOnly|App::Prop_Output),
"Coordinates of the line base point");
ADD_PROPERTY_TYPE(_Direction,(Base::Vector3d(1,1,1)),"DatumLine",
App::PropertyType(App::Prop_ReadOnly|App::Prop_Output),
"Coordinates of the line direction");
}
Line::~Line()
{
}
void Line::onChanged(const App::Property *prop)
{
Datum::onChanged(prop);
if (prop == &References) {
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
std::vector<App::DocumentObject*> refs = References.getValues();
std::vector<std::string> refnames = References.getSubValues();
Base::Vector3d* base = NULL;
Base::Vector3d* direction = NULL;
Base::Vector3d* p1 = NULL;
Base::Vector3d* p2 = NULL;
gp_Lin* line = NULL;
Handle_Geom_Surface s1 = NULL;
Handle_Geom_Surface s2 = 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->_Point.getValue());
else
p2 = new Base::Vector3d (p->_Point.getValue());
} else if (refs[i]->getTypeId().isDerivedFrom(PartDesign::Line::getClassTypeId())) {
PartDesign::Line* l = static_cast<PartDesign::Line*>(refs[i]);
base = new Base::Vector3d (l->_Base.getValue());
direction = new Base::Vector3d (l->_Direction.getValue());
} else if (refs[i]->getTypeId().isDerivedFrom(PartDesign::Plane::getClassTypeId())) {
PartDesign::Plane* p = static_cast<PartDesign::Plane*>(refs[i]);
Base::Vector3d base = p->_Base.getValue();
Base::Vector3d normal = p->_Normal.getValue();
if (s1.IsNull())
s1 = new Geom_Plane(gp_Pnt(base.x, base.y, base.z), gp_Dir(normal.x, normal.y, normal.z));
else
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->getNameInDocument(), "BaseplaneXY") == 0)
normal = gp_Dir(0,0,1);
else if (strcmp(p->getNameInDocument(), "BaseplaneYZ") == 0)
normal = gp_Dir(1,0,0);
else if (strcmp(p->getNameInDocument(), "BaseplaneXZ") == 0)
normal = gp_Dir(0,1,0);
if (s1.IsNull())
s1 = new Geom_Plane(base, normal);
else
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_Line)
return; // Non-linear edge
line = new gp_Lin(adapt.Line());
} else if (subshape.ShapeType() == TopAbs_FACE) {
TopoDS_Face f = TopoDS::Face(subshape);
if (s1.IsNull())
s1 = BRep_Tool::Surface(f);
else
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 (!s1.IsNull() && !s2.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");
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;
}
_Base.setValue(*base);
_Direction.setValue(*direction);
_Base.touch(); // This triggers ViewProvider::updateData()
delete base;
delete direction;
if (p1 != NULL) delete p1;
if (p2 != NULL) delete p2;
if (line != NULL) delete line;
}
}
const std::set<QString> Line::getHint()
{
if (hints.find(refTypes) != hints.end())
return hints[refTypes];
else
return std::set<QString>();
}
PROPERTY_SOURCE(PartDesign::Plane, PartDesign::Datum)
Plane::Plane()
{
ADD_PROPERTY_TYPE(_Base,(Base::Vector3d(0,0,0)),"DatumPlane",
App::PropertyType(App::Prop_ReadOnly|App::Prop_Output),
"Coordinates of the plane base point");
ADD_PROPERTY_TYPE(_Normal,(Base::Vector3d(1,1,1)),"DatumPlane",
App::PropertyType(App::Prop_ReadOnly|App::Prop_Output),
"Coordinates of the plane normal");
}
void Plane::onChanged(const App::Property *prop)
{
Datum::onChanged(prop);
if (prop == &References) {
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
std::vector<App::DocumentObject*> refs = References.getValues();
std::vector<std::string> refnames = References.getSubValues();
Base::Vector3d* p1 = NULL;
Base::Vector3d* p2 = NULL;
Base::Vector3d* p3 = NULL;
Base::Vector3d* normal = NULL;
gp_Lin* line = 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->_Point.getValue());
else if (p2 == NULL)
p2 = new Base::Vector3d (p->_Point.getValue());
else
p3 = new Base::Vector3d (p->_Point.getValue());
} else if (refs[i]->getTypeId().isDerivedFrom(PartDesign::Line::getClassTypeId())) {
PartDesign::Line* l = static_cast<PartDesign::Line*>(refs[i]);
Base::Vector3d base = l->_Base.getValue();
Base::Vector3d dir = l->_Direction.getValue();
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->_Base.getValue());
normal = new Base::Vector3d(p->_Normal.getValue());
} 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->getNameInDocument(), "BaseplaneXY") == 0)
*normal = Base::Vector3d(0,0,1);
else if (strcmp(p->getNameInDocument(), "BaseplaneYZ") == 0)
*normal = Base::Vector3d(1,0,0);
else if (strcmp(p->getNameInDocument(), "BaseplaneXZ") == 0)
*normal = Base::Vector3d(0,1,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)
return; // Non-planar face
gp_Pnt b = adapt.Plane().Location();
gp_Dir d = adapt.Plane().Axis().Direction();
p1 = new Base::Vector3d(b.X(), b.Y(), b.Z());
normal = new Base::Vector3d(d.X(), d.Y(), d.Z());
}
} else {
return; //"PartDesign::Plane: Invalid reference type"
}
}
*normal = normal->Normalize();
if ((line != NULL) && (normal != NULL) && (p1 != NULL) && (fabs(Angle.getValue()) > Precision::Confusion())) {
// plane from line, plane, and angle to plane
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 ((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 {
return;
}
if (fabs(Offset.getValue()) > Precision::Confusion())
*p1 += Offset.getValue() * *normal;
_Base.setValue(*p1);
_Normal.setValue(*normal);
_Base.touch(); // This triggers ViewProvider::updateData()
delete p1;
delete normal;
if (p2 != NULL) delete p2;
if (p3 != NULL) delete p3;
if (line != NULL) delete line;
}
}
const std::set<QString> Plane::getHint()
{
if (hints.find(refTypes) != hints.end())
return hints[refTypes];
else
return std::set<QString>();
}

View File

@ -1,148 +0,0 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef PARTDESIGN_DATUMFEATURE_H
#define PARTDESIGN_DATUMFEATURE_H
#include <QString>
#include <App/PropertyLinks.h>
#include <App/GeoFeature.h>
namespace PartDesign
{
class PartDesignExport Datum : public App::GeoFeature
{
PROPERTY_HEADER(PartDesign::Datum);
public:
Datum();
virtual ~Datum();
/// The references defining the datum object, e.g. three planes for a point, two planes for a line
App::PropertyLinkSubList References;
/// Offset and angle for defining planes
App::PropertyFloat Offset;
App::PropertyFloat Angle;
/// recalculate the feature
App::DocumentObjectExecReturn *execute(void);
/// returns the type name of the view provider
const char* getViewProviderName(void) const {
return "PartDesignGui::ViewProviderDatum";
}
virtual const std::set<QString> getHint() = 0;
protected:
void onChanged (const App::Property* prop);
void onDocumentRestored();
protected:
std::multiset<QString> refTypes;
static const QString getRefType(const App::DocumentObject* obj, const std::string& subname);
};
class PartDesignExport Point : public PartDesign::Datum
{
PROPERTY_HEADER(PartDesign::Point);
public:
App::PropertyVector _Point;
Point();
virtual ~Point();
const char* getViewProviderName(void) const {
return "PartDesignGui::ViewProviderDatumPoint";
}
static void initHints();
const std::set<QString> getHint();
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;
};
class PartDesignExport Line : public PartDesign::Datum
{
PROPERTY_HEADER(PartDesign::Line);
public:
App::PropertyVector _Base;
App::PropertyVector _Direction;
Line();
virtual ~Line();
const char* getViewProviderName(void) const {
return "PartDesignGui::ViewProviderDatumLine";
}
static void initHints();
const std::set<QString> getHint();
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;
};
class PartDesignExport Plane : public PartDesign::Datum
{
PROPERTY_HEADER(PartDesign::Plane);
public:
App::PropertyVector _Base;
App::PropertyVector _Normal;
Plane();
const char* getViewProviderName(void) const {
return "PartDesignGui::ViewProviderDatumPlane";
}
static void initHints();
const std::set<QString> getHint();
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
#endif // PARTDESIGN_DATUMFEATURE_H

View File

@ -0,0 +1,280 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <cfloat>
# include <BRepLib.hxx>
# include <BRepBuilderAPI_MakeEdge.hxx>
# include <BRepBuilderAPI_MakeFace.hxx>
# include <BRepBuilderAPI_MakeVertex.hxx>
# include <BRepBuilderAPI_MakeWire.hxx>
# include <BRepBuilderAPI_GTransform.hxx>
# include <BRep_Tool.hxx>
# include <gp_GTrsf.hxx>
# include <gp_Lin.hxx>
# include <gp_Pln.hxx>
# include <Geom_Line.hxx>
# include <Geom_Plane.hxx>
# include <Geom2d_Line.hxx>
# include <Handle_Geom_Curve.hxx>
# include <Handle_Geom_Surface.hxx>
# include <Handle_Geom_Plane.hxx>
# include <Handle_Geom2d_Line.hxx>
# include <GeomAPI_IntCS.hxx>
# include <GeomAPI_IntSS.hxx>
# include <GeomAPI_ExtremaCurveCurve.hxx>
# include <Precision.hxx>
# include <Standard_Real.hxx>
# include <TopoDS.hxx>
# include <TopoDS_Vertex.hxx>
# include <TopoDS_Edge.hxx>
# include <TopoDS_Face.hxx>
# include <BRepAdaptor_Curve.hxx>
# include <BRepAdaptor_Surface.hxx>
# include <Standard_Version.hxx>
#endif
#include <QObject>
#include <App/Plane.h>
#include "DatumPoint.h"
#include "DatumLine.h"
#include "DatumPlane.h"
#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 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(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);
hints[key] = value; // PLANE -> 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();
value.insert(POINT); value.insert(LINE); value.insert(PLANE);
hints[key] = value;
}
PROPERTY_SOURCE(PartDesign::Line, Part::Datum)
Line::Line()
{
ADD_PROPERTY_TYPE(_Base,(Base::Vector3d(0,0,0)),"DatumLine",
App::PropertyType(App::Prop_ReadOnly|App::Prop_Output),
"Coordinates of the line base point");
ADD_PROPERTY_TYPE(_Direction,(Base::Vector3d(1,1,1)),"DatumLine",
App::PropertyType(App::Prop_ReadOnly|App::Prop_Output),
"Coordinates of the line direction");
}
Line::~Line()
{
}
void Line::onChanged(const App::Property *prop)
{
Datum::onChanged(prop);
if (prop == &References) {
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* base = NULL;
Base::Vector3d* direction = NULL;
Base::Vector3d* p1 = NULL;
Base::Vector3d* p2 = NULL;
gp_Lin* line = NULL;
Handle_Geom_Surface s1 = NULL;
Handle_Geom_Surface s2 = 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->_Point.getValue());
else
p2 = new Base::Vector3d (p->_Point.getValue());
} else if (refs[i]->getTypeId().isDerivedFrom(PartDesign::Line::getClassTypeId())) {
PartDesign::Line* l = static_cast<PartDesign::Line*>(refs[i]);
base = new Base::Vector3d (l->_Base.getValue());
direction = new Base::Vector3d (l->_Direction.getValue());
} else if (refs[i]->getTypeId().isDerivedFrom(PartDesign::Plane::getClassTypeId())) {
PartDesign::Plane* p = static_cast<PartDesign::Plane*>(refs[i]);
Base::Vector3d base = p->_Base.getValue();
Base::Vector3d normal = p->_Normal.getValue();
if (s1.IsNull())
s1 = new Geom_Plane(gp_Pnt(base.x, base.y, base.z), gp_Dir(normal.x, normal.y, normal.z));
else
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->getNameInDocument(), "BaseplaneXY") == 0)
normal = gp_Dir(0,0,1);
else if (strcmp(p->getNameInDocument(), "BaseplaneYZ") == 0)
normal = gp_Dir(1,0,0);
else if (strcmp(p->getNameInDocument(), "BaseplaneXZ") == 0)
normal = gp_Dir(0,1,0);
if (s1.IsNull())
s1 = new Geom_Plane(base, normal);
else
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_Line)
return; // Non-linear edge
line = new gp_Lin(adapt.Line());
} else if (subshape.ShapeType() == TopAbs_FACE) {
TopoDS_Face f = TopoDS::Face(subshape);
if (s1.IsNull())
s1 = BRep_Tool::Surface(f);
else
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 (!s1.IsNull() && !s2.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");
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;
}
_Base.setValue(*base);
_Direction.setValue(*direction);
_Base.touch(); // This triggers ViewProvider::updateData()
// 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(base->x, base->y, base->z), gp_Dir(direction->x, direction->y, direction->z)));
if (!builder.IsDone())
return;
Shape.setValue(builder.Shape());
delete base;
delete direction;
if (p1 != NULL) delete p1;
if (p2 != NULL) delete p2;
if (line != NULL) delete line;
}
Part::Datum::onChanged(prop);
}
const std::set<QString> Line::getHint()
{
if (hints.find(refTypes) != hints.end())
return hints[refTypes];
else
return std::set<QString>();
}

View File

@ -0,0 +1,64 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef PARTDESIGN_DATUMLINE_H
#define PARTDESIGN_DATUMLINE_H
#include <QString>
#include <App/PropertyLinks.h>
#include <App/GeoFeature.h>
#include <Mod/Part/App/DatumFeature.h>
namespace PartDesign
{
class PartDesignExport Line : public Part::Datum
{
PROPERTY_HEADER(PartDesign::Line);
public:
App::PropertyVector _Base;
App::PropertyVector _Direction;
Line();
virtual ~Line();
const char* getViewProviderName(void) const {
return "PartDesignGui::ViewProviderDatumLine";
}
static void initHints();
const std::set<QString> getHint();
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
#endif // PARTDESIGN_DATUMLINE_H

View File

@ -0,0 +1,317 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <cfloat>
# include <BRepLib.hxx>
# include <BRepBuilderAPI_MakeEdge.hxx>
# include <BRepBuilderAPI_MakeFace.hxx>
# include <BRepBuilderAPI_MakeVertex.hxx>
# include <BRepBuilderAPI_MakeWire.hxx>
# include <BRepBuilderAPI_GTransform.hxx>
# include <BRep_Tool.hxx>
# include <gp_GTrsf.hxx>
# include <gp_Lin.hxx>
# include <gp_Pln.hxx>
# include <Geom_Line.hxx>
# include <Geom_Plane.hxx>
# include <Geom2d_Line.hxx>
# include <Handle_Geom_Curve.hxx>
# include <Handle_Geom_Surface.hxx>
# include <Handle_Geom_Plane.hxx>
# include <Handle_Geom2d_Line.hxx>
# include <GeomAPI_IntCS.hxx>
# include <GeomAPI_IntSS.hxx>
# include <GeomAPI_ExtremaCurveCurve.hxx>
# include <Precision.hxx>
# include <Standard_Real.hxx>
# include <TopoDS.hxx>
# include <TopoDS_Vertex.hxx>
# include <TopoDS_Edge.hxx>
# include <TopoDS_Face.hxx>
# include <BRepAdaptor_Curve.hxx>
# include <BRepAdaptor_Surface.hxx>
# include <Standard_Version.hxx>
#endif
#include <QObject>
#include <App/Plane.h>
#include "DatumPoint.h"
#include "DatumLine.h"
#include "DatumPlane.h"
#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 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();
value.insert(POINT); value.insert(LINE); value.insert(PLANE); value.insert(ANGLE);
hints[key] = value;
}
// ============================================================================
PROPERTY_SOURCE(PartDesign::Plane, Part::Datum)
Plane::Plane()
{
ADD_PROPERTY_TYPE(_Base,(Base::Vector3d(0,0,0)),"DatumPlane",
App::PropertyType(App::Prop_ReadOnly|App::Prop_Output),
"Coordinates of the plane base point");
ADD_PROPERTY_TYPE(_Normal,(Base::Vector3d(1,1,1)),"DatumPlane",
App::PropertyType(App::Prop_ReadOnly|App::Prop_Output),
"Coordinates of the plane normal");
}
void Plane::onChanged(const App::Property *prop)
{
Datum::onChanged(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) {
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]));
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;
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->_Point.getValue());
else if (p2 == NULL)
p2 = new Base::Vector3d (p->_Point.getValue());
else
p3 = new Base::Vector3d (p->_Point.getValue());
} else if (refs[i]->getTypeId().isDerivedFrom(PartDesign::Line::getClassTypeId())) {
PartDesign::Line* l = static_cast<PartDesign::Line*>(refs[i]);
Base::Vector3d base = l->_Base.getValue();
Base::Vector3d dir = l->_Direction.getValue();
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->_Base.getValue());
normal = new Base::Vector3d(p->_Normal.getValue());
} 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->getNameInDocument(), "BaseplaneXY") == 0)
*normal = Base::Vector3d(0,0,1);
else if (strcmp(p->getNameInDocument(), "BaseplaneYZ") == 0)
*normal = Base::Vector3d(1,0,0);
else if (strcmp(p->getNameInDocument(), "BaseplaneXZ") == 0)
*normal = Base::Vector3d(0,1,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)
return; // Non-planar face
gp_Pnt b = adapt.Plane().Location();
gp_Dir d = adapt.Plane().Axis().Direction();
p1 = new Base::Vector3d(b.X(), b.Y(), b.Z());
normal = new Base::Vector3d(d.X(), d.Y(), d.Z());
}
} 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 ((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 {
return;
}
*normal = normal->Normalize();
if (fabs(Offset.getValue()) > Precision::Confusion())
*p1 += Offset.getValue() * *normal;
_Base.setValue(*p1);
_Normal.setValue(*normal);
_Base.touch(); // This triggers ViewProvider::updateData()
// 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(p1->x, p1->y, p1->z), gp_Dir(normal->x, normal->y, normal->z)));
if (!builder.IsDone())
return;
Shape.setValue(builder.Shape());
delete p1;
delete normal;
if (p2 != NULL) delete p2;
if (p3 != NULL) delete p3;
if (line != NULL) delete line;
}
Part::Datum::onChanged(prop);
}
const std::set<QString> Plane::getHint()
{
if (hints.find(refTypes) != hints.end())
return hints[refTypes];
else
return std::set<QString>();
}

View File

@ -0,0 +1,62 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef PARTDESIGN_DATUMPLANE_H
#define PARTDESIGN_DATUMPLANE_H
#include <QString>
#include <App/PropertyLinks.h>
#include <Mod/Part/App/DatumFeature.h>
namespace PartDesign
{
class PartDesignExport Plane : public Part::Datum
{
PROPERTY_HEADER(PartDesign::Plane);
public:
App::PropertyVector _Base;
App::PropertyVector _Normal;
Plane();
const char* getViewProviderName(void) const {
return "PartDesignGui::ViewProviderDatumPlane";
}
static void initHints();
const std::set<QString> getHint();
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
#endif // PARTDESIGN_DATUMPLANE_H

View File

@ -0,0 +1,331 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <cfloat>
# include <BRepLib.hxx>
# include <BRepBuilderAPI_MakeEdge.hxx>
# include <BRepBuilderAPI_MakeFace.hxx>
# include <BRepBuilderAPI_MakeVertex.hxx>
# include <BRepBuilderAPI_MakeWire.hxx>
# include <BRepBuilderAPI_GTransform.hxx>
# include <BRep_Tool.hxx>
# include <gp_GTrsf.hxx>
# include <gp_Lin.hxx>
# include <gp_Pln.hxx>
# include <Geom_Line.hxx>
# include <Geom_Plane.hxx>
# include <Geom2d_Line.hxx>
# include <Handle_Geom_Curve.hxx>
# include <Handle_Geom_Surface.hxx>
# include <Handle_Geom_Plane.hxx>
# include <Handle_Geom2d_Line.hxx>
# include <GeomAPI_IntCS.hxx>
# include <GeomAPI_IntSS.hxx>
# include <GeomAPI_ExtremaCurveCurve.hxx>
# include <Precision.hxx>
# include <Standard_Real.hxx>
# include <TopoDS.hxx>
# include <TopoDS_Vertex.hxx>
# include <TopoDS_Edge.hxx>
# include <TopoDS_Face.hxx>
# include <BRepAdaptor_Curve.hxx>
# include <BRepAdaptor_Surface.hxx>
# include <Standard_Version.hxx>
#endif
#include <QObject>
#include <App/Plane.h>
#include "DatumPoint.h"
#include "DatumLine.h"
#include "DatumPlane.h"
#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 POINT QObject::tr("DPOINT")
#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(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()
{
ADD_PROPERTY_TYPE(_Point,(Base::Vector3d(0,0,0)),"DatumPoint",
App::PropertyType(App::Prop_ReadOnly|App::Prop_Output),
"Coordinates of the datum point");
}
Point::~Point()
{
}
void Point::onChanged(const App::Property* prop)
{
if (prop == &References) {
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;
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->_Point.getValue());
} else if (refs[i]->getTypeId().isDerivedFrom(PartDesign::Line::getClassTypeId())) {
PartDesign::Line* l = static_cast<PartDesign::Line*>(refs[i]);
Base::Vector3d base = l->_Base.getValue();
Base::Vector3d dir = l->_Direction.getValue();
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->_Base.getValue();
Base::Vector3d normal = p->_Normal.getValue();
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::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->getNameInDocument(), "BaseplaneXY") == 0)
normal = gp_Dir(0,0,1);
else if (strcmp(p->getNameInDocument(), "BaseplaneYZ") == 0)
normal = gp_Dir(1,0,0);
else if (strcmp(p->getNameInDocument(), "BaseplaneXZ") == 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);
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);
if (s1.IsNull())
s1 = BRep_Tool::Surface(f);
else if (s2.IsNull())
s2 = BRep_Tool::Surface(f);
else
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 (!c1.IsNull()) {
if (!c2.IsNull()) {
// Point from intersection of two curves
GeomAPI_ExtremaCurveCurve intersector(c1, c2);
if ((intersector.LowerDistance() > Precision::Confusion()) || (intersector.NbExtrema() == 0))
return; // No intersection
// Note: We don't check for multiple intersection points
gp_Pnt p, p2;
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))
return;
if (intersector.NbPoints() > 1)
Base::Console().Warning("More than one intersection point for datum point from curve and surface");
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");
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");
gp_Pnt p = intersector.Point(1);
point = new Base::Vector3d(p.X(), p.Y(), p.Z());
} else {
return;
}
_Point.setValue(*point);
_Point.touch(); // This triggers ViewProvider::updateData()
// 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(point->x, point->y, point->z));
if (!builder.IsDone())
return;
Shape.setValue(builder.Shape());
delete point;
}
Part::Datum::onChanged(prop);
}
const std::set<QString> Point::getHint()
{
if (hints.find(refTypes) != hints.end())
return hints[refTypes];
else
return std::set<QString>();
}
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 == PartDesign::Line::getClassTypeId())
return LINE;
else if (type == PartDesign::Point::getClassTypeId())
return POINT;
else if (type.isDerivedFrom(Part::Feature::getClassTypeId())) {
// Note: For now, only planar references are possible
if (subname.size() > 4 && subname.substr(0,4) == "Face")
return PLANE;
else if (subname.size() > 4 && subname.substr(0,4) == "Edge")
return LINE;
else if (subname.size() > 6 && subname.substr(0,6) == "Vertex")
return POINT;
}
throw Base::Exception("Part::Datum::getRefType(): Illegal object type");
}
}

View File

@ -0,0 +1,69 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef PARTDESIGN_DATUMPOINT_H
#define PARTDESIGN_DATUMPOINT_H
#include <QString>
#include <App/PropertyLinks.h>
#include <App/GeoFeature.h>
#include <Mod/Part/App/DatumFeature.h>
namespace PartDesign
{
class PartDesignExport Point : public Part::Datum
{
PROPERTY_HEADER(PartDesign::Point);
public:
App::PropertyVector _Point;
Point();
virtual ~Point();
const char* getViewProviderName(void) const {
return "PartDesignGui::ViewProviderDatumPoint";
}
static void initHints();
const std::set<QString> getHint();
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
#endif // PARTDESIGN_DATUMPOINT_H

View File

@ -48,7 +48,9 @@
#include "ViewProviderPolarPattern.h" #include "ViewProviderPolarPattern.h"
#include "ViewProviderScaled.h" #include "ViewProviderScaled.h"
#include "ViewProviderMultiTransform.h" #include "ViewProviderMultiTransform.h"
#include "ViewProviderDatum.h" #include "ViewProviderDatumPoint.h"
#include "ViewProviderDatumLine.h"
#include "ViewProviderDatumPlane.h"
// use a different name to CreateCommand() // use a different name to CreateCommand()
void CreatePartDesignCommands(void); void CreatePartDesignCommands(void);

View File

@ -106,6 +106,12 @@ SET(PartDesignGuiViewProvider_SRCS
ViewProviderMultiTransform.h ViewProviderMultiTransform.h
ViewProviderDatum.cpp ViewProviderDatum.cpp
ViewProviderDatum.h ViewProviderDatum.h
ViewProviderDatumPoint.cpp
ViewProviderDatumPoint.h
ViewProviderDatumLine.cpp
ViewProviderDatumLine.h
ViewProviderDatumPlane.cpp
ViewProviderDatumPlane.h
) )
SOURCE_GROUP("ViewProvider" FILES ${PartDesignGuiViewProvider_SRCS}) SOURCE_GROUP("ViewProvider" FILES ${PartDesignGuiViewProvider_SRCS})

View File

@ -63,13 +63,15 @@
#include <Mod/Part/App/Part2DObject.h> #include <Mod/Part/App/Part2DObject.h>
#include <Mod/PartDesign/App/Body.h> #include <Mod/PartDesign/App/Body.h>
#include <Mod/PartDesign/App/DatumFeature.h>
#include <Mod/Sketcher/App/SketchObject.h> #include <Mod/Sketcher/App/SketchObject.h>
#include <Mod/Sketcher/Gui/SketchOrientationDialog.h> #include <Mod/Sketcher/Gui/SketchOrientationDialog.h>
#include <Mod/PartDesign/App/FeatureAdditive.h> #include <Mod/PartDesign/App/FeatureAdditive.h>
#include <Mod/PartDesign/App/FeatureSubtractive.h> #include <Mod/PartDesign/App/FeatureSubtractive.h>
#include <Mod/PartDesign/App/FeatureGroove.h> #include <Mod/PartDesign/App/FeatureGroove.h>
#include <Mod/PartDesign/App/FeatureRevolution.h> #include <Mod/PartDesign/App/FeatureRevolution.h>
#include <Mod/PartDesign/App/DatumPoint.h>
#include <Mod/PartDesign/App/DatumLine.h>
#include <Mod/PartDesign/App/DatumPlane.h>
#include "FeaturePickDialog.h" #include "FeaturePickDialog.h"
#include "Workbench.h" #include "Workbench.h"

View File

@ -34,7 +34,9 @@
#include <Mod/Part/App/TopoShape.h> #include <Mod/Part/App/TopoShape.h>
#include <Mod/Part/App/PartFeature.h> #include <Mod/Part/App/PartFeature.h>
#include <Mod/PartDesign/App/Body.h> #include <Mod/PartDesign/App/Body.h>
#include <Mod/PartDesign/App/DatumFeature.h> #include <Mod/PartDesign/App/DatumPoint.h>
#include <Mod/PartDesign/App/DatumLine.h>
#include <Mod/PartDesign/App/DatumPlane.h>
#include "ReferenceSelection.h" #include "ReferenceSelection.h"
#include "Workbench.h" #include "Workbench.h"
@ -49,8 +51,8 @@ bool ReferenceSelection::allow(App::Document* pDoc, App::DocumentObject* pObj, c
// Note: It is assumed that a Part has exactly 3 App::Plane objects at the root of the feature tree // Note: It is assumed that a Part has exactly 3 App::Plane objects at the root of the feature tree
return true; return true;
if (pObj->getTypeId().isDerivedFrom(PartDesign::Datum::getClassTypeId())) { if (pObj->getTypeId().isDerivedFrom(Part::Datum::getClassTypeId())) {
// Allow selecting PartDesign::Datum features // Allow selecting Part::Datum features
if (!ActivePartObject->hasFeature(pObj)) if (!ActivePartObject->hasFeature(pObj))
return false; return false;

View File

@ -45,7 +45,7 @@
#include <Gui/Selection.h> #include <Gui/Selection.h>
#include <Gui/Command.h> #include <Gui/Command.h>
#include <Mod/Part/App/PrimitiveFeature.h> #include <Mod/Part/App/PrimitiveFeature.h>
#include <Mod/PartDesign/App/DatumFeature.h> #include <Mod/Part/App/DatumFeature.h>
#include <Mod/PartDesign/App/Body.h> #include <Mod/PartDesign/App/Body.h>
#include "ReferenceSelection.h" #include "ReferenceSelection.h"
#include "Workbench.h" #include "Workbench.h"
@ -62,7 +62,7 @@ const QString makeRefString(const App::DocumentObject* obj, const std::string& s
return QObject::tr("No reference selected"); return QObject::tr("No reference selected");
if (obj->getTypeId().isDerivedFrom(App::Plane::getClassTypeId()) || if (obj->getTypeId().isDerivedFrom(App::Plane::getClassTypeId()) ||
obj->getTypeId().isDerivedFrom(PartDesign::Datum::getClassTypeId())) obj->getTypeId().isDerivedFrom(Part::Datum::getClassTypeId()))
// App::Plane or Datum feature // App::Plane or Datum feature
return QString::fromAscii(obj->getNameInDocument()); return QString::fromAscii(obj->getNameInDocument());
@ -81,7 +81,7 @@ const QString makeRefString(const App::DocumentObject* obj, const std::string& s
} }
void TaskDatumParameters::makeRefStrings(std::vector<QString>& refstrings, std::vector<std::string>& refnames) { void TaskDatumParameters::makeRefStrings(std::vector<QString>& refstrings, std::vector<std::string>& refnames) {
PartDesign::Datum* pcDatum = static_cast<PartDesign::Datum*>(DatumView->getObject()); Part::Datum* pcDatum = static_cast<Part::Datum*>(DatumView->getObject());
std::vector<App::DocumentObject*> refs = pcDatum->References.getValues(); std::vector<App::DocumentObject*> refs = pcDatum->References.getValues();
refnames = pcDatum->References.getSubValues(); refnames = pcDatum->References.getSubValues();
@ -139,7 +139,7 @@ TaskDatumParameters::TaskDatumParameters(ViewProviderDatum *DatumView,QWidget *p
ui->lineRef3->blockSignals(true); ui->lineRef3->blockSignals(true);
// Get the feature data // Get the feature data
PartDesign::Datum* pcDatum = static_cast<PartDesign::Datum*>(DatumView->getObject()); Part::Datum* pcDatum = static_cast<Part::Datum*>(DatumView->getObject());
//std::vector<App::DocumentObject*> refs = pcDatum->References.getValues(); //std::vector<App::DocumentObject*> refs = pcDatum->References.getValues();
std::vector<std::string> refnames = pcDatum->References.getSubValues(); std::vector<std::string> refnames = pcDatum->References.getSubValues();
@ -203,7 +203,7 @@ void TaskDatumParameters::updateUI()
ui->spinOffset->setVisible(false); ui->spinOffset->setVisible(false);
} }
PartDesign::Datum* pcDatum = static_cast<PartDesign::Datum*>(DatumView->getObject()); Part::Datum* pcDatum = static_cast<Part::Datum*>(DatumView->getObject());
std::vector<App::DocumentObject*> refs = pcDatum->References.getValues(); std::vector<App::DocumentObject*> refs = pcDatum->References.getValues();
completed = false; completed = false;
@ -308,7 +308,7 @@ void TaskDatumParameters::onSelectionChanged(const Gui::SelectionChanges& msg)
return; return;
// Note: The validity checking has already been done in ReferenceSelection.cpp // Note: The validity checking has already been done in ReferenceSelection.cpp
PartDesign::Datum* pcDatum = static_cast<PartDesign::Datum*>(DatumView->getObject()); Part::Datum* pcDatum = static_cast<Part::Datum*>(DatumView->getObject());
std::vector<App::DocumentObject*> refs = pcDatum->References.getValues(); std::vector<App::DocumentObject*> refs = pcDatum->References.getValues();
std::vector<std::string> refnames = pcDatum->References.getSubValues(); std::vector<std::string> refnames = pcDatum->References.getSubValues();
App::DocumentObject* selObj = pcDatum->getDocument()->getObject(msg.pObjectName); App::DocumentObject* selObj = pcDatum->getDocument()->getObject(msg.pObjectName);
@ -317,7 +317,7 @@ void TaskDatumParameters::onSelectionChanged(const Gui::SelectionChanges& msg)
// Remove subname for planes and datum features // Remove subname for planes and datum features
if (selObj->getTypeId().isDerivedFrom(App::Plane::getClassTypeId()) || if (selObj->getTypeId().isDerivedFrom(App::Plane::getClassTypeId()) ||
selObj->getTypeId().isDerivedFrom(PartDesign::Datum::getClassTypeId())) selObj->getTypeId().isDerivedFrom(Part::Datum::getClassTypeId()))
subname = ""; subname = "";
// eliminate duplicate selections // eliminate duplicate selections
@ -349,7 +349,7 @@ void TaskDatumParameters::onSelectionChanged(const Gui::SelectionChanges& msg)
void TaskDatumParameters::onOffsetChanged(double val) void TaskDatumParameters::onOffsetChanged(double val)
{ {
PartDesign::Datum* pcDatum = static_cast<PartDesign::Datum*>(DatumView->getObject()); Part::Datum* pcDatum = static_cast<Part::Datum*>(DatumView->getObject());
pcDatum->Offset.setValue(val); pcDatum->Offset.setValue(val);
pcDatum->getDocument()->recomputeFeature(pcDatum); pcDatum->getDocument()->recomputeFeature(pcDatum);
updateUI(); updateUI();
@ -357,7 +357,7 @@ void TaskDatumParameters::onOffsetChanged(double val)
void TaskDatumParameters::onAngleChanged(double val) void TaskDatumParameters::onAngleChanged(double val)
{ {
PartDesign::Datum* pcDatum = static_cast<PartDesign::Datum*>(DatumView->getObject()); Part::Datum* pcDatum = static_cast<Part::Datum*>(DatumView->getObject());
pcDatum->Angle.setValue(val); pcDatum->Angle.setValue(val);
pcDatum->getDocument()->recomputeFeature(pcDatum); pcDatum->getDocument()->recomputeFeature(pcDatum);
updateUI(); updateUI();
@ -365,14 +365,14 @@ void TaskDatumParameters::onAngleChanged(double val)
void TaskDatumParameters::onCheckFlip(bool on) void TaskDatumParameters::onCheckFlip(bool on)
{ {
PartDesign::Datum* pcDatum = static_cast<PartDesign::Datum*>(DatumView->getObject()); Part::Datum* pcDatum = static_cast<Part::Datum*>(DatumView->getObject());
//pcDatum->Reversed.setValue(on); //pcDatum->Reversed.setValue(on);
pcDatum->getDocument()->recomputeFeature(pcDatum); pcDatum->getDocument()->recomputeFeature(pcDatum);
} }
void TaskDatumParameters::onButtonRef(const bool pressed, const int idx) void TaskDatumParameters::onButtonRef(const bool pressed, const int idx)
{ {
// Note: Even if there is no solid, App::Plane and PartDesign::Datum can still be selected // Note: Even if there is no solid, App::Plane and Part::Datum can still be selected
App::DocumentObject* solid = PartDesignGui::ActivePartObject->getPrevSolidFeature(); App::DocumentObject* solid = PartDesignGui::ActivePartObject->getPrevSolidFeature();
if (pressed) { if (pressed) {
@ -410,7 +410,7 @@ void TaskDatumParameters::onRefName(const QString& text, const int idx)
if (text.length() == 0) { if (text.length() == 0) {
// Reference was removed // Reference was removed
// Update the reference list // Update the reference list
PartDesign::Datum* pcDatum = static_cast<PartDesign::Datum*>(DatumView->getObject()); Part::Datum* pcDatum = static_cast<Part::Datum*>(DatumView->getObject());
std::vector<App::DocumentObject*> refs = pcDatum->References.getValues(); std::vector<App::DocumentObject*> refs = pcDatum->References.getValues();
std::vector<std::string> refnames = pcDatum->References.getSubValues(); std::vector<std::string> refnames = pcDatum->References.getSubValues();
std::vector<App::DocumentObject*> newrefs; std::vector<App::DocumentObject*> newrefs;
@ -439,7 +439,7 @@ void TaskDatumParameters::onRefName(const QString& text, const int idx)
QStringList parts = text.split(QChar::fromAscii(':')); QStringList parts = text.split(QChar::fromAscii(':'));
if (parts.length() < 2) if (parts.length() < 2)
parts.push_back(QString::fromAscii("")); parts.push_back(QString::fromAscii(""));
// Check whether this is the name of an App::Plane or PartDesign::Datum feature // Check whether this is the name of an App::Plane or Part::Datum feature
App::DocumentObject* obj = DatumView->getObject()->getDocument()->getObject(parts[0].toAscii()); App::DocumentObject* obj = DatumView->getObject()->getDocument()->getObject(parts[0].toAscii());
if (obj == NULL) return; if (obj == NULL) return;
@ -448,7 +448,7 @@ void TaskDatumParameters::onRefName(const QString& text, const int idx)
if (obj->getTypeId().isDerivedFrom(App::Plane::getClassTypeId())) { if (obj->getTypeId().isDerivedFrom(App::Plane::getClassTypeId())) {
// everything is OK (we assume a Part can only have exactly 3 App::Plane objects located at the base of the feature tree) // everything is OK (we assume a Part can only have exactly 3 App::Plane objects located at the base of the feature tree)
subElement = ""; subElement = "";
} else if (obj->getTypeId().isDerivedFrom(PartDesign::Datum::getClassTypeId())) { } else if (obj->getTypeId().isDerivedFrom(Part::Datum::getClassTypeId())) {
if (!PartDesignGui::ActivePartObject->hasFeature(obj)) if (!PartDesignGui::ActivePartObject->hasFeature(obj))
return; return;
subElement = ""; subElement = "";
@ -484,7 +484,7 @@ void TaskDatumParameters::onRefName(const QString& text, const int idx)
subElement = ss.str(); subElement = ss.str();
} }
PartDesign::Datum* pcDatum = static_cast<PartDesign::Datum*>(DatumView->getObject()); Part::Datum* pcDatum = static_cast<Part::Datum*>(DatumView->getObject());
std::vector<App::DocumentObject*> refs = pcDatum->References.getValues(); std::vector<App::DocumentObject*> refs = pcDatum->References.getValues();
std::vector<std::string> refnames = pcDatum->References.getSubValues(); std::vector<std::string> refnames = pcDatum->References.getSubValues();
if (idx < refs.size()) { if (idx < refs.size()) {

View File

@ -52,7 +52,9 @@
#include "ViewProviderDatum.h" #include "ViewProviderDatum.h"
#include "TaskDatumParameters.h" #include "TaskDatumParameters.h"
#include "Workbench.h" #include "Workbench.h"
#include <Mod/PartDesign/App/DatumFeature.h> #include <Mod/PartDesign/App/DatumPoint.h>
#include <Mod/PartDesign/App/DatumLine.h>
#include <Mod/PartDesign/App/DatumPlane.h>
#include <Gui/Control.h> #include <Gui/Control.h>
#include <Gui/Command.h> #include <Gui/Command.h>
#include <Gui/Application.h> #include <Gui/Application.h>
@ -77,12 +79,12 @@ void ViewProviderDatum::attach(App::DocumentObject *obj)
{ {
ViewProviderGeometryObject::attach(obj); ViewProviderGeometryObject::attach(obj);
PartDesign::Datum* pcDatum = static_cast<PartDesign::Datum*>(getObject()); App::DocumentObject* o = getObject();
if (pcDatum->getTypeId() == PartDesign::Plane::getClassTypeId()) if (o->getTypeId() == PartDesign::Plane::getClassTypeId())
datumType = QObject::tr("Plane"); datumType = QObject::tr("Plane");
else if (pcDatum->getTypeId() == PartDesign::Line::getClassTypeId()) else if (o->getTypeId() == PartDesign::Line::getClassTypeId())
datumType = QObject::tr("Line"); datumType = QObject::tr("Line");
else if (pcDatum->getTypeId() == PartDesign::Point::getClassTypeId()) else if (o->getTypeId() == PartDesign::Point::getClassTypeId())
datumType = QObject::tr("Point"); datumType = QObject::tr("Point");
SoSeparator* sep = new SoSeparator(); SoSeparator* sep = new SoSeparator();
@ -265,274 +267,3 @@ void ViewProviderDatum::unsetEdit(int ModNum)
} }
} }
PROPERTY_SOURCE(PartDesignGui::ViewProviderDatumPoint,PartDesignGui::ViewProviderDatum)
ViewProviderDatumPoint::ViewProviderDatumPoint()
{
SoMarkerSet* points = new SoMarkerSet();
points->markerIndex = SoMarkerSet::DIAMOND_FILLED_9_9;
points->numPoints = 0;
pShapeSep->addChild(points);
}
ViewProviderDatumPoint::~ViewProviderDatumPoint()
{
}
void ViewProviderDatumPoint::updateData(const App::Property* prop)
{
// Gets called whenever a property of the attached object changes
PartDesign::Point* pcDatum = static_cast<PartDesign::Point*>(this->getObject());
if (strcmp(prop->getName(),"_Point") == 0) {
Base::Vector3d p = pcDatum->_Point.getValue();
SoMFVec3f v;
v.setNum(1);
v.set1Value(0, p.x, p.y, p.z);
SoMarkerSet* points = static_cast<SoMarkerSet*>(pShapeSep->getChild(0));
SoVertexProperty* vprop;
if (points->vertexProperty.getValue() == NULL) {
vprop = new SoVertexProperty();
vprop->vertex = v;
points->vertexProperty = vprop;
} else {
vprop = static_cast<SoVertexProperty*>(points->vertexProperty.getValue());
vprop->vertex = v;
}
points->numPoints = 1;
}
ViewProviderDatum::updateData(prop);
}
PROPERTY_SOURCE(PartDesignGui::ViewProviderDatumLine,PartDesignGui::ViewProviderDatum)
ViewProviderDatumLine::ViewProviderDatumLine()
{
SoMaterial* material = new SoMaterial();
material->diffuseColor.setValue(0.9f, 0.9f, 0.13);
material->transparency.setValue(0.2);
pShapeSep->addChild(material);
}
ViewProviderDatumLine::~ViewProviderDatumLine()
{
}
void ViewProviderDatumLine::updateData(const App::Property* prop)
{
// Gets called whenever a property of the attached object changes
PartDesign::Line* pcDatum = static_cast<PartDesign::Line*>(this->getObject());
if (strcmp(prop->getName(),"_Base") == 0) {
Base::Vector3d base = pcDatum->_Base.getValue();
Base::Vector3d dir = pcDatum->_Direction.getValue();
// Get limits of the line from bounding box of the body
PartDesign::Body* body = PartDesign::Body::findBodyOf(this->getObject());
if (body == NULL)
return;
Part::Feature* tipSolid = static_cast<Part::Feature*>(body->getPrevSolidFeature());
if (tipSolid == NULL)
return;
Base::BoundBox3d bbox = tipSolid->Shape.getShape().getBoundBox();
bbox.Enlarge(0.1 * bbox.CalcDiagonalLength());
Base::Vector3d p1, p2;
if (bbox.IsInBox(base)) {
bbox.IntersectionPoint(base, dir, p1, Precision::Confusion());
bbox.IntersectionPoint(base, -dir, p2, Precision::Confusion());
} else {
bbox.IntersectWithLine(base, dir, p1, p2);
if ((p1 == Base::Vector3d(0,0,0)) && (p2 == Base::Vector3d(0,0,0)))
bbox.IntersectWithLine(base, -dir, p1, p2);
}
// Display the line
SoMFVec3f v;
v.setNum(2);
v.set1Value(0, p1.x, p1.y, p1.z);
v.set1Value(1, p2.x, p2.y, p2.z);
SoMFInt32 idx;
idx.setNum(1);
idx.set1Value(0, 2);
SoLineSet* lineSet;
SoVertexProperty* vprop;
if (pShapeSep->getNumChildren() == 1) {
lineSet = new SoLineSet();
vprop = new SoVertexProperty();
vprop->vertex = v;
lineSet->vertexProperty = vprop;
lineSet->numVertices = idx;
pShapeSep->addChild(lineSet);
} else {
lineSet = static_cast<SoLineSet*>(pShapeSep->getChild(1));
vprop = static_cast<SoVertexProperty*>(lineSet->vertexProperty.getValue());
vprop->vertex = v;
lineSet->numVertices = idx;
}
}
ViewProviderDatum::updateData(prop);
}
PROPERTY_SOURCE(PartDesignGui::ViewProviderDatumPlane,PartDesignGui::ViewProviderDatum)
ViewProviderDatumPlane::ViewProviderDatumPlane()
{
SoMaterial* material = new SoMaterial();
material->diffuseColor.setValue(0.9f, 0.9f, 0.13);
material->transparency.setValue(0.2);
pShapeSep->addChild(material);
}
ViewProviderDatumPlane::~ViewProviderDatumPlane()
{
}
void ViewProviderDatumPlane::updateData(const App::Property* prop)
{
// Gets called whenever a property of the attached object changes
PartDesign::Plane* pcDatum = static_cast<PartDesign::Plane*>(this->getObject());
if (strcmp(prop->getName(),"_Base") == 0) {
Base::Vector3d base = pcDatum->_Base.getValue();
Base::Vector3d normal = pcDatum->_Normal.getValue();
// Get limits of the plane from bounding box of the body
PartDesign::Body* body = PartDesign::Body::findBodyOf(this->getObject());
if (body == NULL)
return;
Part::Feature* tipSolid = static_cast<Part::Feature*>(body->getPrevSolidFeature());
if (tipSolid == NULL)
return;
Base::BoundBox3d bbox = tipSolid->Shape.getShape().getBoundBox();
bbox.Enlarge(0.1 * bbox.CalcDiagonalLength());
// Calculate intersection of plane with bounding box edges
// TODO: This can be a lot more efficient if we do the maths ourselves, e.g.
// http://cococubed.asu.edu/code_pages/raybox.shtml
// http://www.fho-emden.de/~hoffmann/cubeplane12112006.pdf
Handle_Geom_Plane plane = new Geom_Plane(gp_Pnt(base.x, base.y, base.z), gp_Dir(normal.x, normal.y, normal.z));
std::vector<Base::Vector3d> points;
for (int i = 0; i < 12; i++) {
// Get the edge of the bounding box
Base::Vector3d p1, p2;
bbox.CalcDistance(i, p1, p2);
Base::Vector3d ldir = p2 - p1;
Handle_Geom_Line line = new Geom_Line(gp_Pnt(p1.x, p1.y, p1.z), gp_Dir(ldir.x, ldir.y, ldir.z));
GeomAPI_IntCS intersector(line, plane);
if (!intersector.IsDone() || (intersector.NbPoints() == 0))
continue;
gp_Pnt pnt = intersector.Point(1);
Base::Vector3d point(pnt.X(), pnt.Y(), pnt.Z());
// Check whether intersection is on the bbox edge (bbox.IsInside() always tests false)
double edgeLength = (p1 - p2).Length();
double l1 = (p1 - point).Length();
double l2 = (p2 - point).Length();
if (fabs(edgeLength - l1 - l2) > 0.001)
continue;
// Check for duplicates
bool duplicate = false;
for (std::vector<Base::Vector3d>::const_iterator p = points.begin(); p != points.end(); p++) {
if ((point - *p).Sqr() < Precision::Confusion()) {
duplicate = true;
break;
}
}
if (!duplicate)
points.push_back(point);
}
if (points.size() < 3)
return;
// Sort the points to get a proper polygon, see http://www.fho-emden.de/~hoffmann/cubeplane12112006.pdf p.5
if (points.size() > 3) {
// Longest component of normal vector
int longest;
if (normal.x > normal.y)
if (normal.x > normal.z)
longest = 0; // x is longest
else
longest = 2; // z is longest
else
if (normal.y > normal.z)
longest = 1; // y is longest
else
longest = 2; // z is longest
// mean value for intersection points
Base::Vector3d m;
for (std::vector<Base::Vector3d>::iterator p = points.begin(); p != points.end(); p++)
m += *p;
m /= points.size();
// Sort by angles
double a[points.size()];
for (int i = 0; i < points.size() - 1; i++) {
if (longest == 0)
a[i] = atan2(points[i].z - m.z, points[i].y - m.y);
else if (longest == 1)
a[i] = atan2(points[i].z - m.z, points[i].x - m.x);
else
a[i] = atan2(points[i].y - m.y, points[i].x - m.x);
for (int k = i+1; k < points.size(); k++) {
if (longest == 0)
a[k] = atan2(points[k].z - m.z, points[k].y - m.y);
else if (longest == 1)
a[k] = atan2(points[k].z - m.z, points[k].x - m.x);
else
a[k] = atan2(points[k].y - m.y, points[k].x - m.x);
if (a[k] < a[i]) {
Base::Vector3d temp = points[i];
points[i] = points[k];
points[k] = temp;
a[i] = a[k];
}
}
}
}
// Display the plane
SoMFVec3f v;
v.setNum(points.size());
for (int p = 0; p < points.size(); p++)
v.set1Value(p, points[p].x, points[p].y, points[p].z);
SoMFInt32 idx;
idx.setNum(1);
idx.set1Value(0, points.size());
SoFaceSet* faceSet;
SoVertexProperty* vprop;
if (pShapeSep->getNumChildren() == 1) {
faceSet = new SoFaceSet();
vprop = new SoVertexProperty();
vprop->vertex = v;
faceSet->vertexProperty = vprop;
faceSet->numVertices = idx;
pShapeSep->addChild(faceSet);
} else {
faceSet = static_cast<SoFaceSet*>(pShapeSep->getChild(1));
vprop = static_cast<SoVertexProperty*>(faceSet->vertexProperty.getValue());
vprop->vertex = v;
faceSet->numVertices = idx;
}
}
ViewProviderDatum::updateData(prop);
}

View File

@ -69,46 +69,6 @@ protected:
}; };
class PartDesignGuiExport ViewProviderDatumPoint : public PartDesignGui::ViewProviderDatum
{
PROPERTY_HEADER(PartDesignGui::ViewProviderDatumPoint);
public:
/// Constructor
ViewProviderDatumPoint();
virtual ~ViewProviderDatumPoint();
virtual void updateData(const App::Property*);
};
class PartDesignGuiExport ViewProviderDatumLine : public PartDesignGui::ViewProviderDatum
{
PROPERTY_HEADER(PartDesignGui::ViewProviderDatumLine);
public:
/// Constructor
ViewProviderDatumLine();
virtual ~ViewProviderDatumLine();
virtual void updateData(const App::Property*);
};
class PartDesignGuiExport ViewProviderDatumPlane : public PartDesignGui::ViewProviderDatum
{
PROPERTY_HEADER(PartDesignGui::ViewProviderDatumPlane);
public:
/// Constructor
ViewProviderDatumPlane();
virtual ~ViewProviderDatumPlane();
virtual void updateData(const App::Property*);
};
} // namespace PartDesignGui } // namespace PartDesignGui

View File

@ -0,0 +1,132 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinlaender <jrheinlaender@users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <Inventor/nodes/SoSeparator.h>
# include <Inventor/nodes/SoPickStyle.h>
# include <Inventor/nodes/SoShapeHints.h>
# include <Inventor/nodes/SoMaterial.h>
# include <Inventor/nodes/SoBaseColor.h>
# include <Inventor/nodes/SoMarkerSet.h>
# include <Inventor/nodes/SoVertexProperty.h>
# include <Inventor/nodes/SoLineSet.h>
# include <Inventor/nodes/SoFaceSet.h>
# include <Inventor/details/SoLineDetail.h>
# include <Inventor/details/SoFaceDetail.h>
# include <Inventor/details/SoPointDetail.h>
# include <TopoDS_Vertex.hxx>
# include <TopoDS.hxx>
# include <BRep_Tool.hxx>
# include <gp_Pnt.hxx>
# include <Precision.hxx>
# include <Geom_Plane.hxx>
# include <Geom_Line.hxx>
# include <GeomAPI_IntCS.hxx>
#endif
#include "ViewProviderDatumLine.h"
#include "TaskDatumParameters.h"
#include "Workbench.h"
#include <Mod/PartDesign/App/DatumLine.h>
#include <Gui/Control.h>
#include <Gui/Command.h>
#include <Gui/Application.h>
#include <Mod/PartDesign/App/Body.h>
using namespace PartDesignGui;
PROPERTY_SOURCE(PartDesignGui::ViewProviderDatumLine,PartDesignGui::ViewProviderDatum)
ViewProviderDatumLine::ViewProviderDatumLine()
{
SoMaterial* material = new SoMaterial();
material->diffuseColor.setValue(0.9f, 0.9f, 0.13);
material->transparency.setValue(0.2);
pShapeSep->addChild(material);
}
ViewProviderDatumLine::~ViewProviderDatumLine()
{
}
void ViewProviderDatumLine::updateData(const App::Property* prop)
{
// Gets called whenever a property of the attached object changes
PartDesign::Line* pcDatum = static_cast<PartDesign::Line*>(this->getObject());
if (strcmp(prop->getName(),"_Base") == 0) {
Base::Vector3d base = pcDatum->_Base.getValue();
Base::Vector3d dir = pcDatum->_Direction.getValue();
// Get limits of the line from bounding box of the body
PartDesign::Body* body = PartDesign::Body::findBodyOf(this->getObject());
if (body == NULL)
return;
Part::Feature* tipSolid = static_cast<Part::Feature*>(body->getPrevSolidFeature());
if (tipSolid == NULL)
return;
Base::BoundBox3d bbox = tipSolid->Shape.getShape().getBoundBox();
bbox.Enlarge(0.1 * bbox.CalcDiagonalLength());
Base::Vector3d p1, p2;
if (bbox.IsInBox(base)) {
bbox.IntersectionPoint(base, dir, p1, Precision::Confusion());
bbox.IntersectionPoint(base, -dir, p2, Precision::Confusion());
} else {
bbox.IntersectWithLine(base, dir, p1, p2);
if ((p1 == Base::Vector3d(0,0,0)) && (p2 == Base::Vector3d(0,0,0)))
bbox.IntersectWithLine(base, -dir, p1, p2);
}
// Display the line
SoMFVec3f v;
v.setNum(2);
v.set1Value(0, p1.x, p1.y, p1.z);
v.set1Value(1, p2.x, p2.y, p2.z);
SoMFInt32 idx;
idx.setNum(1);
idx.set1Value(0, 2);
SoLineSet* lineSet;
SoVertexProperty* vprop;
if (pShapeSep->getNumChildren() == 1) {
lineSet = new SoLineSet();
vprop = new SoVertexProperty();
vprop->vertex = v;
lineSet->vertexProperty = vprop;
lineSet->numVertices = idx;
pShapeSep->addChild(lineSet);
} else {
lineSet = static_cast<SoLineSet*>(pShapeSep->getChild(1));
vprop = static_cast<SoVertexProperty*>(lineSet->vertexProperty.getValue());
vprop->vertex = v;
lineSet->numVertices = idx;
}
}
ViewProviderDatum::updateData(prop);
}

View File

@ -0,0 +1,48 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinlaender <jrheinlaender@users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef PARTGUI_ViewProviderDatumLine_H
#define PARTGUI_ViewProviderDatumLine_H
#include "Gui/ViewProviderGeometryObject.h"
#include "ViewProviderDatum.h"
namespace PartDesignGui {
class PartDesignGuiExport ViewProviderDatumLine : public PartDesignGui::ViewProviderDatum
{
PROPERTY_HEADER(PartDesignGui::ViewProviderDatumLine);
public:
/// Constructor
ViewProviderDatumLine();
virtual ~ViewProviderDatumLine();
virtual void updateData(const App::Property*);
};
} // namespace PartDesignGui
#endif // PARTGUI_ViewProviderDatumLine_H

View File

@ -0,0 +1,223 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinlaender <jrheinlaender@users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <Inventor/nodes/SoSeparator.h>
# include <Inventor/nodes/SoPickStyle.h>
# include <Inventor/nodes/SoShapeHints.h>
# include <Inventor/nodes/SoMaterial.h>
# include <Inventor/nodes/SoBaseColor.h>
# include <Inventor/nodes/SoMarkerSet.h>
# include <Inventor/nodes/SoVertexProperty.h>
# include <Inventor/nodes/SoLineSet.h>
# include <Inventor/nodes/SoFaceSet.h>
# include <Inventor/details/SoLineDetail.h>
# include <Inventor/details/SoFaceDetail.h>
# include <Inventor/details/SoPointDetail.h>
# include <TopoDS_Vertex.hxx>
# include <TopoDS.hxx>
# include <BRep_Tool.hxx>
# include <gp_Pnt.hxx>
# include <Precision.hxx>
# include <Geom_Plane.hxx>
# include <Geom_Line.hxx>
# include <GeomAPI_IntCS.hxx>
#endif
#include "ViewProviderDatumPlane.h"
#include "TaskDatumParameters.h"
#include "Workbench.h"
#include <Mod/PartDesign/App/DatumPlane.h>
#include <Gui/Control.h>
#include <Gui/Command.h>
#include <Gui/Application.h>
#include <Mod/PartDesign/App/Body.h>
using namespace PartDesignGui;
PROPERTY_SOURCE(PartDesignGui::ViewProviderDatumPlane,PartDesignGui::ViewProviderDatum)
ViewProviderDatumPlane::ViewProviderDatumPlane()
{
SoMaterial* material = new SoMaterial();
material->diffuseColor.setValue(0.9f, 0.9f, 0.13);
material->transparency.setValue(0.2);
pShapeSep->addChild(material);
}
ViewProviderDatumPlane::~ViewProviderDatumPlane()
{
}
void ViewProviderDatumPlane::updateData(const App::Property* prop)
{
// Gets called whenever a property of the attached object changes
PartDesign::Plane* pcDatum = static_cast<PartDesign::Plane*>(this->getObject());
if (strcmp(prop->getName(),"_Base") == 0) {
Base::Vector3d base = pcDatum->_Base.getValue();
Base::Vector3d normal = pcDatum->_Normal.getValue();
// Get limits of the plane from bounding box of the body
PartDesign::Body* body = PartDesign::Body::findBodyOf(this->getObject());
if (body == NULL)
return;
Part::Feature* tipSolid = static_cast<Part::Feature*>(body->getPrevSolidFeature());
if (tipSolid == NULL)
return;
Base::BoundBox3d bbox = tipSolid->Shape.getShape().getBoundBox();
bbox.Enlarge(0.1 * bbox.CalcDiagonalLength());
// Calculate intersection of plane with bounding box edges
// TODO: This can be a lot more efficient if we do the maths ourselves, e.g.
// http://cococubed.asu.edu/code_pages/raybox.shtml
// http://www.fho-emden.de/~hoffmann/cubeplane12112006.pdf
Handle_Geom_Plane plane = new Geom_Plane(gp_Pnt(base.x, base.y, base.z), gp_Dir(normal.x, normal.y, normal.z));
std::vector<Base::Vector3d> points;
for (int i = 0; i < 12; i++) {
// Get the edge of the bounding box
Base::Vector3d p1, p2;
bbox.CalcEdge(i, p1, p2);
Base::Vector3d ldir = p2 - p1;
Handle_Geom_Line line = new Geom_Line(gp_Pnt(p1.x, p1.y, p1.z), gp_Dir(ldir.x, ldir.y, ldir.z));
GeomAPI_IntCS intersector(line, plane);
if (!intersector.IsDone() || (intersector.NbPoints() == 0))
continue;
gp_Pnt pnt = intersector.Point(1);
Base::Vector3d point(pnt.X(), pnt.Y(), pnt.Z());
// Check whether intersection is on the bbox edge (bbox.IsInside() always tests false)
double edgeLength = (p1 - p2).Length();
double l1 = (p1 - point).Length();
double l2 = (p2 - point).Length();
if (fabs(edgeLength - l1 - l2) > 0.001)
continue;
// Check for duplicates
bool duplicate = false;
for (std::vector<Base::Vector3d>::const_iterator p = points.begin(); p != points.end(); p++) {
if ((point - *p).Sqr() < Precision::Confusion()) {
duplicate = true;
break;
}
}
if (!duplicate)
points.push_back(point);
}
if (points.size() < 3)
return;
// Sort the points to get a proper polygon, see http://www.fho-emden.de/~hoffmann/cubeplane12112006.pdf p.5
if (points.size() > 3) {
// Longest component of normal vector
int longest;
if (normal.x > normal.y)
if (normal.x > normal.z)
longest = 0; // x is longest
else
longest = 2; // z is longest
else
if (normal.y > normal.z)
longest = 1; // y is longest
else
longest = 2; // z is longest
// mean value for intersection points
Base::Vector3d m;
for (std::vector<Base::Vector3d>::iterator p = points.begin(); p != points.end(); p++)
m += *p;
m /= points.size();
// Sort by angles
double a[points.size()];
for (int i = 0; i < points.size() - 1; i++) {
if (longest == 0)
a[i] = atan2(points[i].z - m.z, points[i].y - m.y);
else if (longest == 1)
a[i] = atan2(points[i].z - m.z, points[i].x - m.x);
else
a[i] = atan2(points[i].y - m.y, points[i].x - m.x);
for (int k = i+1; k < points.size(); k++) {
if (longest == 0)
a[k] = atan2(points[k].z - m.z, points[k].y - m.y);
else if (longest == 1)
a[k] = atan2(points[k].z - m.z, points[k].x - m.x);
else
a[k] = atan2(points[k].y - m.y, points[k].x - m.x);
if (a[k] < a[i]) {
Base::Vector3d temp = points[i];
points[i] = points[k];
points[k] = temp;
a[i] = a[k];
}
}
}
}
// Display the plane
SoMFVec3f v;
v.setNum(points.size());
for (int p = 0; p < points.size(); p++)
v.set1Value(p, points[p].x, points[p].y, points[p].z);
SoMFInt32 idx;
idx.setNum(1);
idx.set1Value(0, points.size());
SoFaceSet* faceSet;
SoLineSet* lineSet;
SoVertexProperty* vprop;
if (pShapeSep->getNumChildren() == 1) {
faceSet = new SoFaceSet();
vprop = new SoVertexProperty();
vprop->vertex = v;
faceSet->vertexProperty = vprop;
faceSet->numVertices = idx;
pShapeSep->addChild(faceSet);
lineSet = new SoLineSet();
lineSet->vertexProperty = vprop;
lineSet->numVertices = idx;
pShapeSep->addChild(lineSet);
} else {
faceSet = static_cast<SoFaceSet*>(pShapeSep->getChild(1));
vprop = static_cast<SoVertexProperty*>(faceSet->vertexProperty.getValue());
vprop->vertex = v;
faceSet->numVertices = idx;
lineSet = static_cast<SoLineSet*>(pShapeSep->getChild(2));
vprop = static_cast<SoVertexProperty*>(lineSet->vertexProperty.getValue());
vprop->vertex = v;
lineSet->numVertices = idx;
}
}
ViewProviderDatum::updateData(prop);
}

View File

@ -0,0 +1,48 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinlaender <jrheinlaender@users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef PARTGUI_ViewProviderDatumPlane_H
#define PARTGUI_ViewProviderDatumPlane_H
#include "Gui/ViewProviderGeometryObject.h"
#include "ViewProviderDatum.h"
namespace PartDesignGui {
class PartDesignGuiExport ViewProviderDatumPlane : public PartDesignGui::ViewProviderDatum
{
PROPERTY_HEADER(PartDesignGui::ViewProviderDatumPlane);
public:
/// Constructor
ViewProviderDatumPlane();
virtual ~ViewProviderDatumPlane();
virtual void updateData(const App::Property*);
};
} // namespace PartDesignGui
#endif // PARTGUI_ViewProviderDatumPlane_H

View File

@ -0,0 +1,101 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinlaender <jrheinlaender@users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <Inventor/nodes/SoSeparator.h>
# include <Inventor/nodes/SoPickStyle.h>
# include <Inventor/nodes/SoShapeHints.h>
# include <Inventor/nodes/SoMaterial.h>
# include <Inventor/nodes/SoBaseColor.h>
# include <Inventor/nodes/SoMarkerSet.h>
# include <Inventor/nodes/SoVertexProperty.h>
# include <Inventor/nodes/SoLineSet.h>
# include <Inventor/nodes/SoFaceSet.h>
# include <Inventor/details/SoLineDetail.h>
# include <Inventor/details/SoFaceDetail.h>
# include <Inventor/details/SoPointDetail.h>
# include <TopoDS_Vertex.hxx>
# include <TopoDS.hxx>
# include <BRep_Tool.hxx>
# include <gp_Pnt.hxx>
# include <Precision.hxx>
# include <Geom_Plane.hxx>
# include <Geom_Line.hxx>
# include <GeomAPI_IntCS.hxx>
#endif
#include "ViewProviderDatumPoint.h"
#include "TaskDatumParameters.h"
#include "Workbench.h"
#include <Mod/PartDesign/App/DatumPoint.h>
#include <Gui/Control.h>
#include <Gui/Command.h>
#include <Gui/Application.h>
#include <Mod/PartDesign/App/Body.h>
using namespace PartDesignGui;
PROPERTY_SOURCE(PartDesignGui::ViewProviderDatumPoint,PartDesignGui::ViewProviderDatum)
ViewProviderDatumPoint::ViewProviderDatumPoint()
{
SoMarkerSet* points = new SoMarkerSet();
points->markerIndex = SoMarkerSet::DIAMOND_FILLED_9_9;
points->numPoints = 0;
pShapeSep->addChild(points);
}
ViewProviderDatumPoint::~ViewProviderDatumPoint()
{
}
void ViewProviderDatumPoint::updateData(const App::Property* prop)
{
// Gets called whenever a property of the attached object changes
PartDesign::Point* pcDatum = static_cast<PartDesign::Point*>(this->getObject());
if (strcmp(prop->getName(),"_Point") == 0) {
Base::Vector3d p = pcDatum->_Point.getValue();
SoMFVec3f v;
v.setNum(1);
v.set1Value(0, p.x, p.y, p.z);
SoMarkerSet* points = static_cast<SoMarkerSet*>(pShapeSep->getChild(0));
SoVertexProperty* vprop;
if (points->vertexProperty.getValue() == NULL) {
vprop = new SoVertexProperty();
vprop->vertex = v;
points->vertexProperty = vprop;
} else {
vprop = static_cast<SoVertexProperty*>(points->vertexProperty.getValue());
vprop->vertex = v;
}
points->numPoints = 1;
}
ViewProviderDatum::updateData(prop);
}

View File

@ -0,0 +1,48 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinlaender <jrheinlaender@users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef PARTGUI_ViewProviderDatumPoint_H
#define PARTGUI_ViewProviderDatumPoint_H
#include "Gui/ViewProviderGeometryObject.h"
#include "ViewProviderDatum.h"
namespace PartDesignGui {
class PartDesignGuiExport ViewProviderDatumPoint : public PartDesignGui::ViewProviderDatum
{
PROPERTY_HEADER(PartDesignGui::ViewProviderDatumPoint);
public:
/// Constructor
ViewProviderDatumPoint();
virtual ~ViewProviderDatumPoint();
virtual void updateData(const App::Property*);
};
} // namespace PartDesignGui
#endif // PARTGUI_ViewProviderDatumPoint_H

View File

@ -47,7 +47,7 @@
#include <Mod/PartDesign/App/Body.h> #include <Mod/PartDesign/App/Body.h>
#include <Mod/PartDesign/App/Feature.h> #include <Mod/PartDesign/App/Feature.h>
#include <Mod/PartDesign/App/FeatureSketchBased.h> #include <Mod/PartDesign/App/FeatureSketchBased.h>
#include <Mod/PartDesign/App/DatumFeature.h> #include <Mod/Part/App/DatumFeature.h>
#include <Mod/Sketcher/App/SketchObject.h> #include <Mod/Sketcher/App/SketchObject.h>
using namespace PartDesignGui; using namespace PartDesignGui;
@ -262,7 +262,7 @@ void Workbench::setupContextMenu(const char* recipient, Gui::MenuItem* item) con
if (strcmp(recipient,"Tree") == 0) if (strcmp(recipient,"Tree") == 0)
{ {
if (Gui::Selection().countObjectsOfType(PartDesign::Feature::getClassTypeId()) + if (Gui::Selection().countObjectsOfType(PartDesign::Feature::getClassTypeId()) +
Gui::Selection().countObjectsOfType(PartDesign::Datum::getClassTypeId()) + Gui::Selection().countObjectsOfType(Part::Datum::getClassTypeId()) +
Gui::Selection().countObjectsOfType(Part::Part2DObject::getClassTypeId()) > 0 ) Gui::Selection().countObjectsOfType(Part::Part2DObject::getClassTypeId()) > 0 )
*item << "PartDesign_MoveTip"; *item << "PartDesign_MoveTip";
} }

View File

@ -25,6 +25,7 @@
#ifndef _PreComp_ #ifndef _PreComp_
# include <TopoDS_Shape.hxx> # include <TopoDS_Shape.hxx>
# include <TopoDS_Face.hxx> # include <TopoDS_Face.hxx>
# include <TopoDS_Edge.hxx>
# include <TopoDS.hxx> # include <TopoDS.hxx>
# include <TopExp_Explorer.hxx> # include <TopExp_Explorer.hxx>
# include <gp_Pln.hxx> # include <gp_Pln.hxx>
@ -34,6 +35,7 @@
# include <BRepAdaptor_Surface.hxx> # include <BRepAdaptor_Surface.hxx>
# include <BRepAdaptor_Curve.hxx> # include <BRepAdaptor_Curve.hxx>
# include <BRep_Tool.hxx> # include <BRep_Tool.hxx>
# include <Geom_Line.hxx>
# include <Geom_Plane.hxx> # include <Geom_Plane.hxx>
# include <Geom_Circle.hxx> # include <Geom_Circle.hxx>
# include <Geom_Ellipse.hxx> # include <Geom_Ellipse.hxx>
@ -41,6 +43,9 @@
# include <GeomAPI_ProjectPointOnSurf.hxx> # include <GeomAPI_ProjectPointOnSurf.hxx>
# include <BRepOffsetAPI_NormalProjection.hxx> # include <BRepOffsetAPI_NormalProjection.hxx>
# include <BRepBuilderAPI_MakeFace.hxx> # include <BRepBuilderAPI_MakeFace.hxx>
# include <BRepBuilderAPI_MakeEdge.hxx>
# include <GeomAPI_IntSS.hxx>
# include <BRepProj_Projection.hxx>
# include <Standard_Version.hxx> # include <Standard_Version.hxx>
# include <cmath> # include <cmath>
# include <vector> # include <vector>
@ -56,8 +61,10 @@
#include <Base/Console.h> #include <Base/Console.h>
#include <Base/Vector3D.h> #include <Base/Vector3D.h>
#include <App/Plane.h>
#include <Mod/Part/App/Geometry.h> #include <Mod/Part/App/Geometry.h>
#include <Mod/PartDesign/App/DatumFeature.h> #include <Mod/Part/App/DatumFeature.h>
#include "SketchObject.h" #include "SketchObject.h"
#include "SketchObjectPy.h" #include "SketchObjectPy.h"
@ -119,15 +126,7 @@ App::DocumentObjectExecReturn *SketchObject::execute(void)
if (support == NULL) if (support == NULL)
throw Base::Exception("Sketch support has been deleted"); throw Base::Exception("Sketch support has been deleted");
if (support->getTypeId().isDerivedFrom(PartDesign::Plane::getClassTypeId())) { this->positionBySupport();
// We don't want to handle this case in Part::Part2DObject because then Part would depend on PartDesign
PartDesign::Plane* plane = static_cast<PartDesign::Plane*>(support);
Base::Vector3d pos = plane->_Base.getValue();
Base::Vector3d normal = plane->_Normal.getValue();
this->Placement.setValue(Base::Placement(pos, Base::Rotation(Base::Vector3d(0,0,1), normal)));
} else {
this->positionBySupport();
}
} }
catch (const Base::Exception& e) { catch (const Base::Exception& e) {
return new App::DocumentObjectExecReturn(e.what()); return new App::DocumentObjectExecReturn(e.what());
@ -2713,8 +2712,10 @@ int SketchObject::DeleteUnusedInternalGeometry(int GeoId)
int SketchObject::addExternal(App::DocumentObject *Obj, const char* SubName) int SketchObject::addExternal(App::DocumentObject *Obj, const char* SubName)
{ {
// so far only externals to the support of the sketch // so far only externals to the support of the sketch and datum features
if (Support.getValue() != Obj) if (Support.getValue() != Obj)
if (!Obj->getTypeId().isDerivedFrom(App::Plane::getClassTypeId()) &&
!Obj->getTypeId().isDerivedFrom(Part::Datum::getClassTypeId()))
return -1; return -1;
// get the actual lists of the externals // get the actual lists of the externals
@ -2889,6 +2890,56 @@ const Part::Geometry* SketchObject::getGeometry(int GeoId) const
return 0; return 0;
} }
// Auxiliary method
Part::Geometry* projectLine(const BRepAdaptor_Curve& curve, const Handle(Geom_Plane)& gPlane, const Base::Placement& invPlm)
{
double first = curve.FirstParameter();
bool infinite = false;
if (fabs(first) > 1E99) {
// TODO: What is OCE's definition of Infinite?
// TODO: The clean way to do this is to handle a new sketch geometry Geom::Line
// but its a lot of work to implement...
first = -10000;
//infinite = true;
}
double last = curve.LastParameter();
if (fabs(last) > 1E99) {
last = +10000;
//infinite = true;
}
gp_Pnt P1 = curve.Value(first);
gp_Pnt P2 = curve.Value(last);
GeomAPI_ProjectPointOnSurf proj1(P1,gPlane);
P1 = proj1.NearestPoint();
GeomAPI_ProjectPointOnSurf proj2(P2,gPlane);
P2 = proj2.NearestPoint();
Base::Vector3d p1(P1.X(),P1.Y(),P1.Z());
Base::Vector3d p2(P2.X(),P2.Y(),P2.Z());
invPlm.multVec(p1,p1);
invPlm.multVec(p2,p2);
if (Base::Distance(p1,p2) < Precision::Confusion()) {
Base::Vector3d p = (p1 + p2) / 2;
Part::GeomPoint* point = new Part::GeomPoint(p);
point->Construction = true;
return point;
}
else if (!infinite) {
Part::GeomLineSegment* line = new Part::GeomLineSegment();
line->setPoints(p1,p2);
line->Construction = true;
return line;
} else {
Part::GeomLine* line = new Part::GeomLine();
line->setLine(p1, p2 - p1);
line->Construction = true;
return line;
}
}
bool SketchObject::evaluateSupport(void) bool SketchObject::evaluateSupport(void)
{ {
// returns false if the shape if broken, null or non-planar // returns false if the shape if broken, null or non-planar
@ -3028,18 +3079,39 @@ void SketchObject::rebuildExternalGeometry(void)
ExternalGeo.push_back(VLine); ExternalGeo.push_back(VLine);
for (int i=0; i < int(Objects.size()); i++) { for (int i=0; i < int(Objects.size()); i++) {
const App::DocumentObject *Obj=Objects[i]; const App::DocumentObject *Obj=Objects[i];
const std::string SubElement=SubElements[i]; const std::string SubElement=SubElements[i];
const Part::Feature *refObj=static_cast<const Part::Feature*>(Obj);
const Part::TopoShape& refShape=refObj->Shape.getShape();
TopoDS_Shape refSubShape; TopoDS_Shape refSubShape;
try {
refSubShape = refShape.getSubShape(SubElement.c_str()); if (Obj->getTypeId().isDerivedFrom(Part::Datum::getClassTypeId())) {
} const Part::Datum* datum = static_cast<const Part::Datum*>(Obj);
catch (Standard_Failure) { refSubShape = datum->Shape.getValue();
Handle_Standard_Failure e = Standard_Failure::Caught(); } else if (Obj->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
throw Base::Exception(e->GetMessageString()); try {
const Part::Feature *refObj=static_cast<const Part::Feature*>(Obj);
const Part::TopoShape& refShape=refObj->Shape.getShape();
refSubShape = refShape.getSubShape(SubElement.c_str());
}
catch (Standard_Failure) {
Handle_Standard_Failure e = Standard_Failure::Caught();
throw Base::Exception(e->GetMessageString());
}
} else if (Obj->getTypeId().isDerivedFrom(App::Plane::getClassTypeId())) {
const App::Plane* pl = static_cast<const App::Plane*>(Obj);
Base::Placement plm = pl->Placement.getValue();
Base::Vector3d base = plm.getPosition();
Base::Rotation rot = plm.getRotation();
Base::Vector3d normal(0,0,1);
rot.multVec(normal, normal);
gp_Pln plane(gp_Pnt(base.x,base.y,base.z), gp_Dir(normal.x, normal.y, normal.z));
BRepBuilderAPI_MakeFace fBuilder(plane);
if (!fBuilder.IsDone())
throw Base::Exception("Sketcher: addExternal(): Failed to build face from App::Plane");
TopoDS_Face f = TopoDS::Face(fBuilder.Shape());
refSubShape = f;
} else {
throw Base::Exception("Datum feature type is not yet supported as external geometry for a sketch");
} }
switch (refSubShape.ShapeType()) switch (refSubShape.ShapeType())
@ -3049,8 +3121,27 @@ void SketchObject::rebuildExternalGeometry(void)
const TopoDS_Face& face = TopoDS::Face(refSubShape); const TopoDS_Face& face = TopoDS::Face(refSubShape);
BRepAdaptor_Surface surface(face); BRepAdaptor_Surface surface(face);
if (surface.GetType() == GeomAbs_Plane) { if (surface.GetType() == GeomAbs_Plane) {
// Check that the plane is perpendicular to the sketch plane
Geom_Plane plane = surface.Plane();
gp_Dir dnormal = plane.Axis().Direction();
gp_Dir snormal = sketchPlane.Axis().Direction();
if (fabs(dnormal.Angle(snormal) - M_PI_2) < Precision::Confusion()) {
// Get vector that is normal to both sketch plane normal and plane normal. This is the line's direction
gp_Dir lnormal = dnormal.Crossed(snormal);
BRepBuilderAPI_MakeEdge builder(gp_Lin(plane.Location(), lnormal));
builder.Build();
if (builder.IsDone()) {
const TopoDS_Edge& edge = TopoDS::Edge(builder.Shape());
BRepAdaptor_Curve curve(edge);
if (curve.GetType() == GeomAbs_Line) {
ExternalGeo.push_back(projectLine(curve, gPlane, invPlm));
}
}
}
} else {
throw Base::Exception("Non-planar faces are not yet supported for external geometry of sketches");
} }
throw Base::Exception("Faces are not yet supported for external geometry of sketches");
} }
break; break;
case TopAbs_EDGE: case TopAbs_EDGE:
@ -3058,31 +3149,7 @@ void SketchObject::rebuildExternalGeometry(void)
const TopoDS_Edge& edge = TopoDS::Edge(refSubShape); const TopoDS_Edge& edge = TopoDS::Edge(refSubShape);
BRepAdaptor_Curve curve(edge); BRepAdaptor_Curve curve(edge);
if (curve.GetType() == GeomAbs_Line) { if (curve.GetType() == GeomAbs_Line) {
gp_Pnt P1 = curve.Value(curve.FirstParameter()); ExternalGeo.push_back(projectLine(curve, gPlane, invPlm));
gp_Pnt P2 = curve.Value(curve.LastParameter());
GeomAPI_ProjectPointOnSurf proj1(P1,gPlane);
P1 = proj1.NearestPoint();
GeomAPI_ProjectPointOnSurf proj2(P2,gPlane);
P2 = proj2.NearestPoint();
Base::Vector3d p1(P1.X(),P1.Y(),P1.Z());
Base::Vector3d p2(P2.X(),P2.Y(),P2.Z());
invPlm.multVec(p1,p1);
invPlm.multVec(p2,p2);
if (Base::Distance(p1,p2) < Precision::Confusion()) {
Base::Vector3d p = (p1 + p2) / 2;
Part::GeomPoint* point = new Part::GeomPoint(p);
point->Construction = true;
ExternalGeo.push_back(point);
}
else {
Part::GeomLineSegment* line = new Part::GeomLineSegment();
line->setPoints(p1,p2);
line->Construction = true;
ExternalGeo.push_back(line);
}
} }
else if (curve.GetType() == GeomAbs_Circle) { else if (curve.GetType() == GeomAbs_Circle) {
gp_Dir vec1 = sketchPlane.Axis().Direction(); gp_Dir vec1 = sketchPlane.Axis().Direction();

File diff suppressed because it is too large Load Diff

View File

@ -31,12 +31,14 @@
#include <Mod/Sketcher/App/SketchObject.h> #include <Mod/Sketcher/App/SketchObject.h>
#include <Mod/Part/App/LinePy.h> #include <Mod/Part/App/LinePy.h>
#include <Mod/Part/App/Geometry.h> #include <Mod/Part/App/Geometry.h>
#include <Mod/Part/App/DatumFeature.h>
#include <Base/GeometryPyCXX.h> #include <Base/GeometryPyCXX.h>
#include <Base/VectorPy.h> #include <Base/VectorPy.h>
#include <Base/AxisPy.h> #include <Base/AxisPy.h>
#include <Base/Tools.h> #include <Base/Tools.h>
#include <Base/QuantityPy.h> #include <Base/QuantityPy.h>
#include <App/Document.h> #include <App/Document.h>
#include <App/Plane.h>
#include <CXX/Objects.hxx> #include <CXX/Objects.hxx>
// inclusion of the generated files (generated out of SketchObjectSFPy.xml) // inclusion of the generated files (generated out of SketchObjectSFPy.xml)
@ -381,10 +383,20 @@ PyObject* SketchObjectPy::addExternal(PyObject *args)
PyErr_SetString(PyExc_ValueError, str.str().c_str()); PyErr_SetString(PyExc_ValueError, str.str().c_str());
return 0; return 0;
} }
// check if it belongs to the sketch support // check if it is a datum feature
if (this->getSketchObjectPtr()->Support.getValue() != Obj) { // TODO: Allow selection only from Body which this sketch belongs to?
if (Obj->getTypeId().isDerivedFrom(Part::Datum::getClassTypeId())) {
// OK
} else if (Obj->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
if (this->getSketchObjectPtr()->Support.getValue() != Obj) {
std::stringstream str;
str << ObjectName << "is not supported by this sketch";
PyErr_SetString(PyExc_ValueError, str.str().c_str());
return 0;
}
} else if (!Obj->getTypeId().isDerivedFrom(App::Plane::getClassTypeId())) {
std::stringstream str; std::stringstream str;
str << ObjectName << "is not supported by this sketch"; str << ObjectName << "must be a Part feature or a datum feature";
PyErr_SetString(PyExc_ValueError, str.str().c_str()); PyErr_SetString(PyExc_ValueError, str.str().c_str());
return 0; return 0;
} }

View File

@ -36,6 +36,7 @@
#include <Base/Exception.h> #include <Base/Exception.h>
#include <Base/Tools.h> #include <Base/Tools.h>
#include <App/Plane.h>
#include <Gui/Action.h> #include <Gui/Action.h>
#include <Gui/Application.h> #include <Gui/Application.h>
#include <Gui/BitmapFactory.h> #include <Gui/BitmapFactory.h>
@ -46,6 +47,7 @@
#include <Gui/Selection.h> #include <Gui/Selection.h>
#include <Gui/SelectionFilter.h> #include <Gui/SelectionFilter.h>
#include <Mod/Sketcher/App/SketchObject.h> #include <Mod/Sketcher/App/SketchObject.h>
#include <Mod/Part/App/DatumFeature.h>
#include "ViewProviderSketch.h" #include "ViewProviderSketch.h"
#include "DrawSketchHandler.h" #include "DrawSketchHandler.h"
@ -4473,7 +4475,12 @@ namespace SketcherGui {
{ {
Sketcher::SketchObject *sketch = static_cast<Sketcher::SketchObject*>(object); Sketcher::SketchObject *sketch = static_cast<Sketcher::SketchObject*>(object);
App::DocumentObject *support = sketch->Support.getValue(); App::DocumentObject *support = sketch->Support.getValue();
// for the moment we allow external constraints only from the support
// for the moment we allow external constraints only from the support and datum features
if(pObj->getTypeId().isDerivedFrom(App::Plane::getClassTypeId()) ||
pObj->getTypeId().isDerivedFrom(Part::Datum::getClassTypeId()))
return true;
if (pObj != support) if (pObj != support)
return false; return false;
if (!sSubName || sSubName[0] == '\0') if (!sSubName || sSubName[0] == '\0')
@ -4582,8 +4589,13 @@ public:
virtual bool onSelectionChanged(const Gui::SelectionChanges& msg) virtual bool onSelectionChanged(const Gui::SelectionChanges& msg)
{ {
if (msg.Type == Gui::SelectionChanges::AddSelection) { if (msg.Type == Gui::SelectionChanges::AddSelection) {
App::DocumentObject* obj = sketchgui->getObject()->getDocument()->getObject(msg.pObjectName);
if (obj == NULL)
throw Base::Exception("Sketcher: External geometry: Invalid object in selection");
std::string subName(msg.pSubName); std::string subName(msg.pSubName);
if ((subName.size() > 4 && subName.substr(0,4) == "Edge") || if (obj->getTypeId().isDerivedFrom(App::Plane::getClassTypeId()) ||
obj->getTypeId().isDerivedFrom(Part::Datum::getClassTypeId()) ||
(subName.size() > 4 && subName.substr(0,4) == "Edge") ||
(subName.size() > 6 && subName.substr(0,6) == "Vertex")) { (subName.size() > 6 && subName.substr(0,6) == "Vertex")) {
try { try {
Gui::Command::openCommand("Add external geometry"); Gui::Command::openCommand("Add external geometry");