DrawSketchHandler.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) 2010 Jürgen Riegel <juergen.riegel@web.de>              *
00003  *                                                                         *
00004  *   This file is part of the FreeCAD CAx development system.              *
00005  *                                                                         *
00006  *   This library is free software; you can redistribute it and/or         *
00007  *   modify it under the terms of the GNU Library General Public           *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2 of the License, or (at your option) any later version.      *
00010  *                                                                         *
00011  *   This library  is distributed in the hope that it will be useful,      *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00014  *   GNU Library General Public License for more details.                  *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Library General Public     *
00017  *   License along with this library; see the file COPYING.LIB. If not,    *
00018  *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
00019  *   Suite 330, Boston, MA  02111-1307, USA                                *
00020  *                                                                         *
00021  ***************************************************************************/
00022 
00023 
00024 #include "PreCompiled.h"
00025 
00026 #ifndef _PreComp_
00027 # include <Standard_math.hxx>
00028 # include <Inventor/nodes/SoTranslation.h>
00029 # include <Inventor/nodes/SoText2.h>
00030 # include <Inventor/nodes/SoFont.h>
00031 # include <QPainter>
00032 #endif
00033 
00035 #include <Base/Console.h>
00036 #include <Base/Exception.h>
00037 #include <Base/Interpreter.h>
00038 #include <Gui/Application.h>
00039 #include <Gui/BitmapFactory.h>
00040 #include <Gui/Command.h>
00041 #include <Gui/Document.h>
00042 #include <Gui/Macro.h>
00043 #include <Gui/MainWindow.h>
00044 #include <Gui/View3DInventorViewer.h>
00045 #include <Gui/View3DInventor.h>
00046 
00047 #include <Mod/Part/App/Geometry.h>
00048 #include <Mod/Sketcher/App/SketchObject.h>
00049 
00050 #include "DrawSketchHandler.h"
00051 #include "ViewProviderSketch.h"
00052 
00053 
00054 using namespace SketcherGui;
00055 using namespace Sketcher;
00056 
00057 
00058 //**************************************************************************
00059 // Construction/Destruction
00060 
00061 DrawSketchHandler::DrawSketchHandler()
00062         : sketchgui(0)
00063 {
00064 
00065 }
00066 
00067 DrawSketchHandler::~DrawSketchHandler()
00068 {
00069 
00070 }
00071 
00072 void DrawSketchHandler::quit(void)
00073 {
00074     assert(sketchgui);
00075     sketchgui->drawEdit(std::vector<Base::Vector2D>());
00076     resetPositionText();
00077 
00078     unsetCursor();
00079     sketchgui->purgeHandler();
00080 }
00081 
00082 //**************************************************************************
00083 // Helpers
00084 
00085 Sketcher::SketchObject* DrawSketchHandler::getObject(void)
00086 {
00087     return dynamic_cast<Sketcher::SketchObject*>(sketchgui->getObject());
00088 }
00089 
00090 int DrawSketchHandler::getHighestVertexIndex(void)
00091 {
00092     return getObject()->getHighestVertexIndex();
00093 }
00094 
00095 int DrawSketchHandler::getHighestCurveIndex(void)
00096 {
00097     return getObject()->getHighestCurveIndex();
00098 }
00099 
00100 void DrawSketchHandler::setCursor(const QPixmap &p,int x,int y)
00101 {
00102     Gui::MDIView* view = Gui::getMainWindow()->activeWindow();
00103     if (view && view->isDerivedFrom(Gui::View3DInventor::getClassTypeId())) {
00104         Gui::View3DInventorViewer* viewer = static_cast<Gui::View3DInventor*>(view)->getViewer();
00105 
00106         oldCursor = viewer->getWidget()->cursor();
00107         QCursor cursor(p, x, y);
00108         actCursor = cursor;
00109 
00110         viewer->getWidget()->setCursor(cursor);
00111     }
00112 }
00113 
00114 void DrawSketchHandler::applyCursor(void)
00115 {
00116     applyCursor(actCursor);
00117 }
00118 
00119 void DrawSketchHandler::applyCursor(QCursor &newCursor)
00120 {
00121     Gui::MDIView* view = Gui::getMainWindow()->activeWindow();
00122     if (view && view->isDerivedFrom(Gui::View3DInventor::getClassTypeId())) {
00123         Gui::View3DInventorViewer* viewer = static_cast<Gui::View3DInventor*>(view)->getViewer();
00124         viewer->getWidget()->setCursor(newCursor);
00125     }
00126 }
00127 
00128 void DrawSketchHandler::unsetCursor(void)
00129 {
00130     Gui::MDIView* view = Gui::getMainWindow()->activeWindow();
00131     if (view && view->isDerivedFrom(Gui::View3DInventor::getClassTypeId())) {
00132         Gui::View3DInventorViewer* viewer = static_cast<Gui::View3DInventor*>(view)->getViewer();
00133         viewer->getWidget()->setCursor(oldCursor);
00134     }
00135 }
00136 
00137 int DrawSketchHandler::seekAutoConstraint(std::vector<AutoConstraint> &suggestedConstraints,
00138                                           const Base::Vector2D& Pos, const Base::Vector2D& Dir, Type type)
00139 {
00140     suggestedConstraints.clear();
00141 
00142     if (!sketchgui->Autoconstraints.getValue())
00143         return 0; // If Autoconstraints property is not set quit
00144 
00145     // Get Preselection
00146     // Currently only considers objects in current Sketcher
00147     if (type == VERTEX && sketchgui->getPreselectPoint() != -1) {
00148         AutoConstraint coincident;
00149         coincident.Type       = Sketcher::Coincident;
00150         coincident.Index      = sketchgui->getPreselectPoint();
00151         suggestedConstraints.push_back(coincident);
00152     }
00153     else if (type == CURVE && sketchgui->getPreselectPoint() != -1) {
00154         AutoConstraint pointOnObject;
00155         pointOnObject.Type       = Sketcher::PointOnObject;
00156         pointOnObject.Index      = sketchgui->getPreselectPoint();
00157         suggestedConstraints.push_back(pointOnObject);
00158     }
00159     else if (type == VERTEX && sketchgui->getPreselectCurve() != -1) {
00160         AutoConstraint pointOnObject;
00161         pointOnObject.Type       = Sketcher::PointOnObject;
00162         pointOnObject.Index      = sketchgui->getPreselectCurve();
00163         suggestedConstraints.push_back(pointOnObject);
00164     }
00165     else if (type == CURVE && sketchgui->getPreselectCurve() != -1) {
00166         AutoConstraint tangent;
00167         tangent.Type       = Sketcher::Tangent;
00168         tangent.Index      = sketchgui->getPreselectCurve();
00169         suggestedConstraints.push_back(tangent);
00170     }
00171 
00172     if (Dir.Length() < 1)
00173         // Direction not set so return;
00174         return suggestedConstraints.size();
00175 
00176     // Suggest vertical and horizontal constraints
00177 
00178     // Number of Degree of deviation from horizontal or vertical lines
00179     const double angleDev = 2;
00180     const double angleDevRad = angleDev *  M_PI / 180.;
00181 
00182     double angle = std::abs(atan2(Dir.fY, Dir.fX));
00183     if (angle < angleDevRad || (M_PI - angle) < angleDevRad ) {
00184         // Suggest horizontal constraint
00185         AutoConstraint horConstr;
00186         horConstr.Index = -1;
00187         horConstr.Type = Horizontal;
00188         suggestedConstraints.push_back(horConstr);
00189     }
00190     else if (std::abs(angle - M_PI_2) < angleDevRad) {
00191         // Suggest vertical constraint
00192         AutoConstraint vertConstr;
00193         vertConstr.Index = -1;
00194         vertConstr.Type = Vertical;
00195         suggestedConstraints.push_back(vertConstr);
00196     }
00197 
00198     // Find if there are tangent constraints (currently arcs and circles)
00199     // FIXME needs to consider when zooming out?
00200     const float tangDeviation = 2.;
00201 
00202     int tangId = -1;
00203     float smlTangDist = 0;
00204 
00205     // Get geometry list
00206     const std::vector<Part::Geometry *> geomlist = getObject()->Geometry.getValues();
00207 
00208     // Iterate through geometry
00209     int i = 0;
00210     for (std::vector<Part::Geometry *>::const_iterator it = geomlist.begin(); it != geomlist.end(); ++it, i++) {
00211 
00212         if ((*it)->getTypeId() == Part::GeomCircle::getClassTypeId()) {
00213             const Part::GeomCircle *circle = dynamic_cast<const Part::GeomCircle *>((*it));
00214 
00215             Base::Vector3d center = circle->getCenter();
00216             Base::Vector3d tmpPos(Pos.fX, Pos.fY, 0.f);
00217 
00218             float radius = (float) circle->getRadius();
00219 
00220             Base::Vector3d projPnt(0.f, 0.f, 0.f);
00221             projPnt = projPnt.ProjToLine(center - tmpPos, Base::Vector3d(Dir.fX, Dir.fY));
00222             float projDist = projPnt.Length();
00223 
00224             if ( (projDist < radius + tangDeviation ) && (projDist > radius - tangDeviation))
00225             {
00226                 // Find if nearest
00227                 if (tangId == -1 || projDist< smlTangDist)
00228                 {
00229                     tangId = i;
00230                     smlTangDist = projDist;
00231                 }
00232             }
00233 
00234         } else if ((*it)->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) {
00235             const Part::GeomArcOfCircle *arc = dynamic_cast<const Part::GeomArcOfCircle *>((*it));
00236 
00237             Base::Vector3d center = arc->getCenter();
00238             double radius = arc->getRadius();
00239 
00240             Base::Vector3d projPnt(0.f, 0.f, 0.f);
00241             Base::Vector3d tmpPos(Pos.fX, Pos.fY, 0.f);
00242 
00243             projPnt = projPnt.ProjToLine(center - tmpPos, Base::Vector3d(Dir.fX, Dir.fY));
00244             float projDist = projPnt.Length();
00245 
00246             if ( projDist < radius + tangDeviation && projDist > radius - tangDeviation) {
00247                 double startAngle, endAngle;
00248                 arc->getRange(startAngle, endAngle);
00249 
00250                 projPnt += center;
00251                 double angle = atan2(projPnt.y, projPnt.x);
00252 
00253                 // if the pnt is on correct side of arc and find if nearest
00254                 if ((angle > startAngle && angle < endAngle) &&
00255                     (tangId == -1 || projDist < smlTangDist) ) {
00256                     tangId = i;
00257                     smlTangDist = projDist;
00258                 }
00259             }
00260         }
00261     }
00262 
00263     if (tangId != -1) {
00264         // Suggest vertical constraint
00265         AutoConstraint tangConstr;
00266         tangConstr.Index = tangId;
00267         tangConstr.Type = Tangent;
00268         suggestedConstraints.push_back(tangConstr);
00269     }
00270 
00271     return suggestedConstraints.size();
00272 }
00273 
00274 void DrawSketchHandler::createAutoConstraints(const std::vector<AutoConstraint> &autoConstrs,
00275                                               int geoId, Sketcher::PointPos pointPos)
00276 {
00277     if (!sketchgui->Autoconstraints.getValue())
00278         return; // If Autoconstraints property is not set quit
00279 
00280     if (autoConstrs.size() > 0) {
00281         // Open the Command
00282         Gui::Command::openCommand("Add auto constraints");
00283 
00284         // Iterate through constraints
00285         std::vector<AutoConstraint>::const_iterator it = autoConstrs.begin();
00286         for (; it != autoConstrs.end(); ++it) {
00287             switch (it->Type)
00288             {
00289             case Sketcher::Coincident: {
00290                 if (pointPos == Sketcher::none)
00291                     continue;
00292                 // If the auto constraint has a point create a coincident otherwise it is an edge on a point
00293                 Sketcher::PointPos pointPos2;
00294                 int geoId2;
00295                 sketchgui->getSketchObject()->getGeoVertexIndex(it->Index, geoId2, pointPos2);
00296 
00297                 Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Coincident',%i,%i,%i,%i)) "
00298                                         ,sketchgui->getObject()->getNameInDocument()
00299                                         ,geoId, pointPos, geoId2, pointPos2
00300                                         );
00301                 } break;
00302             case Sketcher::PointOnObject: {
00303                 int index = it->Index;
00304                 if (pointPos == Sketcher::none) {
00305                     // Auto constraining an edge so swap parameters
00306                     index = geoId;
00307                     sketchgui->getSketchObject()->getGeoVertexIndex(it->Index, geoId, pointPos);
00308                 }
00309 
00310                 Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('PointOnObject',%i,%i,%i)) "
00311                                         ,sketchgui->getObject()->getNameInDocument()
00312                                         ,geoId, pointPos, index
00313                                        );
00314                 } break;
00315             case Sketcher::Horizontal: {
00316                 Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Horizontal',%i)) "
00317                                         ,sketchgui->getObject()->getNameInDocument()
00318                                         ,geoId
00319                                        );
00320                 } break;
00321             case Sketcher::Vertical: {
00322                 Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Vertical',%i)) "
00323                                         ,sketchgui->getObject()->getNameInDocument()
00324                                         ,geoId
00325                                        );
00326                 } break;
00327             case Sketcher::Tangent: {
00328                 Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Tangent',%i, %i)) "
00329                                         ,sketchgui->getObject()->getNameInDocument()
00330                                         ,geoId, it->Index
00331                                        );
00332                 } break;
00333             }
00334 
00335             Gui::Command::commitCommand();
00336             Gui::Command::updateActive();
00337         }
00338     }
00339 }
00340 
00341 void DrawSketchHandler::renderSuggestConstraintsCursor(std::vector<AutoConstraint> &suggestedConstraints)
00342 {
00343     // Auto Constrait icon size in px
00344     int iconSize = 16;
00345 
00346     // Create a pixmap that will contain icon and each autoconstraint icon
00347     QPixmap baseIcon = actCursor.pixmap();
00348     QPixmap newIcon(baseIcon.width() + suggestedConstraints.size() * iconSize,
00349                     baseIcon.height());
00350     newIcon.fill(Qt::transparent);
00351 
00352     QPainter qp;
00353     qp.begin(&newIcon);
00354 
00355     qp.drawPixmap(0,0, baseIcon);
00356 
00357     // Iterate through AutoConstraints type and add icons to the cursor pixmap
00358     std::vector<AutoConstraint>::iterator it=suggestedConstraints.begin();
00359     int i = 0;
00360     for (; it != suggestedConstraints.end(); ++it, i++) {
00361         QString iconType;
00362         switch (it->Type)
00363         {
00364         case Horizontal:
00365             iconType = QString::fromAscii("Constraint_Horizontal");
00366             break;
00367         case Vertical:
00368             iconType = QString::fromAscii("Constraint_Vertical");
00369             break;
00370         case Coincident:
00371             iconType = QString::fromAscii("Constraint_PointOnPoint");
00372             break;
00373         case PointOnObject:
00374             iconType = QString::fromAscii("Constraint_PointOnObject");
00375             break;
00376         case Tangent:
00377             iconType = QString::fromAscii("Constraint_Tangent");
00378             break;
00379         }
00380 
00381         QPixmap icon = Gui::BitmapFactory().pixmap(iconType.toAscii()).scaledToWidth(iconSize);
00382         qp.drawPixmap(QPoint(baseIcon.width() + i * iconSize, baseIcon.height() - iconSize), icon);
00383     }
00384 
00385     qp.end(); // Finish painting
00386 
00387     // Create the new cursor with the icon.
00388     QPoint p=actCursor.hotSpot();
00389     QCursor newCursor(newIcon, p.x(), p.y());
00390     applyCursor(newCursor);
00391 }
00392 
00393 void DrawSketchHandler::setPositionText(const Base::Vector2D &Pos)
00394 {
00395     sketchgui->setPositionText(Pos);
00396 }
00397 
00398 void DrawSketchHandler::resetPositionText(void)
00399 {
00400     sketchgui->resetPositionText();
00401 }

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