/*************************************************************************** * Copyright (c) 2004 Werner Mayer * * * * 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_ # ifdef FC_OS_WIN32 # include # endif # include # include # include # include # include # include # include # include # include #endif /// Here the FreeCAD includes sorted by Base,App,Gui,... #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ViewProvider.h" #include "../App/Properties.h" using namespace PointsGui; using namespace Points; PROPERTY_SOURCE(PointsGui::ViewProviderPoints, Gui::ViewProviderGeometryObject) App::PropertyFloatConstraint::Constraints ViewProviderPoints::floatRange = {1.0,64.0,1.0}; ViewProviderPoints::ViewProviderPoints() { ADD_PROPERTY(PointSize,(2.0f)); PointSize.setConstraints(&floatRange); pcPointsCoord = new SoCoordinate3(); pcPointsCoord->ref(); pcPoints = new SoPointSet(); pcPoints->ref(); pcPointsNormal = new SoNormal(); pcPointsNormal->ref(); pcColorMat = new SoMaterial; pcColorMat->ref(); pcPointStyle = new SoDrawStyle(); pcPointStyle->ref(); pcPointStyle->style = SoDrawStyle::POINTS; pcPointStyle->pointSize = PointSize.getValue(); } ViewProviderPoints::~ViewProviderPoints() { pcPointsCoord->unref(); pcPoints->unref(); pcPointsNormal->unref(); pcColorMat->unref(); pcPointStyle->unref(); } void ViewProviderPoints::onChanged(const App::Property* prop) { if ( prop == &PointSize ) { pcPointStyle->pointSize = PointSize.getValue(); } else { ViewProviderGeometryObject::onChanged(prop); } } void ViewProviderPoints::setVertexColorMode(App::PropertyColorList* pcProperty) { const std::vector& val = pcProperty->getValues(); unsigned long i=0; pcColorMat->enableNotify(false); pcColorMat->diffuseColor.deleteValues(0); pcColorMat->diffuseColor.setNum(val.size()); for ( std::vector::const_iterator it = val.begin(); it != val.end(); ++it ) { pcColorMat->diffuseColor.set1Value(i++, SbColor(it->r, it->g, it->b)); } pcColorMat->enableNotify(true); pcColorMat->touch(); } void ViewProviderPoints::setVertexGreyvalueMode(Points::PropertyGreyValueList* pcProperty) { const std::vector& val = pcProperty->getValues(); unsigned long i=0; pcColorMat->enableNotify(false); pcColorMat->diffuseColor.deleteValues(0); pcColorMat->diffuseColor.setNum(val.size()); for ( std::vector::const_iterator it = val.begin(); it != val.end(); ++it ) { pcColorMat->diffuseColor.set1Value(i++, SbColor(*it, *it, *it)); } pcColorMat->enableNotify(true); pcColorMat->touch(); } void ViewProviderPoints::setVertexNormalMode(Points::PropertyNormalList* pcProperty) { const std::vector& val = pcProperty->getValues(); unsigned long i=0; pcPointsNormal->enableNotify(false); pcPointsNormal->vector.deleteValues(0); pcPointsNormal->vector.setNum(val.size()); for ( std::vector::const_iterator it = val.begin(); it != val.end(); ++it ) { pcPointsNormal->vector.set1Value(i++, it->x, it->y, it->z); } pcPointsNormal->enableNotify(true); pcPointsNormal->touch(); } void ViewProviderPoints::attach(App::DocumentObject* pcObj) { // call parent's attach to define display modes ViewProviderGeometryObject::attach(pcObj); SoGroup* pcPointRoot = new SoGroup(); SoGroup* pcPointShadedRoot = new SoGroup(); SoGroup* pcColorShadedRoot = new SoGroup(); // Hilight for selection pcHighlight->addChild(pcPointsCoord); pcHighlight->addChild(pcPoints); // points part --------------------------------------------- pcPointRoot->addChild(pcPointStyle); pcPointRoot->addChild(pcShapeMaterial); pcPointRoot->addChild(pcHighlight); // points shaded --------------------------------------------- pcPointShadedRoot->addChild(pcPointStyle); pcPointShadedRoot->addChild(pcShapeMaterial); pcPointShadedRoot->addChild(pcPointsNormal); pcPointShadedRoot->addChild(pcHighlight); // color shaded ------------------------------------------ pcColorShadedRoot->addChild(pcPointStyle); SoMaterialBinding* pcMatBinding = new SoMaterialBinding; pcMatBinding->value = SoMaterialBinding::PER_VERTEX_INDEXED; pcColorShadedRoot->addChild(pcColorMat); pcColorShadedRoot->addChild(pcMatBinding); pcColorShadedRoot->addChild(pcHighlight); // putting all together with a switch addDisplayMaskMode(pcPointRoot, "Point"); addDisplayMaskMode(pcColorShadedRoot, "Color"); addDisplayMaskMode(pcPointShadedRoot, "Shaded"); } void ViewProviderPoints::setDisplayMode(const char* ModeName) { int numPoints = pcPointsCoord->point.getNum(); if ( strcmp("Color",ModeName)==0 ) { std::map Map; pcObject->getPropertyMap(Map); for( std::map::iterator it = Map.begin(); it != Map.end(); ++it ) { Base::Type t = it->second->getTypeId(); if ( t==App::PropertyColorList::getClassTypeId() ) { App::PropertyColorList* colors = (App::PropertyColorList*)it->second; if ( numPoints != colors->getSize() ) { #ifdef FC_DEBUG SoDebugError::postWarning("ViewProviderPoints::setDisplayMode", "The number of points (%d) doesn't match with the number of colors (%d).", numPoints, colors->getSize()); #endif // fallback setDisplayMaskMode("Point"); } else { setVertexColorMode(colors); setDisplayMaskMode("Color"); } break; } } } else if ( strcmp("Intensity",ModeName)==0 ) { std::map Map; pcObject->getPropertyMap(Map); for( std::map::iterator it = Map.begin(); it != Map.end(); ++it ) { Base::Type t = it->second->getTypeId(); if ( t==Points::PropertyGreyValueList::getClassTypeId() ) { Points::PropertyGreyValueList* greyValues = (Points::PropertyGreyValueList*)it->second; if ( numPoints != greyValues->getSize() ) { #ifdef FC_DEBUG SoDebugError::postWarning("ViewProviderPoints::setDisplayMode", "The number of points (%d) doesn't match with the number of grey values (%d).", numPoints, greyValues->getSize()); #endif // Intensity mode is not possible then set the default () mode instead. setDisplayMaskMode("Point"); } else { setVertexGreyvalueMode((Points::PropertyGreyValueList*)it->second); setDisplayMaskMode("Color"); } break; } } } else if ( strcmp("Shaded",ModeName)==0 ) { std::map Map; pcObject->getPropertyMap(Map); for( std::map::iterator it = Map.begin(); it != Map.end(); ++it ) { Base::Type t = it->second->getTypeId(); if ( t==Points::PropertyNormalList::getClassTypeId() ) { Points::PropertyNormalList* normals = (Points::PropertyNormalList*)it->second; if ( numPoints != normals->getSize() ) { #ifdef FC_DEBUG SoDebugError::postWarning("ViewProviderPoints::setDisplayMode", "The number of points (%d) doesn't match with the number of normals (%d).", numPoints, normals->getSize()); #endif // fallback setDisplayMaskMode("Point"); } else { setVertexNormalMode(normals); setDisplayMaskMode("Shaded"); } break; } } } else if ( strcmp("Points",ModeName)==0 ) { setDisplayMaskMode("Point"); } ViewProviderGeometryObject::setDisplayMode(ModeName); } std::vector ViewProviderPoints::getDisplayModes(void) const { std::vector StrList; StrList.push_back("Points"); if ( pcObject ) { std::map Map; pcObject->getPropertyMap(Map); for( std::map::iterator it = Map.begin(); it != Map.end(); ++it ) { Base::Type t = it->second->getTypeId(); if ( t==Points::PropertyNormalList::getClassTypeId() ) StrList.push_back("Shaded"); else if ( t==Points::PropertyGreyValueList::getClassTypeId() ) StrList.push_back("Intensity"); else if ( t==App::PropertyColorList::getClassTypeId() ) StrList.push_back("Color"); } } 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[] = { "16 16 4 1", ". c none", "s c #000000", "b c #FFFF00", "r c #FF0000", "ss.....ss.....bb", "ss..ss.ss.....bb", "....ss..........", "...........bb...", ".ss..ss....bb...", ".ss..ss.........", "........bb....bb", "ss......bb....bb", "ss..rr......bb..", "....rr......bb..", "........bb......", "..rr....bb..bb..", "..rr........bb..", ".....rr.........", "rr...rr..rr..rr.", "rr.......rr..rr."}; QPixmap px(Points_Feature_xpm); return px; } bool ViewProviderPoints::setEdit(int) { return true; } void ViewProviderPoints::unsetEdit(int) { } void ViewProviderPoints::clipPointsCallback(void * ud, SoEventCallback * n) { // When this callback function is invoked we must in either case leave the edit mode Gui::View3DInventorViewer* view = reinterpret_cast(n->getUserData()); view->setEditing(false); view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), clipPointsCallback); n->setHandled(); std::vector clPoly = view->getGLPolygon(); if (clPoly.size() < 3) return; if (clPoly.front() != clPoly.back()) clPoly.push_back(clPoly.front()); std::vector views = view->getViewProvidersOfType(ViewProviderPoints::getClassTypeId()); for (std::vector::iterator it = views.begin(); it != views.end(); ++it) { ViewProviderPoints* that = static_cast(*it); if (that->getEditingMode() > -1) { that->finishEditing(); that->cut(clPoly, *view); } } view->render(); } void ViewProviderPoints::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 = (Points::Feature*)pcObject; const Points::PointKernel& points = fea->Points.getValue(); SoCamera* pCam = Viewer.getCamera(); SbViewVolume vol = pCam->getViewVolume(); // search for all points inside/outside the polygon Points::PointKernel newKernel; for ( Points::PointKernel::const_iterator jt = points.begin(); jt != points.end(); ++jt ) { 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]))) newKernel.push_back(*jt); } if (newKernel.size() == points.size()) return; // nothing needs to be done //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) /// @endcond // explicit template instantiation template class PointsGuiExport ViewProviderPythonFeatureT; } // ------------------------------------------------- void ViewProviderPointsBuilder::buildNodes(const App::Property* prop, std::vector& nodes) const { SoCoordinate3 *pcPointsCoord=0; SoPointSet *pcPoints=0; if (nodes.empty()) { pcPointsCoord = new SoCoordinate3(); nodes.push_back(pcPointsCoord); pcPoints = new SoPointSet(); nodes.push_back(pcPoints); } else if (nodes.size() == 2) { if (nodes[0]->getTypeId() == SoCoordinate3::getClassTypeId()) pcPointsCoord = static_cast(nodes[0]); if (nodes[1]->getTypeId() == SoPointSet::getClassTypeId()) pcPoints = static_cast(nodes[1]); } if (pcPointsCoord && pcPoints) createPoints(prop, pcPointsCoord, pcPoints); } void ViewProviderPointsBuilder::createPoints(const App::Property* prop, SoCoordinate3* coords, SoPointSet* points) const { const Points::PropertyPointKernel* prop_points = static_cast(prop); const Points::PointKernel& cPts = prop_points->getValue(); // disable the notification, otherwise whenever a point is inserted SoPointSet gets notified coords->enableNotify(false); coords->point.deleteValues(0); coords->point.setNum(cPts.size()); // get all points int idx=0; const std::vector& kernel = cPts.getBasicPoints(); for (std::vector::const_iterator it = kernel.begin(); it != kernel.end(); ++it, idx++) { coords->point.set1Value(idx, (float)it->x, (float)it->y, (float)it->z); } points->numPoints = cPts.size(); coords->enableNotify(true); coords->touch(); }