From 1333cb87348c8a99a99edb77c54746a03ebac2c1 Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 21 Nov 2013 12:50:49 +0100 Subject: [PATCH] + Get exact point on data model when picking in 3d view --- src/Gui/ManualAlignment.cpp | 34 ++++++++++++++------ src/Gui/ManualAlignment.h | 2 +- src/Gui/View3DInventorViewer.cpp | 8 +++++ src/Gui/View3DInventorViewer.h | 1 + src/Gui/ViewProvider.cpp | 9 ++++++ src/Gui/ViewProvider.h | 1 + src/Mod/Part/Gui/ViewProviderExt.cpp | 46 ++++++++++++++++++++++++++++ src/Mod/Part/Gui/ViewProviderExt.h | 1 + 8 files changed, 91 insertions(+), 11 deletions(-) diff --git a/src/Gui/ManualAlignment.cpp b/src/Gui/ManualAlignment.cpp index 9dd0a9bcc3a9..b8824b43404f 100644 --- a/src/Gui/ManualAlignment.cpp +++ b/src/Gui/ManualAlignment.cpp @@ -1143,17 +1143,21 @@ void ManualAlignment::probePickedCallback(void * ud, SoEventCallback * n) // Get the closest point to the camera of the whole scene. // This point doesn't need to be part of this view provider. Gui::WaitCursor wc; - const SoPickedPoint * point = n->getPickedPoint(); + const SoPickedPoint * point = view->getPickedPoint(n); if (point) { Gui::ViewProvider* vp = static_cast(view->getViewProviderByPath(point->getPath())); if (vp && vp->getTypeId().isDerivedFrom(Gui::ViewProviderDocumentObject::getClassTypeId())) { Gui::ViewProviderDocumentObject* that = static_cast(vp); - self->applyPickedProbe(that, point); - - const SbVec3f& vec = point->getPoint(); - Gui::getMainWindow()->showMessage( - tr("Point picked at (%1,%2,%3)") - .arg(vec[0]).arg(vec[1]).arg(vec[2])); + if (self->applyPickedProbe(that, point)) { + const SbVec3f& vec = point->getPoint(); + Gui::getMainWindow()->showMessage( + tr("Point picked at (%1,%2,%3)") + .arg(vec[0]).arg(vec[1]).arg(vec[2])); + } + else { + Gui::getMainWindow()->showMessage( + tr("No point was found on model")); + } } } else { @@ -1229,22 +1233,32 @@ void ManualAlignment::probePickedCallback(void * ud, SoEventCallback * n) * This method stores the picked point \a pnt from the view provider \a prov. If enough points in both windows have been picked * the alignment gets invoked. */ -void ManualAlignment::applyPickedProbe(Gui::ViewProviderDocumentObject* prov, const SoPickedPoint* pnt) +bool ManualAlignment::applyPickedProbe(Gui::ViewProviderDocumentObject* prov, const SoPickedPoint* pnt) { const SbVec3f& vec = pnt->getPoint(); const SbVec3f& nor = pnt->getNormal(); // add to the list for the non-aligned view in the left view if (myAlignModel.activeGroup().hasView(prov)) { - myAlignModel.activeGroup().addPoint(Base::Vector3d(vec[0],vec[1],vec[2])); + std::vector pts = prov->getPickedPoints(pnt); + if (pts.empty()) + return false; + myAlignModel.activeGroup().addPoint(pts.front()); // Adds a point marker for the picked point. d->picksepLeft->addChild(pickedPointsSubGraph(vec, nor, myAlignModel.activeGroup().countPoints())); + return true; } else if (myFixedGroup.hasView(prov)) { - myFixedGroup.addPoint(Base::Vector3d(vec[0],vec[1],vec[2])); + std::vector pts = prov->getPickedPoints(pnt); + if (pts.empty()) + return false; + myFixedGroup.addPoint(pts.front()); // Adds a point marker for the picked point. d->picksepRight->addChild(pickedPointsSubGraph(vec, nor, myFixedGroup.countPoints())); + return true; } + + return false; } #include "moc_ManualAlignment.cpp" diff --git a/src/Gui/ManualAlignment.h b/src/Gui/ManualAlignment.h index 027d90ccea74..4fbc22893e8a 100644 --- a/src/Gui/ManualAlignment.h +++ b/src/Gui/ManualAlignment.h @@ -215,7 +215,7 @@ class GuiExport ManualAlignment : public QObject /** @name Probe picking */ //@{ static void probePickedCallback(void * ud, SoEventCallback * n); - void applyPickedProbe(Gui::ViewProviderDocumentObject*, const SoPickedPoint* pnt); + bool applyPickedProbe(Gui::ViewProviderDocumentObject*, const SoPickedPoint* pnt); //@} protected Q_SLOTS: diff --git a/src/Gui/View3DInventorViewer.cpp b/src/Gui/View3DInventorViewer.cpp index a48e8d0116f2..b85cb77184ff 100644 --- a/src/Gui/View3DInventorViewer.cpp +++ b/src/Gui/View3DInventorViewer.cpp @@ -1412,6 +1412,14 @@ SoPickedPoint* View3DInventorViewer::pickPoint(const SbVec2s& pos) const return (pick ? new SoPickedPoint(*pick) : 0); } +const SoPickedPoint* View3DInventorViewer::getPickedPoint(SoEventCallback * n) const +{ + if (selectionRoot) + return selectionRoot->getPickedPoint(n->getAction()); + else + return n->getPickedPoint(); +} + SbBool View3DInventorViewer::pubSeekToPoint(const SbVec2s& pos) { return this->seekToPoint(pos); diff --git a/src/Gui/View3DInventorViewer.h b/src/Gui/View3DInventorViewer.h index f78081a79ff6..d37fc910199e 100644 --- a/src/Gui/View3DInventorViewer.h +++ b/src/Gui/View3DInventorViewer.h @@ -202,6 +202,7 @@ class GuiExport View3DInventorViewer : public SoQtViewer, public Gui::SelectionS // calls a PickAction on the scene graph bool pickPoint(const SbVec2s& pos,SbVec3f &point,SbVec3f &norm) const; SoPickedPoint* pickPoint(const SbVec2s& pos) const; + const SoPickedPoint* getPickedPoint(SoEventCallback * n) const; SbBool pubSeekToPoint(const SbVec2s& pos); void pubSeekToPoint(const SbVec3f& pos); //@} diff --git a/src/Gui/ViewProvider.cpp b/src/Gui/ViewProvider.cpp index e7ec6e4d65aa..f148fafae802 100644 --- a/src/Gui/ViewProvider.cpp +++ b/src/Gui/ViewProvider.cpp @@ -369,3 +369,12 @@ SoPickedPoint* ViewProvider::getPointOnRay(const SbVec3f& pos,const SbVec3f& dir //return (pick ? pick->copy() : 0); // needs the same instance of CRT under MS Windows return (pick ? new SoPickedPoint(*pick) : 0); } + +std::vector ViewProvider::getPickedPoints(const SoPickedPoint* pp) const +{ + // the default implementation just returns the picked point from the visual representation + std::vector pts; + const SbVec3f& vec = pp->getPoint(); + pts.push_back(Base::Vector3d(vec[0],vec[1],vec[2])); + return pts; +} diff --git a/src/Gui/ViewProvider.h b/src/Gui/ViewProvider.h index 2ad3a0b8af57..3d2ae6dbfa8f 100644 --- a/src/Gui/ViewProvider.h +++ b/src/Gui/ViewProvider.h @@ -121,6 +121,7 @@ class GuiExport ViewProvider : public App::PropertyContainer /// return a hit element to the selection path or 0 virtual std::string getElement(const SoDetail *) const { return std::string(); } virtual SoDetail* getDetail(const char*) const { return 0; } + virtual std::vector getPickedPoints(const SoPickedPoint *) const; /// return the higlight lines for a given element or the whole shape virtual std::vector getSelectionShape(const char* Element) const { return std::vector(); }; diff --git a/src/Mod/Part/Gui/ViewProviderExt.cpp b/src/Mod/Part/Gui/ViewProviderExt.cpp index 8606d5add5d9..673e4cde4042 100644 --- a/src/Mod/Part/Gui/ViewProviderExt.cpp +++ b/src/Mod/Part/Gui/ViewProviderExt.cpp @@ -27,6 +27,8 @@ # include # include # include +# include +# include # include # include # include @@ -51,6 +53,7 @@ # include # include # include +# include # include # include # include @@ -472,6 +475,49 @@ SoDetail* ViewProviderPartExt::getDetail(const char* subelement) const return detail; } +std::vector ViewProviderPartExt::getPickedPoints(const SoPickedPoint* pp) const +{ + try { + std::vector pts; + std::string element = this->getElement(pp->getDetail()); + const Part::TopoShape& shape = static_cast(getObject())->Shape.getShape(); + + TopoDS_Shape subShape = shape.getSubShape(element.c_str()); + + // get the point of the vertex directly + if (subShape.ShapeType() == TopAbs_VERTEX) { + const TopoDS_Vertex& v = TopoDS::Vertex(subShape); + gp_Pnt p = BRep_Tool::Pnt(v); + pts.push_back(Base::Vector3d(p.X(),p.Y(),p.Z())); + } + // get the nearest point on the edge + else if (subShape.ShapeType() == TopAbs_EDGE) { + const SbVec3f& vec = pp->getPoint(); + BRepBuilderAPI_MakeVertex mkVert(gp_Pnt(vec[0],vec[1],vec[2])); + BRepExtrema_DistShapeShape distSS(subShape, mkVert.Vertex(), 0.1); + if (distSS.NbSolution() > 0) { + gp_Pnt p = distSS.PointOnShape1(1); + pts.push_back(Base::Vector3d(p.X(),p.Y(),p.Z())); + } + } + // get the nearest point on the face + else if (subShape.ShapeType() == TopAbs_FACE) { + const SbVec3f& vec = pp->getPoint(); + BRepBuilderAPI_MakeVertex mkVert(gp_Pnt(vec[0],vec[1],vec[2])); + BRepExtrema_DistShapeShape distSS(subShape, mkVert.Vertex(), 0.1); + if (distSS.NbSolution() > 0) { + gp_Pnt p = distSS.PointOnShape1(1); + pts.push_back(Base::Vector3d(p.X(),p.Y(),p.Z())); + } + } + + return pts; + } + catch (...) { + return ViewProvider::getPickedPoints(pp); + } +} + std::vector ViewProviderPartExt::getSelectionShape(const char* Element) const { return std::vector(); diff --git a/src/Mod/Part/Gui/ViewProviderExt.h b/src/Mod/Part/Gui/ViewProviderExt.h index ca104b59b5d0..23cfad12bac6 100644 --- a/src/Mod/Part/Gui/ViewProviderExt.h +++ b/src/Mod/Part/Gui/ViewProviderExt.h @@ -101,6 +101,7 @@ class PartGuiExport ViewProviderPartExt : public Gui::ViewProviderGeometryObject /// return a hit element to the selection path or 0 virtual std::string getElement(const SoDetail*) const; virtual SoDetail* getDetail(const char*) const; + virtual std::vector getPickedPoints(const SoPickedPoint *) const; /// return the higlight lines for a given element or the whole shape virtual std::vector getSelectionShape(const char* Element) const; //@}