Mod/Mesh/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 # include <QMenu>
00028 # include <Inventor/SbBox2s.h>
00029 # include <Inventor/SoPickedPoint.h>
00030 # include <Inventor/details/SoFaceDetail.h>
00031 # include <Inventor/events/SoMouseButtonEvent.h>
00032 # include <Inventor/nodes/SoBaseColor.h>
00033 # include <Inventor/nodes/SoCallback.h>
00034 # include <Inventor/nodes/SoCoordinate3.h>
00035 # include <Inventor/nodes/SoLightModel.h>
00036 # include <Inventor/nodes/SoIndexedFaceSet.h>
00037 # include <Inventor/nodes/SoIndexedLineSet.h>
00038 # include <Inventor/nodes/SoDrawStyle.h>
00039 # include <Inventor/nodes/SoMaterial.h>
00040 # include <Inventor/nodes/SoMaterialBinding.h>
00041 # include <Inventor/nodes/SoNormalBinding.h>
00042 # include <Inventor/nodes/SoOrthographicCamera.h>
00043 # include <Inventor/nodes/SoPerspectiveCamera.h>
00044 # include <Inventor/nodes/SoPolygonOffset.h>
00045 # include <Inventor/nodes/SoShapeHints.h>
00046 # include <Inventor/nodes/SoSeparator.h>
00047 #endif
00048 
00050 #include <Base/Console.h>
00051 #include <Base/Exception.h>
00052 #include <Base/Sequencer.h>
00053 #include <Base/Tools.h>
00054 #include <Base/ViewProj.h>
00055 
00056 #include <App/Document.h>
00057 #include <App/PropertyLinks.h>
00058 
00059 #include <Gui/Application.h>
00060 #include <Gui/BitmapFactory.h>
00061 #include <Gui/Command.h>
00062 #include <Gui/Document.h>
00063 #include <Gui/SoFCOffscreenRenderer.h>
00064 #include <Gui/SoFCSelection.h>
00065 #include <Gui/SoFCSelectionAction.h>
00066 #include <Gui/MainWindow.h>
00067 #include <Gui/Selection.h>
00068 #include <Gui/Utilities.h>
00069 #include <Gui/Window.h>
00070 #include <Gui/WaitCursor.h>
00071 #include <Gui/View3DInventor.h>
00072 #include <Gui/View3DInventorViewer.h>
00073 
00074 #include <Mod/Mesh/App/Core/Algorithm.h>
00075 #include <Mod/Mesh/App/Core/Evaluation.h>
00076 #include <Mod/Mesh/App/Core/Grid.h>
00077 #include <Mod/Mesh/App/Core/Iterator.h>
00078 #include <Mod/Mesh/App/Core/MeshIO.h>
00079 #include <Mod/Mesh/App/Core/Triangulation.h>
00080 #include <Mod/Mesh/App/Core/Visitor.h>
00081 #include <Mod/Mesh/App/Mesh.h>
00082 #include <Mod/Mesh/App/MeshFeature.h>
00083 
00084 #include "ViewProvider.h"
00085 #include "SoFCIndexedFaceSet.h"
00086 #include "SoFCMeshObject.h"
00087 
00088 
00089 using namespace MeshGui;
00090 
00091 using Mesh::Feature;
00092 using MeshCore::MeshKernel;
00093 using MeshCore::MeshPointIterator;
00094 using MeshCore::MeshFacetIterator;
00095 using MeshCore::MeshGeomFacet;
00096 using MeshCore::MeshFacet;
00097 
00098 void ViewProviderMeshBuilder::buildNodes(const App::Property* prop, std::vector<SoNode*>& nodes) const
00099 {
00100     SoCoordinate3 *pcPointsCoord=0;
00101     SoIndexedFaceSet *pcFaces=0;
00102 
00103     if (nodes.empty()) {
00104         pcPointsCoord = new SoCoordinate3();
00105         nodes.push_back(pcPointsCoord);
00106         pcFaces = new SoIndexedFaceSet();
00107         nodes.push_back(pcFaces);
00108     }
00109     else if (nodes.size() == 2) {
00110         if (nodes[0]->getTypeId() == SoCoordinate3::getClassTypeId())
00111             pcPointsCoord = static_cast<SoCoordinate3*>(nodes[0]);
00112         if (nodes[1]->getTypeId() == SoIndexedFaceSet::getClassTypeId())
00113             pcFaces = static_cast<SoIndexedFaceSet*>(nodes[1]);
00114     }
00115 
00116     if (pcPointsCoord && pcFaces)
00117         createMesh(prop, pcPointsCoord, pcFaces);
00118 }
00119 
00120 void ViewProviderMeshBuilder::createMesh(const App::Property* prop, SoCoordinate3* coords, SoIndexedFaceSet* faces) const
00121 {
00122     const Mesh::PropertyMeshKernel* mesh = static_cast<const Mesh::PropertyMeshKernel*>(prop);
00123     const MeshCore::MeshKernel& rcMesh = mesh->getValue().getKernel();
00124 
00125     // set the point coordinates
00126     const MeshCore::MeshPointArray& cP = rcMesh.GetPoints();
00127     coords->point.setNum(rcMesh.CountPoints());
00128     SbVec3f* verts = coords->point.startEditing();
00129     unsigned long i=0;
00130     for (MeshCore::MeshPointArray::_TConstIterator it = cP.begin(); it != cP.end(); ++it, i++) {
00131         verts[i].setValue(it->x, it->y, it->z);
00132     }
00133     coords->point.finishEditing();
00134 
00135     // set the face indices
00136     unsigned long j=0;
00137     const MeshCore::MeshFacetArray& cF = rcMesh.GetFacets();
00138     faces->coordIndex.setNum(4*rcMesh.CountFacets());
00139     int32_t* indices = faces->coordIndex.startEditing();
00140     for (MeshCore::MeshFacetArray::_TConstIterator it = cF.begin(); it != cF.end(); ++it, j++) {
00141         for (int i=0; i<3; i++) {
00142             indices[4*j+i] = it->_aulPoints[i];
00143         }
00144         indices[4*j+3] = SO_END_FACE_INDEX;
00145     }
00146     faces->coordIndex.finishEditing();
00147 }
00148 
00149 PROPERTY_SOURCE(MeshGui::ViewProviderExport, Gui::ViewProviderDocumentObject)
00150 
00151 ViewProviderExport::ViewProviderExport()
00152 {
00153 }
00154 
00155 ViewProviderExport::~ViewProviderExport()
00156 {
00157 }
00158 
00159 std::vector<std::string> ViewProviderExport::getDisplayModes(void) const
00160 {
00161     std::vector<std::string> mode;
00162     mode.push_back("");
00163     return mode;
00164 }
00165 
00166 const char* ViewProviderExport::getDefaultDisplayMode() const
00167 {
00168     return "";
00169 }
00170 
00171 QIcon ViewProviderExport::getIcon() const
00172 {
00173     const char * Mesh_Feature_xpm[] = {
00174         "22 22 6 1",
00175         ". c None",
00176         "# c #000000",
00177         "c c #ffff00",
00178         "a c #808080",
00179         "b c #c0c0c0",
00180         "f c #008000",
00181         ".............##.......",
00182         ".............###......",
00183         ".............#f##.....",
00184         ".#....####...#ff##....",
00185         ".##.##....#..#fff##...",
00186         ".###.........#ffff##..",
00187         ".####........#fffff##.",
00188         ".#####.......#ffffff##",
00189         ".............#########",
00190         ".####.................",
00191         "#abab##########.......",
00192         "#babababababab#.......",
00193         "#ababababababa#.......",
00194         "#babab################",
00195         "#abab##cccccccccccc##.",
00196         "#bab##cccccccccccc##..",
00197         "#ab##cccccccccccc##...",
00198         "#b##cccccccccccc##....",
00199         "###cccccccccccc##.....",
00200         "##cccccccccccc##......",
00201         "###############.......",
00202         "......................"};
00203     QPixmap px(Mesh_Feature_xpm);
00204     return px;
00205 }
00206 
00207 // ------------------------------------------------------
00208 
00209 App::PropertyFloatConstraint::Constraints ViewProviderMesh::floatRange = {1.0f,64.0f,1.0f};
00210 App::PropertyFloatConstraint::Constraints ViewProviderMesh::angleRange = {0.0f,180.0f,1.0f};
00211 App::PropertyIntegerConstraint::Constraints ViewProviderMesh::intPercent = {0,100,1};
00212 const char* ViewProviderMesh::LightingEnums[]= {"One side","Two side",NULL};
00213 
00214 PROPERTY_SOURCE(MeshGui::ViewProviderMesh, Gui::ViewProviderGeometryObject)
00215 
00216 ViewProviderMesh::ViewProviderMesh() : pcOpenEdge(0)
00217 {
00218     ADD_PROPERTY(LineTransparency,(0));
00219     LineTransparency.setConstraints(&intPercent);
00220     ADD_PROPERTY(LineWidth,(1.0f));
00221     LineWidth.setConstraints(&floatRange);
00222     ADD_PROPERTY(PointSize,(2.0f));
00223     PointSize.setConstraints(&floatRange);
00224     ADD_PROPERTY(CreaseAngle,(0.0f));
00225     CreaseAngle.setConstraints(&angleRange);
00226     ADD_PROPERTY(OpenEdges,(false));
00227     ADD_PROPERTY(Lighting,(1));
00228     Lighting.setEnums(LightingEnums);
00229     ADD_PROPERTY(LineColor,(0,0,0));
00230 
00231     pOpenColor = new SoBaseColor();
00232     setOpenEdgeColorFrom(ShapeColor.getValue());
00233     pOpenColor->ref();
00234 
00235     pcLineStyle = new SoDrawStyle();
00236     pcLineStyle->ref();
00237     pcLineStyle->style = SoDrawStyle::LINES;
00238     pcLineStyle->lineWidth = LineWidth.getValue();
00239 
00240     pcPointStyle = new SoDrawStyle();
00241     pcPointStyle->ref();
00242     pcPointStyle->style = SoDrawStyle::POINTS;
00243     pcPointStyle->pointSize = PointSize.getValue();
00244 
00245     pShapeHints = new SoShapeHints;
00246     pShapeHints->shapeType = SoShapeHints::UNKNOWN_SHAPE_TYPE;
00247     pShapeHints->ref();
00248 
00249     pcMatBinding = new SoMaterialBinding;
00250     pcMatBinding->value = SoMaterialBinding::OVERALL;
00251     pcMatBinding->ref();
00252 
00253     pLineColor = new SoMaterial;
00254     pLineColor->ref();
00255     LineColor.touch();
00256 
00257     // read the correct shape color from the preferences
00258     Base::Reference<ParameterGrp> hGrp = Gui::WindowParameter::getDefaultParameter()->GetGroup("Mod/Mesh");
00259 
00260     // Mesh color
00261     App::Color color = ShapeColor.getValue();
00262     unsigned long current = color.getPackedValue();
00263     unsigned long setting = hGrp->GetUnsigned("MeshColor", current);
00264     if (current != setting) {
00265         color.setPackedValue((uint32_t)setting);
00266         ShapeColor.setValue(color);
00267     }
00268     Transparency.setValue(hGrp->GetInt("MeshTransparency", 0));
00269 
00270     // Line color
00271     color = LineColor.getValue();
00272     current = color.getPackedValue();
00273     setting = hGrp->GetUnsigned("LineColor", current);
00274     if (current != setting) {
00275         color.setPackedValue((uint32_t)setting);
00276         LineColor.setValue(color);
00277     }
00278     LineTransparency.setValue(hGrp->GetInt("LineTransparency", 0));
00279 
00280     bool twoside = hGrp->GetBool("TwoSideRendering", false);
00281     if (twoside) Lighting.setValue(1);
00282     else Lighting.setValue((long)0);
00283 
00284     bool normal_per_vertex = hGrp->GetBool("VertexPerNormals", false);
00285     if (normal_per_vertex) {
00286         double angle = hGrp->GetFloat("CreaseAngle", 0.0);
00287         CreaseAngle.setValue(angle);
00288     }
00289 
00290     if (hGrp->GetBool("ShowBoundingBox", false))
00291         pcHighlight->style = Gui::SoFCSelection::BOX;
00292 }
00293 
00294 ViewProviderMesh::~ViewProviderMesh()
00295 {
00296     pOpenColor->unref();
00297     pcLineStyle->unref();
00298     pcPointStyle->unref();
00299     pShapeHints->unref();
00300     pcMatBinding->unref();
00301     pLineColor->unref();
00302 }
00303 
00304 void ViewProviderMesh::onChanged(const App::Property* prop)
00305 {
00306     // we gonna change the number of colors to one
00307     if (prop == &ShapeColor || prop == &ShapeMaterial) {
00308         pcMatBinding->value = SoMaterialBinding::OVERALL;
00309     }
00310     if (prop == &LineTransparency) {
00311         float trans = LineTransparency.getValue()/100.0f;
00312         pLineColor->transparency = trans;
00313     }
00314     else if (prop == &LineWidth) {
00315         pcLineStyle->lineWidth = LineWidth.getValue();
00316     }
00317     else if (prop == &PointSize) {
00318         pcPointStyle->pointSize = PointSize.getValue();
00319     }
00320     else if (prop == &CreaseAngle) {
00321         pShapeHints->creaseAngle = (F_PI*CreaseAngle.getValue())/180.0;
00322     }
00323     else if (prop == &OpenEdges) {
00324         showOpenEdges(OpenEdges.getValue());
00325     }
00326     else if (prop == &Lighting) {
00327         if (Lighting.getValue() == 0) {
00328             pShapeHints->vertexOrdering = SoShapeHints::UNKNOWN_ORDERING;
00329             //pShapeHints->vertexOrdering = SoShapeHints::COUNTERCLOCKWISE;
00330         }
00331         else {
00332             pShapeHints->vertexOrdering = SoShapeHints::COUNTERCLOCKWISE;
00333         }
00334     }
00335     else if (prop == &LineColor) {
00336         const App::Color& c = LineColor.getValue();
00337         pLineColor->diffuseColor.setValue(c.r,c.g,c.b);
00338     }
00339     else {
00340         // Set the inverse color for open edges
00341         if (prop == &ShapeColor) {
00342             setOpenEdgeColorFrom(ShapeColor.getValue());
00343         }
00344         else if (prop == &ShapeMaterial) {
00345             setOpenEdgeColorFrom(ShapeMaterial.getValue().diffuseColor);
00346         }
00347     }
00348 
00349     ViewProviderGeometryObject::onChanged(prop);
00350 }
00351 
00352 void ViewProviderMesh::setOpenEdgeColorFrom(const App::Color& c)
00353 {
00354     float r=1.0f-c.r; r = r < 0.5f ? 0.0f : 1.0f;
00355     float g=1.0f-c.g; g = g < 0.5f ? 0.0f : 1.0f;
00356     float b=1.0f-c.b; b = b < 0.5f ? 0.0f : 1.0f;
00357     pOpenColor->rgb.setValue(r, g, b);
00358 }
00359 
00360 SoShape* ViewProviderMesh::getShapeNode() const
00361 {
00362     return 0;
00363 }
00364 
00365 SoNode* ViewProviderMesh::getCoordNode() const
00366 {
00367     return 0;
00368 }
00369 
00374 void ViewProviderMesh::attach(App::DocumentObject *pcFeat)
00375 {
00376     ViewProviderGeometryObject::attach(pcFeat);
00377 
00378     // Note: Since for mesh data the SoFCSelection node has no SoSeparator but
00379     // an SoGroup as parent the EMISSIVE style if set has fundamentally no effect.
00380     // This behaviour is given due to the fact that SoFCSelection inherits from
00381     // SoGroup (formerly SoSeparator). If we wanted to enable emissive overlay for
00382     // highlighting or selection we would need an SoSeparator as parent node below.
00383 
00384     // faces
00385     SoGroup* pcFlatRoot = new SoGroup();
00386     pcFlatRoot->addChild(pShapeHints);
00387     pcFlatRoot->addChild(pcShapeMaterial);
00388     pcFlatRoot->addChild(pcMatBinding);
00389     pcFlatRoot->addChild(pcHighlight);
00390     addDisplayMaskMode(pcFlatRoot, "Flat");
00391 
00392     // points
00393     SoGroup* pcPointRoot = new SoGroup();
00394     pcPointRoot->addChild(pcPointStyle);
00395     pcPointRoot->addChild(pcFlatRoot);
00396     addDisplayMaskMode(pcPointRoot, "Point");
00397 
00398     // wires
00399     SoLightModel* pcLightModel = new SoLightModel();
00400     pcLightModel->model = SoLightModel::BASE_COLOR;
00401     SoGroup* pcWireRoot = new SoGroup();
00402     pcWireRoot->addChild(pcLineStyle);
00403     pcWireRoot->addChild(pcLightModel);
00404     SoMaterialBinding* binding = new SoMaterialBinding;
00405     binding->value = SoMaterialBinding::OVERALL; // doesn't set several colors
00406     pcWireRoot->addChild(binding);
00407     pcWireRoot->addChild(pLineColor);
00408     pcWireRoot->addChild(pcHighlight);
00409     addDisplayMaskMode(pcWireRoot, "Wireframe");
00410 
00411     // faces+wires
00412     // Avoid any Z-buffer artefacts, so that the lines always
00413     // appear on top of the faces
00414     SoPolygonOffset* offset = new SoPolygonOffset();
00415     offset->styles = SoPolygonOffset::LINES;
00416     offset->factor = -2.0f;
00417     offset->units = 1.0f;
00418     SoGroup* pcFlatWireRoot = new SoGroup();
00419     pcFlatWireRoot->addChild(pcFlatRoot);
00420     pcFlatWireRoot->addChild(offset);
00421     pcFlatWireRoot->addChild(pcWireRoot);
00422     addDisplayMaskMode(pcFlatWireRoot, "FlatWireframe");
00423 }
00424 
00425 QIcon ViewProviderMesh::getIcon() const
00426 {
00427 #if 1
00428     static QIcon icon = Gui::BitmapFactory().pixmap("Tree_Mesh");
00429     return icon;
00430 #else
00431     static const char * const Mesh_Feature_xpm[] = {
00432         "16 16 4 1",
00433         ".      c None",
00434         "#      c #000000",
00435         "s      c #BEC2FC",
00436         "g      c #00FF00",
00437         ".......##.......",
00438         "....#######.....",
00439         "..##ggg#ggg#....",
00440         "##ggggg#gggg##..",
00441         "#g#ggg#gggggg##.",
00442         "#gg#gg#gggg###s.",
00443         "#gg#gg#gg##gg#s.",
00444         "#ggg#####ggg#ss.",
00445         "#gggg##gggg#ss..",
00446         ".#g##g#gggg#s...",
00447         ".##ggg#ggg#ss...",
00448         ".##gggg#g#ss....",
00449         "..s#####g#s.....",
00450         "....sss##ss.....",
00451         "........ss......",
00452         "................"};
00453     QPixmap px(Mesh_Feature_xpm);
00454     return px;
00455 #endif
00456 }
00457 
00458 void ViewProviderMesh::setDisplayMode(const char* ModeName)
00459 {
00460     if (strcmp("Shaded",ModeName)==0)
00461         setDisplayMaskMode("Flat");
00462     else if (strcmp("Points",ModeName)==0)
00463         setDisplayMaskMode("Point");
00464     else if (strcmp("Flat Lines",ModeName)==0)
00465         setDisplayMaskMode("FlatWireframe");
00466     else if (strcmp("Wireframe",ModeName)==0)
00467         setDisplayMaskMode("Wireframe");
00468 
00469     ViewProviderGeometryObject::setDisplayMode(ModeName);
00470 }
00471 
00472 std::vector<std::string> ViewProviderMesh::getDisplayModes(void) const
00473 {
00474     std::vector<std::string> StrList;
00475 
00476     // add your own modes
00477     StrList.push_back("Shaded");
00478     StrList.push_back("Wireframe");
00479     StrList.push_back("Flat Lines");
00480     StrList.push_back("Points");
00481 
00482     return StrList;
00483 }
00484 
00485 bool ViewProviderMesh::setEdit(int ModNum)
00486 {
00487     if (ModNum == ViewProvider::Transform)
00488         return ViewProviderGeometryObject::setEdit(ModNum);
00489     return true;
00490 }
00491 
00492 void ViewProviderMesh::unsetEdit(int ModNum)
00493 {
00494     if (ModNum == ViewProvider::Transform)
00495         ViewProviderGeometryObject::unsetEdit(ModNum);
00496 }
00497 
00498 bool ViewProviderMesh::createToolMesh(const std::vector<SbVec2f>& rclPoly, const SbViewVolume& vol,
00499                                       const Base::Vector3f& rcNormal, std::vector<MeshCore::MeshGeomFacet>& aFaces)
00500 {
00501     float fX, fY, fZ;
00502     SbVec3f pt1, pt2, pt3, pt4;
00503     MeshGeomFacet face;
00504     std::vector<Base::Vector3f> top, bottom, polygon;
00505 
00506     for (std::vector<SbVec2f>::const_iterator it = rclPoly.begin(); it != rclPoly.end(); ++it) {
00507         // the following element
00508         std::vector<SbVec2f>::const_iterator nt = it + 1;
00509         if (nt == rclPoly.end())
00510             nt = rclPoly.begin();
00511         else if (*it == *nt)
00512             continue; // two adjacent vertices are equal
00513 
00514         vol.projectPointToLine(*it, pt1, pt2);
00515         vol.projectPointToLine(*nt, pt3, pt4);
00516 
00517         // 1st facet
00518         pt1.getValue(fX, fY, fZ);
00519         face._aclPoints[0].Set(fX, fY, fZ);
00520         pt4.getValue(fX, fY, fZ);
00521         face._aclPoints[1].Set(fX, fY, fZ);
00522         pt3.getValue(fX, fY, fZ);
00523         face._aclPoints[2].Set(fX, fY, fZ);
00524         if (face.Area() > 0)
00525             aFaces.push_back(face);
00526 
00527         // 2nd facet
00528         pt1.getValue(fX, fY, fZ);
00529         face._aclPoints[0].Set(fX, fY, fZ);
00530         pt2.getValue(fX, fY, fZ);
00531         face._aclPoints[1].Set(fX, fY, fZ);
00532         pt4.getValue(fX, fY, fZ);
00533         face._aclPoints[2].Set(fX, fY, fZ);
00534         if (face.Area() > 0)
00535             aFaces.push_back(face);
00536 
00537         if (it+1 < rclPoly.end()) {
00538             pt1.getValue(fX, fY, fZ);
00539             top.push_back( Base::Vector3f(fX, fY, fZ) );
00540             pt2.getValue(fX, fY, fZ);
00541             bottom.push_back( Base::Vector3f(fX, fY, fZ) );
00542             // polygon we need to triangulate (in x,y-plane)
00543             it->getValue(fX, fY);
00544             polygon.push_back( Base::Vector3f(fX, fY, 0.0f) );
00545         }
00546     }
00547 
00548     // now create the lids
00549     std::vector<MeshGeomFacet> aLid;
00550     MeshCore::EarClippingTriangulator cTria;
00551     cTria.SetPolygon(polygon);
00552     bool ok = cTria.TriangulatePolygon();
00553   
00554     std::vector<MeshFacet> faces = cTria.GetFacets();
00555     for (std::vector<MeshFacet>::iterator itF = faces.begin(); itF != faces.end(); ++itF) {
00556         MeshGeomFacet topFacet;
00557         topFacet._aclPoints[0] = top[itF->_aulPoints[0]];
00558         topFacet._aclPoints[1] = top[itF->_aulPoints[1]];
00559         topFacet._aclPoints[2] = top[itF->_aulPoints[2]];
00560         if (topFacet.GetNormal() * rcNormal < 0) {
00561             std::swap(topFacet._aclPoints[1], topFacet._aclPoints[2]);
00562             topFacet.CalcNormal();
00563         }
00564         aFaces.push_back(topFacet);
00565 
00566         MeshGeomFacet botFacet;
00567         botFacet._aclPoints[0] = bottom[itF->_aulPoints[0]];
00568         botFacet._aclPoints[1] = bottom[itF->_aulPoints[1]];
00569         botFacet._aclPoints[2] = bottom[itF->_aulPoints[2]];
00570         if (botFacet.GetNormal() * rcNormal > 0) {
00571             std::swap(botFacet._aclPoints[1], botFacet._aclPoints[2]);
00572             botFacet.CalcNormal();
00573         }
00574         aFaces.push_back(botFacet);
00575     }
00576 
00577     return ok;
00578 }
00579 
00580 void ViewProviderMesh::showOpenEdges(bool show)
00581 {
00582 }
00583 
00584 void ViewProviderMesh::clipMeshCallback(void * ud, SoEventCallback * n)
00585 {
00586     // show the wait cursor because this could take quite some time
00587     Gui::WaitCursor wc;
00588 
00589     // When this callback function is invoked we must in either case leave the edit mode
00590     Gui::View3DInventorViewer* view  = reinterpret_cast<Gui::View3DInventorViewer*>(n->getUserData());
00591     view->setEditing(false);
00592     view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), clipMeshCallback,ud);
00593     n->setHandled();
00594 
00595     SbBool clip_inner;
00596     std::vector<SbVec2f> clPoly = view->getGLPolygon(&clip_inner);
00597     if (clPoly.size() < 3)
00598         return;
00599     if (clPoly.front() != clPoly.back())
00600         clPoly.push_back(clPoly.front());
00601 
00602     std::vector<Gui::ViewProvider*> views = view->getViewProvidersOfType(ViewProviderMesh::getClassTypeId());
00603     if (!views.empty()) {
00604         Gui::Application::Instance->activeDocument()->openCommand("Cut");
00605         for (std::vector<Gui::ViewProvider*>::iterator it = views.begin(); it != views.end(); ++it) {
00606             ViewProviderMesh* that = static_cast<ViewProviderMesh*>(*it);
00607             if (that->getEditingMode() > -1) {
00608                 that->finishEditing();
00609                 that->cutMesh(clPoly, *view, clip_inner);
00610             }
00611         }
00612 
00613         Gui::Application::Instance->activeDocument()->commitCommand();
00614 
00615         view->render();
00616     }
00617 }
00618 
00619 void ViewProviderMesh::partMeshCallback(void * ud, SoEventCallback * cb)
00620 {
00621     // show the wait cursor because this could take quite some time
00622     Gui::WaitCursor wc;
00623 
00624     // When this callback function is invoked we must in either case leave the edit mode
00625     Gui::View3DInventorViewer* view  = reinterpret_cast<Gui::View3DInventorViewer*>(cb->getUserData());
00626     view->setEditing(false);
00627     view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), partMeshCallback,ud);
00628     cb->setHandled();
00629 
00630     SbBool clip_inner;
00631     std::vector<SbVec2f> clPoly = view->getGLPolygon(&clip_inner);
00632     if (clPoly.size() < 3)
00633         return;
00634     if (clPoly.front() != clPoly.back())
00635         clPoly.push_back(clPoly.front());
00636 
00637     // get the normal of the front clipping plane
00638     SbVec3f b,n;
00639     view->getNearPlane(b, n);
00640     Base::Vector3f cPoint(b[0],b[1],b[2]), cNormal(n[0],n[1],n[2]);
00641     SoCamera* pCam = view->getCamera();  
00642     SbViewVolume  vol = pCam->getViewVolume(); 
00643 
00644     // create a tool shape from these points
00645     std::vector<MeshCore::MeshGeomFacet> aFaces;
00646     if (!ViewProviderMesh::createToolMesh(clPoly, vol, cNormal, aFaces))
00647         Base::Console().Message("The picked polygon seems to have self-overlappings. This could lead to strange results.");
00648 
00649     MeshCore::MeshKernel toolMesh;
00650     bool locked = Base::Sequencer().setLocked(true);
00651     toolMesh = aFaces;
00652     Base::Sequencer().setLocked(locked);
00653 
00654     // Open a transaction object for the undo/redo stuff
00655     Gui::Application::Instance->activeDocument()->openCommand("Split");
00656 
00657     try {
00658         std::vector<Gui::ViewProvider*> views = view->getViewProvidersOfType(ViewProviderMesh::getClassTypeId());
00659         for (std::vector<Gui::ViewProvider*>::iterator it = views.begin(); it != views.end(); ++it) {
00660             ViewProviderMesh* that = static_cast<ViewProviderMesh*>(*it);
00661             if (that->getEditingMode() > -1) {
00662                 that->finishEditing();
00663                 that->splitMesh(toolMesh, cNormal, clip_inner);
00664             }
00665         }
00666     }
00667     catch(...) {
00668         // Don't rethrow any exception
00669     }
00670 
00671     // Close the transaction
00672     Gui::Application::Instance->activeDocument()->commitCommand();
00673     view->render();
00674 }
00675 
00676 void ViewProviderMesh::segmMeshCallback(void * ud, SoEventCallback * cb)
00677 {
00678     // show the wait cursor because this could take quite some time
00679     Gui::WaitCursor wc;
00680 
00681     // When this callback function is invoked we must in either case leave the edit mode
00682     Gui::View3DInventorViewer* view  = reinterpret_cast<Gui::View3DInventorViewer*>(cb->getUserData());
00683     view->setEditing(false);
00684     view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), segmMeshCallback,ud);
00685     cb->setHandled();
00686 
00687     SbBool clip_inner;
00688     std::vector<SbVec2f> clPoly = view->getGLPolygon(&clip_inner);
00689     if (clPoly.size() < 3)
00690         return;
00691     if (clPoly.front() != clPoly.back())
00692         clPoly.push_back(clPoly.front());
00693 
00694     // get the normal of the front clipping plane
00695     SbVec3f b,n;
00696     view->getNearPlane(b, n);
00697     Base::Vector3f cPoint(b[0],b[1],b[2]), cNormal(n[0],n[1],n[2]);
00698     SoCamera* pCam = view->getCamera();  
00699     SbViewVolume  vol = pCam->getViewVolume(); 
00700 
00701     // create a tool shape from these points
00702     std::vector<MeshCore::MeshGeomFacet> aFaces;
00703     if (!ViewProviderMesh::createToolMesh(clPoly, vol, cNormal, aFaces))
00704         Base::Console().Message("The picked polygon seems to have self-overlappings. This could lead to strange results.");
00705 
00706     MeshCore::MeshKernel toolMesh;
00707     bool locked = Base::Sequencer().setLocked(true);
00708     toolMesh = aFaces;
00709     Base::Sequencer().setLocked(locked);
00710 
00711     // Open a transaction object for the undo/redo stuff
00712     Gui::Application::Instance->activeDocument()->openCommand("Segment");
00713 
00714     try {
00715         std::vector<Gui::ViewProvider*> views = view->getViewProvidersOfType(ViewProviderMesh::getClassTypeId());
00716         for (std::vector<Gui::ViewProvider*>::iterator it = views.begin(); it != views.end(); ++it) {
00717             ViewProviderMesh* that = static_cast<ViewProviderMesh*>(*it);
00718             if (that->getEditingMode() > -1) {
00719                 that->finishEditing();
00720                 that->segmentMesh(toolMesh, cNormal, clip_inner);
00721             }
00722         }
00723     }
00724     catch(...) {
00725         // Don't rethrow any exception
00726     }
00727 
00728     // Close the transaction
00729     Gui::Application::Instance->activeDocument()->commitCommand();
00730     view->render();
00731 }
00732 
00733 void ViewProviderMesh::selectGLCallback(void * ud, SoEventCallback * n)
00734 {
00735     // When this callback function is invoked we must in either case leave the edit mode
00736     Gui::View3DInventorViewer* view  = reinterpret_cast<Gui::View3DInventorViewer*>(n->getUserData());
00737     view->setEditing(false);
00738     view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), selectGLCallback,ud);
00739     n->setHandled();
00740 
00741     std::vector<SbVec2f> clPoly = view->getGLPolygon();
00742     if (clPoly.size() != 1)
00743         return;
00744     const SoEvent* ev = n->getEvent();
00745 
00746     SbVec2f pos = clPoly[0];
00747     float pX,pY; pos.getValue(pX,pY);
00748     const SbVec2s& sz = view->getViewportRegion().getViewportSizePixels();
00749     float fRatio = view->getViewportRegion().getViewportAspectRatio();
00750     if (fRatio > 1.0f) {
00751         pX = (pX - 0.5f) / fRatio + 0.5f;
00752         pos.setValue(pX,pY);
00753     }
00754     else if (fRatio < 1.0f) {
00755         pY = (pY - 0.5f) * fRatio + 0.5f;
00756         pos.setValue(pX,pY);
00757     }
00758 
00759     short x1 = (short)(pX * sz[0] + 0.5f);
00760     short y1 = (short)(pY * sz[1] + 0.5f);
00761     SbVec2s loc = ev->getPosition();
00762     short x2 = loc[0];
00763     short y2 = loc[1];
00764 
00765     short x = (x1+x2)/2;
00766     short y = (y1+y2)/2;
00767     short w = (x2-x1);
00768     short h = (y2-y1);
00769     if (w<0) w = -w;
00770     if (h<0) h = -h;
00771 
00772     std::vector<Gui::ViewProvider*> views;
00773     views = view->getViewProvidersOfType(ViewProviderMesh::getClassTypeId());
00774     for (std::vector<Gui::ViewProvider*>::iterator it = views.begin(); it != views.end(); ++it) {
00775         ViewProviderMesh* that = static_cast<ViewProviderMesh*>(*it);
00776         if (that->getEditingMode() > -1) {
00777             that->finishEditing();
00778             that->selectArea(x, y, w, h, view->getViewportRegion(), view->getCamera());
00779         }
00780     }
00781 
00782     view->render();
00783 }
00784 
00785 void ViewProviderMesh::getFacetsFromPolygon(const std::vector<SbVec2f>& picked,
00786                                             Gui::View3DInventorViewer &Viewer,
00787                                             SbBool inner,
00788                                             std::vector<unsigned long>& indices) const
00789 {
00790 #if 1
00791     bool ok = true;
00792     SoCamera* cam = Viewer.getCamera();
00793     SbViewVolume vv = cam->getViewVolume();
00794     Gui::ViewVolumeProjection proj(vv);
00795     Base::Polygon2D polygon;
00796     for (std::vector<SbVec2f>::const_iterator it = picked.begin(); it != picked.end(); ++it)
00797         polygon.Add(Base::Vector2D((*it)[0],(*it)[1]));
00798 
00799     // Get the attached mesh property
00800     Mesh::PropertyMeshKernel& meshProp = static_cast<Mesh::Feature*>(pcObject)->Mesh;
00801     MeshCore::MeshAlgorithm cAlg(meshProp.getValue().getKernel());
00802     cAlg.CheckFacets(&proj, polygon, true, indices);
00803 #else
00804     // get the normal of the front clipping plane
00805     SbVec3f b,n;
00806     Viewer.getNearPlane(b, n);
00807     Base::Vector3f cPoint(b[0],b[1],b[2]), cNormal(n[0],n[1],n[2]);
00808     SoCamera* pCam = Viewer.getCamera();  
00809     SbViewVolume  vol = pCam->getViewVolume(); 
00810 
00811     // create a tool shape from these points
00812     std::vector<MeshCore::MeshGeomFacet> aFaces;
00813     bool ok = ViewProviderMesh::createToolMesh(picked, vol, cNormal, aFaces);
00814 
00815     // Get the attached mesh property
00816     Mesh::PropertyMeshKernel& meshProp = static_cast<Mesh::Feature*>(pcObject)->Mesh;
00817 
00818     // Get the facet indices inside the tool mesh
00819     MeshCore::MeshKernel cToolMesh;
00820     bool locked = Base::Sequencer().setLocked(true);
00821     cToolMesh = aFaces;
00822     Base::Sequencer().setLocked(locked);
00823     MeshCore::MeshFacetGrid cGrid(meshProp.getValue().getKernel());
00824     MeshCore::MeshAlgorithm cAlg(meshProp.getValue().getKernel());
00825     cAlg.GetFacetsFromToolMesh(cToolMesh, cNormal, cGrid, indices);
00826 #endif
00827     if (!inner) {
00828         // get the indices that are completely outside
00829         std::vector<unsigned long> complete(meshProp.getValue().countFacets());
00830         std::generate(complete.begin(), complete.end(), Base::iotaGen<unsigned long>(0));
00831         std::sort(indices.begin(), indices.end());
00832         std::vector<unsigned long> complementary;
00833         std::back_insert_iterator<std::vector<unsigned long> > biit(complementary);
00834         std::set_difference(complete.begin(), complete.end(), indices.begin(), indices.end(), biit);
00835         indices = complementary;
00836     }
00837 
00838     if (!ok) // note: the mouse grabbing needs to be released
00839         Base::Console().Message("The picked polygon seems to have self-overlappings. This could lead to strange results.");
00840 }
00841 
00842 std::vector<unsigned long> ViewProviderMesh::getFacetsOfRegion(const SbViewportRegion& select,
00843                                                                const SbViewportRegion& region,
00844                                                                SoCamera* camera) const
00845 {
00846     SoSeparator* root = new SoSeparator();
00847     root->ref();
00848     root->addChild(camera);
00849     root->addChild(const_cast<ViewProviderMesh*>(this)->getCoordNode());
00850     root->addChild(const_cast<ViewProviderMesh*>(this)->getShapeNode());
00851     Gui::SoGLSelectAction gl(region, select);
00852     gl.apply(root);
00853     root->unref();
00854 
00855     std::vector<unsigned long> faces;
00856     faces.insert(faces.end(), gl.indices.begin(), gl.indices.end());
00857     return faces;
00858 }
00859 
00860 void ViewProviderMesh::panCamera(SoCamera * cam, float aspectratio, const SbPlane & panplane,
00861                                  const SbVec2f & currpos, const SbVec2f & prevpos)
00862 {
00863     if (cam == NULL) return; // can happen for empty scenegraph
00864     if (currpos == prevpos) return; // useless invocation
00865 
00866 
00867     // Find projection points for the last and current mouse coordinates.
00868     SbViewVolume vv = cam->getViewVolume(aspectratio);
00869     SbLine line;
00870     vv.projectPointToLine(currpos, line);
00871     SbVec3f current_planept;
00872     panplane.intersect(line, current_planept);
00873     vv.projectPointToLine(prevpos, line);
00874     SbVec3f old_planept;
00875     panplane.intersect(line, old_planept);
00876 
00877     // Reposition camera according to the vector difference between the
00878     // projected points.
00879     cam->position = cam->position.getValue() - (current_planept - old_planept);
00880 }
00881 
00882 void ViewProviderMesh::boxZoom(const SbBox2s& box, const SbViewportRegion & vp, SoCamera* cam)
00883 {
00884     SbViewVolume vv = cam->getViewVolume(vp.getViewportAspectRatio());
00885 
00886     short sizeX,sizeY;
00887     box.getSize(sizeX, sizeY);
00888     SbVec2s size = vp.getViewportSizePixels();
00889 
00890     // The bbox must not be empty i.e. width and length is zero, but it is possible that
00891     // either width or length is zero
00892     if (sizeX == 0 && sizeY == 0) 
00893         return;
00894 
00895     // Get the new center in normalized pixel coordinates
00896     short xmin,xmax,ymin,ymax;
00897     box.getBounds(xmin,ymin,xmax,ymax);
00898     const SbVec2f center((float) ((xmin+xmax)/2) / (float) SoQtMax((int)(size[0] - 1), 1),
00899                          (float) (size[1]-(ymin+ymax)/2) / (float) SoQtMax((int)(size[1] - 1), 1));
00900 
00901     SbPlane plane = vv.getPlane(cam->focalDistance.getValue());
00902     panCamera(cam,vp.getViewportAspectRatio(),plane, SbVec2f(0.5,0.5), center);
00903 
00904     // Set height or height angle of the camera
00905     float scaleX = (float)sizeX/(float)size[0];
00906     float scaleY = (float)sizeY/(float)size[1];
00907     float scale = std::max<float>(scaleX, scaleY);
00908     if (cam && cam->getTypeId() == SoOrthographicCamera::getClassTypeId()) {
00909         float height = static_cast<SoOrthographicCamera*>(cam)->height.getValue() * scale;
00910         static_cast<SoOrthographicCamera*>(cam)->height = height;
00911     }
00912     else if (cam && cam->getTypeId() == SoPerspectiveCamera::getClassTypeId()) {
00913         float height = static_cast<SoPerspectiveCamera*>(cam)->heightAngle.getValue() / 2.0f;
00914         height = 2.0f * atan(tan(height) * scale);
00915         static_cast<SoPerspectiveCamera*>(cam)->heightAngle = height;
00916     }
00917 }
00918 
00919 std::vector<unsigned long> ViewProviderMesh::getVisibleFacetsAfterZoom(const SbBox2s& rect,
00920                                                                        const SbViewportRegion& vp,
00921                                                                        SoCamera* camera) const
00922 {
00923     // camera copy will be deleted inside getVisibleFacets()
00924     // because the ref counter reaches 0
00925     camera = static_cast<SoCamera*>(camera->copy());
00926     boxZoom(rect,vp,camera);
00927     return getVisibleFacets(vp, camera);
00928 }
00929 
00930 void ViewProviderMesh::renderGLCallback(void * ud, SoAction * action)
00931 {
00932     if (action->isOfType(SoGLRenderAction::getClassTypeId())) {
00933         ViewProviderMesh* mesh = reinterpret_cast<ViewProviderMesh*>(ud);
00934         Gui::SoVisibleFaceAction fa;
00935         fa.apply(mesh->getRoot());
00936     }
00937 }
00938 
00939 std::vector<unsigned long> ViewProviderMesh::getVisibleFacets(const SbViewportRegion& vp,
00940                                                               SoCamera* camera) const
00941 {
00942     const Mesh::PropertyMeshKernel& meshProp = static_cast<Mesh::Feature*>(pcObject)->Mesh;
00943     const Mesh::MeshObject& mesh = meshProp.getValue();
00944     uint32_t count = (uint32_t)mesh.countFacets();
00945 
00946     SoSeparator* root = new SoSeparator;
00947     root->ref();
00948     root->addChild(camera);
00949 
00950 #if 0
00951     SoCallback* cb = new SoCallback;
00952     cb->setCallback(renderGLCallback, const_cast<ViewProviderMesh*>(this));
00953     root->addChild(cb);
00954 #else
00955     SoLightModel* lm = new SoLightModel();
00956     lm->model = SoLightModel::BASE_COLOR;
00957     root->addChild(lm);
00958     SoMaterial* mat = new SoMaterial();
00959     mat->diffuseColor.setNum(count);
00960     SbColor* diffcol = mat->diffuseColor.startEditing();
00961     for (uint32_t i=0; i<count; i++) {
00962         float t;
00963         diffcol[i].setPackedValue(i<<8,t);
00964     }
00965 
00966     mat->diffuseColor.finishEditing();
00967     SoMaterialBinding* bind = new SoMaterialBinding();
00968     bind->value = SoMaterialBinding::PER_FACE;
00969     root->addChild(mat);
00970     root->addChild(bind);
00971 #endif
00972     root->addChild(this->getCoordNode());
00973     root->addChild(this->getShapeNode());
00974 
00975     Gui::SoFCOffscreenRenderer& renderer = Gui::SoFCOffscreenRenderer::instance();
00976     renderer.setViewportRegion(vp);
00977     renderer.setBackgroundColor(SbColor(0.0f, 0.0f, 0.0f));
00978 
00979     QImage img;
00980     renderer.render(root);
00981     renderer.writeToImage(img);
00982     root->unref();
00983 
00984     int width = img.width();
00985     int height = img.height();
00986     QRgb color=0;
00987     std::vector<unsigned long> faces;
00988     for (int y = 0; y < height; y++) {
00989         for (int x = 0; x < width; x++) {
00990             QRgb rgb = img.pixel(x,y);
00991             rgb = rgb-(0xff << 24);
00992             if (rgb != 0 && rgb != color) {
00993                 color = rgb;
00994                 faces.push_back((unsigned long)rgb);
00995             }
00996         }
00997     }
00998 
00999     std::sort(faces.begin(), faces.end());
01000     faces.erase(std::unique(faces.begin(), faces.end()), faces.end());
01001 
01002     return faces;
01003 }
01004 
01005 void ViewProviderMesh::cutMesh(const std::vector<SbVec2f>& picked, 
01006                                Gui::View3DInventorViewer &Viewer, SbBool inner)
01007 {
01008     // Get the facet indices inside the tool mesh
01009     std::vector<unsigned long> indices;
01010     getFacetsFromPolygon(picked, Viewer, inner, indices);
01011 
01012     // Get the attached mesh property
01013     Mesh::PropertyMeshKernel& meshProp = static_cast<Mesh::Feature*>(pcObject)->Mesh;
01014 
01015     //Remove the facets from the mesh and open a transaction object for the undo/redo stuff
01016     meshProp.deleteFacetIndices(indices);
01017     pcObject->purgeTouched();
01018 }
01019 
01020 void ViewProviderMesh::splitMesh(const MeshCore::MeshKernel& toolMesh, const Base::Vector3f& normal, SbBool clip_inner)
01021 {
01022     // Get the attached mesh property
01023     Mesh::PropertyMeshKernel& meshProp = static_cast<Mesh::Feature*>(pcObject)->Mesh;
01024     const MeshCore::MeshKernel& meshPropKernel = meshProp.getValue().getKernel();
01025 
01026     // Get the facet indices inside the tool mesh
01027     std::vector<unsigned long> indices;
01028     MeshCore::MeshFacetGrid cGrid(meshPropKernel);
01029     MeshCore::MeshAlgorithm cAlg(meshPropKernel);
01030     cAlg.GetFacetsFromToolMesh(toolMesh, normal, cGrid, indices);
01031     if (!clip_inner) {
01032         // get the indices that are completely outside
01033         std::vector<unsigned long> complete(meshPropKernel.CountFacets());
01034         std::generate(complete.begin(), complete.end(), Base::iotaGen<unsigned long>(0));
01035         std::sort(indices.begin(), indices.end());
01036         std::vector<unsigned long> complementary;
01037         std::back_insert_iterator<std::vector<unsigned long> > biit(complementary);
01038         std::set_difference(complete.begin(), complete.end(), indices.begin(), indices.end(), biit);
01039         indices = complementary;
01040     }
01041 
01042     // Remove the facets from the mesh and create a new one
01043     Mesh::MeshObject* kernel = meshProp.getValue().meshFromSegment(indices);
01044     meshProp.deleteFacetIndices(indices);
01045     Mesh::Feature* splitMesh = static_cast<Mesh::Feature*>(App::GetApplication().getActiveDocument()
01046         ->addObject("Mesh::Feature",pcObject->getNameInDocument()));
01047     // Note: deletes also kernel
01048     splitMesh->Mesh.setValuePtr(kernel);
01049     static_cast<Mesh::Feature*>(pcObject)->purgeTouched();
01050 }
01051 
01052 void ViewProviderMesh::segmentMesh(const MeshCore::MeshKernel& toolMesh, const Base::Vector3f& normal, SbBool clip_inner)
01053 {
01054     // Get the attached mesh property
01055     Mesh::PropertyMeshKernel& meshProp = static_cast<Mesh::Feature*>(pcObject)->Mesh;
01056     const MeshCore::MeshKernel& meshPropKernel = meshProp.getValue().getKernel();
01057 
01058     // Get the facet indices inside the tool mesh
01059     std::vector<unsigned long> indices;
01060     MeshCore::MeshFacetGrid cGrid(meshPropKernel);
01061     MeshCore::MeshAlgorithm cAlg(meshPropKernel);
01062     cAlg.GetFacetsFromToolMesh(toolMesh, normal, cGrid, indices);
01063     if (!clip_inner) {
01064         // get the indices that are completely outside
01065         std::vector<unsigned long> complete(meshPropKernel.CountFacets());
01066         std::generate(complete.begin(), complete.end(), Base::iotaGen<unsigned long>(0));
01067         std::sort(indices.begin(), indices.end());
01068         std::vector<unsigned long> complementary;
01069         std::back_insert_iterator<std::vector<unsigned long> > biit(complementary);
01070         std::set_difference(complete.begin(), complete.end(), indices.begin(), indices.end(), biit);
01071         indices = complementary;
01072     }
01073 
01074     meshProp.createSegment(indices);
01075     static_cast<Mesh::Feature*>(pcObject)->purgeTouched();
01076 }
01077 
01078 void ViewProviderMesh::faceInfoCallback(void * ud, SoEventCallback * n)
01079 {
01080     const SoMouseButtonEvent * mbe = (SoMouseButtonEvent *)n->getEvent();
01081     Gui::View3DInventorViewer* view  = reinterpret_cast<Gui::View3DInventorViewer*>(n->getUserData());
01082 
01083     // Mark all incoming mouse button events as handled, especially, to deactivate the selection node
01084     n->getAction()->setHandled();
01085     if (mbe->getButton() == SoMouseButtonEvent::BUTTON2 && mbe->getState() == SoButtonEvent::UP) {
01086         n->setHandled();
01087         // context-menu
01088         QMenu menu;
01089         QAction* cl = menu.addAction(QObject::tr("Leave info mode"));
01090         QAction* id = menu.exec(QCursor::pos());
01091         if (cl == id) {
01092             view->setEditing(false);
01093             view->getWidget()->setCursor(QCursor(Qt::ArrowCursor));
01094             view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), faceInfoCallback,ud);
01095         }
01096     }
01097     else if (mbe->getButton() == SoMouseButtonEvent::BUTTON1 && mbe->getState() == SoButtonEvent::DOWN) {
01098         const SoPickedPoint * point = n->getPickedPoint();
01099         if (point == NULL) {
01100             Base::Console().Message("No facet picked.\n");
01101             return;
01102         }
01103 
01104         n->setHandled();
01105 
01106         // By specifying the indexed mesh node 'pcFaceSet' we make sure that the picked point is
01107         // really from the mesh we render and not from any other geometry
01108         Gui::ViewProvider* vp = static_cast<Gui::ViewProvider*>(view->getViewProviderByPath(point->getPath()));
01109         if (!vp || !vp->getTypeId().isDerivedFrom(ViewProviderMesh::getClassTypeId()))
01110             return;
01111         ViewProviderMesh* that = static_cast<ViewProviderMesh*>(vp);
01112         const SoDetail* detail = point->getDetail(that->getShapeNode());
01113         if ( detail && detail->getTypeId() == SoFaceDetail::getClassTypeId() ) {
01114             // get the boundary to the picked facet
01115             unsigned long uFacet = ((SoFaceDetail*)detail)->getFaceIndex();
01116             that->faceInfo(uFacet);
01117             Gui::Flag* flag = new Gui::Flag;
01118             flag->setText(QObject::tr("Index: %1").arg(uFacet));
01119             flag->setOrigin(point->getPoint());
01120             view->addFlag(flag, Gui::FlagLayout::TopRight);
01121         }
01122     }
01123 }
01124 
01125 void ViewProviderMesh::fillHoleCallback(void * ud, SoEventCallback * n)
01126 {
01127     const SoMouseButtonEvent * mbe = (SoMouseButtonEvent *)n->getEvent();
01128     Gui::View3DInventorViewer* view  = reinterpret_cast<Gui::View3DInventorViewer*>(n->getUserData());
01129 
01130     // Mark all incoming mouse button events as handled, especially, to deactivate the selection node
01131     n->getAction()->setHandled();
01132     if (mbe->getButton() == SoMouseButtonEvent::BUTTON2 && mbe->getState() == SoButtonEvent::UP) {
01133         n->setHandled();
01134         // context-menu
01135         QMenu menu;
01136         QAction* cl = menu.addAction(QObject::tr("Leave hole-filling mode"));
01137         QAction* id = menu.exec(QCursor::pos());
01138         if (cl == id) {
01139             view->setEditing(false);
01140             view->getWidget()->setCursor(QCursor(Qt::ArrowCursor));
01141             view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), fillHoleCallback,ud);
01142         }
01143     }
01144     else if (mbe->getButton() == SoMouseButtonEvent::BUTTON1 && mbe->getState() == SoButtonEvent::DOWN) {
01145         const SoPickedPoint * point = n->getPickedPoint();
01146         if (point == NULL) {
01147             Base::Console().Message("No facet picked.\n");
01148             return;
01149         }
01150 
01151         n->setHandled();
01152 
01153         // By specifying the indexed mesh node 'pcFaceSet' we make sure that the picked point is
01154         // really from the mesh we render and not from any other geometry
01155         Gui::ViewProvider* vp = static_cast<Gui::ViewProvider*>(view->getViewProviderByPath(point->getPath()));
01156         if (!vp || !vp->getTypeId().isDerivedFrom(ViewProviderMesh::getClassTypeId()))
01157             return;
01158         ViewProviderMesh* that = static_cast<ViewProviderMesh*>(vp);
01159         const SoDetail* detail = point->getDetail(that->getShapeNode());
01160         if ( detail && detail->getTypeId() == SoFaceDetail::getClassTypeId() ) {
01161             // get the boundary to the picked facet
01162             unsigned long uFacet = ((SoFaceDetail*)detail)->getFaceIndex();
01163             that->fillHole(uFacet);
01164         }
01165     }
01166 }
01167 
01168 void ViewProviderMesh::markPartCallback(void * ud, SoEventCallback * n)
01169 {
01170     // handle only mouse button events
01171     if (n->getEvent()->isOfType(SoMouseButtonEvent::getClassTypeId())) {
01172         const SoMouseButtonEvent * mbe = static_cast<const SoMouseButtonEvent*>(n->getEvent());
01173         Gui::View3DInventorViewer* view  = reinterpret_cast<Gui::View3DInventorViewer*>(n->getUserData());
01174 
01175         // Mark all incoming mouse button events as handled, especially, to deactivate the selection node
01176         n->getAction()->setHandled();
01177         if (mbe->getButton() == SoMouseButtonEvent::BUTTON2 && mbe->getState() == SoButtonEvent::UP) {
01178             n->setHandled();
01179             // context-menu
01180             QMenu menu;
01181             QAction* cl = menu.addAction(QObject::tr("Leave removal mode"));
01182             QAction* rm = menu.addAction(QObject::tr("Delete selected faces"));
01183             QAction* cf = menu.addAction(QObject::tr("Clear selected faces"));
01184             QAction* id = menu.exec(QCursor::pos());
01185             if (cl == id) {
01186                 view->setEditing(false);
01187                 view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), markPartCallback,ud);
01188 
01189                 std::vector<ViewProvider*> views = view->getViewProvidersOfType(ViewProviderMesh::getClassTypeId());
01190                 for (std::vector<ViewProvider*>::iterator it = views.begin(); it != views.end(); ++it) {
01191                     static_cast<ViewProviderMesh*>(*it)->clearSelection();
01192                 }
01193             }
01194             else if (cf == id) {
01195                 std::vector<ViewProvider*> views = view->getViewProvidersOfType(ViewProviderMesh::getClassTypeId());
01196                 for (std::vector<ViewProvider*>::iterator it = views.begin(); it != views.end(); ++it) {
01197                     static_cast<ViewProviderMesh*>(*it)->clearSelection();
01198                 }
01199             }
01200             else if (rm == id) {
01201                 Gui::Application::Instance->activeDocument()->openCommand("Delete");
01202                 std::vector<ViewProvider*> views = view->getViewProvidersOfType(ViewProviderMesh::getClassTypeId());
01203                 for (std::vector<ViewProvider*>::iterator it = views.begin(); it != views.end(); ++it) {
01204                     static_cast<ViewProviderMesh*>(*it)->deleteSelection();
01205                 }
01206                 view->render();
01207                 Gui::Application::Instance->activeDocument()->commitCommand();
01208             }
01209         }
01210         else if (mbe->getButton() == SoMouseButtonEvent::BUTTON1 && mbe->getState() == SoButtonEvent::DOWN) {
01211             const SoPickedPoint * point = n->getPickedPoint();
01212             if (point == NULL) {
01213                 Base::Console().Message("No facet picked.\n");
01214                 return;
01215             }
01216 
01217             n->setHandled();
01218 
01219             // By specifying the indexed mesh node 'pcFaceSet' we make sure that the picked point is
01220             // really from the mesh we render and not from any other geometry
01221             Gui::ViewProvider* vp = static_cast<Gui::ViewProvider*>(view->getViewProviderByPath(point->getPath()));
01222             if (!vp || !vp->getTypeId().isDerivedFrom(ViewProviderMesh::getClassTypeId()))
01223                 return;
01224             ViewProviderMesh* that = static_cast<ViewProviderMesh*>(vp);
01225             const SoDetail* detail = point->getDetail(that->getShapeNode());
01226             if ( detail && detail->getTypeId() == SoFaceDetail::getClassTypeId() ) {
01227                 // get the boundary to the picked facet
01228                 unsigned long uFacet = static_cast<const SoFaceDetail*>(detail)->getFaceIndex();
01229                 that->selectComponent(uFacet);
01230             }
01231         }
01232     }
01233 }
01234 
01235 void ViewProviderMesh::faceInfo(unsigned long uFacet)
01236 {
01237     Mesh::Feature* fea = reinterpret_cast<Mesh::Feature*>(this->getObject());
01238     const MeshCore::MeshKernel& rKernel = fea->Mesh.getValue().getKernel();
01239     const MeshCore::MeshFacetArray& facets = rKernel.GetFacets();
01240     if (uFacet < facets.size()) {
01241         MeshCore::MeshFacet face = facets[uFacet];
01242         MeshCore::MeshGeomFacet tria = rKernel.GetFacet(face);
01243         Base::Console().Message("Mesh: %s Facet %ld: Points: <%ld, %ld, %ld>, Neighbours: <%ld, %ld, %ld>\n"
01244             "Triangle: <[%.6f, %.6f, %.6f], [%.6f, %.6f, %.6f], [%.6f, %.6f, %.6f]>\n", fea->getNameInDocument(), uFacet, 
01245             face._aulPoints[0], face._aulPoints[1], face._aulPoints[2], 
01246             face._aulNeighbours[0], face._aulNeighbours[1], face._aulNeighbours[2],
01247             tria._aclPoints[0].x, tria._aclPoints[0].y, tria._aclPoints[0].z,
01248             tria._aclPoints[1].x, tria._aclPoints[1].y, tria._aclPoints[1].z,
01249             tria._aclPoints[2].x, tria._aclPoints[2].y, tria._aclPoints[2].z);
01250     }
01251 }
01252 
01253 void ViewProviderMesh::fillHole(unsigned long uFacet)
01254 {
01255     // get parameter from user settings
01256     Base::Reference<ParameterGrp> hGrp = Gui::WindowParameter::getDefaultParameter()->GetGroup("Mod/Mesh");
01257     int level = (int)hGrp->GetInt("FillHoleLevel", 2);
01258 
01259     // get the boundary to the picked facet
01260     std::list<unsigned long> aBorder;
01261     Mesh::Feature* fea = reinterpret_cast<Mesh::Feature*>(this->getObject());
01262     const MeshCore::MeshKernel& rKernel = fea->Mesh.getValue().getKernel();
01263     MeshCore::MeshRefPointToFacets cPt2Fac(rKernel);
01264     MeshCore::MeshAlgorithm meshAlg(rKernel);
01265     meshAlg.GetMeshBorder(uFacet, aBorder);
01266     std::vector<unsigned long> boundary(aBorder.begin(), aBorder.end());
01267     std::list<std::vector<unsigned long> > boundaries;
01268     boundaries.push_back(boundary);
01269     meshAlg.SplitBoundaryLoops(boundaries);
01270 
01271     std::vector<MeshCore::MeshFacet> newFacets;
01272     std::vector<Base::Vector3f> newPoints;
01273     unsigned long numberOfOldPoints = rKernel.CountPoints();
01274     for (std::list<std::vector<unsigned long> >::iterator it = boundaries.begin(); it != boundaries.end(); ++it) {
01275         if (it->size() < 3/* || it->size() > 200*/)
01276             continue;
01277         boundary = *it;
01278         MeshCore::MeshFacetArray faces;
01279         MeshCore::MeshPointArray points;
01280         MeshCore::QuasiDelaunayTriangulator cTria/*(0.05f)*/;
01281         if (meshAlg.FillupHole(boundary, cTria, faces, points, level, &cPt2Fac)) {
01282             if (boundary.front() == boundary.back())
01283                 boundary.pop_back();
01284             // the triangulation may produce additional points which we must take into account when appending to the mesh
01285             unsigned long countBoundaryPoints = boundary.size();
01286             unsigned long countDifference = points.size() - countBoundaryPoints;
01287             if (countDifference > 0) {
01288                 MeshCore::MeshPointArray::_TIterator pt = points.begin() + countBoundaryPoints;
01289                 for (unsigned long i=0; i<countDifference; i++, pt++) {
01290                     boundary.push_back(numberOfOldPoints++);
01291                     newPoints.push_back(*pt);
01292                  }
01293             }
01294             for (MeshCore::MeshFacetArray::_TIterator kt = faces.begin(); kt != faces.end(); ++kt ) {
01295                 kt->_aulPoints[0] = boundary[kt->_aulPoints[0]];
01296                 kt->_aulPoints[1] = boundary[kt->_aulPoints[1]];
01297                 kt->_aulPoints[2] = boundary[kt->_aulPoints[2]];
01298                 newFacets.push_back(*kt);
01299             }
01300         }
01301     }
01302 
01303     if (newFacets.empty())
01304         return; // nothing to do
01305  
01306     //add the facets to the mesh and open a transaction object for the undo/redo stuff
01307     Gui::Application::Instance->activeDocument()->openCommand("Fill hole");
01308     fea->Mesh.append(newFacets, newPoints);
01309     Gui::Application::Instance->activeDocument()->commitCommand();
01310 }
01311 
01312 void ViewProviderMesh::selectFacet(unsigned long facet)
01313 {
01314     std::vector<unsigned long> selection;
01315     selection.push_back(facet);
01316 
01317     const Mesh::MeshObject& rMesh = static_cast<Mesh::Feature*>(pcObject)->Mesh.getValue();
01318     rMesh.addFacetsToSelection(selection);
01319 
01320     // Colorize the selection
01321     pcMatBinding->value = SoMaterialBinding::PER_FACE;
01322     int uCtFacets = (int)rMesh.countFacets();
01323 
01324     if (uCtFacets != pcShapeMaterial->diffuseColor.getNum()) {
01325         highlightSelection();
01326     }
01327     else {
01328         pcShapeMaterial->diffuseColor.set1Value(facet,1.0f,0.0f,0.0f);
01329     }
01330 }
01331 
01332 void ViewProviderMesh::deselectFacet(unsigned long facet)
01333 {
01334     std::vector<unsigned long> selection;
01335     selection.push_back(facet);
01336 
01337     const Mesh::MeshObject& rMesh = static_cast<Mesh::Feature*>(pcObject)->Mesh.getValue();
01338     rMesh.removeFacetsFromSelection(selection);
01339 
01340     // Colorize the selection
01341     pcMatBinding->value = SoMaterialBinding::PER_FACE;
01342     int uCtFacets = (int)rMesh.countFacets();
01343 
01344     if (uCtFacets != pcShapeMaterial->diffuseColor.getNum()) {
01345         highlightSelection();
01346     }
01347     else {
01348         App::Color c = ShapeColor.getValue();
01349         pcShapeMaterial->diffuseColor.set1Value(facet,c.r,c.g,c.b);
01350     }
01351 }
01352 
01353 void ViewProviderMesh::selectComponent(unsigned long uFacet)
01354 {
01355     std::vector<unsigned long> selection;
01356     selection.push_back(uFacet);
01357 
01358     MeshCore::MeshTopFacetVisitor clVisitor(selection);
01359     const Mesh::MeshObject& rMesh = static_cast<Mesh::Feature*>(pcObject)->Mesh.getValue();
01360     const MeshCore::MeshKernel& rKernel = rMesh.getKernel();
01361     MeshCore::MeshAlgorithm(rKernel).ResetFacetFlag(MeshCore::MeshFacet::VISIT);
01362     rKernel.VisitNeighbourFacets(clVisitor, uFacet);
01363     rMesh.addFacetsToSelection(selection);
01364 
01365     // Colorize the selection
01366     highlightSelection();
01367 }
01368 
01369 void ViewProviderMesh::deselectComponent(unsigned long uFacet)
01370 {
01371     std::vector<unsigned long> selection;
01372     selection.push_back(uFacet);
01373 
01374     MeshCore::MeshTopFacetVisitor clVisitor(selection);
01375     const Mesh::MeshObject& rMesh = static_cast<Mesh::Feature*>(pcObject)->Mesh.getValue();
01376     const MeshCore::MeshKernel& rKernel = rMesh.getKernel();
01377     MeshCore::MeshAlgorithm(rKernel).ResetFacetFlag(MeshCore::MeshFacet::VISIT);
01378     rKernel.VisitNeighbourFacets(clVisitor, uFacet);
01379     rMesh.removeFacetsFromSelection(selection);
01380 
01381     // Colorize the selection
01382     highlightSelection();
01383 }
01384 
01385 void ViewProviderMesh::setSelection(const std::vector<unsigned long>& indices)
01386 {
01387     const Mesh::MeshObject& rMesh = static_cast<Mesh::Feature*>(pcObject)->Mesh.getValue();
01388     rMesh.clearFacetSelection();
01389     rMesh.addFacetsToSelection(indices);
01390 
01391     // Colorize the selection
01392     highlightSelection();
01393 }
01394 
01395 void ViewProviderMesh::addSelection(const std::vector<unsigned long>& indices)
01396 {
01397     const Mesh::MeshObject& rMesh = static_cast<Mesh::Feature*>(pcObject)->Mesh.getValue();
01398     rMesh.addFacetsToSelection(indices);
01399 
01400     // Colorize the selection
01401     highlightSelection();
01402 }
01403 
01404 void ViewProviderMesh::removeSelection(const std::vector<unsigned long>& indices)
01405 {
01406     const Mesh::MeshObject& rMesh = static_cast<Mesh::Feature*>(pcObject)->Mesh.getValue();
01407     rMesh.removeFacetsFromSelection(indices);
01408 
01409     // Colorize the selection
01410     highlightSelection();
01411 }
01412 
01413 void ViewProviderMesh::clearSelection()
01414 {
01415     const Mesh::MeshObject& rMesh = static_cast<Mesh::Feature*>(pcObject)->Mesh.getValue();
01416     rMesh.clearFacetSelection();
01417     unhighlightSelection();
01418 }
01419 
01420 void ViewProviderMesh::deleteSelection()
01421 {
01422     std::vector<unsigned long> indices;
01423     Mesh::PropertyMeshKernel& meshProp = static_cast<Mesh::Feature*>(pcObject)->Mesh;
01424     const Mesh::MeshObject& rMesh = meshProp.getValue();
01425     rMesh.getFacetsFromSelection(indices);
01426     if (!indices.empty()) {
01427         unhighlightSelection();
01428 
01429         Mesh::MeshObject* pMesh = meshProp.startEditing();
01430         pMesh->deleteFacets(indices);
01431         meshProp.finishEditing();
01432         pcObject->purgeTouched();
01433     }
01434 }
01435 
01436 void ViewProviderMesh::selectArea(short x, short y, short w, short h,
01437                                   const SbViewportRegion& region,
01438                                   SoCamera* camera)
01439 {
01440     SbViewportRegion vp;
01441     vp.setViewportPixels (x, y, w, h);
01442     std::vector<unsigned long> faces = getFacetsOfRegion(vp, region, camera);
01443 
01444     const Mesh::MeshObject& rMesh = static_cast<Mesh::Feature*>(pcObject)->Mesh.getValue();
01445     rMesh.addFacetsToSelection(faces);
01446 
01447     // Colorize the selected part
01448     highlightSelection();
01449 }
01450 
01451 void ViewProviderMesh::highlightSelection()
01452 {
01453     std::vector<unsigned long> selection;
01454     const Mesh::MeshObject& rMesh = static_cast<Mesh::Feature*>(pcObject)->Mesh.getValue();
01455     rMesh.getFacetsFromSelection(selection);
01456     if (selection.empty()) {
01457         // If no faces are selected then simply return even without
01458         // without calling unhighlightSelection()
01459         return;
01460     }
01461 
01462     // Colorize the selection
01463     pcMatBinding->value = SoMaterialBinding::PER_FACE;
01464     App::Color c = ShapeColor.getValue();
01465     int uCtFacets = (int)rMesh.countFacets();
01466     pcShapeMaterial->diffuseColor.setNum(uCtFacets);
01467 
01468     SbColor* cols = pcShapeMaterial->diffuseColor.startEditing();
01469     for (int i=0; i<uCtFacets; i++)
01470         cols[i].setValue(c.r,c.g,c.b);
01471     for (std::vector<unsigned long>::iterator it = selection.begin(); it != selection.end(); ++it)
01472         cols[*it].setValue(1.0f,0.0f,0.0f);
01473     pcShapeMaterial->diffuseColor.finishEditing();
01474 }
01475 
01476 void ViewProviderMesh::unhighlightSelection()
01477 {
01478     App::Color c = ShapeColor.getValue();
01479     pcMatBinding->value = SoMaterialBinding::OVERALL;
01480     pcShapeMaterial->diffuseColor.setNum(1);
01481     pcShapeMaterial->diffuseColor.setValue(c.r,c.g,c.b);
01482 }
01483 
01484 // ------------------------------------------------------
01485 
01486 PROPERTY_SOURCE(MeshGui::ViewProviderIndexedFaceSet, MeshGui::ViewProviderMesh)
01487 
01488 ViewProviderIndexedFaceSet::ViewProviderIndexedFaceSet()
01489 {
01490 }
01491 
01492 ViewProviderIndexedFaceSet::~ViewProviderIndexedFaceSet()
01493 {
01494 }
01495 
01500 void ViewProviderIndexedFaceSet::attach(App::DocumentObject *pcFeat)
01501 {
01502     ViewProviderMesh::attach(pcFeat);
01503 
01504     pcMeshCoord = new SoCoordinate3;
01505     pcHighlight->addChild(pcMeshCoord);
01506 
01507     pcMeshFaces = new SoFCIndexedFaceSet;
01508     pcHighlight->addChild(pcMeshFaces);
01509 
01510     // read the threshold from the preferences
01511     Base::Reference<ParameterGrp> hGrp = Gui::WindowParameter::getDefaultParameter()->GetGroup("Mod/Mesh");
01512     int size = hGrp->GetInt("RenderTriangleLimit", -1);
01513     if (size > 0) static_cast<SoFCIndexedFaceSet*>(pcMeshFaces)->renderTriangleLimit = (unsigned int)(pow(10.0f,size));
01514 }
01515 
01516 void ViewProviderIndexedFaceSet::updateData(const App::Property* prop)
01517 {
01518     Gui::ViewProviderGeometryObject::updateData(prop);
01519     if (prop->getTypeId() == Mesh::PropertyMeshKernel::getClassTypeId()) {
01520         ViewProviderMeshBuilder builder;
01521         builder.createMesh(prop, pcMeshCoord, pcMeshFaces);
01522         showOpenEdges(OpenEdges.getValue());
01523         highlightSelection();
01524     }
01525 }
01526 
01527 void ViewProviderIndexedFaceSet::showOpenEdges(bool show)
01528 {
01529     if (pcOpenEdge) {
01530         // remove the node and destroy the data
01531         pcRoot->removeChild(pcOpenEdge);
01532         pcOpenEdge = 0;
01533     }
01534 
01535     if (show) {
01536         pcOpenEdge = new SoSeparator();
01537         pcOpenEdge->addChild(pcLineStyle);
01538         pcOpenEdge->addChild(pOpenColor);
01539 
01540         pcOpenEdge->addChild(pcMeshCoord);
01541         SoIndexedLineSet* lines = new SoIndexedLineSet;
01542         pcOpenEdge->addChild(lines);
01543 
01544         // add to the highlight node
01545         pcRoot->addChild(pcOpenEdge);
01546 
01547         // Build up the lines with indices to the list of vertices 'pcMeshCoord'
01548         int index=0;
01549         const MeshCore::MeshKernel& rMesh = static_cast<Mesh::Feature*>(pcObject)->Mesh.getValue().getKernel();
01550         const MeshCore::MeshFacetArray& rFaces = rMesh.GetFacets();
01551         for (MeshCore::MeshFacetArray::_TConstIterator it = rFaces.begin(); it != rFaces.end(); ++it) {
01552             for (int i=0; i<3; i++) {
01553                 if (it->_aulNeighbours[i] == ULONG_MAX) {
01554                     lines->coordIndex.set1Value(index++,it->_aulPoints[i]);
01555                     lines->coordIndex.set1Value(index++,it->_aulPoints[(i+1)%3]);
01556                     lines->coordIndex.set1Value(index++,SO_END_LINE_INDEX);
01557                 }
01558             }
01559         }
01560     }
01561 }
01562 
01563 SoShape* ViewProviderIndexedFaceSet::getShapeNode() const
01564 {
01565     return this->pcMeshFaces;
01566 }
01567 
01568 SoNode* ViewProviderIndexedFaceSet::getCoordNode() const
01569 {
01570     return this->pcMeshCoord;
01571 }
01572 
01573 // ------------------------------------------------------
01574 
01575 PROPERTY_SOURCE(MeshGui::ViewProviderMeshObject, MeshGui::ViewProviderMesh)
01576 
01577 ViewProviderMeshObject::ViewProviderMeshObject()
01578 {
01579 }
01580 
01581 ViewProviderMeshObject::~ViewProviderMeshObject()
01582 {
01583 }
01584 
01585 void ViewProviderMeshObject::attach(App::DocumentObject *pcFeat)
01586 {
01587     ViewProviderMesh::attach(pcFeat);
01588 
01589     pcMeshNode = new SoFCMeshObjectNode;
01590     pcHighlight->addChild(pcMeshNode);
01591 
01592     pcMeshShape = new SoFCMeshObjectShape;
01593     pcHighlight->addChild(pcMeshShape);
01594 
01595     // read the threshold from the preferences
01596     Base::Reference<ParameterGrp> hGrp = Gui::WindowParameter::getDefaultParameter()->GetGroup("Mod/Mesh");
01597     int size = hGrp->GetInt("RenderTriangleLimit", -1);
01598     if (size > 0) pcMeshShape->renderTriangleLimit = (unsigned int)(pow(10.0f,size));
01599 }
01600 
01601 void ViewProviderMeshObject::updateData(const App::Property* prop)
01602 {
01603     Gui::ViewProviderGeometryObject::updateData(prop);
01604     if (prop->getTypeId() == Mesh::PropertyMeshKernel::getClassTypeId()) {
01605         const Mesh::PropertyMeshKernel* mesh = static_cast<const Mesh::PropertyMeshKernel*>(prop);
01606         this->pcMeshNode->mesh.setValue(mesh->getValuePtr());
01607         // Needs to update internal bounding box caches
01608         this->pcMeshShape->touch();
01609     }
01610 }
01611 
01612 void ViewProviderMeshObject::showOpenEdges(bool show)
01613 {
01614     if (pcOpenEdge) {
01615         // remove the node and destroy the data
01616         pcRoot->removeChild(pcOpenEdge);
01617         pcOpenEdge = 0;
01618     }
01619 
01620     if (show) {
01621         pcOpenEdge = new SoSeparator();
01622         pcOpenEdge->addChild(pcLineStyle);
01623         pcOpenEdge->addChild(pOpenColor);
01624 
01625         pcOpenEdge->addChild(pcMeshNode);
01626         pcOpenEdge->addChild(new SoFCMeshObjectBoundary);
01627 
01628         // add to the highlight node
01629         pcRoot->addChild(pcOpenEdge);
01630     }
01631 }
01632 
01633 SoShape* ViewProviderMeshObject::getShapeNode() const
01634 {
01635     return this->pcMeshShape;
01636 }
01637 
01638 SoNode* ViewProviderMeshObject::getCoordNode() const
01639 {
01640     return this->pcMeshNode;
01641 }

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