ViewProviderMeasureDistance.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) 2008 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 <sstream>
00028 # include <QApplication>
00029 # include <Inventor/SoPickedPoint.h>
00030 # include <Inventor/events/SoMouseButtonEvent.h>
00031 # include <Inventor/nodes/SoSeparator.h>
00032 # include <Inventor/nodes/SoBaseColor.h>
00033 # include <Inventor/nodes/SoFontStyle.h>
00034 # include <Inventor/nodes/SoPickStyle.h>
00035 # include <Inventor/nodes/SoText2.h>
00036 # include <Inventor/nodes/SoTranslation.h>
00037 # include <Inventor/nodes/SoCoordinate3.h>
00038 # include <Inventor/nodes/SoIndexedLineSet.h>
00039 # include <Inventor/nodes/SoMarkerSet.h>
00040 # include <Inventor/nodes/SoDrawStyle.h>
00041 #endif
00042 
00043 #include "ViewProviderMeasureDistance.h"
00044 #include "SoFCSelection.h"
00045 #include "Application.h"
00046 #include "Document.h"
00047 #include "View3DInventorViewer.h"
00048 
00049 #include <App/PropertyGeo.h>
00050 #include <App/PropertyStandard.h>
00051 #include <App/MeasureDistance.h>
00052 #include <Base/Console.h>
00053 
00054 using namespace Gui;
00055 
00056 PROPERTY_SOURCE(Gui::ViewProviderMeasureDistance, Gui::ViewProviderDocumentObject)
00057 
00058 
00059 ViewProviderMeasureDistance::ViewProviderMeasureDistance() 
00060 {
00061     ADD_PROPERTY(TextColor,(0.0f,0.0f,0.0f));
00062     ADD_PROPERTY(LineColor,(1.0f,1.0f,1.0f));
00063     ADD_PROPERTY(FontSize,(18));
00064     ADD_PROPERTY(DistFactor,(1.0));
00065     ADD_PROPERTY(Mirror,(false));
00066 
00067     pFont = new SoFontStyle();
00068     pFont->ref();
00069     pLabel = new SoText2();
00070     pLabel->ref();
00071     pColor = new SoBaseColor();
00072     pColor->ref();
00073     pTextColor = new SoBaseColor();
00074     pTextColor->ref();
00075     pTranslation = new SoTranslation();
00076     pTranslation->ref();
00077 
00078     TextColor.touch();
00079     FontSize.touch();
00080     LineColor.touch();
00081 
00082     static const SbVec3f verts[4] =
00083     {
00084         SbVec3f(0,0,0), SbVec3f(0,0,0),
00085         SbVec3f(0,0,0), SbVec3f(0,0,0)
00086     };
00087 
00088     // indexes used to create the edges
00089     static const int32_t lines[9] =
00090     {
00091         0,2,-1,
00092         1,3,-1,
00093         2,3,-1
00094     };
00095 
00096     pCoords = new SoCoordinate3();
00097     pCoords->ref();
00098     pCoords->point.setNum(4);
00099     pCoords->point.setValues(0, 4, verts);
00100 
00101     pLines  = new SoIndexedLineSet();
00102     pLines->ref();
00103     pLines->coordIndex.setNum(9);
00104     pLines->coordIndex.setValues(0, 9, lines);
00105     sPixmap = "view-measurement";
00106 }
00107 
00108 ViewProviderMeasureDistance::~ViewProviderMeasureDistance()
00109 {
00110     pFont->unref();
00111     pLabel->unref();
00112     pColor->unref();
00113     pTextColor->unref();
00114     pTranslation->unref();
00115     pCoords->unref();
00116     pLines->unref();
00117 }
00118 
00119 void ViewProviderMeasureDistance::onChanged(const App::Property* prop)
00120 {
00121     if (prop == &Mirror || prop == &DistFactor) {
00122         updateData(prop);
00123     }
00124     else if (prop == &TextColor) {
00125         const App::Color& c = TextColor.getValue();
00126         pTextColor->rgb.setValue(c.r,c.g,c.b);
00127     }
00128     else if (prop == &LineColor) {
00129         const App::Color& c = LineColor.getValue();
00130         pColor->rgb.setValue(c.r,c.g,c.b);
00131     }
00132     else if (prop == &FontSize) {
00133         pFont->size = FontSize.getValue();
00134     }
00135     else {
00136         ViewProviderDocumentObject::onChanged(prop);
00137     }
00138 }
00139 
00140 std::vector<std::string> ViewProviderMeasureDistance::getDisplayModes(void) const
00141 {
00142     // add modes
00143     std::vector<std::string> StrList;
00144     StrList.push_back("Base");
00145     return StrList;
00146 }
00147 
00148 void ViewProviderMeasureDistance::setDisplayMode(const char* ModeName)
00149 {
00150     if (strcmp(ModeName, "Base") == 0)
00151         setDisplayMaskMode("Base");
00152     ViewProviderDocumentObject::setDisplayMode(ModeName);
00153 }
00154 
00155 void ViewProviderMeasureDistance::attach(App::DocumentObject* pcObject)
00156 {
00157     ViewProviderDocumentObject::attach(pcObject);
00158 
00159     SoPickStyle* ps = new SoPickStyle();
00160     ps->style = SoPickStyle::UNPICKABLE;
00161 
00162     SoSeparator *lineSep = new SoSeparator();
00163     SoDrawStyle* style = new SoDrawStyle();
00164     style->lineWidth = 2.0f;
00165     lineSep->addChild(ps);
00166     lineSep->addChild(style);
00167     lineSep->addChild(pColor);
00168     lineSep->addChild(pCoords);
00169     lineSep->addChild(pLines);
00170     SoMarkerSet* points = new SoMarkerSet();
00171     points->markerIndex = SoMarkerSet::CROSS_9_9;
00172     points->numPoints=2;
00173     lineSep->addChild(points);
00174 
00175     // Making the whole measurement object selectable by 3d view can
00176     // become cumbersome since it has influence to any raypick action.
00177     // Thus, it's only selectable by its text label
00178     SoFCSelection* textsep = new SoFCSelection();
00179     textsep->objectName = pcObject->getNameInDocument();
00180     textsep->documentName = pcObject->getDocument()->getName();
00181     textsep->subElementName = "Main";
00182     //SoSeparator* textsep = new SoSeparator();
00183     textsep->addChild(pTranslation);
00184     textsep->addChild(pTextColor);
00185     textsep->addChild(pFont);
00186     textsep->addChild(pLabel);
00187 
00188     SoSeparator* sep = new SoSeparator();
00189     sep->addChild(lineSep);
00190     sep->addChild(textsep);
00191     addDisplayMaskMode(sep, "Base");
00192 }
00193 
00194 void ViewProviderMeasureDistance::updateData(const App::Property* prop)
00195 {
00196     if (prop->getTypeId() == App::PropertyVector::getClassTypeId() ||
00197         prop == &Mirror || prop == &DistFactor) {
00198         if (strcmp(prop->getName(),"P1") == 0) {
00199             Base::Vector3f v = static_cast<const App::PropertyVector*>(prop)->getValue();
00200             pCoords->point.set1Value(0, SbVec3f(v.x,v.y,v.z));
00201         }
00202         else if (strcmp(prop->getName(),"P2") == 0) {
00203             Base::Vector3f v = static_cast<const App::PropertyVector*>(prop)->getValue();
00204             pCoords->point.set1Value(1, SbVec3f(v.x,v.y,v.z));
00205         }
00206 
00207         SbVec3f pt1 = pCoords->point[0];
00208         SbVec3f pt2 = pCoords->point[1];
00209         SbVec3f dif = pt1-pt2;
00210 
00211         float length = fabs(dif.length())*DistFactor.getValue();
00212         if (Mirror.getValue())
00213             length = -length;
00214 
00215 
00216         if (dif.sqrLength() < 10.0e-6f) {
00217             pCoords->point.set1Value(2, pt1+SbVec3f(0.0f,0.0f,length));
00218             pCoords->point.set1Value(3, pt2+SbVec3f(0.0f,0.0f,length));
00219         }
00220         else {
00221             SbVec3f dir = dif.cross(SbVec3f(1.0f,0.0f,0.0f));
00222             if (dir.sqrLength() < 10.0e-6f)
00223                 dir = dif.cross(SbVec3f(0.0f,1.0f,0.0f));
00224             if (dir.sqrLength() < 10.0e-6f)
00225                 dir = dif.cross(SbVec3f(0.0f,0.0f,1.0f));
00226             dir.normalize();
00227             if (dir.dot(SbVec3f(0.0f,0.0f,1.0f)) < 0.0f)
00228                 length = -length;
00229             pCoords->point.set1Value(2, pt1 + length*dir);
00230             pCoords->point.set1Value(3, pt2 + length*dir);
00231         }
00232 
00233         SbVec3f pos = (pCoords->point[2]+pCoords->point[3])/2.0f;
00234         pTranslation->translation.setValue(pos);
00235 
00236         std::stringstream s;
00237         s.precision(3);
00238         s.setf(std::ios::fixed | std::ios::showpoint);
00239         s << dif.length();
00240         pLabel->string.setValue(s.str().c_str());
00241     }
00242 
00243     ViewProviderDocumentObject::updateData(prop);
00244 }
00245 
00246 // ----------------------------------------------------------------------------
00247 
00248 PointMarker::PointMarker(View3DInventorViewer* iv) : view(iv),
00249     vp(new ViewProviderPointMarker)
00250 {
00251     view->addViewProvider(vp);
00252 }
00253 
00254 PointMarker::~PointMarker()
00255 {
00256     view->removeViewProvider(vp);
00257     delete vp;
00258 }
00259 
00260 void PointMarker::addPoint(const SbVec3f& pt)
00261 {
00262     int ct = countPoints();
00263     vp->pCoords->point.set1Value(ct, pt);
00264     vp->pMarker->numPoints=ct+1;
00265 }
00266 
00267 int PointMarker::countPoints() const
00268 {
00269     return vp->pCoords->point.getNum();
00270 }
00271 
00272 void PointMarker::customEvent(QEvent* e)
00273 {
00274     Gui::Document* doc = Gui::Application::Instance->activeDocument();
00275     App::DocumentObject* obj = doc->getDocument()->addObject
00276         (App::MeasureDistance::getClassTypeId().getName(),"Distance");
00277 
00278     App::MeasureDistance* md = static_cast<App::MeasureDistance*>(obj);
00279     const SbVec3f& pt1 = vp->pCoords->point[0];
00280     const SbVec3f& pt2 = vp->pCoords->point[1];
00281     md->P1.setValue(Base::Vector3f(pt1[0],pt1[1],pt1[2]));
00282     md->P2.setValue(Base::Vector3f(pt2[0],pt2[1],pt2[2]));
00283     std::stringstream s;
00284     s.precision(3);
00285     s.setf(std::ios::fixed | std::ios::showpoint);
00286     s << "Distance: " << md->Distance.getValue();
00287     md->Label.setValue(s.str());
00288 }
00289 
00290 PROPERTY_SOURCE(Gui::ViewProviderPointMarker, Gui::ViewProviderDocumentObject)
00291 
00292 ViewProviderPointMarker::ViewProviderPointMarker()
00293 {
00294     pCoords = new SoCoordinate3();
00295     pCoords->ref();
00296     pCoords->point.setNum(0);
00297     pMarker = new SoMarkerSet();
00298     pMarker->markerIndex = SoMarkerSet::CROSS_9_9;
00299     pMarker->numPoints=0;
00300     pMarker->ref();
00301 
00302     SoGroup* grp = new SoGroup();
00303     grp->addChild(pCoords);
00304     grp->addChild(pMarker);
00305     addDisplayMaskMode(grp, "Base");
00306     setDisplayMaskMode("Base");
00307 }
00308 
00309 ViewProviderPointMarker::~ViewProviderPointMarker()
00310 {
00311     pCoords->unref();
00312     pMarker->unref();
00313 }
00314 
00315 void ViewProviderMeasureDistance::measureDistanceCallback(void * ud, SoEventCallback * n)
00316 {
00317     const SoMouseButtonEvent * mbe = static_cast<const SoMouseButtonEvent*>(n->getEvent());
00318     Gui::View3DInventorViewer* view  = reinterpret_cast<Gui::View3DInventorViewer*>(n->getUserData());
00319     PointMarker *pm = reinterpret_cast<PointMarker*>(ud);
00320 
00321     // Mark all incoming mouse button events as handled, especially, to deactivate the selection node
00322     n->getAction()->setHandled();
00323     if (mbe->getButton() == SoMouseButtonEvent::BUTTON2 && mbe->getState() == SoButtonEvent::UP) {
00324         n->setHandled();
00325         view->setEditing(false);
00326         view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), measureDistanceCallback, ud);
00327         pm->deleteLater();
00328     }
00329     else if (mbe->getButton() == SoMouseButtonEvent::BUTTON1 && mbe->getState() == SoButtonEvent::DOWN) {
00330         const SoPickedPoint * point = n->getPickedPoint();
00331         if (point == NULL) {
00332             Base::Console().Message("No point picked.\n");
00333             return;
00334         }
00335 
00336         n->setHandled();
00337         pm->addPoint(point->getPoint());
00338         if (pm->countPoints() == 2) {
00339             QEvent *e = new QEvent(QEvent::User);
00340             QApplication::postEvent(pm, e);
00341             // leave mode
00342             view->setEditing(false);
00343             view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), measureDistanceCallback, ud);
00344             pm->deleteLater();
00345         }
00346     }
00347 }

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