From 24e4e08be555c9e51a11e0f2b2cc7757ad4b97d4 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 21 Feb 2016 13:52:17 +0100 Subject: [PATCH] + view provider for scattered and organized point clouds --- src/Mod/Points/App/AppPointsPy.cpp | 4 + src/Mod/Points/App/PointsFeature.cpp | 9 +- src/Mod/Points/App/PointsFeature.h | 3 +- src/Mod/Points/Gui/AppPointsGui.cpp | 1 + src/Mod/Points/Gui/ViewProvider.cpp | 280 ++++++++++++++++++++------- src/Mod/Points/Gui/ViewProvider.h | 53 ++++- 6 files changed, 271 insertions(+), 79 deletions(-) diff --git a/src/Mod/Points/App/AppPointsPy.cpp b/src/Mod/Points/App/AppPointsPy.cpp index 38242adcf..a46e2ccae 100644 --- a/src/Mod/Points/App/AppPointsPy.cpp +++ b/src/Mod/Points/App/AppPointsPy.cpp @@ -155,12 +155,14 @@ private: // delayed adding of the points feature pcDoc->addObject(pcFeature, file.fileNamePure().c_str()); pcDoc->recomputeFeature(pcFeature); + pcFeature->purgeTouched(); } else { Points::Feature *pcFeature = static_cast (pcDoc->addObject("Points::Feature", file.fileNamePure().c_str())); pcFeature->Points.setValue(reader->getPoints()); pcDoc->recomputeFeature(pcFeature); + pcFeature->purgeTouched(); } } catch (const Base::Exception& e) { @@ -260,12 +262,14 @@ private: // delayed adding of the points feature pcDoc->addObject(pcFeature, file.fileNamePure().c_str()); pcDoc->recomputeFeature(pcFeature); + pcFeature->purgeTouched(); } else { Points::Feature *pcFeature = static_cast (pcDoc->addObject("Points::Feature", file.fileNamePure().c_str())); pcFeature->Points.setValue(reader->getPoints()); pcDoc->recomputeFeature(pcFeature); + pcFeature->purgeTouched(); } } catch (const Base::Exception& e) { diff --git a/src/Mod/Points/App/PointsFeature.cpp b/src/Mod/Points/App/PointsFeature.cpp index eabc65df4..dc1a06b46 100644 --- a/src/Mod/Points/App/PointsFeature.cpp +++ b/src/Mod/Points/App/PointsFeature.cpp @@ -54,6 +54,11 @@ Feature::~Feature() { } +short Feature::mustExecute() const +{ + return 0; +} + App::DocumentObjectExecReturn *Feature::execute(void) { this->Points.touch(); @@ -95,8 +100,8 @@ PROPERTY_SOURCE(Points::Organized, Points::Feature) Organized::Organized() { - ADD_PROPERTY_TYPE(Width,(1),"Width",App::Prop_ReadOnly,"Width"); - ADD_PROPERTY_TYPE(Height,(1),"Height",App::Prop_ReadOnly,"Height"); + ADD_PROPERTY_TYPE(Width,(1),"Organized points",App::Prop_ReadOnly,"Width of the frame"); + ADD_PROPERTY_TYPE(Height,(1),"Organized points",App::Prop_ReadOnly,"Height of the frame"); } Organized::~Organized() diff --git a/src/Mod/Points/App/PointsFeature.h b/src/Mod/Points/App/PointsFeature.h index be8a5cf03..e643d176a 100644 --- a/src/Mod/Points/App/PointsFeature.h +++ b/src/Mod/Points/App/PointsFeature.h @@ -62,11 +62,12 @@ public: //@{ void Restore(Base::XMLReader &reader); void RestoreDocFile(Base::Reader &reader); + short mustExecute() const; /// recalculate the Feature virtual App::DocumentObjectExecReturn *execute(void); /// returns the type name of the ViewProvider virtual const char* getViewProviderName(void) const { - return "PointsGui::ViewProviderPoints"; + return "PointsGui::ViewProviderScattered"; } protected: void onChanged(const App::Property* prop); diff --git a/src/Mod/Points/Gui/AppPointsGui.cpp b/src/Mod/Points/Gui/AppPointsGui.cpp index bd6dbb0ed..17d689d91 100644 --- a/src/Mod/Points/Gui/AppPointsGui.cpp +++ b/src/Mod/Points/Gui/AppPointsGui.cpp @@ -88,6 +88,7 @@ PyMODINIT_FUNC initPointsGui() CreatePointsCommands(); PointsGui::ViewProviderPoints ::init(); + PointsGui::ViewProviderScattered ::init(); PointsGui::ViewProviderOrganized ::init(); PointsGui::ViewProviderPython ::init(); PointsGui::Workbench ::init(); diff --git a/src/Mod/Points/Gui/ViewProvider.cpp b/src/Mod/Points/Gui/ViewProvider.cpp index 17c55289b..dc620f52c 100644 --- a/src/Mod/Points/Gui/ViewProvider.cpp +++ b/src/Mod/Points/Gui/ViewProvider.cpp @@ -28,6 +28,7 @@ # include # include # include +# include # include # include # include @@ -35,6 +36,9 @@ # include #endif +#include +#include + /// Here the FreeCAD includes sorted by Base,App,Gui,... #include #include @@ -60,7 +64,7 @@ using namespace PointsGui; using namespace Points; -PROPERTY_SOURCE(PointsGui::ViewProviderPoints, Gui::ViewProviderGeometryObject) +PROPERTY_SOURCE_ABSTRACT(PointsGui::ViewProviderPoints, Gui::ViewProviderGeometryObject) App::PropertyFloatConstraint::Constraints ViewProviderPoints::floatRange = {1.0,64.0,1.0}; @@ -78,8 +82,6 @@ ViewProviderPoints::ViewProviderPoints() pcPointsCoord = new SoCoordinate3(); pcPointsCoord->ref(); - pcPoints = new SoPointSet(); - pcPoints->ref(); pcPointsNormal = new SoNormal(); pcPointsNormal->ref(); pcColorMat = new SoMaterial; @@ -95,7 +97,6 @@ ViewProviderPoints::~ViewProviderPoints() { pcHighlight->unref(); pcPointsCoord->unref(); - pcPoints->unref(); pcPointsNormal->unref(); pcColorMat->unref(); pcPointStyle->unref(); @@ -190,52 +191,6 @@ void ViewProviderPoints::setVertexNormalMode(Points::PropertyNormalList* pcPrope pcPointsNormal->vector.finishEditing(); } -void ViewProviderPoints::attach(App::DocumentObject* pcObj) -{ - // call parent's attach to define display modes - ViewProviderGeometryObject::attach(pcObj); - - pcHighlight->objectName = pcObj->getNameInDocument(); - pcHighlight->documentName = pcObj->getDocument()->getName(); - pcHighlight->subElementName = "Main"; - - // Hilight for selection - pcHighlight->addChild(pcPointsCoord); - pcHighlight->addChild(pcPoints); - - std::vector modes = getDisplayModes(); - - // points part --------------------------------------------- - SoGroup* pcPointRoot = new SoGroup(); - pcPointRoot->addChild(pcPointStyle); - pcPointRoot->addChild(pcShapeMaterial); - pcPointRoot->addChild(pcHighlight); - addDisplayMaskMode(pcPointRoot, "Point"); - - // points shaded --------------------------------------------- - if (std::find(modes.begin(), modes.end(), std::string("Shaded")) != modes.end()) { - SoGroup* pcPointShadedRoot = new SoGroup(); - pcPointShadedRoot->addChild(pcPointStyle); - pcPointShadedRoot->addChild(pcShapeMaterial); - pcPointShadedRoot->addChild(pcPointsNormal); - pcPointShadedRoot->addChild(pcHighlight); - addDisplayMaskMode(pcPointShadedRoot, "Shaded"); - } - - // color shaded ------------------------------------------ - if (std::find(modes.begin(), modes.end(), std::string("Color")) != modes.end() || - std::find(modes.begin(), modes.end(), std::string("Intensity")) != modes.end()) { - SoGroup* pcColorShadedRoot = new SoGroup(); - pcColorShadedRoot->addChild(pcPointStyle); - SoMaterialBinding* pcMatBinding = new SoMaterialBinding; - pcMatBinding->value = SoMaterialBinding::PER_VERTEX_INDEXED; - pcColorShadedRoot->addChild(pcColorMat); - pcColorShadedRoot->addChild(pcMatBinding); - pcColorShadedRoot->addChild(pcHighlight); - addDisplayMaskMode(pcColorShadedRoot, "Color"); - } -} - void ViewProviderPoints::setDisplayMode(const char* ModeName) { int numPoints = pcPointsCoord->point.getNum(); @@ -339,18 +294,6 @@ std::vector ViewProviderPoints::getDisplayModes(void) const return StrList; } -void ViewProviderPoints::updateData(const App::Property* prop) -{ - Gui::ViewProviderGeometryObject::updateData(prop); - if (prop->getTypeId() == Points::PropertyPointKernel::getClassTypeId()) { - ViewProviderPointsBuilder builder; - builder.createPoints(prop, pcPointsCoord, pcPoints); - - // The number of points might have changed, so force also a resize of the Inventor internals - setActiveMode(); - } -} - QIcon ViewProviderPoints::getIcon() const { static const char * const Points_Feature_xpm[] = { @@ -414,7 +357,80 @@ void ViewProviderPoints::clipPointsCallback(void * ud, SoEventCallback * n) view->redraw(); } -void ViewProviderPoints::cut(const std::vector& picked, Gui::View3DInventorViewer &Viewer) +// ------------------------------------------------- + +PROPERTY_SOURCE(PointsGui::ViewProviderScattered, PointsGui::ViewProviderPoints) + +ViewProviderScattered::ViewProviderScattered() +{ + pcPoints = new SoPointSet(); + pcPoints->ref(); +} + +ViewProviderScattered::~ViewProviderScattered() +{ + pcPoints->unref(); +} + +void ViewProviderScattered::attach(App::DocumentObject* pcObj) +{ + // call parent's attach to define display modes + ViewProviderGeometryObject::attach(pcObj); + + pcHighlight->objectName = pcObj->getNameInDocument(); + pcHighlight->documentName = pcObj->getDocument()->getName(); + pcHighlight->subElementName = "Main"; + + // Hilight for selection + pcHighlight->addChild(pcPointsCoord); + pcHighlight->addChild(pcPoints); + + std::vector modes = getDisplayModes(); + + // points part --------------------------------------------- + SoGroup* pcPointRoot = new SoGroup(); + pcPointRoot->addChild(pcPointStyle); + pcPointRoot->addChild(pcShapeMaterial); + pcPointRoot->addChild(pcHighlight); + addDisplayMaskMode(pcPointRoot, "Point"); + + // points shaded --------------------------------------------- + if (std::find(modes.begin(), modes.end(), std::string("Shaded")) != modes.end()) { + SoGroup* pcPointShadedRoot = new SoGroup(); + pcPointShadedRoot->addChild(pcPointStyle); + pcPointShadedRoot->addChild(pcShapeMaterial); + pcPointShadedRoot->addChild(pcPointsNormal); + pcPointShadedRoot->addChild(pcHighlight); + addDisplayMaskMode(pcPointShadedRoot, "Shaded"); + } + + // color shaded ------------------------------------------ + if (std::find(modes.begin(), modes.end(), std::string("Color")) != modes.end() || + std::find(modes.begin(), modes.end(), std::string("Intensity")) != modes.end()) { + SoGroup* pcColorShadedRoot = new SoGroup(); + pcColorShadedRoot->addChild(pcPointStyle); + SoMaterialBinding* pcMatBinding = new SoMaterialBinding; + pcMatBinding->value = SoMaterialBinding::PER_VERTEX_INDEXED; + pcColorShadedRoot->addChild(pcColorMat); + pcColorShadedRoot->addChild(pcMatBinding); + pcColorShadedRoot->addChild(pcHighlight); + addDisplayMaskMode(pcColorShadedRoot, "Color"); + } +} + +void ViewProviderScattered::updateData(const App::Property* prop) +{ + ViewProviderPoints::updateData(prop); + if (prop->getTypeId() == Points::PropertyPointKernel::getClassTypeId()) { + ViewProviderPointsBuilder builder; + builder.createPoints(prop, pcPointsCoord, pcPoints); + + // The number of points might have changed, so force also a resize of the Inventor internals + setActiveMode(); + } +} + +void ViewProviderScattered::cut(const std::vector& picked, Gui::View3DInventorViewer &Viewer) { // create the polygon from the picked points Base::Polygon2D cPoly; @@ -460,15 +476,64 @@ PROPERTY_SOURCE(PointsGui::ViewProviderOrganized, PointsGui::ViewProviderPoints) ViewProviderOrganized::ViewProviderOrganized() { + pcPoints = new SoIndexedPointSet(); + pcPoints->ref(); } ViewProviderOrganized::~ViewProviderOrganized() { + pcPoints->unref(); +} + +void ViewProviderOrganized::attach(App::DocumentObject* pcObj) +{ + // call parent's attach to define display modes + ViewProviderGeometryObject::attach(pcObj); + + pcHighlight->objectName = pcObj->getNameInDocument(); + pcHighlight->documentName = pcObj->getDocument()->getName(); + pcHighlight->subElementName = "Main"; + + // Hilight for selection + pcHighlight->addChild(pcPointsCoord); + pcHighlight->addChild(pcPoints); + + std::vector modes = getDisplayModes(); + + // points part --------------------------------------------- + SoGroup* pcPointRoot = new SoGroup(); + pcPointRoot->addChild(pcPointStyle); + pcPointRoot->addChild(pcShapeMaterial); + pcPointRoot->addChild(pcHighlight); + addDisplayMaskMode(pcPointRoot, "Point"); + + // points shaded --------------------------------------------- + if (std::find(modes.begin(), modes.end(), std::string("Shaded")) != modes.end()) { + SoGroup* pcPointShadedRoot = new SoGroup(); + pcPointShadedRoot->addChild(pcPointStyle); + pcPointShadedRoot->addChild(pcShapeMaterial); + pcPointShadedRoot->addChild(pcPointsNormal); + pcPointShadedRoot->addChild(pcHighlight); + addDisplayMaskMode(pcPointShadedRoot, "Shaded"); + } + + // color shaded ------------------------------------------ + if (std::find(modes.begin(), modes.end(), std::string("Color")) != modes.end() || + std::find(modes.begin(), modes.end(), std::string("Intensity")) != modes.end()) { + SoGroup* pcColorShadedRoot = new SoGroup(); + pcColorShadedRoot->addChild(pcPointStyle); + SoMaterialBinding* pcMatBinding = new SoMaterialBinding; + pcMatBinding->value = SoMaterialBinding::PER_VERTEX_INDEXED; + pcColorShadedRoot->addChild(pcColorMat); + pcColorShadedRoot->addChild(pcMatBinding); + pcColorShadedRoot->addChild(pcHighlight); + addDisplayMaskMode(pcColorShadedRoot, "Color"); + } } void ViewProviderOrganized::updateData(const App::Property* prop) { - Gui::ViewProviderGeometryObject::updateData(prop); + ViewProviderPoints::updateData(prop); if (prop->getTypeId() == Points::PropertyPointKernel::getClassTypeId()) { ViewProviderPointsBuilder builder; builder.createPoints(prop, pcPointsCoord, pcPoints); @@ -478,15 +543,66 @@ void ViewProviderOrganized::updateData(const App::Property* prop) } } +void ViewProviderOrganized::cut(const std::vector& picked, Gui::View3DInventorViewer &Viewer) +{ + // create the polygon from the picked points + Base::Polygon2D cPoly; + for (std::vector::const_iterator it = picked.begin(); it != picked.end(); ++it) { + cPoly.Add(Base::Vector2D((*it)[0],(*it)[1])); + } + + // get a reference to the point feature + Points::Feature* fea = static_cast(pcObject); + const Points::PointKernel& points = fea->Points.getValue(); + + SoCamera* pCam = Viewer.getSoRenderManager()->getCamera(); + SbViewVolume vol = pCam->getViewVolume(); + + // search for all points inside/outside the polygon + Points::PointKernel newKernel; + newKernel.reserve(points.size()); + + bool invalidatePoints = false; + double nan = std::numeric_limits::quiet_NaN(); + for (Points::PointKernel::const_iterator jt = points.begin(); jt != points.end(); ++jt) { + // valid point? + Base::Vector3d vec(*jt); + if (!(boost::math::isnan(jt->x) || boost::math::isnan(jt->y) || boost::math::isnan(jt->z))) { + SbVec3f pt(jt->x,jt->y,jt->z); + + // project from 3d to 2d + vol.projectToScreen(pt, pt); + if (cPoly.Contains(Base::Vector2D(pt[0],pt[1]))) { + invalidatePoints = true; + vec.Set(nan, nan, nan); + } + } + + newKernel.push_back(vec); + } + + if (invalidatePoints) { + //Remove the points from the cloud and open a transaction object for the undo/redo stuff + Gui::Application::Instance->activeDocument()->openCommand("Cut points"); + + // sets the points outside the polygon to update the Inventor node + fea->Points.setValue(newKernel); + + // unset the modified flag because we don't need the features' execute() to be called + Gui::Application::Instance->activeDocument()->commitCommand(); + fea->purgeTouched(); + } +} + // ------------------------------------------------- namespace Gui { /// @cond DOXERR -PROPERTY_SOURCE_TEMPLATE(PointsGui::ViewProviderPython, PointsGui::ViewProviderPoints) +PROPERTY_SOURCE_TEMPLATE(PointsGui::ViewProviderPython, PointsGui::ViewProviderScattered) /// @endcond // explicit template instantiation -template class PointsGuiExport ViewProviderPythonFeatureT; +template class PointsGuiExport ViewProviderPythonFeatureT; } // ------------------------------------------------- @@ -531,3 +647,35 @@ void ViewProviderPointsBuilder::createPoints(const App::Property* prop, SoCoordi points->numPoints = cPts.size(); coords->point.finishEditing(); } + +void ViewProviderPointsBuilder::createPoints(const App::Property* prop, SoCoordinate3* coords, SoIndexedPointSet* points) const +{ + const Points::PropertyPointKernel* prop_points = static_cast(prop); + const Points::PointKernel& cPts = prop_points->getValue(); + + coords->point.setNum(cPts.size()); + SbVec3f* vec = coords->point.startEditing(); + + // get all points + std::size_t idx=0; + std::vector indices; + indices.reserve(cPts.size()); + const std::vector& kernel = cPts.getBasicPoints(); + for (std::vector::const_iterator it = kernel.begin(); it != kernel.end(); ++it, idx++) { + vec[idx].setValue(it->x, it->y, it->z); + // valid point? + if (!(boost::math::isnan(it->x) || boost::math::isnan(it->y) || boost::math::isnan(it->z))) { + indices.push_back(idx); + } + } + coords->point.finishEditing(); + + // get all point indices + idx=0; + points->coordIndex.setNum(indices.size()); + int32_t* pos = points->coordIndex.startEditing(); + for (std::vector::iterator it = indices.begin(); it != indices.end(); ++it) { + pos[idx++] = *it; + } + points->coordIndex.finishEditing(); +} diff --git a/src/Mod/Points/Gui/ViewProvider.h b/src/Mod/Points/Gui/ViewProvider.h index bc2928672..ec82604f8 100644 --- a/src/Mod/Points/Gui/ViewProvider.h +++ b/src/Mod/Points/Gui/ViewProvider.h @@ -32,6 +32,7 @@ class SoSwitch; class SoPointSet; +class SoIndexedPointSet; class SoLocateHighlight; class SoCoordinate3; class SoNormal; @@ -61,6 +62,7 @@ public: ~ViewProviderPointsBuilder(){} virtual void buildNodes(const App::Property*, std::vector&) const; void createPoints(const App::Property*, SoCoordinate3*, SoPointSet*) const; + void createPoints(const App::Property*, SoCoordinate3*, SoIndexedPointSet*) const; }; /** @@ -78,17 +80,10 @@ public: App::PropertyFloatConstraint PointSize; - /** - * Extracts the point data from the feature \a pcFeature and creates - * an Inventor node \a SoNode with these data. - */ - virtual void attach(App::DocumentObject *); /// set the viewing mode virtual void setDisplayMode(const char* ModeName); /// returns a list of all possible modes virtual std::vector getDisplayModes(void) const; - /// Update the point representation - virtual void updateData(const App::Property*); virtual QIcon getIcon() const; /// Sets the edit mnode @@ -105,12 +100,11 @@ protected: void setVertexColorMode(App::PropertyColorList*); void setVertexGreyvalueMode(Points::PropertyGreyValueList*); void setVertexNormalMode(Points::PropertyNormalList*); - virtual void cut( const std::vector& picked, Gui::View3DInventorViewer &Viewer); + virtual void cut(const std::vector& picked, Gui::View3DInventorViewer &Viewer) = 0; protected: Gui::SoFCSelection * pcHighlight; SoCoordinate3 * pcPointsCoord; - SoPointSet * pcPoints; SoMaterial * pcColorMat; SoNormal * pcPointsNormal; SoDrawStyle * pcPointStyle; @@ -119,6 +113,34 @@ private: static App::PropertyFloatConstraint::Constraints floatRange; }; +/** + * The ViewProviderScattered class creates + * a node representing the scattered point cloud. + * @author Werner Mayer + */ +class PointsGuiExport ViewProviderScattered : public ViewProviderPoints +{ + PROPERTY_HEADER(PointsGui::ViewProviderScattered); + +public: + ViewProviderScattered(); + virtual ~ViewProviderScattered(); + + /** + * Extracts the point data from the feature \a pcFeature and creates + * an Inventor node \a SoNode with these data. + */ + virtual void attach(App::DocumentObject *); + /// Update the point representation + virtual void updateData(const App::Property*); + +protected: + virtual void cut( const std::vector& picked, Gui::View3DInventorViewer &Viewer); + +protected: + SoPointSet * pcPoints; +}; + /** * The ViewProviderOrganized class creates * a node representing the organized points. @@ -132,11 +154,22 @@ public: ViewProviderOrganized(); virtual ~ViewProviderOrganized(); + /** + * Extracts the point data from the feature \a pcFeature and creates + * an Inventor node \a SoNode with these data. + */ + virtual void attach(App::DocumentObject *); /// Update the point representation virtual void updateData(const App::Property*); + +protected: + virtual void cut(const std::vector& picked, Gui::View3DInventorViewer &Viewer); + +protected: + SoIndexedPointSet * pcPoints; }; -typedef Gui::ViewProviderPythonFeatureT ViewProviderPython; +typedef Gui::ViewProviderPythonFeatureT ViewProviderPython; } // namespace PointsGui