ViewProviderMeshNode.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) 2006 Werner Mayer <werner.wm.mayer@gmx.de>              *
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 # include <Inventor/nodes/SoBaseColor.h>
00028 # include <Inventor/nodes/SoDrawStyle.h>
00029 # include <Inventor/nodes/SoMaterial.h>
00030 # include <Inventor/nodes/SoShapeHints.h>
00031 # include <Inventor/nodes/SoOrthographicCamera.h>
00032 # include <qmessagebox.h>
00033 #endif
00034 
00036 #include <Base/Console.h>
00037 #include <Base/Exception.h>
00038 #include <Base/Sequencer.h>
00039 #include <Base/Tools2D.h>
00040 #include <Base/ViewProj.h>
00041 
00042 #include <App/Document.h>
00043 #include <App/PropertyLinks.h>
00044 
00045 #include <Gui/Application.h>
00046 #include <Gui/Command.h>
00047 #include <Gui/Document.h>
00048 #include <Gui/SoFCSelection.h>
00049 #include <Gui/MainWindow.h>
00050 #include <Gui/MouseModel.h>
00051 #include <Gui/Selection.h>
00052 #include <Gui/Window.h>
00053 #include <Gui/View3DInventor.h>
00054 #include <Gui/View3DInventorViewer.h>
00055 
00056 #include <Mod/Mesh/App/Core/Algorithm.h>
00057 #include <Mod/Mesh/App/Core/Evaluation.h>
00058 #include <Mod/Mesh/App/Core/Grid.h>
00059 #include <Mod/Mesh/App/Core/Iterator.h>
00060 #include <Mod/Mesh/App/Core/MeshIO.h>
00061 #include <Mod/Mesh/App/Core/Visitor.h>
00062 #include <Mod/Mesh/App/Mesh.h>
00063 #include <Mod/Mesh/App/MeshFeature.h>
00064 #include <Mod/Mesh/Gui/SoFCMeshNode.h>
00065 
00066 #include "ViewProvider.h"
00067 #include "ViewProviderMeshNode.h"
00068 
00069 
00070 using namespace MeshGui;
00071 
00072 
00073 App::PropertyFloatConstraint::Constraints ViewProviderMeshNode::floatRange = {1.0f,64.0f,1.0f};
00074 
00075 PROPERTY_SOURCE(MeshGui::ViewProviderMeshNode, Gui::ViewProviderGeometryObject)
00076 
00077 ViewProviderMeshNode::ViewProviderMeshNode() : pcOpenEdge(0), m_bEdit(false)
00078 {
00079   ADD_PROPERTY(LineWidth,(2.0f));
00080   LineWidth.setConstraints(&floatRange);
00081   ADD_PROPERTY(PointSize,(2.0f));
00082   PointSize.setConstraints(&floatRange);
00083   ADD_PROPERTY(OpenEdges,(false));
00084 
00085   pOpenColor = new SoBaseColor();
00086   setOpenEdgeColorFrom(ShapeColor.getValue());
00087   pOpenColor->ref();
00088 
00089   pcLineStyle = new SoDrawStyle();
00090   pcLineStyle->ref();
00091   pcLineStyle->style = SoDrawStyle::LINES;
00092   pcLineStyle->lineWidth = LineWidth.getValue();
00093 
00094   pcPointStyle = new SoDrawStyle();
00095   pcPointStyle->ref();
00096   pcPointStyle->style = SoDrawStyle::POINTS;
00097   pcPointStyle->pointSize = PointSize.getValue();
00098 
00099   // read the correct shape color from the preferences
00100   Base::Reference<ParameterGrp> hGrp = Gui::WindowParameter::getDefaultParameter()->GetGroup("Mod/Mesh");
00101   App::Color color = ShapeColor.getValue();
00102   unsigned long current = color.getPackedValue();
00103   unsigned long setting = hGrp->GetUnsigned("MeshColor", current);
00104   if ( current != setting )
00105   {
00106     color.setPackedValue((uint32_t)setting);
00107     ShapeColor.setValue(color);
00108   }
00109 }
00110 
00111 ViewProviderMeshNode::~ViewProviderMeshNode()
00112 {
00113   pOpenColor->unref();
00114   pcLineStyle->unref();
00115   pcPointStyle->unref();
00116 }
00117 
00118 void ViewProviderMeshNode::onChanged(const App::Property* prop)
00119 {
00120   if ( prop == &LineWidth ) {
00121     pcLineStyle->lineWidth = LineWidth.getValue();
00122   } else if ( prop == &PointSize ) {
00123     pcPointStyle->pointSize = PointSize.getValue();
00124   } else if ( prop == &OpenEdges ) {
00125     showOpenEdges( OpenEdges.getValue() );
00126   } else {
00127     // Set the inverse color for open edges
00128     if ( prop == &ShapeColor ) {
00129       setOpenEdgeColorFrom(ShapeColor.getValue());
00130     } else if ( prop == &ShapeMaterial ) {
00131       setOpenEdgeColorFrom(ShapeMaterial.getValue().diffuseColor);
00132     }
00133     ViewProviderGeometryObject::onChanged(prop);
00134   }
00135 }
00136 
00137 void ViewProviderMeshNode::setOpenEdgeColorFrom( const App::Color& c )
00138 {
00139   float r=1.0f-c.r; r = r < 0.5f ? 0.0f : 1.0f;
00140   float g=1.0f-c.g; g = g < 0.5f ? 0.0f : 1.0f;
00141   float b=1.0f-c.b; b = b < 0.5f ? 0.0f : 1.0f;
00142   pOpenColor->rgb.setValue(r, g, b);
00143 }
00144 
00145 void ViewProviderMeshNode::attach(App::DocumentObject *pcFeat)
00146 {
00147   ViewProviderGeometryObject::attach(pcFeat);
00148 
00149   // only one selection node for the mesh
00150   const Mesh::Feature* meshFeature = dynamic_cast<Mesh::Feature*>(pcFeat);
00151   MeshGui::SoFCMeshNode* mesh = new MeshGui::SoFCMeshNode();
00152   mesh->setMesh(meshFeature->Mesh.getValuePtr());
00153   pcHighlight->addChild(mesh);
00154 
00155 
00156   // faces
00157   SoGroup* pcFlatRoot = new SoGroup();
00158 
00159   // read the correct shape color from the preferences
00160   Base::Reference<ParameterGrp> hGrp = Gui::WindowParameter::getDefaultParameter()->GetGroup("Mod/Mesh");
00161   bool twoSide = hGrp->GetBool("TwoSideRendering", true);
00162   if ( twoSide )
00163   {
00164     // enable two-side rendering
00165     SoShapeHints * flathints = new SoShapeHints;
00166     flathints->vertexOrdering = SoShapeHints::COUNTERCLOCKWISE;
00167     flathints->shapeType = SoShapeHints::UNKNOWN_SHAPE_TYPE;
00168     pcFlatRoot->addChild(flathints);
00169   }
00170 
00171   pcFlatRoot->addChild(pcShapeMaterial);
00172   pcFlatRoot->addChild(pcHighlight);
00173   addDisplayMaskMode(pcFlatRoot, "Flat");
00174 
00175   // points
00176   SoGroup* pcPointRoot = new SoGroup();
00177   pcPointRoot->addChild(pcPointStyle);
00178   pcPointRoot->addChild(pcFlatRoot);
00179   addDisplayMaskMode(pcPointRoot, "Point");
00180 
00181   // wires
00182   SoLightModel* pcLightModel = new SoLightModel();
00183   pcLightModel->model = SoLightModel::BASE_COLOR;
00184   SoGroup* pcWireRoot = new SoGroup();
00185   pcWireRoot->addChild(pcLineStyle);
00186   pcWireRoot->addChild(pcLightModel);
00187   pcWireRoot->addChild(pcShapeMaterial);
00188   pcWireRoot->addChild(pcHighlight);
00189   addDisplayMaskMode(pcWireRoot, "Wireframe");
00190 
00191   // faces+wires
00192   SoGroup* pcFlatWireRoot = new SoGroup();
00193   pcFlatWireRoot->addChild(pcFlatRoot);
00194   pcFlatWireRoot->addChild(pcWireRoot);
00195   addDisplayMaskMode(pcFlatWireRoot, "FlatWireframe");
00196 }
00197 
00198 void ViewProviderMeshNode::updateData(const App::Property*)
00199 {
00200   // Needs to update internal bounding box caches
00201   pcHighlight->touch();
00202 }
00203 
00204 QIcon ViewProviderMeshNode::getIcon() const
00205 {
00206   const char * Mesh_Feature_xpm[] = {
00207     "16 16 4 1",
00208     ".  c None",
00209     "#  c #000000",
00210     "s  c #BEC2FC",
00211     "g  c #00FF00",
00212     ".......##.......",
00213     "....#######.....",
00214     "..##ggg#ggg#....",
00215     "##ggggg#gggg##..",
00216     "#g#ggg#gggggg##.",
00217     "#gg#gg#gggg###s.",
00218     "#gg#gg#gg##gg#s.",
00219     "#ggg#####ggg#ss.",
00220     "#gggg##gggg#ss..",
00221     ".#g##g#gggg#s...",
00222     ".##ggg#ggg#ss...",
00223     ".##gggg#g#ss....",
00224     "..s#####g#s.....",
00225     "....sss##ss.....",
00226     "........ss......",
00227     "................"};
00228   QPixmap px(Mesh_Feature_xpm);
00229   return px;
00230 }
00231 
00232 void ViewProviderMeshNode::setDisplayMode(const char* ModeName)
00233 {
00234   if ( strcmp("Shaded",ModeName)==0 )
00235     setDisplayMaskMode("Flat");
00236   else if ( strcmp("Points",ModeName)==0 )
00237     setDisplayMaskMode("Point");
00238   else if ( strcmp("Shaded+Wireframe",ModeName)==0 )
00239     setDisplayMaskMode("FlatWireframe");
00240   else if ( strcmp("Wireframe",ModeName)==0 )
00241     setDisplayMaskMode("Wireframe");
00242 
00243   ViewProviderGeometryObject::setDisplayMode( ModeName );
00244 }
00245 
00246 std::vector<std::string> ViewProviderMeshNode::getDisplayModes(void) const
00247 {
00248   std::vector<std::string> StrList;
00249 
00250   // add your own modes
00251   StrList.push_back("Shaded");
00252   StrList.push_back("Wireframe");
00253   StrList.push_back("Shaded+Wireframe");
00254   StrList.push_back("Points");
00255 
00256   return StrList;
00257 }
00258 
00259 bool ViewProviderMeshNode::setEdit(int ModNum)
00260 {
00261   if ( m_bEdit ) return true;
00262   m_bEdit = true;
00263   return true;
00264 }
00265 
00266 void ViewProviderMeshNode::unsetEdit(void)
00267 {
00268   m_bEdit = false;
00269 }
00270 
00271 const char* ViewProviderMeshNode::getEditModeName(void)
00272 {
00273   return "Polygon picking";
00274 }
00275 
00276 bool ViewProviderMeshNode::handleEvent(const SoEvent * const ev,Gui::View3DInventorViewer &Viewer)
00277 {
00278   if ( m_bEdit )
00279   {
00280     unsetEdit();
00281     std::vector<SbVec2f> clPoly = Viewer.getPickedPolygon();
00282     if ( clPoly.size() < 3 )
00283       return true;
00284     if ( clPoly.front() != clPoly.back() )
00285       clPoly.push_back(clPoly.front());
00286 
00287     // get the normal of the front clipping plane
00288     SbVec3f b,n;
00289     Viewer.getNearPlane(b, n);
00290     Base::Vector3f cPoint(b[0],b[1],b[2]), cNormal(n[0],n[1],n[2]);
00291     SoCamera* pCam = Viewer.getCamera();  
00292     SbViewVolume  vol = pCam->getViewVolume (); 
00293 
00294     // create a tool shape from these points
00295     std::vector<MeshCore::MeshGeomFacet> aFaces;
00296     bool ok = ViewProviderMesh::createToolMesh( clPoly, vol, cNormal, aFaces );
00297 
00298     // Get the attached mesh property
00299     Mesh::PropertyMeshKernel& meshProp = ((Mesh::Feature*)pcObject)->Mesh;
00300 
00301     // Get the facet indices inside the tool mesh
00302     std::vector<unsigned long> indices;
00303     MeshCore::MeshKernel cToolMesh;
00304     cToolMesh = aFaces;
00305     MeshCore::MeshFacetGrid cGrid(meshProp.getValue().getKernel());
00306     MeshCore::MeshAlgorithm cAlg(meshProp.getValue().getKernel());
00307     cAlg.GetFacetsFromToolMesh(cToolMesh, cNormal, cGrid, indices);
00308     meshProp.deleteFacetIndices( indices );
00309 
00310       // update open edge display if needed
00311 //      if ( pcOpenEdge ) 
00312 //      {
00313 //        showOpenEdges(false);
00314 //        showOpenEdges(true);
00315 //      }
00316 
00317     Viewer.render();
00318     if ( !ok ) // note: the mouse grabbing needs to be released
00319       //QMessageBox::warning(Viewer.getWidget(),"Invalid polygon","The picked polygon seems to have self-overlappings.\n\nThis could lead to strange rersults.");
00320       Base::Console().Message("The picked polygon seems to have self-overlappings. This could lead to strange results.");
00321   }
00322 
00323   return false;
00324 }
00325 
00326 void ViewProviderMeshNode::showOpenEdges(bool show)
00327 {
00328 #if 1
00329   if ( show ) {
00330     pcOpenEdge = new SoSeparator();
00331     pcOpenEdge->addChild(pcLineStyle);
00332     pcOpenEdge->addChild(pOpenColor);
00333 
00334     const Mesh::Feature* meshFeature = dynamic_cast<Mesh::Feature*>(pcObject);
00335     MeshGui::SoFCMeshOpenEdge* mesh = new MeshGui::SoFCMeshOpenEdge();
00336     mesh->setMesh(meshFeature->Mesh.getValuePtr());
00337     pcOpenEdge->addChild(mesh);
00338     
00339     // add to the highlight node
00340     pcHighlight->addChild(pcOpenEdge);
00341   } else if (pcOpenEdge) {
00342     // remove the node and destroy the data
00343     pcHighlight->removeChild(pcOpenEdge);
00344     pcOpenEdge = 0;
00345   }
00346 #else
00347   if ( show ) {
00348     pcOpenEdge = new SoSeparator();
00349     pcOpenEdge->addChild(pcLineStyle);
00350     pcOpenEdge->addChild(pOpenColor);
00351     SoCoordinate3* points = new SoCoordinate3();
00352     pcOpenEdge->addChild(points);
00353     SoLineSet* lines = new SoLineSet();
00354     pcOpenEdge->addChild(lines);
00355     // add to the highlight node
00356     pcHighlight->addChild(pcOpenEdge);
00357 
00358     // Build up the array of border points
00359     int index=0;
00360     const MeshCore::MeshKernel& rMesh = dynamic_cast<Mesh::Feature*>(pcObject)->getMesh();
00361     const MeshCore::MeshFacetArray& rFaces = rMesh.GetFacets();
00362     const MeshCore::MeshPointArray& rPoint = rMesh.GetPoints();
00363 
00364     // Count number of open edges first
00365     int ctEdges=0;
00366     for ( MeshCore::MeshFacetArray::_TConstIterator jt = rFaces.begin(); jt != rFaces.end(); ++jt ) {
00367       for ( int i=0; i<3; i++ ) {
00368         if ( jt->_aulNeighbours[i] == ULONG_MAX ) {
00369           ctEdges++;
00370         }
00371       }
00372     }
00373 
00374     // disable internal notification for speedup
00375     points->enableNotify(false);
00376     lines->enableNotify(false);
00377 
00378     points->point.setNum(2*ctEdges);
00379     lines->numVertices.setNum(ctEdges);
00380     for ( MeshCore::MeshFacetArray::_TConstIterator it = rFaces.begin(); it != rFaces.end(); ++it ) {
00381       for ( int i=0; i<3; i++ ) {
00382         if ( it->_aulNeighbours[i] == ULONG_MAX ) {
00383           const MeshCore::MeshPoint& cP0 = rPoint[it->_aulPoints[i]];
00384           const MeshCore::MeshPoint& cP1 = rPoint[it->_aulPoints[(i+1)%3]];
00385           points->point.set1Value(index++, cP0.x, cP0.y, cP0.z);
00386           points->point.set1Value(index++, cP1.x, cP1.y, cP1.z);
00387           lines->numVertices.set1Value(index/2-1,2);
00388         }
00389       }
00390     }
00391 
00392     // enable notification
00393     points->enableNotify(true);
00394     lines->enableNotify(true);
00395     points->touch();
00396     lines->touch();
00397   } else {
00398     // remove the node and destroy the data
00399     pcHighlight->removeChild(pcOpenEdge);
00400     pcOpenEdge = 0;
00401   }
00402 #endif
00403 }

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