Moved generic Datum class to Part module to avoid Sketcher dependency on PartDesign
This commit is contained in:
parent
20ba1983a4
commit
5b3d5e6bd8
|
@ -91,6 +91,7 @@
|
|||
#include "BRepOffsetAPI_MakePipeShellPy.h"
|
||||
#include "PartFeaturePy.h"
|
||||
#include "PropertyGeometryList.h"
|
||||
#include "DatumFeature.h"
|
||||
|
||||
namespace Part {
|
||||
extern PyObject* initModule();
|
||||
|
@ -301,7 +302,7 @@ PyMODINIT_FUNC initPart()
|
|||
Part::GeomTrimmedSurface ::init();
|
||||
Part::GeomSurfaceOfRevolution ::init();
|
||||
Part::GeomSurfaceOfExtrusion ::init();
|
||||
|
||||
Part::Datum ::init();
|
||||
|
||||
IGESControl_Controller::Init();
|
||||
STEPControl_Controller::Init();
|
||||
|
|
|
@ -137,6 +137,8 @@ SET(Features_SRCS
|
|||
CustomFeature.h
|
||||
BodyBase.h
|
||||
BodyBase.cpp
|
||||
DatumFeature.cpp
|
||||
DatumFeature.h
|
||||
)
|
||||
SOURCE_GROUP("Features" FILES ${Features_SRCS})
|
||||
|
||||
|
|
103
src/Mod/Part/App/DatumFeature.cpp
Normal file
103
src/Mod/Part/App/DatumFeature.cpp
Normal 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();
|
||||
}
|
||||
|
75
src/Mod/Part/App/DatumFeature.h
Normal file
75
src/Mod/Part/App/DatumFeature.h
Normal 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
|
|
@ -48,6 +48,7 @@
|
|||
#include <App/Plane.h>
|
||||
#include "Part2DObject.h"
|
||||
#include "Geometry.h"
|
||||
#include "DatumFeature.h"
|
||||
|
||||
#include <App/FeaturePythonPyImp.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
|
||||
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)) {
|
||||
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));
|
||||
|
@ -111,6 +112,18 @@ void Part2DObject::positionBySupport(void)
|
|||
Place.getRotation().multVec(Base::Vector3d(0,0,1),dir);
|
||||
Base::Vector3d pos = Place.getPosition();
|
||||
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 {
|
||||
Part::Feature *part = static_cast<Part::Feature*>(support);
|
||||
if (!part || !part->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId()))
|
||||
|
|
|
@ -49,7 +49,9 @@
|
|||
#include "FeatureScaled.h"
|
||||
#include "FeatureMultiTransform.h"
|
||||
#include "FeatureHole.h"
|
||||
#include "DatumFeature.h"
|
||||
#include "DatumPlane.h"
|
||||
#include "DatumLine.h"
|
||||
#include "DatumPoint.h"
|
||||
|
||||
namespace PartDesign {
|
||||
extern PyObject* initModule();
|
||||
|
@ -97,7 +99,6 @@ PyMODINIT_FUNC init_PartDesign()
|
|||
PartDesign::Groove ::init();
|
||||
PartDesign::Chamfer ::init();
|
||||
PartDesign::Draft ::init();
|
||||
PartDesign::Datum ::init();
|
||||
PartDesign::Plane ::init();
|
||||
PartDesign::Line ::init();
|
||||
PartDesign::Point ::init();
|
||||
|
|
|
@ -28,14 +28,14 @@
|
|||
#include <Base/Placement.h>
|
||||
|
||||
#include "Feature.h"
|
||||
#include "DatumFeature.h"
|
||||
#include "Body.h"
|
||||
#include "BodyPy.h"
|
||||
#include "FeatureSketchBased.h"
|
||||
|
||||
#include <App/Application.h>
|
||||
#include <App/Document.h>
|
||||
#include <Base/Console.h>
|
||||
#include "FeatureSketchBased.h"
|
||||
#include <Mod/Part/App/DatumFeature.h>
|
||||
|
||||
|
||||
using namespace PartDesign;
|
||||
|
@ -192,7 +192,7 @@ const bool Body::isAllowed(const App::DocumentObject* f)
|
|||
return false;
|
||||
|
||||
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()));
|
||||
}
|
||||
|
||||
|
@ -214,7 +214,6 @@ Body* Body::findBodyOf(const App::DocumentObject* f)
|
|||
void Body::addFeature(App::DocumentObject *feature)
|
||||
{
|
||||
// Set the BaseFeature property
|
||||
// Note: This is not strictly necessary for Datum features
|
||||
if (feature->getTypeId().isDerivedFrom(PartDesign::Feature::getClassTypeId())) {
|
||||
App::DocumentObject* prevSolidFeature = getPrevSolidFeature(NULL, true);
|
||||
if (prevSolidFeature != NULL)
|
||||
|
|
|
@ -91,13 +91,13 @@ public:
|
|||
/**
|
||||
* 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
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
#include "Mod/Part/App/Part2DObject.h"
|
||||
#include "Mod/PartDesign/App/Body.h"
|
||||
#include "Mod/PartDesign/App/DatumFeature.h"
|
||||
|
||||
// inclusion of the generated files (generated out of ItemPy.xml)
|
||||
#include "BodyPy.h"
|
||||
|
|
|
@ -39,8 +39,12 @@ SET(Features_SRCS
|
|||
SOURCE_GROUP("Features" FILES ${Features_SRCS})
|
||||
|
||||
SET(DatumFeatures_SRCS
|
||||
DatumFeature.cpp
|
||||
DatumFeature.h
|
||||
DatumPlane.cpp
|
||||
DatumPlane.h
|
||||
DatumLine.cpp
|
||||
DatumLine.h
|
||||
DatumPoint.cpp
|
||||
DatumPoint.h
|
||||
)
|
||||
SOURCE_GROUP("DatumFeatures" FILES ${DatumFeatures_SRCS})
|
||||
|
||||
|
|
|
@ -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>();
|
||||
}
|
|
@ -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
|
280
src/Mod/PartDesign/App/DatumLine.cpp
Normal file
280
src/Mod/PartDesign/App/DatumLine.cpp
Normal 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>();
|
||||
}
|
64
src/Mod/PartDesign/App/DatumLine.h
Normal file
64
src/Mod/PartDesign/App/DatumLine.h
Normal 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
|
317
src/Mod/PartDesign/App/DatumPlane.cpp
Normal file
317
src/Mod/PartDesign/App/DatumPlane.cpp
Normal 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>();
|
||||
}
|
62
src/Mod/PartDesign/App/DatumPlane.h
Normal file
62
src/Mod/PartDesign/App/DatumPlane.h
Normal 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
|
331
src/Mod/PartDesign/App/DatumPoint.cpp
Normal file
331
src/Mod/PartDesign/App/DatumPoint.cpp
Normal 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");
|
||||
}
|
||||
|
||||
}
|
69
src/Mod/PartDesign/App/DatumPoint.h
Normal file
69
src/Mod/PartDesign/App/DatumPoint.h
Normal 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
|
|
@ -48,7 +48,9 @@
|
|||
#include "ViewProviderPolarPattern.h"
|
||||
#include "ViewProviderScaled.h"
|
||||
#include "ViewProviderMultiTransform.h"
|
||||
#include "ViewProviderDatum.h"
|
||||
#include "ViewProviderDatumPoint.h"
|
||||
#include "ViewProviderDatumLine.h"
|
||||
#include "ViewProviderDatumPlane.h"
|
||||
|
||||
// use a different name to CreateCommand()
|
||||
void CreatePartDesignCommands(void);
|
||||
|
|
|
@ -106,6 +106,12 @@ SET(PartDesignGuiViewProvider_SRCS
|
|||
ViewProviderMultiTransform.h
|
||||
ViewProviderDatum.cpp
|
||||
ViewProviderDatum.h
|
||||
ViewProviderDatumPoint.cpp
|
||||
ViewProviderDatumPoint.h
|
||||
ViewProviderDatumLine.cpp
|
||||
ViewProviderDatumLine.h
|
||||
ViewProviderDatumPlane.cpp
|
||||
ViewProviderDatumPlane.h
|
||||
)
|
||||
SOURCE_GROUP("ViewProvider" FILES ${PartDesignGuiViewProvider_SRCS})
|
||||
|
||||
|
|
|
@ -63,13 +63,15 @@
|
|||
#include <Mod/Part/App/Part2DObject.h>
|
||||
|
||||
#include <Mod/PartDesign/App/Body.h>
|
||||
#include <Mod/PartDesign/App/DatumFeature.h>
|
||||
#include <Mod/Sketcher/App/SketchObject.h>
|
||||
#include <Mod/Sketcher/Gui/SketchOrientationDialog.h>
|
||||
#include <Mod/PartDesign/App/FeatureAdditive.h>
|
||||
#include <Mod/PartDesign/App/FeatureSubtractive.h>
|
||||
#include <Mod/PartDesign/App/FeatureGroove.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 "Workbench.h"
|
||||
|
|
|
@ -34,7 +34,9 @@
|
|||
#include <Mod/Part/App/TopoShape.h>
|
||||
#include <Mod/Part/App/PartFeature.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 "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
|
||||
return true;
|
||||
|
||||
if (pObj->getTypeId().isDerivedFrom(PartDesign::Datum::getClassTypeId())) {
|
||||
// Allow selecting PartDesign::Datum features
|
||||
if (pObj->getTypeId().isDerivedFrom(Part::Datum::getClassTypeId())) {
|
||||
// Allow selecting Part::Datum features
|
||||
if (!ActivePartObject->hasFeature(pObj))
|
||||
return false;
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
#include <Gui/Selection.h>
|
||||
#include <Gui/Command.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 "ReferenceSelection.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");
|
||||
|
||||
if (obj->getTypeId().isDerivedFrom(App::Plane::getClassTypeId()) ||
|
||||
obj->getTypeId().isDerivedFrom(PartDesign::Datum::getClassTypeId()))
|
||||
obj->getTypeId().isDerivedFrom(Part::Datum::getClassTypeId()))
|
||||
// App::Plane or Datum feature
|
||||
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) {
|
||||
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();
|
||||
refnames = pcDatum->References.getSubValues();
|
||||
|
||||
|
@ -139,7 +139,7 @@ TaskDatumParameters::TaskDatumParameters(ViewProviderDatum *DatumView,QWidget *p
|
|||
ui->lineRef3->blockSignals(true);
|
||||
|
||||
// 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<std::string> refnames = pcDatum->References.getSubValues();
|
||||
|
||||
|
@ -203,7 +203,7 @@ void TaskDatumParameters::updateUI()
|
|||
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();
|
||||
completed = false;
|
||||
|
||||
|
@ -308,7 +308,7 @@ void TaskDatumParameters::onSelectionChanged(const Gui::SelectionChanges& msg)
|
|||
return;
|
||||
|
||||
// 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<std::string> refnames = pcDatum->References.getSubValues();
|
||||
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
|
||||
if (selObj->getTypeId().isDerivedFrom(App::Plane::getClassTypeId()) ||
|
||||
selObj->getTypeId().isDerivedFrom(PartDesign::Datum::getClassTypeId()))
|
||||
selObj->getTypeId().isDerivedFrom(Part::Datum::getClassTypeId()))
|
||||
subname = "";
|
||||
|
||||
// eliminate duplicate selections
|
||||
|
@ -349,7 +349,7 @@ void TaskDatumParameters::onSelectionChanged(const Gui::SelectionChanges& msg)
|
|||
|
||||
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->getDocument()->recomputeFeature(pcDatum);
|
||||
updateUI();
|
||||
|
@ -357,7 +357,7 @@ void TaskDatumParameters::onOffsetChanged(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->getDocument()->recomputeFeature(pcDatum);
|
||||
updateUI();
|
||||
|
@ -365,14 +365,14 @@ void TaskDatumParameters::onAngleChanged(double val)
|
|||
|
||||
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->getDocument()->recomputeFeature(pcDatum);
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
if (pressed) {
|
||||
|
@ -410,7 +410,7 @@ void TaskDatumParameters::onRefName(const QString& text, const int idx)
|
|||
if (text.length() == 0) {
|
||||
// Reference was removed
|
||||
// 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<std::string> refnames = pcDatum->References.getSubValues();
|
||||
std::vector<App::DocumentObject*> newrefs;
|
||||
|
@ -439,7 +439,7 @@ void TaskDatumParameters::onRefName(const QString& text, const int idx)
|
|||
QStringList parts = text.split(QChar::fromAscii(':'));
|
||||
if (parts.length() < 2)
|
||||
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());
|
||||
if (obj == NULL) return;
|
||||
|
||||
|
@ -448,7 +448,7 @@ void TaskDatumParameters::onRefName(const QString& text, const int idx)
|
|||
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)
|
||||
subElement = "";
|
||||
} else if (obj->getTypeId().isDerivedFrom(PartDesign::Datum::getClassTypeId())) {
|
||||
} else if (obj->getTypeId().isDerivedFrom(Part::Datum::getClassTypeId())) {
|
||||
if (!PartDesignGui::ActivePartObject->hasFeature(obj))
|
||||
return;
|
||||
subElement = "";
|
||||
|
@ -484,7 +484,7 @@ void TaskDatumParameters::onRefName(const QString& text, const int idx)
|
|||
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<std::string> refnames = pcDatum->References.getSubValues();
|
||||
if (idx < refs.size()) {
|
||||
|
|
|
@ -52,7 +52,9 @@
|
|||
#include "ViewProviderDatum.h"
|
||||
#include "TaskDatumParameters.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/Command.h>
|
||||
#include <Gui/Application.h>
|
||||
|
@ -77,12 +79,12 @@ void ViewProviderDatum::attach(App::DocumentObject *obj)
|
|||
{
|
||||
ViewProviderGeometryObject::attach(obj);
|
||||
|
||||
PartDesign::Datum* pcDatum = static_cast<PartDesign::Datum*>(getObject());
|
||||
if (pcDatum->getTypeId() == PartDesign::Plane::getClassTypeId())
|
||||
App::DocumentObject* o = getObject();
|
||||
if (o->getTypeId() == PartDesign::Plane::getClassTypeId())
|
||||
datumType = QObject::tr("Plane");
|
||||
else if (pcDatum->getTypeId() == PartDesign::Line::getClassTypeId())
|
||||
else if (o->getTypeId() == PartDesign::Line::getClassTypeId())
|
||||
datumType = QObject::tr("Line");
|
||||
else if (pcDatum->getTypeId() == PartDesign::Point::getClassTypeId())
|
||||
else if (o->getTypeId() == PartDesign::Point::getClassTypeId())
|
||||
datumType = QObject::tr("Point");
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
132
src/Mod/PartDesign/Gui/ViewProviderDatumLine.cpp
Normal file
132
src/Mod/PartDesign/Gui/ViewProviderDatumLine.cpp
Normal 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);
|
||||
}
|
||||
|
48
src/Mod/PartDesign/Gui/ViewProviderDatumLine.h
Normal file
48
src/Mod/PartDesign/Gui/ViewProviderDatumLine.h
Normal 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
|
223
src/Mod/PartDesign/Gui/ViewProviderDatumPlane.cpp
Normal file
223
src/Mod/PartDesign/Gui/ViewProviderDatumPlane.cpp
Normal 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);
|
||||
}
|
||||
|
||||
|
48
src/Mod/PartDesign/Gui/ViewProviderDatumPlane.h
Normal file
48
src/Mod/PartDesign/Gui/ViewProviderDatumPlane.h
Normal 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
|
101
src/Mod/PartDesign/Gui/ViewProviderDatumPoint.cpp
Normal file
101
src/Mod/PartDesign/Gui/ViewProviderDatumPoint.cpp
Normal 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);
|
||||
}
|
48
src/Mod/PartDesign/Gui/ViewProviderDatumPoint.h
Normal file
48
src/Mod/PartDesign/Gui/ViewProviderDatumPoint.h
Normal 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
|
|
@ -47,7 +47,7 @@
|
|||
#include <Mod/PartDesign/App/Body.h>
|
||||
#include <Mod/PartDesign/App/Feature.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>
|
||||
|
||||
using namespace PartDesignGui;
|
||||
|
@ -262,7 +262,7 @@ void Workbench::setupContextMenu(const char* recipient, Gui::MenuItem* item) con
|
|||
if (strcmp(recipient,"Tree") == 0)
|
||||
{
|
||||
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 )
|
||||
*item << "PartDesign_MoveTip";
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#ifndef _PreComp_
|
||||
# include <TopoDS_Shape.hxx>
|
||||
# include <TopoDS_Face.hxx>
|
||||
# include <TopoDS_Edge.hxx>
|
||||
# include <TopoDS.hxx>
|
||||
# include <TopExp_Explorer.hxx>
|
||||
# include <gp_Pln.hxx>
|
||||
|
@ -34,6 +35,7 @@
|
|||
# include <BRepAdaptor_Surface.hxx>
|
||||
# include <BRepAdaptor_Curve.hxx>
|
||||
# include <BRep_Tool.hxx>
|
||||
# include <Geom_Line.hxx>
|
||||
# include <Geom_Plane.hxx>
|
||||
# include <Geom_Circle.hxx>
|
||||
# include <Geom_Ellipse.hxx>
|
||||
|
@ -41,6 +43,9 @@
|
|||
# include <GeomAPI_ProjectPointOnSurf.hxx>
|
||||
# include <BRepOffsetAPI_NormalProjection.hxx>
|
||||
# include <BRepBuilderAPI_MakeFace.hxx>
|
||||
# include <BRepBuilderAPI_MakeEdge.hxx>
|
||||
# include <GeomAPI_IntSS.hxx>
|
||||
# include <BRepProj_Projection.hxx>
|
||||
# include <Standard_Version.hxx>
|
||||
# include <cmath>
|
||||
# include <vector>
|
||||
|
@ -56,8 +61,10 @@
|
|||
#include <Base/Console.h>
|
||||
#include <Base/Vector3D.h>
|
||||
|
||||
#include <App/Plane.h>
|
||||
|
||||
#include <Mod/Part/App/Geometry.h>
|
||||
#include <Mod/PartDesign/App/DatumFeature.h>
|
||||
#include <Mod/Part/App/DatumFeature.h>
|
||||
|
||||
#include "SketchObject.h"
|
||||
#include "SketchObjectPy.h"
|
||||
|
@ -119,15 +126,7 @@ App::DocumentObjectExecReturn *SketchObject::execute(void)
|
|||
if (support == NULL)
|
||||
throw Base::Exception("Sketch support has been deleted");
|
||||
|
||||
if (support->getTypeId().isDerivedFrom(PartDesign::Plane::getClassTypeId())) {
|
||||
// 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();
|
||||
}
|
||||
this->positionBySupport();
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
return new App::DocumentObjectExecReturn(e.what());
|
||||
|
@ -2713,8 +2712,10 @@ int SketchObject::DeleteUnusedInternalGeometry(int GeoId)
|
|||
|
||||
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 (!Obj->getTypeId().isDerivedFrom(App::Plane::getClassTypeId()) &&
|
||||
!Obj->getTypeId().isDerivedFrom(Part::Datum::getClassTypeId()))
|
||||
return -1;
|
||||
|
||||
// get the actual lists of the externals
|
||||
|
@ -2889,6 +2890,56 @@ const Part::Geometry* SketchObject::getGeometry(int GeoId) const
|
|||
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)
|
||||
{
|
||||
// returns false if the shape if broken, null or non-planar
|
||||
|
@ -3030,16 +3081,37 @@ void SketchObject::rebuildExternalGeometry(void)
|
|||
const App::DocumentObject *Obj=Objects[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;
|
||||
try {
|
||||
refSubShape = refShape.getSubShape(SubElement.c_str());
|
||||
}
|
||||
catch (Standard_Failure) {
|
||||
Handle_Standard_Failure e = Standard_Failure::Caught();
|
||||
throw Base::Exception(e->GetMessageString());
|
||||
|
||||
if (Obj->getTypeId().isDerivedFrom(Part::Datum::getClassTypeId())) {
|
||||
const Part::Datum* datum = static_cast<const Part::Datum*>(Obj);
|
||||
refSubShape = datum->Shape.getValue();
|
||||
} else if (Obj->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
|
||||
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())
|
||||
|
@ -3049,8 +3121,27 @@ void SketchObject::rebuildExternalGeometry(void)
|
|||
const TopoDS_Face& face = TopoDS::Face(refSubShape);
|
||||
BRepAdaptor_Surface surface(face);
|
||||
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;
|
||||
case TopAbs_EDGE:
|
||||
|
@ -3058,31 +3149,7 @@ void SketchObject::rebuildExternalGeometry(void)
|
|||
const TopoDS_Edge& edge = TopoDS::Edge(refSubShape);
|
||||
BRepAdaptor_Curve curve(edge);
|
||||
if (curve.GetType() == GeomAbs_Line) {
|
||||
gp_Pnt P1 = curve.Value(curve.FirstParameter());
|
||||
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);
|
||||
}
|
||||
ExternalGeo.push_back(projectLine(curve, gPlane, invPlm));
|
||||
}
|
||||
else if (curve.GetType() == GeomAbs_Circle) {
|
||||
gp_Dir vec1 = sketchPlane.Axis().Direction();
|
||||
|
|
4180
src/Mod/Sketcher/App/SketchObject.cpp.orig
Normal file
4180
src/Mod/Sketcher/App/SketchObject.cpp.orig
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -31,12 +31,14 @@
|
|||
#include <Mod/Sketcher/App/SketchObject.h>
|
||||
#include <Mod/Part/App/LinePy.h>
|
||||
#include <Mod/Part/App/Geometry.h>
|
||||
#include <Mod/Part/App/DatumFeature.h>
|
||||
#include <Base/GeometryPyCXX.h>
|
||||
#include <Base/VectorPy.h>
|
||||
#include <Base/AxisPy.h>
|
||||
#include <Base/Tools.h>
|
||||
#include <Base/QuantityPy.h>
|
||||
#include <App/Document.h>
|
||||
#include <App/Plane.h>
|
||||
#include <CXX/Objects.hxx>
|
||||
|
||||
// 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());
|
||||
return 0;
|
||||
}
|
||||
// check if it belongs to the sketch support
|
||||
if (this->getSketchObjectPtr()->Support.getValue() != Obj) {
|
||||
// check if it is a datum feature
|
||||
// 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;
|
||||
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());
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include <Base/Exception.h>
|
||||
#include <Base/Tools.h>
|
||||
|
||||
#include <App/Plane.h>
|
||||
#include <Gui/Action.h>
|
||||
#include <Gui/Application.h>
|
||||
#include <Gui/BitmapFactory.h>
|
||||
|
@ -46,6 +47,7 @@
|
|||
#include <Gui/Selection.h>
|
||||
#include <Gui/SelectionFilter.h>
|
||||
#include <Mod/Sketcher/App/SketchObject.h>
|
||||
#include <Mod/Part/App/DatumFeature.h>
|
||||
|
||||
#include "ViewProviderSketch.h"
|
||||
#include "DrawSketchHandler.h"
|
||||
|
@ -4473,7 +4475,12 @@ namespace SketcherGui {
|
|||
{
|
||||
Sketcher::SketchObject *sketch = static_cast<Sketcher::SketchObject*>(object);
|
||||
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)
|
||||
return false;
|
||||
if (!sSubName || sSubName[0] == '\0')
|
||||
|
@ -4582,8 +4589,13 @@ public:
|
|||
virtual bool onSelectionChanged(const Gui::SelectionChanges& msg)
|
||||
{
|
||||
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);
|
||||
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")) {
|
||||
try {
|
||||
Gui::Command::openCommand("Add external geometry");
|
||||
|
|
Loading…
Reference in New Issue
Block a user