MeshEditor.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) 2010 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 <algorithm>
00028 # include <QMenu>
00029 # include <QTimer>
00030 # include <Inventor/SoPickedPoint.h>
00031 # include <Inventor/details/SoFaceDetail.h>
00032 # include <Inventor/details/SoPointDetail.h>
00033 # include <Inventor/events/SoLocation2Event.h>
00034 # include <Inventor/events/SoMouseButtonEvent.h>
00035 # include <Inventor/nodes/SoBaseColor.h>
00036 # include <Inventor/nodes/SoCamera.h>
00037 # include <Inventor/nodes/SoCoordinate3.h>
00038 # include <Inventor/nodes/SoDirectionalLight.h>
00039 # include <Inventor/nodes/SoDrawStyle.h>
00040 # include <Inventor/nodes/SoFaceSet.h>
00041 # include <Inventor/nodes/SoLineSet.h>
00042 # include <Inventor/nodes/SoMarkerSet.h>
00043 # include <Inventor/nodes/SoSeparator.h>
00044 # include <Inventor/nodes/SoShapeHints.h>
00045 #endif
00046 
00047 #include "MeshEditor.h"
00048 #include "SoFCMeshObject.h"
00049 #include <App/Document.h>
00050 #include <Mod/Mesh/App/MeshFeature.h>
00051 #include <Gui/Application.h>
00052 #include <Gui/View3DInventor.h>
00053 #include <Gui/View3DInventorViewer.h>
00054 
00055 using namespace MeshGui;
00056 
00057 PROPERTY_SOURCE(MeshGui::ViewProviderFace, Gui::ViewProviderDocumentObject)
00058 
00059 ViewProviderFace::ViewProviderFace() : mesh(0), current_index(-1)
00060 {
00061     pcCoords = new SoCoordinate3();
00062     pcCoords->ref();
00063     pcCoords->point.setNum(0);
00064     pcFaces = new SoFaceSet;
00065     pcFaces->ref();
00066     pcMeshPick = new SoFCMeshPickNode();
00067     pcMeshPick->ref();
00068 }
00069 
00070 ViewProviderFace::~ViewProviderFace()
00071 {
00072     pcCoords->unref();
00073     pcFaces->unref();
00074     pcMeshPick->unref();
00075 }
00076 
00077 void ViewProviderFace::attach(App::DocumentObject* obj)
00078 {
00079     ViewProviderDocumentObject::attach(obj);
00080 
00081     pcMeshPick->mesh.setValue(static_cast<Mesh::Feature*>(obj)->Mesh.getValuePtr());
00082 
00083     // Draw markers
00084     SoGroup* markers = new SoGroup();
00085     SoDrawStyle* pointStyle = new SoDrawStyle();
00086     pointStyle->style = SoDrawStyle::POINTS;
00087     pointStyle->pointSize = 8.0f;
00088     markers->addChild(pointStyle);
00089 
00090     SoBaseColor * markcol = new SoBaseColor;
00091     markcol->rgb.setValue(1.0f, 1.0f, 0.0f);
00092     SoPointSet* marker = new SoPointSet();
00093     markers->addChild(markcol);
00094     markers->addChild(pcCoords);
00095     markers->addChild(marker);
00096 
00097     // Draw face
00098     SoGroup* faces = new SoGroup();
00099     SoDrawStyle* faceStyle = new SoDrawStyle();
00100     faceStyle->style = SoDrawStyle::FILLED;
00101     faces->addChild(faceStyle);
00102 
00103     SoShapeHints * flathints = new SoShapeHints;
00104     //flathints->vertexOrdering = SoShapeHints::COUNTERCLOCKWISE ;
00105     //flathints->shapeType = SoShapeHints::UNKNOWN_SHAPE_TYPE;
00106     faces->addChild(flathints);
00107 
00108     SoBaseColor* basecol = new SoBaseColor;
00109     if (mesh) {
00110         App::Color col = mesh->ShapeColor.getValue();
00111         basecol->rgb.setValue(col.r, col.g, col.b);
00112     }
00113     else {
00114         basecol->rgb.setValue(1.0f, 0.0f, 0.0f);
00115     }
00116 
00117     faces->addChild(basecol);
00118     faces->addChild(pcCoords);
00119     faces->addChild(pcFaces);
00120 
00121     SoGroup* face_marker = new SoGroup();
00122     face_marker->addChild(faces);
00123     face_marker->addChild(markers);
00124 
00125     addDisplayMaskMode(markers, "Marker");
00126     addDisplayMaskMode(face_marker, "Face");
00127     setDisplayMode("Marker");
00128 }
00129 
00130 void ViewProviderFace::setDisplayMode(const char* ModeName)
00131 {
00132     if (strcmp(ModeName, "Face") == 0)
00133         setDisplayMaskMode("Face");
00134     else if (strcmp(ModeName, "Marker") == 0)
00135         setDisplayMaskMode("Marker");
00136     ViewProviderDocumentObject::setDisplayMode(ModeName);
00137 }
00138 
00139 const char* ViewProviderFace::getDefaultDisplayMode() const
00140 {
00141     return "Marker";
00142 }
00143 
00144 std::vector<std::string> ViewProviderFace::getDisplayModes(void) const
00145 {
00146     std::vector<std::string> modes;
00147     modes.push_back("Marker");
00148     modes.push_back("Face");
00149     return modes;
00150 }
00151 
00152 SoPickedPoint* ViewProviderFace::getPickedPoint(const SbVec2s& pos, const SoQtViewer* viewer) const
00153 {
00154     SoSeparator* root = new SoSeparator;
00155     root->ref();
00156     root->addChild(viewer->getHeadlight());
00157     root->addChild(viewer->getCamera());
00158     root->addChild(this->pcMeshPick);
00159 
00160     SoRayPickAction rp(viewer->getViewportRegion());
00161     rp.setPoint(pos);
00162     rp.apply(root);
00163     root->unref();
00164 
00165     // returns a copy of the point
00166     SoPickedPoint* pick = rp.getPickedPoint();
00167     //return (pick ? pick->copy() : 0); // needs the same instance of CRT under MS Windows
00168     return (pick ? new SoPickedPoint(*pick) : 0);
00169 }
00170 
00171 // ----------------------------------------------------------------------
00172 
00173 /* TRANSLATOR MeshGui::MeshFaceAddition */
00174 
00175 MeshFaceAddition::MeshFaceAddition(Gui::View3DInventor* parent)
00176   : QObject(parent), faceView(new MeshGui::ViewProviderFace())
00177 {
00178 }
00179 
00180 MeshFaceAddition::~MeshFaceAddition()
00181 {
00182     delete faceView;
00183 }
00184 
00185 void MeshFaceAddition::startEditing(MeshGui::ViewProviderMesh* vp)
00186 {
00187     Gui::View3DInventor* view = static_cast<Gui::View3DInventor*>(parent());
00188     Gui::View3DInventorViewer* viewer = view->getViewer();
00189     viewer->setEditing(true);
00190     viewer->setRedirectToSceneGraph(true);
00191 
00192     faceView->mesh = vp;
00193     faceView->attach(vp->getObject());
00194     viewer->addViewProvider(faceView);
00195     //faceView->mesh->startEditing();
00196     viewer->addEventCallback(SoEvent::getClassTypeId(),
00197         MeshFaceAddition::addFacetCallback, this);
00198 }
00199 
00200 void MeshFaceAddition::finishEditing()
00201 {
00202     Gui::View3DInventor* view = static_cast<Gui::View3DInventor*>(parent());
00203     Gui::View3DInventorViewer* viewer = view->getViewer();
00204     viewer->setEditing(false);
00205     viewer->setRedirectToSceneGraph(false);
00206 
00207     viewer->removeViewProvider(faceView);
00208     //faceView->mesh->finishEditing();
00209     viewer->removeEventCallback(SoEvent::getClassTypeId(),
00210         MeshFaceAddition::addFacetCallback, this);
00211     this->deleteLater();
00212 }
00213 
00214 void MeshFaceAddition::addFace()
00215 {
00216     Mesh::Feature* mf = static_cast<Mesh::Feature*>(faceView->mesh->getObject());
00217     App::Document* doc = mf->getDocument();
00218     doc->openTransaction("Add triangle");
00219     Mesh::MeshObject* mesh = mf->Mesh.startEditing();
00220     MeshCore::MeshFacet f;
00221     f._aulPoints[0] = faceView->index[0];
00222     f._aulPoints[1] = faceView->index[1];
00223     f._aulPoints[2] = faceView->index[2];
00224     std::vector<MeshCore::MeshFacet> faces;
00225     faces.push_back(f);
00226     mesh->addFacets(faces);
00227     mf->Mesh.finishEditing();
00228     doc->commitTransaction();
00229 
00230     clearPoints();
00231 }
00232 
00233 void MeshFaceAddition::clearPoints()
00234 {
00235     faceView->index.clear();
00236     faceView->current_index = -1;
00237     faceView->pcCoords->point.setNum(0);
00238     faceView->setDisplayMode("Marker");
00239 }
00240 
00241 void MeshFaceAddition::flipNormal()
00242 {
00243     if (faceView->index.size() < 3)
00244         return;
00245     std::swap(faceView->index[0], faceView->index[1]);
00246     SbVec3f v1 = faceView->pcCoords->point[0];
00247     SbVec3f v2 = faceView->pcCoords->point[1];
00248     faceView->pcCoords->point.set1Value(0, v2);
00249     faceView->pcCoords->point.set1Value(1, v1);
00250 }
00251 
00252 bool MeshFaceAddition::addMarkerPoint()
00253 {
00254     if (faceView->current_index < 0)
00255         return false;
00256     if (faceView->index.size() >= 3)
00257         return false;
00258     faceView->index.push_back(faceView->current_index);
00259     faceView->current_index = -1;
00260     if (faceView->index.size() == 3)
00261         faceView->setDisplayMode("Face");
00262     return true;
00263 }
00264 
00265 void MeshFaceAddition::showMarker(SoPickedPoint* pp)
00266 {
00267     const SbVec3f& vec = pp->getPoint();
00268     const SoDetail* detail = pp->getDetail();
00269     if (detail) {
00270         if (detail->isOfType(SoFaceDetail::getClassTypeId())) {
00271             const SoFaceDetail* fd = static_cast<const SoFaceDetail*>(detail);
00272             Mesh::Feature* mf = static_cast<Mesh::Feature*>(faceView->mesh->getObject());
00273             const MeshCore::MeshFacetArray& facets = mf->Mesh.getValuePtr()->getKernel().GetFacets();
00274             const MeshCore::MeshPointArray& points = mf->Mesh.getValuePtr()->getKernel().GetPoints();
00275             // is the face index valid?
00276             int face_index = fd->getFaceIndex();
00277             if (face_index >= (int)facets.size())
00278                 return;
00279             // is a border facet picked? 
00280             MeshCore::MeshFacet f = facets[face_index];
00281             if (!f.HasOpenEdge())
00282                 return;
00283 
00284             int point_index = -1;
00285             float distance = FLT_MAX;
00286             Base::Vector3f pnt;
00287             SbVec3f face_pnt;
00288 
00289             for (int i=0; i<3; i++) {
00290                 int index = (int)f._aulPoints[i];
00291                 if (std::find(faceView->index.begin(), faceView->index.end(), index) != faceView->index.end())
00292                     continue; // already inside
00293                 if (f._aulNeighbours[i] == ULONG_MAX ||
00294                     f._aulNeighbours[(i+2)%3] == ULONG_MAX) {
00295                     pnt = points[index];
00296                     float len = Base::DistanceP2(pnt, Base::Vector3f(vec[0],vec[1],vec[2]));
00297                     if (len < distance) {
00298                         distance = len;
00299                         point_index = index;
00300                         face_pnt.setValue(pnt.x,pnt.y,pnt.z);
00301                     }
00302                 }
00303             }
00304 
00305             if (point_index < 0)
00306                 return; // picked point is rejected
00307 
00308             int num = faceView->pcCoords->point.getNum();
00309             if (faceView->current_index >= 0) {
00310                 num = std::max<int>(num-1, 0);
00311             }
00312             faceView->current_index = point_index;
00313             faceView->pcCoords->point.set1Value(num, face_pnt);
00314             return;
00315         }
00316     }
00317 }
00318 
00319 void MeshFaceAddition::addFacetCallback(void * ud, SoEventCallback * n)
00320 {
00321     MeshFaceAddition* that = reinterpret_cast<MeshFaceAddition*>(ud);
00322     ViewProviderFace* face =  that->faceView;
00323     Gui::View3DInventorViewer* view  = reinterpret_cast<Gui::View3DInventorViewer*>(n->getUserData());
00324 
00325     const SoEvent* ev = n->getEvent();
00326     if (ev->getTypeId() == SoLocation2Event::getClassTypeId()) {
00327         // set as handled
00328         n->getAction()->setHandled();
00329         n->setHandled();
00330         if (face->index.size() < 3) {
00331             SoPickedPoint * point = face->getPickedPoint(ev->getPosition(), view);
00332             if (point) {
00333                 that->showMarker(point);
00334                 delete point;
00335             }
00336         }
00337     }
00338     else if (ev->getTypeId() == SoMouseButtonEvent::getClassTypeId()) {
00339         // set as handled
00340         n->getAction()->setHandled();
00341         n->setHandled();
00342         const SoMouseButtonEvent * mbe = static_cast<const SoMouseButtonEvent *>(ev);
00343         if (mbe->getButton() == SoMouseButtonEvent::BUTTON1 && mbe->getState() == SoButtonEvent::DOWN) {
00344             that->addMarkerPoint();
00345         }
00346         else if (mbe->getButton() == SoMouseButtonEvent::BUTTON1 && mbe->getState() == SoButtonEvent::UP) {
00347             if (face->index.size() == 3) {
00348                 QMenu menu;
00349                 QAction* add = menu.addAction(MeshFaceAddition::tr("Add triangle"));
00350                 QAction* swp = menu.addAction(MeshFaceAddition::tr("Flip normal"));
00351                 QAction* clr = menu.addAction(MeshFaceAddition::tr("Clear"));
00352                 QAction* act = menu.exec(QCursor::pos());
00353                 if (act == add) {
00354                     QTimer::singleShot(300, that, SLOT(addFace()));
00355                 }
00356                 else if (act == swp) {
00357                     QTimer::singleShot(300, that, SLOT(flipNormal()));
00358                 }
00359                 else if (act == clr) {
00360                     QTimer::singleShot(300, that, SLOT(clearPoints()));
00361                 }
00362             }
00363         }
00364         else if (mbe->getButton() == SoMouseButtonEvent::BUTTON2 && mbe->getState() == SoButtonEvent::UP) {
00365             QMenu menu;
00366             QAction* fin = menu.addAction(MeshFaceAddition::tr("Finish"));
00367             QAction* act = menu.exec(QCursor::pos());
00368             if (act == fin) {
00369                 QTimer::singleShot(300, that, SLOT(finishEditing()));
00370             }
00371         }
00372     }
00373 }
00374 
00375 #include "moc_MeshEditor.cpp"

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