Visualization of datum lines and planes
This commit is contained in:
committed by
Stefan Tröger
parent
b7fe543ca9
commit
6effd7d864
457
src/Mod/PartDesign/App/DatumFeature.cpp
Normal file
457
src/Mod/PartDesign/App/DatumFeature.cpp
Normal file
@@ -0,0 +1,457 @@
|
||||
/***************************************************************************
|
||||
* 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 <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/Exception.h>
|
||||
#include <Base/Console.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::DocumentObject)
|
||||
|
||||
Datum::Datum(void)
|
||||
{
|
||||
ADD_PROPERTY_TYPE(References,(0,0),"References",(App::PropertyType)(App::Prop_None),"References defining the datum feature");
|
||||
ADD_PROPERTY(Values,(0.0));
|
||||
touch();
|
||||
}
|
||||
|
||||
Datum::~Datum()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
App::DocumentObjectExecReturn *Datum::execute(void)
|
||||
{
|
||||
References.touch();
|
||||
return StdReturn;
|
||||
}
|
||||
|
||||
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]));
|
||||
}
|
||||
|
||||
App::DocumentObject::onChanged(prop);
|
||||
}
|
||||
|
||||
void Datum::onDocumentRestored()
|
||||
{
|
||||
// This seems to be the only way to make the ViewProvider display the datum feature
|
||||
References.touch();
|
||||
App::DocumentObject::onDocumentRestored();
|
||||
}
|
||||
|
||||
// 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")
|
||||
|
||||
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("Point"));
|
||||
|
||||
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("Line"));
|
||||
|
||||
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("Plane"));
|
||||
|
||||
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);
|
||||
hints[key] = value; // LINE -> POINT
|
||||
|
||||
key.clear(); value.clear();
|
||||
value.insert(POINT); value.insert(LINE); value.insert(PLANE);
|
||||
hints[key] = value;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
||||
PROPERTY_SOURCE(PartDesign::Point, PartDesign::Datum)
|
||||
|
||||
Point::Point()
|
||||
{
|
||||
ADD_PROPERTY_TYPE(_Point,(Base::Vector3d(0,0,1)),"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("Point")) != 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::Vector3f* 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]);
|
||||
//point = new Base::Vector3f (p->_Point.getValue());
|
||||
} else if (refs[i]->getTypeId().isDerivedFrom(PartDesign::Plane::getClassTypeId())) {
|
||||
PartDesign::Plane* p = static_cast<PartDesign::Plane*>(refs[i]);
|
||||
//point = new Base::Vector3f (p->_Point.getValue());
|
||||
} else if (refs[i]->getTypeId().isDerivedFrom(App::Plane::getClassTypeId())) {
|
||||
App::Plane* p = static_cast<App::Plane*>(refs[i]);
|
||||
//point = new Base::Vector3f (p->_Point.getValue());
|
||||
} 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::Vector3f(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::Vector3f(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::Vector3f(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::Vector3f(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()
|
||||
{
|
||||
}
|
||||
|
||||
Line::~Line()
|
||||
{
|
||||
}
|
||||
|
||||
void Line::onChanged(const App::Property *prop)
|
||||
{
|
||||
gp_Pnt point1(0,0,0);
|
||||
|
||||
gp_Pnt point2(10,10,10);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
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()
|
||||
{
|
||||
}
|
||||
|
||||
void Plane::onChanged(const App::Property *prop)
|
||||
{
|
||||
double O = 10.0; //this->Offset.getValue();
|
||||
double A = 45.0; //this->Angle.getValue();
|
||||
|
||||
if (fabs(A) > 360.0)
|
||||
return; // "Angle too large (please use -360.0 .. +360.0)"
|
||||
|
||||
gp_Pnt pnt(0.0,0.0,0.0);
|
||||
gp_Dir dir(0.0,0.0,1.0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const std::set<QString> Plane::getHint()
|
||||
{
|
||||
if (hints.find(refTypes) != hints.end())
|
||||
return hints[refTypes];
|
||||
else
|
||||
return std::set<QString>();
|
||||
}
|
||||
@@ -95,6 +95,9 @@ class PartDesignExport Line : public PartDesign::Datum
|
||||
PROPERTY_HEADER(PartDesign::Line);
|
||||
|
||||
public:
|
||||
App::PropertyVector _Base;
|
||||
App::PropertyVector _Direction;
|
||||
|
||||
Line();
|
||||
virtual ~Line();
|
||||
|
||||
@@ -118,6 +121,9 @@ class PartDesignExport Plane : public PartDesign::Datum
|
||||
PROPERTY_HEADER(PartDesign::Plane);
|
||||
|
||||
public:
|
||||
App::PropertyVector _Base;
|
||||
App::PropertyVector _Normal;
|
||||
|
||||
Plane();
|
||||
|
||||
const char* getViewProviderName(void) const {
|
||||
|
||||
@@ -28,14 +28,22 @@
|
||||
# include <QAction>
|
||||
# include <QMenu>
|
||||
# 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 <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 "ViewProviderDatum.h"
|
||||
@@ -44,6 +52,7 @@
|
||||
#include <Mod/PartDesign/App/DatumFeature.h>
|
||||
#include <Gui/Control.h>
|
||||
#include <Gui/Command.h>
|
||||
#include <Mod/PartDesign/App/Body.h>
|
||||
|
||||
using namespace PartDesignGui;
|
||||
|
||||
@@ -73,13 +82,19 @@ void ViewProviderDatum::attach(App::DocumentObject *obj)
|
||||
datumType = QObject::tr("Point");
|
||||
|
||||
SoSeparator* sep = new SoSeparator();
|
||||
SoPickStyle* ps = new SoPickStyle();
|
||||
ps->style = SoPickStyle::SHAPE;
|
||||
SoShapeHints* hints = new SoShapeHints();
|
||||
hints->shapeType.setValue(SoShapeHints::UNKNOWN_SHAPE_TYPE);
|
||||
hints->vertexOrdering.setValue(SoShapeHints::COUNTERCLOCKWISE);
|
||||
SoBaseColor* color = new SoBaseColor();
|
||||
color->rgb.setValue(0.9, 0.9, 0.2);
|
||||
color->rgb.setValue(0.9, 0.9, 0.1);
|
||||
SoMaterial* material = new SoMaterial();
|
||||
material->diffuseColor.setValue(0.9f, 0.9f, 0.1f);
|
||||
material->transparency.setValue(0.2);
|
||||
sep->addChild(hints);
|
||||
sep->addChild(color);
|
||||
sep->addChild(material);
|
||||
sep->addChild(pShapeSep);
|
||||
addDisplayMaskMode(sep, "Base");
|
||||
}
|
||||
@@ -182,7 +197,7 @@ ViewProviderDatumPoint::ViewProviderDatumPoint()
|
||||
{
|
||||
SoMarkerSet* points = new SoMarkerSet();
|
||||
points->markerIndex = SoMarkerSet::DIAMOND_FILLED_9_9;
|
||||
points->numPoints = 1;
|
||||
points->numPoints = 0;
|
||||
pShapeSep->addChild(points);
|
||||
}
|
||||
|
||||
@@ -197,13 +212,23 @@ void ViewProviderDatumPoint::updateData(const App::Property* prop)
|
||||
PartDesign::Point* pcDatum = static_cast<PartDesign::Point*>(this->getObject());
|
||||
|
||||
if (strcmp(prop->getName(),"_Point") == 0) {
|
||||
Base::Vector3f p = pcDatum->_Point.getValue();
|
||||
Base::Vector3d p = pcDatum->_Point.getValue();
|
||||
SoMFVec3f v;
|
||||
v.setNum(1);
|
||||
v.set1Value(0, p.x, p.y, p.z);
|
||||
SoVertexProperty* vprop = new SoVertexProperty();
|
||||
vprop->vertex = v;
|
||||
SoMarkerSet* points = static_cast<SoMarkerSet*>(pShapeSep->getChild(0));
|
||||
points->vertexProperty = vprop;
|
||||
|
||||
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);
|
||||
@@ -213,12 +238,8 @@ PROPERTY_SOURCE(PartDesignGui::ViewProviderDatumLine,PartDesignGui::ViewProvider
|
||||
|
||||
ViewProviderDatumLine::ViewProviderDatumLine()
|
||||
{
|
||||
/*
|
||||
SoMarkerSet* points = new SoMarkerSet();
|
||||
points->markerIndex = SoMarkerSet::DIAMOND_FILLED_9_9;
|
||||
points->numPoints = 1;
|
||||
pShapeSep->addChild(points);
|
||||
*/
|
||||
SoLineSet* lineSet = new SoLineSet();
|
||||
pShapeSep->addChild(lineSet);
|
||||
}
|
||||
|
||||
ViewProviderDatumLine::~ViewProviderDatumLine()
|
||||
@@ -231,16 +252,51 @@ 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(),"_Point") == 0) {
|
||||
Base::Vector3f p = pcDatum->_Point.getValue();
|
||||
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.set1Value(0, p.x, p.y, p.z);
|
||||
SoVertexProperty* vprop = new SoVertexProperty();
|
||||
vprop->vertex = v;
|
||||
SoMarkerSet* points = static_cast<SoMarkerSet*>(pShapeSep->getChild(0));
|
||||
points->vertexProperty = vprop;
|
||||
}*/
|
||||
v.setNum(2);
|
||||
v.set1Value(0, p1.x, p1.y, p1.z);
|
||||
v.set1Value(1, p2.x, p2.y, p2.z);
|
||||
SoLineSet* lineSet = static_cast<SoLineSet*>(pShapeSep->getChild(0));
|
||||
|
||||
SoVertexProperty* vprop;
|
||||
if (lineSet->vertexProperty.getValue() == NULL) {
|
||||
vprop = new SoVertexProperty();
|
||||
vprop->vertex = v;
|
||||
lineSet->vertexProperty = vprop;
|
||||
} else {
|
||||
vprop = static_cast<SoVertexProperty*>(lineSet->vertexProperty.getValue());
|
||||
vprop->vertex = v;
|
||||
}
|
||||
|
||||
SoMFInt32 idx;
|
||||
idx.setNum(1);
|
||||
idx.set1Value(0, 2);
|
||||
lineSet->numVertices = idx;
|
||||
}
|
||||
|
||||
ViewProviderDatum::updateData(prop);
|
||||
}
|
||||
@@ -249,12 +305,8 @@ PROPERTY_SOURCE(PartDesignGui::ViewProviderDatumPlane,PartDesignGui::ViewProvide
|
||||
|
||||
ViewProviderDatumPlane::ViewProviderDatumPlane()
|
||||
{
|
||||
/*
|
||||
SoMarkerSet* points = new SoMarkerSet();
|
||||
points->markerIndex = SoMarkerSet::DIAMOND_FILLED_9_9;
|
||||
points->numPoints = 1;
|
||||
pShapeSep->addChild(points);
|
||||
*/
|
||||
SoFaceSet* faceSet = new SoFaceSet();
|
||||
pShapeSep->addChild(faceSet);
|
||||
}
|
||||
|
||||
ViewProviderDatumPlane::~ViewProviderDatumPlane()
|
||||
@@ -266,16 +318,133 @@ 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(),"_Point") == 0) {
|
||||
Base::Vector3f p = pcDatum->_Point.getValue();
|
||||
|
||||
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.set1Value(0, p.x, p.y, p.z);
|
||||
SoVertexProperty* vprop = new SoVertexProperty();
|
||||
vprop->vertex = v;
|
||||
SoMarkerSet* points = static_cast<SoMarkerSet*>(pShapeSep->getChild(0));
|
||||
points->vertexProperty = vprop;
|
||||
}*/
|
||||
v.setNum(points.size());
|
||||
for (int p = 0; p < points.size(); p++)
|
||||
v.set1Value(p, points[p].x, points[p].y, points[p].z);
|
||||
SoFaceSet* faceSet = static_cast<SoFaceSet*>(pShapeSep->getChild(0));
|
||||
|
||||
SoVertexProperty* vprop;
|
||||
if (faceSet->vertexProperty.getValue() == NULL) {
|
||||
vprop = new SoVertexProperty();
|
||||
vprop->vertex = v;
|
||||
faceSet->vertexProperty = vprop;
|
||||
} else {
|
||||
vprop = static_cast<SoVertexProperty*>(faceSet->vertexProperty.getValue());
|
||||
vprop->vertex = v;
|
||||
}
|
||||
|
||||
SoMFInt32 idx;
|
||||
idx.setNum(1);
|
||||
idx.set1Value(0, points.size());
|
||||
faceSet->numVertices = idx;
|
||||
}
|
||||
|
||||
ViewProviderDatum::updateData(prop);
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
#include <Gui/Control.h>
|
||||
#include <Gui/Command.h>
|
||||
#include <Gui/Application.h>
|
||||
#include <Gui/Command.h>
|
||||
#include <Mod/Part/App/TopoShape.h>
|
||||
#include <Mod/PartDesign/App/FeatureAdditive.h>
|
||||
#include <Mod/PartDesign/App/FeatureSubtractive.h>
|
||||
|
||||
Reference in New Issue
Block a user