Mod/Points/Gui/ViewProvider.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) 2004 Werner Mayer <wmayer[at]users.sourceforge.net>     *
00003  *                                                                         *
00004  *   This file is part of the FreeCAD CAx development system.              *
00005  *                                                                         *
00006  *   This library is free software; you can redistribute it and/or         *
00007  *   modify it under the terms of the GNU Library General Public           *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2 of the License, or (at your option) any later version.      *
00010  *                                                                         *
00011  *   This library  is distributed in the hope that it will be useful,      *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00014  *   GNU Library General Public License for more details.                  *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Library General Public     *
00017  *   License along with this library; see the file COPYING.LIB. If not,    *
00018  *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
00019  *   Suite 330, Boston, MA  02111-1307, USA                                *
00020  *                                                                         *
00021  ***************************************************************************/
00022 
00023 
00024 #include "PreCompiled.h"
00025 
00026 #ifndef _PreComp_
00027 # ifdef FC_OS_WIN32
00028 #  include <windows.h>
00029 # endif
00030 # include <Inventor/nodes/SoCamera.h>
00031 # include <Inventor/nodes/SoCoordinate3.h>
00032 # include <Inventor/nodes/SoDrawStyle.h>
00033 # include <Inventor/nodes/SoPointSet.h>
00034 # include <Inventor/nodes/SoMaterial.h>
00035 # include <Inventor/nodes/SoMaterialBinding.h>
00036 # include <Inventor/nodes/SoNormal.h>
00037 # include <Inventor/errors/SoDebugError.h>
00038 # include <Inventor/events/SoMouseButtonEvent.h>
00039 #endif
00040 
00042 #include <Base/Console.h>
00043 #include <Base/Parameter.h>
00044 #include <Base/Exception.h>
00045 #include <Base/Sequencer.h>
00046 #include <Base/Tools2D.h>
00047 #include <Base/Vector3D.h>
00048 #include <App/Application.h>
00049 #include <App/Document.h>
00050 #include <Gui/Application.h>
00051 #include <Gui/Document.h>
00052 #include <Gui/SoFCSelection.h>
00053 
00054 #include <Gui/View3DInventorViewer.h>
00055 #include <Mod/Points/App/PointsFeature.h>
00056 
00057 #include "ViewProvider.h"
00058 #include "../App/Properties.h"
00059 
00060 
00061 using namespace PointsGui;
00062 using namespace Points;
00063 
00064 
00065 PROPERTY_SOURCE(PointsGui::ViewProviderPoints, Gui::ViewProviderGeometryObject)
00066 
00067 
00068 App::PropertyFloatConstraint::Constraints ViewProviderPoints::floatRange = {1.0f,64.0f,1.0f};
00069 
00070 ViewProviderPoints::ViewProviderPoints()
00071 {
00072     ADD_PROPERTY(PointSize,(2.0f));
00073     PointSize.setConstraints(&floatRange);
00074 
00075     pcPointsCoord = new SoCoordinate3();
00076     pcPointsCoord->ref();
00077     pcPoints = new SoPointSet();
00078     pcPoints->ref();
00079     pcPointsNormal = new SoNormal();  
00080     pcPointsNormal->ref();
00081     pcColorMat = new SoMaterial;
00082     pcColorMat->ref();
00083 
00084     pcPointStyle = new SoDrawStyle();
00085     pcPointStyle->ref();
00086     pcPointStyle->style = SoDrawStyle::POINTS;
00087     pcPointStyle->pointSize = PointSize.getValue();
00088 }
00089 
00090 ViewProviderPoints::~ViewProviderPoints()
00091 {
00092     pcPointsCoord->unref();
00093     pcPoints->unref();
00094     pcPointsNormal->unref();
00095     pcColorMat->unref();
00096     pcPointStyle->unref();
00097 }
00098 
00099 void ViewProviderPoints::onChanged(const App::Property* prop)
00100 {
00101     if ( prop == &PointSize ) {
00102         pcPointStyle->pointSize = PointSize.getValue();
00103     }
00104     else {
00105         ViewProviderGeometryObject::onChanged(prop);
00106     }
00107 }
00108 
00109 void ViewProviderPoints::setVertexColorMode(App::PropertyColorList* pcProperty)
00110 {
00111     const std::vector<App::Color>& val = pcProperty->getValues();
00112     unsigned long i=0;
00113 
00114     pcColorMat->enableNotify(false);
00115     pcColorMat->diffuseColor.deleteValues(0);
00116     pcColorMat->diffuseColor.setNum(val.size());
00117 
00118     for ( std::vector<App::Color>::const_iterator it = val.begin(); it != val.end(); ++it ) {
00119         pcColorMat->diffuseColor.set1Value(i++, SbColor(it->r, it->g, it->b));
00120     }
00121 
00122     pcColorMat->enableNotify(true);
00123     pcColorMat->touch();
00124 }
00125 
00126 void ViewProviderPoints::setVertexGreyvalueMode(Points::PropertyGreyValueList* pcProperty)
00127 {
00128     const std::vector<float>& val = pcProperty->getValues();
00129     unsigned long i=0;
00130 
00131     pcColorMat->enableNotify(false);
00132     pcColorMat->diffuseColor.deleteValues(0);
00133     pcColorMat->diffuseColor.setNum(val.size());
00134 
00135     for ( std::vector<float>::const_iterator it = val.begin(); it != val.end(); ++it ) {
00136         pcColorMat->diffuseColor.set1Value(i++, SbColor(*it, *it, *it));
00137     }
00138 
00139     pcColorMat->enableNotify(true);
00140     pcColorMat->touch();
00141 }
00142 
00143 void ViewProviderPoints::setVertexNormalMode(Points::PropertyNormalList* pcProperty)
00144 {
00145     const std::vector<Base::Vector3f>& val = pcProperty->getValues();
00146     unsigned long i=0;
00147 
00148     pcPointsNormal->enableNotify(false);
00149     pcPointsNormal->vector.deleteValues(0);
00150     pcPointsNormal->vector.setNum(val.size());
00151 
00152     for ( std::vector<Base::Vector3f>::const_iterator it = val.begin(); it != val.end(); ++it ) {
00153         pcPointsNormal->vector.set1Value(i++, it->x, it->y, it->z);
00154     }
00155 
00156     pcPointsNormal->enableNotify(true);
00157     pcPointsNormal->touch();
00158 }
00159 
00160 void ViewProviderPoints::attach(App::DocumentObject* pcObj)
00161 {
00162     // call parent's attach to define display modes
00163     ViewProviderGeometryObject::attach(pcObj);
00164 
00165     SoGroup* pcPointRoot = new SoGroup();
00166     SoGroup* pcPointShadedRoot = new SoGroup();
00167     SoGroup* pcColorShadedRoot = new SoGroup();
00168 
00169     // Hilight for selection
00170     pcHighlight->addChild(pcPointsCoord);
00171     pcHighlight->addChild(pcPoints);
00172 
00173     // points part ---------------------------------------------
00174     pcPointRoot->addChild(pcPointStyle);
00175     pcPointRoot->addChild(pcShapeMaterial);
00176     pcPointRoot->addChild(pcHighlight);
00177 
00178     // points shaded ---------------------------------------------
00179     pcPointShadedRoot->addChild(pcPointStyle);
00180     pcPointShadedRoot->addChild(pcShapeMaterial);
00181     pcPointShadedRoot->addChild(pcPointsNormal);
00182     pcPointShadedRoot->addChild(pcHighlight);
00183 
00184     // color shaded  ------------------------------------------
00185     pcColorShadedRoot->addChild(pcPointStyle);
00186     SoMaterialBinding* pcMatBinding = new SoMaterialBinding;
00187     pcMatBinding->value = SoMaterialBinding::PER_VERTEX_INDEXED;
00188     pcColorShadedRoot->addChild(pcColorMat);
00189     pcColorShadedRoot->addChild(pcMatBinding);
00190     pcColorShadedRoot->addChild(pcHighlight);
00191 
00192     // putting all together with a switch
00193     addDisplayMaskMode(pcPointRoot, "Point");
00194     addDisplayMaskMode(pcColorShadedRoot, "Color");
00195     addDisplayMaskMode(pcPointShadedRoot, "Shaded");
00196 }
00197 
00198 void ViewProviderPoints::setDisplayMode(const char* ModeName)
00199 {
00200   int numPoints = pcPointsCoord->point.getNum();
00201 
00202   if ( strcmp("Color",ModeName)==0 )
00203   {
00204     std::map<std::string,App::Property*> Map;
00205     pcObject->getPropertyMap(Map);
00206     for( std::map<std::string,App::Property*>::iterator it = Map.begin(); it != Map.end(); ++it )
00207     {
00208       Base::Type t = it->second->getTypeId();
00209       if ( t==App::PropertyColorList::getClassTypeId() )
00210       {
00211         App::PropertyColorList* colors = (App::PropertyColorList*)it->second;
00212         if ( numPoints != colors->getSize() ) {
00213 #ifdef FC_DEBUG
00214           SoDebugError::postWarning("ViewProviderPoints::setDisplayMode",
00215                                     "The number of points (%d) doesn't match with the number of colors (%d).", numPoints, colors->getSize());
00216 #endif
00217           // fallback 
00218           setDisplayMaskMode("Point");
00219         } else {
00220           setVertexColorMode(colors);
00221           setDisplayMaskMode("Color");
00222         }
00223         break;
00224       }
00225     }
00226   }
00227   else if ( strcmp("Intensity",ModeName)==0 )
00228   {
00229     std::map<std::string,App::Property*> Map;
00230     pcObject->getPropertyMap(Map);
00231     for( std::map<std::string,App::Property*>::iterator it = Map.begin(); it != Map.end(); ++it )
00232     {
00233       Base::Type t = it->second->getTypeId();
00234       if ( t==Points::PropertyGreyValueList::getClassTypeId() )
00235       {
00236         Points::PropertyGreyValueList* greyValues = (Points::PropertyGreyValueList*)it->second;
00237         if ( numPoints != greyValues->getSize() ) {
00238 #ifdef FC_DEBUG
00239           SoDebugError::postWarning("ViewProviderPoints::setDisplayMode",
00240                                     "The number of points (%d) doesn't match with the number of grey values (%d).", numPoints, greyValues->getSize());
00241 #endif
00242           // Intensity mode is not possible then set the default () mode instead.
00243           setDisplayMaskMode("Point");
00244         } else {
00245           setVertexGreyvalueMode((Points::PropertyGreyValueList*)it->second);
00246           setDisplayMaskMode("Color");
00247         }
00248         break;
00249       }
00250     }
00251   }
00252   else if ( strcmp("Shaded",ModeName)==0 )
00253   {
00254     std::map<std::string,App::Property*> Map;
00255     pcObject->getPropertyMap(Map);
00256     for( std::map<std::string,App::Property*>::iterator it = Map.begin(); it != Map.end(); ++it )
00257     {
00258       Base::Type t = it->second->getTypeId();
00259       if ( t==Points::PropertyNormalList::getClassTypeId() )
00260       {
00261         Points::PropertyNormalList* normals = (Points::PropertyNormalList*)it->second;
00262         if ( numPoints != normals->getSize() ) {
00263 #ifdef FC_DEBUG
00264           SoDebugError::postWarning("ViewProviderPoints::setDisplayMode",
00265                                     "The number of points (%d) doesn't match with the number of normals (%d).", numPoints, normals->getSize());
00266 #endif
00267           // fallback 
00268           setDisplayMaskMode("Point");
00269         } else {
00270           setVertexNormalMode(normals);
00271           setDisplayMaskMode("Shaded");
00272         }
00273         break;
00274       }
00275     }
00276   }
00277   else if ( strcmp("Points",ModeName)==0 )
00278   {
00279     setDisplayMaskMode("Point");
00280   }
00281 
00282   ViewProviderGeometryObject::setDisplayMode(ModeName);
00283 }
00284 
00285 std::vector<std::string> ViewProviderPoints::getDisplayModes(void) const
00286 {
00287   std::vector<std::string> StrList;
00288   StrList.push_back("Points");
00289 
00290   if ( pcObject )
00291   {
00292     std::map<std::string,App::Property*> Map;
00293     pcObject->getPropertyMap(Map);
00294 
00295     for( std::map<std::string,App::Property*>::iterator it = Map.begin(); it != Map.end(); ++it )
00296     {
00297       Base::Type t = it->second->getTypeId();
00298       if ( t==Points::PropertyNormalList::getClassTypeId() )
00299         StrList.push_back("Shaded");
00300       else if ( t==Points::PropertyGreyValueList::getClassTypeId() )
00301         StrList.push_back("Intensity");
00302       else if ( t==App::PropertyColorList::getClassTypeId() )
00303         StrList.push_back("Color");
00304     }
00305   }
00306 
00307   return StrList;
00308 }
00309 
00310 void ViewProviderPoints::updateData(const App::Property* prop)
00311 {
00312     Gui::ViewProviderGeometryObject::updateData(prop);
00313     if (prop->getTypeId() == Points::PropertyPointKernel::getClassTypeId()) {
00314         ViewProviderPointsBuilder builder;
00315         builder.createPoints(prop, pcPointsCoord, pcPoints);
00316 
00317         // The number of points might have changed, so force also a resize of the Inventor internals
00318         setActiveMode();
00319     }
00320 }
00321 
00322 QIcon ViewProviderPoints::getIcon() const
00323 {
00324   static const char * const Points_Feature_xpm[] = {
00325     "16 16 4 1",
00326     ".  c none",
00327     "s  c #000000",
00328     "b  c #FFFF00",
00329     "r  c #FF0000",
00330     "ss.....ss.....bb",
00331     "ss..ss.ss.....bb",
00332     "....ss..........",
00333     "...........bb...",
00334     ".ss..ss....bb...",
00335     ".ss..ss.........",
00336     "........bb....bb",
00337     "ss......bb....bb",
00338     "ss..rr......bb..",
00339     "....rr......bb..",
00340     "........bb......",
00341     "..rr....bb..bb..",
00342     "..rr........bb..",
00343     ".....rr.........",
00344     "rr...rr..rr..rr.",
00345     "rr.......rr..rr."};
00346   QPixmap px(Points_Feature_xpm);
00347   return px;
00348 }
00349 
00350 bool ViewProviderPoints::setEdit(int)
00351 {
00352     return true;
00353 }
00354 
00355 void ViewProviderPoints::unsetEdit(int)
00356 {
00357 }
00358 
00359 void ViewProviderPoints::clipPointsCallback(void * ud, SoEventCallback * n)
00360 {
00361     // When this callback function is invoked we must in either case leave the edit mode
00362     Gui::View3DInventorViewer* view  = reinterpret_cast<Gui::View3DInventorViewer*>(n->getUserData());
00363     view->setEditing(false);
00364     view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), clipPointsCallback);
00365     n->setHandled();
00366 
00367     std::vector<SbVec2f> clPoly = view->getGLPolygon();
00368     if (clPoly.size() < 3)
00369         return;
00370     if (clPoly.front() != clPoly.back())
00371         clPoly.push_back(clPoly.front());
00372 
00373     std::vector<Gui::ViewProvider*> views = view->getViewProvidersOfType(ViewProviderPoints::getClassTypeId());
00374     for (std::vector<Gui::ViewProvider*>::iterator it = views.begin(); it != views.end(); ++it) {
00375         ViewProviderPoints* that = static_cast<ViewProviderPoints*>(*it);
00376         if (that->getEditingMode() > -1) {
00377             that->finishEditing();
00378             that->cut(clPoly, *view);
00379         }
00380     }
00381 
00382     view->render();
00383 }
00384 
00385 void ViewProviderPoints::cut(const std::vector<SbVec2f>& picked, Gui::View3DInventorViewer &Viewer)
00386 {
00387     // create the polygon from the picked points
00388     Base::Polygon2D cPoly;
00389     for (std::vector<SbVec2f>::const_iterator it = picked.begin(); it != picked.end(); ++it) {
00390         cPoly.Add(Base::Vector2D((*it)[0],(*it)[1]));
00391     }
00392 
00393     // get a reference to the point feature
00394     Points::Feature* fea = (Points::Feature*)pcObject;
00395     const Points::PointKernel& points = fea->Points.getValue();
00396 
00397     SoCamera* pCam = Viewer.getCamera();  
00398     SbViewVolume  vol = pCam->getViewVolume(); 
00399 
00400     // search for all points inside/outside the polygon
00401     Points::PointKernel newKernel;
00402     for ( Points::PointKernel::const_iterator jt = points.begin(); jt != points.end(); ++jt ) {
00403         SbVec3f pt(jt->x,jt->y,jt->z);
00404 
00405         // project from 3d to 2d
00406         vol.projectToScreen(pt, pt);
00407         if (!cPoly.Contains(Base::Vector2D(pt[0],pt[1])))
00408             newKernel.push_back(*jt);
00409     }
00410 
00411     if (newKernel.size() == points.size())
00412         return; // nothing needs to be done
00413 
00414     //Remove the points from the cloud and open a transaction object for the undo/redo stuff
00415     Gui::Application::Instance->activeDocument()->openCommand("Cut points");
00416 
00417     // sets the points outside the polygon to update the Inventor node
00418     fea->Points.setValue(newKernel);
00419 
00420     // unset the modified flag because we don't need the features' execute() to be called
00421     Gui::Application::Instance->activeDocument()->commitCommand();
00422     fea->purgeTouched();
00423 }
00424 
00425 // -------------------------------------------------
00426 
00427 namespace Gui {
00429 PROPERTY_SOURCE_TEMPLATE(PointsGui::ViewProviderPython, PointsGui::ViewProviderPoints)
00431 
00432 // explicit template instantiation
00433 template class PointsGuiExport ViewProviderPythonFeatureT<PointsGui::ViewProviderPoints>;
00434 }
00435 
00436 // -------------------------------------------------
00437 
00438 void ViewProviderPointsBuilder::buildNodes(const App::Property* prop, std::vector<SoNode*>& nodes) const
00439 {
00440     SoCoordinate3 *pcPointsCoord=0;
00441     SoPointSet *pcPoints=0;
00442 
00443     if (nodes.empty()) {
00444         pcPointsCoord = new SoCoordinate3();
00445         nodes.push_back(pcPointsCoord);
00446         pcPoints = new SoPointSet();
00447         nodes.push_back(pcPoints);
00448     }
00449     else if (nodes.size() == 2) {
00450         if (nodes[0]->getTypeId() == SoCoordinate3::getClassTypeId())
00451             pcPointsCoord = static_cast<SoCoordinate3*>(nodes[0]);
00452         if (nodes[1]->getTypeId() == SoPointSet::getClassTypeId())
00453             pcPoints = static_cast<SoPointSet*>(nodes[1]);
00454     }
00455 
00456     if (pcPointsCoord && pcPoints)
00457         createPoints(prop, pcPointsCoord, pcPoints);
00458 }
00459 
00460 void ViewProviderPointsBuilder::createPoints(const App::Property* prop, SoCoordinate3* coords, SoPointSet* points) const
00461 {
00462     const Points::PropertyPointKernel* prop_points = static_cast<const Points::PropertyPointKernel*>(prop);
00463     const Points::PointKernel& cPts = prop_points->getValue();
00464 
00465     // disable the notification, otherwise whenever a point is inserted SoPointSet gets notified
00466     coords->enableNotify(false);
00467     coords->point.deleteValues(0);
00468     coords->point.setNum(cPts.size());
00469 
00470     // get all points
00471     int idx=0;
00472     const std::vector<Base::Vector3f>& kernel = cPts.getBasicPoints();
00473     for (std::vector<Base::Vector3f>::const_iterator it = kernel.begin(); it != kernel.end(); ++it, idx++) {
00474         coords->point.set1Value(idx, it->x, it->y, it->z);
00475     }
00476 
00477     points->numPoints = cPts.size();
00478     coords->enableNotify(true);
00479     coords->touch();
00480 }

Generated on Wed Nov 23 19:00:58 2011 for FreeCAD by  doxygen 1.6.1