CommandCreateGeo.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 #ifndef _PreComp_
00026 #endif
00027 
00028 #include <Base/Console.h>
00029 
00030 #include <Gui/Application.h>
00031 #include <Gui/Document.h>
00032 #include <Gui/Command.h>
00033 #include <Gui/MainWindow.h>
00034 #include <Gui/DlgEditFileIncludeProptertyExternal.h>
00035 #include <Gui/Selection.h>
00036 #include <Gui/SelectionFilter.h>
00037 #include <Mod/Sketcher/App/SketchObject.h>
00038 
00039 #include "ViewProviderSketch.h"
00040 #include "DrawSketchHandler.h"
00041 
00042 using namespace std;
00043 using namespace SketcherGui;
00044 
00045 /* helper functions ======================================================*/
00046 
00047 void ActivateHandler(Gui::Document *doc,DrawSketchHandler *handler)
00048 {
00049     if (doc) {
00050         if (doc->getInEdit() && doc->getInEdit()->isDerivedFrom
00051             (SketcherGui::ViewProviderSketch::getClassTypeId()))
00052             dynamic_cast<SketcherGui::ViewProviderSketch*>
00053             (doc->getInEdit())->activateHandler(handler);
00054     }
00055 }
00056 
00057 bool isCreateGeoActive(Gui::Document *doc)
00058 {
00059     if (doc) {
00060         // checks if a Sketch Viewprovider is in Edit and is in no special mode
00061         if (doc->getInEdit() && doc->getInEdit()->isDerivedFrom
00062             (SketcherGui::ViewProviderSketch::getClassTypeId())) {
00063             if (dynamic_cast<SketcherGui::ViewProviderSketch*>(doc->getInEdit())->
00064                 getSketchMode() == ViewProviderSketch::STATUS_NONE)
00065                 return true;
00066         }
00067     }
00068     return false;
00069 }
00070 
00071 SketcherGui::ViewProviderSketch* getSketchViewprovider(Gui::Document *doc)
00072 {
00073     if (doc) {
00074         if (doc->getInEdit() && doc->getInEdit()->isDerivedFrom
00075             (SketcherGui::ViewProviderSketch::getClassTypeId()) )
00076             return dynamic_cast<SketcherGui::ViewProviderSketch*>(doc->getInEdit());
00077     }
00078     return 0;
00079 }
00080 
00081 /* Sketch commands =======================================================*/
00082 
00083 /* XPM */
00084 static const char *cursor_createline[]={
00085 "32 32 3 1",
00086 "+ c white",
00087 "# c red",
00088 ". c None",
00089 "......+.........................",
00090 "......+.........................",
00091 "......+.........................",
00092 "......+.........................",
00093 "......+.........................",
00094 "................................",
00095 "+++++...+++++...................",
00096 "................................",
00097 "......+...............###.......",
00098 "......+...............#.#.......",
00099 "......+...............###.......",
00100 "......+..............#..........",
00101 "......+.............#...........",
00102 "....................#...........",
00103 "...................#............",
00104 "..................#.............",
00105 "..................#.............",
00106 ".................#..............",
00107 "................#...............",
00108 "................#...............",
00109 "...............#................",
00110 "..............#.................",
00111 "..............#.................",
00112 ".............#..................",
00113 "..........###...................",
00114 "..........#.#...................",
00115 "..........###...................",
00116 "................................",
00117 "................................",
00118 "................................",
00119 "................................",
00120 "................................"};
00121 
00122 class DrawSketchHandlerLine: public DrawSketchHandler
00123 {
00124 public:
00125     DrawSketchHandlerLine():Mode(STATUS_SEEK_First),EditCurve(2){}
00126     virtual ~DrawSketchHandlerLine(){}
00128     enum SelectMode {
00129         STATUS_SEEK_First,      
00130         STATUS_SEEK_Second,     
00131         STATUS_End
00132     };
00133 
00134     virtual void activated(ViewProviderSketch *sketchgui)
00135     {
00136         setCursor(QPixmap(cursor_createline),7,7);
00137     }
00138 
00139     virtual void mouseMove(Base::Vector2D onSketchPos)
00140     {
00141         setPositionText(onSketchPos);
00142 
00143         if (Mode==STATUS_SEEK_First) {
00144             if (seekAutoConstraint(sugConstr1, onSketchPos, Base::Vector2D(0.f,0.f))) {
00145                 renderSuggestConstraintsCursor(sugConstr1);
00146                 return;
00147             }
00148         }
00149         else if (Mode==STATUS_SEEK_Second){
00150             EditCurve[1] = onSketchPos;
00151             sketchgui->drawEdit(EditCurve);
00152             if (seekAutoConstraint(sugConstr2, onSketchPos, onSketchPos - EditCurve[0])) {
00153                 renderSuggestConstraintsCursor(sugConstr2);
00154                 return;
00155             }
00156         }
00157         applyCursor();
00158     }
00159 
00160     virtual bool pressButton(Base::Vector2D onSketchPos)
00161     {
00162         if (Mode==STATUS_SEEK_First){
00163             EditCurve[0] = onSketchPos;
00164             Mode = STATUS_SEEK_Second;
00165         }
00166         else {
00167             EditCurve[1] = onSketchPos;
00168             sketchgui->drawEdit(EditCurve);
00169             Mode = STATUS_End;
00170         }
00171         return true;
00172     }
00173 
00174     virtual bool releaseButton(Base::Vector2D onSketchPos)
00175     {
00176         if (Mode==STATUS_End){
00177             unsetCursor();
00178             resetPositionText();
00179 
00180             Gui::Command::openCommand("Add sketch line");
00181             Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addGeometry(Part.Line(App.Vector(%f,%f,0),App.Vector(%f,%f,0)))",
00182                       sketchgui->getObject()->getNameInDocument(),
00183                       EditCurve[0].fX,EditCurve[0].fY,EditCurve[1].fX,EditCurve[1].fY);
00184             Gui::Command::commitCommand();
00185             Gui::Command::updateActive();
00186 
00187             // add auto constraints for the line segment start
00188             if (sugConstr1.size() > 0) {
00189                 createAutoConstraints(sugConstr1, getHighestCurveIndex(), Sketcher::start);
00190                 sugConstr1.clear();
00191             }
00192 
00193             // add auto constraints for the line segment end
00194             if (sugConstr2.size() > 0) {
00195                 createAutoConstraints(sugConstr2, getHighestCurveIndex(), Sketcher::end);
00196                 sugConstr2.clear();
00197             }
00198 
00199             EditCurve.clear();
00200             sketchgui->drawEdit(EditCurve);
00201             sketchgui->purgeHandler(); // no code after this line, Handler get deleted in ViewProvider
00202         }
00203         return true;
00204     }
00205 protected:
00206     SelectMode Mode;
00207     std::vector<Base::Vector2D> EditCurve;
00208     std::vector<AutoConstraint> sugConstr1, sugConstr2;
00209 };
00210 
00211 
00212 
00213 DEF_STD_CMD_A(CmdSketcherCreateLine);
00214 
00215 CmdSketcherCreateLine::CmdSketcherCreateLine()
00216   : Command("Sketcher_CreateLine")
00217 {
00218     sAppModule      = "Sketcher";
00219     sGroup          = QT_TR_NOOP("Sketcher");
00220     sMenuText       = QT_TR_NOOP("Create line");
00221     sToolTipText    = QT_TR_NOOP("Create a line in the sketch");
00222     sWhatsThis      = sToolTipText;
00223     sStatusTip      = sToolTipText;
00224     sPixmap         = "Sketcher_CreateLine";
00225     sAccel          = "L";
00226     eType           = ForEdit;
00227 }
00228 
00229 void CmdSketcherCreateLine::activated(int iMsg)
00230 {
00231     ActivateHandler(getActiveGuiDocument(),new DrawSketchHandlerLine() );
00232 }
00233 
00234 bool CmdSketcherCreateLine::isActive(void)
00235 {
00236     return isCreateGeoActive(getActiveGuiDocument());
00237 }
00238 
00239 
00240 /* Create Box =======================================================*/
00241 
00242 /* XPM */
00243 static const char *cursor_createbox[]={
00244 "32 32 3 1",
00245 "+ c white",
00246 "# c red",
00247 ". c None",
00248 "......+.........................",
00249 "......+.........................",
00250 "......+.........................",
00251 "......+.........................",
00252 "......+.........................",
00253 "................................",
00254 "+++++...+++++...................",
00255 "................................",
00256 "......+.........................",
00257 "......+.........................",
00258 "......+.........................",
00259 "......+.........................",
00260 "......+.........................",
00261 "................................",
00262 "................................",
00263 "..........................###...",
00264 "...........################.#...",
00265 "...........#..............###...",
00266 "...........#...............#....",
00267 "...........#...............#....",
00268 "...........#...............#....",
00269 "...........#...............#....",
00270 "...........#...............#....",
00271 "...........#...............#....",
00272 "..........###..............#....",
00273 "..........#.################....",
00274 "..........###...................",
00275 "................................",
00276 "................................",
00277 "................................",
00278 "................................",
00279 "................................"};
00280 
00281 class DrawSketchHandlerBox: public DrawSketchHandler
00282 {
00283 public:
00284     DrawSketchHandlerBox():Mode(STATUS_SEEK_First),EditCurve(5){}
00285     virtual ~DrawSketchHandlerBox(){}
00287     enum BoxMode {
00288         STATUS_SEEK_First,      
00289         STATUS_SEEK_Second,     
00290         STATUS_End
00291     };
00292 
00293     virtual void activated(ViewProviderSketch *sketchgui)
00294     {
00295         setCursor(QPixmap(cursor_createbox),7,7);
00296     }
00297 
00298     virtual void mouseMove(Base::Vector2D onSketchPos)
00299     {
00300         setPositionText(onSketchPos);
00301 
00302         if (Mode==STATUS_SEEK_First) {
00303             if (seekAutoConstraint(sugConstr1, onSketchPos, Base::Vector2D(0.f,0.f))) {
00304                 renderSuggestConstraintsCursor(sugConstr1);
00305                 return;
00306             }
00307         }
00308         else if (Mode==STATUS_SEEK_Second) {
00309             EditCurve[2] = onSketchPos;
00310             EditCurve[1] = Base::Vector2D(onSketchPos.fX ,EditCurve[0].fY);
00311             EditCurve[3] = Base::Vector2D(EditCurve[0].fX,onSketchPos.fY);
00312             sketchgui->drawEdit(EditCurve);
00313             if (seekAutoConstraint(sugConstr2, onSketchPos, Base::Vector2D(0.f,0.f))) {
00314                 renderSuggestConstraintsCursor(sugConstr2);
00315                 return;
00316             }
00317         }
00318         applyCursor();
00319     }
00320 
00321     virtual bool pressButton(Base::Vector2D onSketchPos)
00322     {
00323         if (Mode==STATUS_SEEK_First){
00324             EditCurve[0] = onSketchPos;
00325             EditCurve[4] = onSketchPos;
00326             Mode = STATUS_SEEK_Second;
00327         }
00328         else {
00329             EditCurve[2] = onSketchPos;
00330             EditCurve[1] = Base::Vector2D(onSketchPos.fX ,EditCurve[0].fY);
00331             EditCurve[3] = Base::Vector2D(EditCurve[0].fX,onSketchPos.fY);
00332             sketchgui->drawEdit(EditCurve);
00333             Mode = STATUS_End;
00334         }
00335         return true;
00336     }
00337 
00338     virtual bool releaseButton(Base::Vector2D onSketchPos)
00339     {
00340         if (Mode==STATUS_End){
00341             unsetCursor();
00342             resetPositionText();
00343             Gui::Command::openCommand("Add sketch box");
00344             int firstCurve = getHighestCurveIndex() + 1;
00345             // add the four line geos
00346             Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addGeometry(Part.Line(App.Vector(%f,%f,0),App.Vector(%f,%f,0)))",
00347                       sketchgui->getObject()->getNameInDocument(),
00348                       EditCurve[0].fX,EditCurve[0].fY,EditCurve[1].fX,EditCurve[1].fY);
00349             Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addGeometry(Part.Line(App.Vector(%f,%f,0),App.Vector(%f,%f,0)))",
00350                       sketchgui->getObject()->getNameInDocument(),
00351                       EditCurve[1].fX,EditCurve[1].fY,EditCurve[2].fX,EditCurve[2].fY);
00352             Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addGeometry(Part.Line(App.Vector(%f,%f,0),App.Vector(%f,%f,0)))",
00353                       sketchgui->getObject()->getNameInDocument(),
00354                       EditCurve[2].fX,EditCurve[2].fY,EditCurve[3].fX,EditCurve[3].fY);
00355             Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addGeometry(Part.Line(App.Vector(%f,%f,0),App.Vector(%f,%f,0)))",
00356                       sketchgui->getObject()->getNameInDocument(),
00357                       EditCurve[3].fX,EditCurve[3].fY,EditCurve[0].fX,EditCurve[0].fY);
00358             // add the four coincidents to ty them together
00359             Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Coincident',%i,2,%i,1)) "
00360                      ,sketchgui->getObject()->getNameInDocument()
00361                      ,firstCurve,firstCurve+1);
00362             Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Coincident',%i,2,%i,1)) "
00363                      ,sketchgui->getObject()->getNameInDocument()
00364                      ,firstCurve+1,firstCurve+2);
00365             Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Coincident',%i,2,%i,1)) "
00366                      ,sketchgui->getObject()->getNameInDocument()
00367                      ,firstCurve+2,firstCurve+3);
00368             Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Coincident',%i,2,%i,1)) "
00369                      ,sketchgui->getObject()->getNameInDocument()
00370                      ,firstCurve+3,firstCurve);
00371             // add the horizontal constraints
00372             Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Horizontal',%i)) "
00373                      ,sketchgui->getObject()->getNameInDocument()
00374                      ,firstCurve);
00375             Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Horizontal',%i)) "
00376                      ,sketchgui->getObject()->getNameInDocument()
00377                      ,firstCurve+2);
00378             // add the vertical constraints
00379             Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Vertical',%i)) "
00380                      ,sketchgui->getObject()->getNameInDocument()
00381                      ,firstCurve+1);
00382             Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Vertical',%i)) "
00383                      ,sketchgui->getObject()->getNameInDocument()
00384                      ,firstCurve+3);
00385 
00386             Gui::Command::commitCommand();
00387             Gui::Command::updateActive();
00388 
00389             // add auto constraints at the start of the first side
00390             if (sugConstr1.size() > 0) {
00391                 createAutoConstraints(sugConstr1, getHighestCurveIndex() - 3 , Sketcher::start);
00392                 sugConstr1.clear();
00393             }
00394 
00395             // add auto constraints at the end of the second side
00396             if (sugConstr2.size() > 0) {
00397                 createAutoConstraints(sugConstr2, getHighestCurveIndex() - 2, Sketcher::end);
00398                 sugConstr2.clear();
00399             }
00400 
00401             EditCurve.clear();
00402             sketchgui->drawEdit(EditCurve);
00403             sketchgui->purgeHandler(); // no code after this line, Handler get deleted in ViewProvider
00404         }
00405         return true;
00406     }
00407 protected:
00408     BoxMode Mode;
00409     std::vector<Base::Vector2D> EditCurve;
00410     std::vector<AutoConstraint> sugConstr1, sugConstr2;
00411 };
00412 
00413 
00414 
00415 DEF_STD_CMD_A(CmdSketcherCreateRectangle);
00416 
00417 CmdSketcherCreateRectangle::CmdSketcherCreateRectangle()
00418   : Command("Sketcher_CreateRectangle")
00419 {
00420     sAppModule      = "Sketcher";
00421     sGroup          = QT_TR_NOOP("Sketcher");
00422     sMenuText       = QT_TR_NOOP("Create rectangle");
00423     sToolTipText    = QT_TR_NOOP("Create a rectangle in the sketch");
00424     sWhatsThis      = sToolTipText;
00425     sStatusTip      = sToolTipText;
00426     sPixmap         = "Sketcher_CreateRectangle";
00427     sAccel          = "R";
00428     eType           = ForEdit;
00429 }
00430 
00431 void CmdSketcherCreateRectangle::activated(int iMsg)
00432 {
00433     ActivateHandler(getActiveGuiDocument(),new DrawSketchHandlerBox() );
00434 }
00435 
00436 bool CmdSketcherCreateRectangle::isActive(void)
00437 {
00438     return isCreateGeoActive(getActiveGuiDocument());
00439 }
00440 
00441 
00442 // ======================================================================================
00443 
00444 /* XPM */
00445 static const char *cursor_createlineset[]={
00446 "32 32 3 1",
00447 "+ c white",
00448 "# c red",
00449 ". c None",
00450 "......+.........................",
00451 "......+.........................",
00452 "......+.........................",
00453 "......+.........................",
00454 "......+.........................",
00455 "................................",
00456 "+++++...+++++...................",
00457 "................................",
00458 "......+...............###.......",
00459 "......+...............#.#.......",
00460 "......+...............###.......",
00461 "......+..............#..#.......",
00462 "......+.............#....#......",
00463 "....................#....#......",
00464 "...................#......#.....",
00465 "..................#.......#.....",
00466 "..................#........#....",
00467 ".................#.........#....",
00468 "................#..........###..",
00469 "................#..........#.#..",
00470 "......#........#...........###..",
00471 ".......#......#.................",
00472 "........#.....#.................",
00473 ".........#...#..................",
00474 "..........###...................",
00475 "..........#.#...................",
00476 "..........###...................",
00477 "................................",
00478 "................................",
00479 "................................",
00480 "................................",
00481 "................................"};
00482 
00483 class DrawSketchHandlerLineSet: public DrawSketchHandler
00484 {
00485 public:
00486     DrawSketchHandlerLineSet()
00487       : Mode(STATUS_SEEK_First),EditCurve(2),firstPoint(-1),previousCurve(-1){}
00488     virtual ~DrawSketchHandlerLineSet(){}
00490     enum SelectMode {
00491         STATUS_SEEK_First,      
00492         STATUS_SEEK_Second,     
00493         STATUS_Do,
00494         STATUS_Close
00495     };
00496 
00497     virtual void activated(ViewProviderSketch *sketchgui)
00498     {
00499         setCursor(QPixmap(cursor_createlineset),7,7);
00500     }
00501 
00502     virtual void mouseMove(Base::Vector2D onSketchPos)
00503     {
00504         setPositionText(onSketchPos);
00505         if (Mode==STATUS_SEEK_First) {
00506             if (seekAutoConstraint(sugConstr1, onSketchPos, Base::Vector2D(0.f,0.f))) {
00507                 renderSuggestConstraintsCursor(sugConstr1);
00508                 return;
00509             }
00510         }
00511         else if (Mode==STATUS_SEEK_Second){
00512             EditCurve[1] = onSketchPos;
00513             sketchgui->drawEdit(EditCurve);
00514             if (seekAutoConstraint(sugConstr2, onSketchPos, onSketchPos - EditCurve[0])) {
00515                 renderSuggestConstraintsCursor(sugConstr2);
00516                 return;
00517             }
00518         }
00519         applyCursor();
00520     }
00521 
00522     virtual bool pressButton(Base::Vector2D onSketchPos)
00523     {
00524         if (Mode==STATUS_SEEK_First) {
00525             // remember our first point
00526             firstPoint = getHighestVertexIndex() + 1;
00527             firstCurve = getHighestCurveIndex() + 1;
00528             EditCurve[0] = onSketchPos;
00529             Mode = STATUS_SEEK_Second;
00530         }
00531         else if (Mode==STATUS_SEEK_Second) {
00532             EditCurve[1] = onSketchPos;
00533             sketchgui->drawEdit(EditCurve);
00534             applyCursor();
00535             // exit on clicking exactly at the same position (e.g. double click)
00536             if (EditCurve[1] == EditCurve[0]) {
00537                 unsetCursor();
00538                 EditCurve.clear();
00539                 resetPositionText();
00540                 sketchgui->drawEdit(EditCurve);
00541                 sketchgui->purgeHandler(); // no code after this line, Handler get deleted in ViewProvider
00542             }
00543             if (sketchgui->getPreselectPoint() == firstPoint)
00544                 Mode = STATUS_Close;
00545             else
00546                 Mode = STATUS_Do;
00547         }
00548         return true;
00549     }
00550 
00551     virtual bool releaseButton(Base::Vector2D onSketchPos)
00552     {
00553         if (Mode==STATUS_Do || Mode==STATUS_Close) {
00554             // open the transaction
00555             Gui::Command::openCommand("add sketch wire");
00556             // issue the geometry
00557             Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addGeometry(Part.Line(App.Vector(%f,%f,0),App.Vector(%f,%f,0)))",
00558                       sketchgui->getObject()->getNameInDocument(),
00559                       EditCurve[0].fX,EditCurve[0].fY,EditCurve[1].fX,EditCurve[1].fY);
00560 
00561             // issue the constraint
00562             if (previousCurve != -1) {
00563                 Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Coincident',%i,2,%i,1)) "
00564                           ,sketchgui->getObject()->getNameInDocument()
00565                           ,previousCurve-1,previousCurve
00566                           );
00567             }
00568 
00569             if (Mode==STATUS_Close) {
00570                 // close the loop by constrain to the first curve point
00571                 Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Coincident',%i,2,%i,1)) "
00572                           ,sketchgui->getObject()->getNameInDocument()
00573                           ,previousCurve,firstCurve
00574                           );
00575 
00576                 Gui::Command::commitCommand();
00577                 Gui::Command::updateActive();
00578 
00579                 if (sugConstr2.size() > 0) {
00580                     // exclude any coincidence constraints
00581                     std::vector<AutoConstraint> sugConstr;
00582                     for (int i=0; i < sugConstr2.size(); i++) {
00583                         if (sugConstr2[i].Type != Sketcher::Coincident)
00584                             sugConstr.push_back(sugConstr2[i]);
00585                     }
00586                     createAutoConstraints(sugConstr, getHighestCurveIndex(), Sketcher::end);
00587                     sugConstr2.clear();
00588                 }
00589 
00590                 unsetCursor();
00591                 EditCurve.clear();
00592                 resetPositionText();
00593                 sketchgui->drawEdit(EditCurve);
00594                 sketchgui->purgeHandler(); // no code after this line, Handler get deleted in ViewProvider
00595             }
00596             else {
00597                 Gui::Command::commitCommand();
00598                 Gui::Command::updateActive();
00599 
00600                 // Add auto constraints
00601                 if (sugConstr1.size() > 0) {
00602                     createAutoConstraints(sugConstr1, getHighestCurveIndex(), Sketcher::start);
00603                     sugConstr1.clear();
00604                 }
00605 
00606                 if (sugConstr2.size() > 0) {
00607                     createAutoConstraints(sugConstr2, getHighestCurveIndex(), Sketcher::end);
00608                     sugConstr2.clear();
00609                 }
00610 
00611                 //remember the vertex for the next rounds constraint...
00612                 previousCurve = getHighestCurveIndex() + 1;
00613 
00614                 // setup for the next line segment
00615                 // Use updated endPoint as autoconstraints can modify the position
00616                 Part::Geometry *geom = getObject()->Geometry.getValues()[getHighestCurveIndex()];
00617                 if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
00618                     const Part::GeomLineSegment *lineSeg = dynamic_cast<const Part::GeomLineSegment *>(geom);
00619                     EditCurve[0] = Base::Vector2D(lineSeg->getEndPoint().x, lineSeg->getEndPoint().y);
00620                 }
00621                 else
00622                     EditCurve[0] = onSketchPos;
00623 
00624                 sketchgui->drawEdit(EditCurve);
00625                 applyCursor();
00626 
00627                 Mode = STATUS_SEEK_Second;
00628             }
00629         }
00630         return true;
00631     }
00632 protected:
00633     SelectMode Mode;
00634     std::vector<Base::Vector2D> EditCurve;
00635     Base::Vector2D lastPos;
00636     int firstPoint;
00637     int firstCurve;
00638     int previousCurve;
00639     std::vector<AutoConstraint> sugConstr1, sugConstr2;
00640 };
00641 
00642 
00643 DEF_STD_CMD_A(CmdSketcherCreatePolyline);
00644 
00645 CmdSketcherCreatePolyline::CmdSketcherCreatePolyline()
00646   : Command("Sketcher_CreatePolyline")
00647 {
00648     sAppModule      = "Sketcher";
00649     sGroup          = QT_TR_NOOP("Sketcher");
00650     sMenuText       = QT_TR_NOOP("Create polyline");
00651     sToolTipText    = QT_TR_NOOP("Create a polyline in the sketch");
00652     sWhatsThis      = sToolTipText;
00653     sStatusTip      = sToolTipText;
00654     sPixmap         = "Sketcher_CreatePolyline";
00655     eType           = ForEdit;
00656 }
00657 
00658 void CmdSketcherCreatePolyline::activated(int iMsg)
00659 {
00660     ActivateHandler(getActiveGuiDocument(),new DrawSketchHandlerLineSet() );
00661 }
00662 
00663 bool CmdSketcherCreatePolyline::isActive(void)
00664 {
00665     return isCreateGeoActive(getActiveGuiDocument());
00666 }
00667 
00668 // ======================================================================================
00669 
00670 /* XPM */
00671 static const char *cursor_createarc[]={
00672 "32 32 3 1",
00673 "+ c white",
00674 "# c red",
00675 ". c None",
00676 "......+...........###...........",
00677 "......+...........#.#...........",
00678 "......+...........###...........",
00679 "......+..............##.........",
00680 "......+...............##........",
00681 ".......................#........",
00682 "+++++...+++++...........#.......",
00683 "........................##......",
00684 "......+..................#......",
00685 "......+..................#......",
00686 "......+...................#.....",
00687 "......+...................#.....",
00688 "......+...................#.....",
00689 "..........................#.....",
00690 "..........................#.....",
00691 "..........................#.....",
00692 "..........................#.....",
00693 ".........................#......",
00694 ".........................#......",
00695 "........................#.......",
00696 "........................#.......",
00697 "...###.................#........",
00698 "...#.#................#.........",
00699 "...###...............#..........",
00700 "......##...........##...........",
00701 ".......###.......##.............",
00702 "..........#######...............",
00703 "................................",
00704 "................................",
00705 "................................",
00706 "................................",
00707 "................................"};
00708 
00709 class DrawSketchHandlerArc : public DrawSketchHandler
00710 {
00711 public:
00712     DrawSketchHandlerArc()
00713       : Mode(STATUS_SEEK_First),EditCurve(2){}
00714     virtual ~DrawSketchHandlerArc(){}
00716     enum SelectMode {
00717         STATUS_SEEK_First,      
00718         STATUS_SEEK_Second,     
00719         STATUS_SEEK_Third,      
00720         STATUS_End
00721     };
00722 
00723     virtual void activated(ViewProviderSketch *sketchgui)
00724     {
00725         setCursor(QPixmap(cursor_createarc),7,7);
00726     }
00727 
00728     virtual void mouseMove(Base::Vector2D onSketchPos)
00729     {
00730         setPositionText(onSketchPos);
00731 
00732         if (Mode==STATUS_SEEK_First) {
00733             if (seekAutoConstraint(sugConstr1, onSketchPos, Base::Vector2D(0.f,0.f))) {
00734                 renderSuggestConstraintsCursor(sugConstr1);
00735                 return;
00736             }
00737         }
00738         else if (Mode==STATUS_SEEK_Second) {
00739             float dx_ = onSketchPos.fX - EditCurve[0].fX;
00740             float dy_ = onSketchPos.fY - EditCurve[0].fY;
00741             for (int i=0; i < 16; i++) {
00742                 float angle = i*M_PI/16.0;
00743                 float dx = dx_ * cos(angle) + dy_ * sin(angle);
00744                 float dy = -dx_ * sin(angle) + dy_ * cos(angle);
00745                 EditCurve[1+i] = Base::Vector2D(EditCurve[0].fX + dx, EditCurve[0].fY + dy);
00746                 EditCurve[17+i] = Base::Vector2D(EditCurve[0].fX - dx, EditCurve[0].fY - dy);
00747             }
00748             EditCurve[33] = EditCurve[1];
00749             sketchgui->drawEdit(EditCurve);
00750             if (seekAutoConstraint(sugConstr2, onSketchPos, Base::Vector2D(0.f,0.f))) {
00751                 renderSuggestConstraintsCursor(sugConstr2);
00752                 return;
00753             }
00754         }
00755         else if (Mode==STATUS_SEEK_Third) {
00756             float angle1 = atan2(onSketchPos.fY - CenterPoint.fY,
00757                                  onSketchPos.fX - CenterPoint.fX) - startAngle;
00758             float angle2 = angle1 + (angle1 < 0. ? 2 : -2) * M_PI ;
00759             arcAngle = abs(angle1-arcAngle) < abs(angle2-arcAngle) ? angle1 : angle2;
00760             for (int i=1; i <= 29; i++) {
00761                 float angle = i*arcAngle/29.0;
00762                 float dx = rx * cos(angle) - ry * sin(angle);
00763                 float dy = rx * sin(angle) + ry * cos(angle);
00764                 EditCurve[i] = Base::Vector2D(CenterPoint.fX + dx, CenterPoint.fY + dy);
00765             }
00766             sketchgui->drawEdit(EditCurve);
00767             if (seekAutoConstraint(sugConstr3, onSketchPos, Base::Vector2D(0.f,0.f))) {
00768                 renderSuggestConstraintsCursor(sugConstr3);
00769                 return;
00770             }
00771         }
00772         applyCursor();
00773 
00774     }
00775 
00776     virtual bool pressButton(Base::Vector2D onSketchPos)
00777     {
00778         if (Mode==STATUS_SEEK_First){
00779             CenterPoint = onSketchPos;
00780             EditCurve.resize(34);
00781             EditCurve[0] = onSketchPos;
00782             Mode = STATUS_SEEK_Second;
00783         }
00784         else if (Mode==STATUS_SEEK_Second){
00785             EditCurve.resize(31);
00786             EditCurve[0] = onSketchPos;
00787             EditCurve[30] = CenterPoint;
00788             rx = EditCurve[0].fX - CenterPoint.fX;
00789             ry = EditCurve[0].fY - CenterPoint.fY;
00790             startAngle = atan2(ry, rx);
00791             arcAngle = 0.;
00792             Mode = STATUS_SEEK_Third;
00793         }
00794         else {
00795             EditCurve.resize(30);
00796             float angle1 = atan2(onSketchPos.fY - CenterPoint.fY,
00797                                  onSketchPos.fX - CenterPoint.fX) - startAngle;
00798             float angle2 = angle1 + (angle1 < 0. ? 2 : -2) * M_PI ;
00799             arcAngle = abs(angle1-arcAngle) < abs(angle2-arcAngle) ? angle1 : angle2;
00800             if (arcAngle > 0)
00801                 endAngle = startAngle + arcAngle;
00802             else {
00803                 endAngle = startAngle;
00804                 startAngle += arcAngle;
00805             }
00806 
00807             sketchgui->drawEdit(EditCurve);
00808             applyCursor();
00809             Mode = STATUS_End;
00810         }
00811 
00812         return true;
00813     }
00814 
00815     virtual bool releaseButton(Base::Vector2D onSketchPos)
00816     {
00817         if (Mode==STATUS_End) {
00818             unsetCursor();
00819             resetPositionText();
00820             Gui::Command::openCommand("Add sketch arc");
00821             Gui::Command::doCommand(Gui::Command::Doc,
00822                 "App.ActiveDocument.%s.addGeometry(Part.ArcOfCircle"
00823                 "(Part.Circle(App.Vector(%f,%f,0),App.Vector(0,0,1),%f),"
00824                 "%f,%f))",
00825                       sketchgui->getObject()->getNameInDocument(),
00826                       CenterPoint.fX, CenterPoint.fY, sqrt(rx*rx + ry*ry),
00827                       startAngle, endAngle); //arcAngle > 0 ? 0 : 1);
00828 
00829             Gui::Command::commitCommand();
00830             Gui::Command::updateActive();
00831 
00832             // Auto Constraint center point
00833             if (sugConstr1.size() > 0) {
00834                 createAutoConstraints(sugConstr1, getHighestCurveIndex(), Sketcher::mid);
00835                 sugConstr1.clear();
00836             }
00837 
00838             // Auto Constraint first picked point
00839             if (sugConstr2.size() > 0) {
00840                 createAutoConstraints(sugConstr2, getHighestCurveIndex(), (arcAngle > 0) ? Sketcher::start : Sketcher::end );
00841                 sugConstr2.clear();
00842             }
00843 
00844             // Auto Constraint second picked point
00845             if (sugConstr3.size() > 0) {
00846                 createAutoConstraints(sugConstr3, getHighestCurveIndex(), (arcAngle > 0) ? Sketcher::end : Sketcher::start);
00847                 sugConstr3.clear();
00848             }
00849 
00850             EditCurve.clear();
00851             sketchgui->drawEdit(EditCurve);
00852             sketchgui->purgeHandler(); // no code after this line, Handler get deleted in ViewProvider
00853         }
00854         return true;
00855     }
00856 protected:
00857     SelectMode Mode;
00858     std::vector<Base::Vector2D> EditCurve;
00859     Base::Vector2D CenterPoint;
00860     float rx, ry, startAngle, endAngle, arcAngle;
00861     std::vector<AutoConstraint> sugConstr1, sugConstr2, sugConstr3;
00862 };
00863 
00864 DEF_STD_CMD_A(CmdSketcherCreateArc);
00865 
00866 CmdSketcherCreateArc::CmdSketcherCreateArc()
00867   : Command("Sketcher_CreateArc")
00868 {
00869     sAppModule      = "Sketcher";
00870     sGroup          = QT_TR_NOOP("Sketcher");
00871     sMenuText       = QT_TR_NOOP("Create arc");
00872     sToolTipText    = QT_TR_NOOP("Create an arc in the sketch");
00873     sWhatsThis      = sToolTipText;
00874     sStatusTip      = sToolTipText;
00875     sPixmap         = "Sketcher_CreateArc";
00876     eType           = ForEdit;
00877 }
00878 
00879 void CmdSketcherCreateArc::activated(int iMsg)
00880 {
00881     ActivateHandler(getActiveGuiDocument(),new DrawSketchHandlerArc() );
00882 }
00883 
00884 bool CmdSketcherCreateArc::isActive(void)
00885 {
00886     return isCreateGeoActive(getActiveGuiDocument());
00887 }
00888 
00889 // ======================================================================================
00890 
00891 /* XPM */
00892 static const char *cursor_createcircle[]={
00893 "32 32 3 1",
00894 "+ c white",
00895 "# c red",
00896 ". c None",
00897 "......+.........................",
00898 "......+.........................",
00899 "......+.........................",
00900 "......+.........................",
00901 "......+.........................",
00902 "................................",
00903 "+++++...+++++...................",
00904 "................................",
00905 "......+........#######..........",
00906 "......+......##.......##........",
00907 "......+.....#...........#.......",
00908 "......+....#.............#......",
00909 "......+...#...............#.....",
00910 ".........#.................#....",
00911 "........#...................#...",
00912 "........#...................#...",
00913 ".......#.....................#..",
00914 ".......#.....................#..",
00915 ".......#.........###.........#..",
00916 ".......#.........#.#.........#..",
00917 ".......#.........###.........#..",
00918 ".......#.....................#..",
00919 ".......#.....................#..",
00920 "........#...................#...",
00921 "........#...................#...",
00922 ".........#.................#....",
00923 "..........#...............#.....",
00924 "...........#.............#......",
00925 "............#...........#.......",
00926 ".............##.......##........",
00927 "...............#######..........",
00928 "................................"};
00929 
00930 class DrawSketchHandlerCircle : public DrawSketchHandler
00931 {
00932 public:
00933     DrawSketchHandlerCircle() : Mode(STATUS_SEEK_First),EditCurve(34){}
00934     virtual ~DrawSketchHandlerCircle(){}
00936     enum SelectMode {
00937         STATUS_SEEK_First,      
00938         STATUS_SEEK_Second,     
00939         STATUS_Close
00940     };
00941 
00942     virtual void activated(ViewProviderSketch *sketchgui)
00943     {
00944         setCursor(QPixmap(cursor_createcircle),7,7);
00945     }
00946 
00947     virtual void mouseMove(Base::Vector2D onSketchPos)
00948     {
00949         setPositionText(onSketchPos);
00950         if (Mode==STATUS_SEEK_First) {
00951             if (seekAutoConstraint(sugConstr1, onSketchPos, Base::Vector2D(0.f,0.f))) {
00952                 renderSuggestConstraintsCursor(sugConstr1);
00953                 return;
00954             }
00955         }
00956         else if (Mode==STATUS_SEEK_Second) {
00957             float rx0 = onSketchPos.fX - EditCurve[0].fX;
00958             float ry0 = onSketchPos.fY - EditCurve[0].fY;
00959             for (int i=0; i < 16; i++) {
00960                 float angle = i*M_PI/16.0;
00961                 float rx = rx0 * cos(angle) + ry0 * sin(angle);
00962                 float ry = -rx0 * sin(angle) + ry0 * cos(angle);
00963                 EditCurve[1+i] = Base::Vector2D(EditCurve[0].fX + rx, EditCurve[0].fY + ry);
00964                 EditCurve[17+i] = Base::Vector2D(EditCurve[0].fX - rx, EditCurve[0].fY - ry);
00965             }
00966             EditCurve[33] = EditCurve[1];
00967             sketchgui->drawEdit(EditCurve);
00968             if (seekAutoConstraint(sugConstr2, onSketchPos, Base::Vector2D(0.f,0.f), CURVE)) {
00969                 renderSuggestConstraintsCursor(sugConstr2);
00970                 return;
00971             }
00972         }
00973         applyCursor();
00974     }
00975 
00976     virtual bool pressButton(Base::Vector2D onSketchPos)
00977     {
00978         if (Mode==STATUS_SEEK_First){
00979             EditCurve[0] = onSketchPos;
00980             Mode = STATUS_SEEK_Second;
00981         } else {
00982             EditCurve[1] = onSketchPos;
00983             Mode = STATUS_Close;
00984         }
00985         return true;
00986     }
00987 
00988     virtual bool releaseButton(Base::Vector2D onSketchPos)
00989     {
00990         if (Mode==STATUS_Close) {
00991             float rx = EditCurve[1].fX - EditCurve[0].fX;
00992             float ry = EditCurve[1].fY - EditCurve[0].fY;
00993             unsetCursor();
00994             resetPositionText();
00995             Gui::Command::openCommand("Add sketch circle");
00996             Gui::Command::doCommand(Gui::Command::Doc,
00997                 "App.ActiveDocument.%s.addGeometry(Part.Circle"
00998                 "(App.Vector(%f,%f,0),App.Vector(0,0,1),%f))",
00999                       sketchgui->getObject()->getNameInDocument(),
01000                       EditCurve[0].fX, EditCurve[0].fY,
01001                       sqrt(rx*rx + ry*ry));
01002 
01003             Gui::Command::commitCommand();
01004             Gui::Command::updateActive();
01005 
01006             // add auto constraints for the center point
01007             if (sugConstr1.size() > 0) {
01008                 createAutoConstraints(sugConstr1, getHighestCurveIndex(), Sketcher::mid);
01009                 sugConstr1.clear();
01010             }
01011 
01012             // add suggested constraints for circumference
01013             if (sugConstr2.size() > 0) {
01014                 createAutoConstraints(sugConstr2, getHighestCurveIndex(), Sketcher::none);
01015                 sugConstr2.clear();
01016             }
01017 
01018             EditCurve.clear();
01019             sketchgui->drawEdit(EditCurve);
01020             sketchgui->purgeHandler(); // no code after this line, Handler get deleted in ViewProvider
01021         }
01022         return true;
01023     }
01024 protected:
01025     SelectMode Mode;
01026     std::vector<Base::Vector2D> EditCurve;
01027     std::vector<AutoConstraint> sugConstr1, sugConstr2;
01028 
01029 };
01030 
01031 DEF_STD_CMD_A(CmdSketcherCreateCircle);
01032 
01033 CmdSketcherCreateCircle::CmdSketcherCreateCircle()
01034   : Command("Sketcher_CreateCircle")
01035 {
01036     sAppModule      = "Sketcher";
01037     sGroup          = QT_TR_NOOP("Sketcher");
01038     sMenuText       = QT_TR_NOOP("Create circle");
01039     sToolTipText    = QT_TR_NOOP("Create a circle in the sketch");
01040     sWhatsThis      = sToolTipText;
01041     sStatusTip      = sToolTipText;
01042     sPixmap         = "Sketcher_CreateCircle";
01043     eType           = ForEdit;
01044 }
01045 
01046 void CmdSketcherCreateCircle::activated(int iMsg)
01047 {
01048     ActivateHandler(getActiveGuiDocument(),new DrawSketchHandlerCircle() );
01049 }
01050 
01051 bool CmdSketcherCreateCircle::isActive(void)
01052 {
01053     return isCreateGeoActive(getActiveGuiDocument());
01054 }
01055 
01056 // ======================================================================================
01057 
01058 DEF_STD_CMD_A(CmdSketcherCreatePoint);
01059 
01060 CmdSketcherCreatePoint::CmdSketcherCreatePoint()
01061   : Command("Sketcher_CreatePoint")
01062 {
01063     sAppModule      = "Sketcher";
01064     sGroup          = QT_TR_NOOP("Sketcher");
01065     sMenuText       = QT_TR_NOOP("Create point");
01066     sToolTipText    = QT_TR_NOOP("Create a point in the sketch");
01067     sWhatsThis      = sToolTipText;
01068     sStatusTip      = sToolTipText;
01069     sPixmap         = "Sketcher_CreatePoint";
01070     eType           = ForEdit;
01071 }
01072 
01073 void CmdSketcherCreatePoint::activated(int iMsg)
01074 {
01075 }
01076 
01077 bool CmdSketcherCreatePoint::isActive(void)
01078 {
01079     return false;
01080 }
01081 
01082 // ======================================================================================
01083 
01084 DEF_STD_CMD_A(CmdSketcherCreateText);
01085 
01086 CmdSketcherCreateText::CmdSketcherCreateText()
01087   : Command("Sketcher_CreateText")
01088 {
01089     sAppModule      = "Sketcher";
01090     sGroup          = QT_TR_NOOP("Sketcher");
01091     sMenuText       = QT_TR_NOOP("Create text");
01092     sToolTipText    = QT_TR_NOOP("Create text in the sketch");
01093     sWhatsThis      = sToolTipText;
01094     sStatusTip      = sToolTipText;
01095     sPixmap         = "Sketcher_CreateText";
01096     eType           = ForEdit;
01097 }
01098 
01099 void CmdSketcherCreateText::activated(int iMsg)
01100 {
01101 }
01102 
01103 bool CmdSketcherCreateText::isActive(void)
01104 {
01105     return false;
01106 }
01107 
01108 // ======================================================================================
01109 
01110 DEF_STD_CMD_A(CmdSketcherCreateDraftLine);
01111 
01112 CmdSketcherCreateDraftLine::CmdSketcherCreateDraftLine()
01113   : Command("Sketcher_CreateDraftLine")
01114 {
01115     sAppModule      = "Sketcher";
01116     sGroup          = QT_TR_NOOP("Sketcher");
01117     sMenuText       = QT_TR_NOOP("Create draft line");
01118     sToolTipText    = QT_TR_NOOP("Create a draft line in the sketch");
01119     sWhatsThis      = sToolTipText;
01120     sStatusTip      = sToolTipText;
01121     sPixmap         = "Sketcher_DraftLine";
01122     eType           = ForEdit;
01123 }
01124 
01125 void CmdSketcherCreateDraftLine::activated(int iMsg)
01126 {
01127 }
01128 
01129 bool CmdSketcherCreateDraftLine::isActive(void)
01130 {
01131     return false;
01132 }
01133 
01134 // ======================================================================================
01135 
01136 namespace SketcherGui {
01137     class FilletSelection : public Gui::SelectionFilterGate
01138     {
01139         App::DocumentObject* object;
01140     public:
01141         FilletSelection(App::DocumentObject* obj)
01142             : Gui::SelectionFilterGate((Gui::SelectionFilter*)0), object(obj)
01143         {}
01144 
01145         bool allow(App::Document *pDoc, App::DocumentObject *pObj, const char *sSubName)
01146         {
01147             if (pObj != this->object)
01148                 return false;
01149             if (!sSubName || sSubName[0] == '\0')
01150                 return false;
01151             std::string element(sSubName);
01152             if (element.substr(0,4) == "Edge") {
01153                 int index=std::atoi(element.substr(4,4000).c_str());
01154                 Sketcher::SketchObject *Sketch = static_cast<Sketcher::SketchObject*>(object);
01155                 const std::vector<Part::Geometry *> &geo = Sketch->Geometry.getValues();
01156                 const Part::Geometry *geom = geo[index];
01157                 if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId())
01158                     return true;
01159             }
01160             if (element.substr(0,6) == "Vertex") {
01161                 int index=std::atoi(element.substr(6,4000).c_str());
01162                 Sketcher::SketchObject *Sketch = static_cast<Sketcher::SketchObject*>(object);
01163                 std::vector<int> GeoIdList;
01164                 std::vector<Sketcher::PointPos> PosIdList;
01165                 Sketch->getCoincidentPoints(index, GeoIdList, PosIdList);
01166                 if (GeoIdList.size() == 2) {
01167                     const std::vector<Part::Geometry *> &geo = Sketch->Geometry.getValues();
01168                     const Part::Geometry *geom1 = geo[GeoIdList[0]];
01169                     const Part::Geometry *geom2 = geo[GeoIdList[1]];
01170                     if (geom1->getTypeId() == Part::GeomLineSegment::getClassTypeId() &&
01171                         geom2->getTypeId() == Part::GeomLineSegment::getClassTypeId())
01172                         return true;
01173                 }
01174             }
01175             return  false;
01176         }
01177     };
01178 };
01179 
01180 /* XPM */
01181 static const char *cursor_createfillet[]={
01182 "32 32 3 1",
01183 "+ c white",
01184 "* c red",
01185 ". c None",
01186 "......+.........................",
01187 "......+.........................",
01188 "......+.........................",
01189 "......+.........................",
01190 "......+.........................",
01191 "................................",
01192 "+++++...+++++...................",
01193 "................................",
01194 "......+.........................",
01195 "......+.........................",
01196 "......+.........................",
01197 "......+.........................",
01198 "......+..*......................",
01199 ".........*......................",
01200 ".........*......................",
01201 ".........*......................",
01202 ".........*......................",
01203 ".........*......................",
01204 ".........*.........***..........",
01205 ".........*.........*.*..........",
01206 ".........*.........***..........",
01207 ".........*......................",
01208 ".........*......................",
01209 "..........*.....................",
01210 "..........*.....................",
01211 "...........*....................",
01212 "............*...................",
01213 ".............*..................",
01214 "..............*.................",
01215 "...............**...............",
01216 ".................**************.",
01217 "................................"};
01218 
01219 class DrawSketchHandlerFillet: public DrawSketchHandler
01220 {
01221 public:
01222     DrawSketchHandlerFillet() : Mode(STATUS_SEEK_First) {}
01223     virtual ~DrawSketchHandlerFillet()
01224     {
01225         Gui::Selection().rmvSelectionGate();
01226     }
01227     enum SelectMode{
01228         STATUS_SEEK_First,
01229         STATUS_SEEK_Second
01230     };
01231 
01232     virtual void activated(ViewProviderSketch *sketchgui)
01233     {
01234         Gui::Selection().rmvSelectionGate();
01235         Gui::Selection().addSelectionGate(new FilletSelection(sketchgui->getObject()));
01236         setCursor(QPixmap(cursor_createfillet),7,7);
01237     }
01238 
01239     virtual void mouseMove(Base::Vector2D onSketchPos)
01240     {
01241     }
01242 
01243     virtual bool pressButton(Base::Vector2D onSketchPos)
01244     {
01245         return true;
01246     }
01247 
01248     virtual bool releaseButton(Base::Vector2D onSketchPos)
01249     {
01250         int VtId = sketchgui->getPreselectPoint();
01251         if (Mode == STATUS_SEEK_First && VtId != -1) {
01252             int GeoId;
01253             Sketcher::PointPos PosId=Sketcher::none;
01254             sketchgui->getSketchObject()->getGeoVertexIndex(VtId,GeoId,PosId);
01255             const std::vector<Part::Geometry *> &geo = sketchgui->getSketchObject()->Geometry.getValues();
01256             const Part::Geometry *geom = geo[GeoId];
01257             if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId() &&
01258                 (PosId == Sketcher::start || PosId == Sketcher::end)) {
01259 
01260                 // guess fillet radius
01261                 double radius=-1;
01262                 std::vector<int> GeoIdList;
01263                 std::vector<Sketcher::PointPos> PosIdList;
01264                 sketchgui->getSketchObject()->getCoincidentPoints(GeoId, PosId, GeoIdList, PosIdList);
01265                 if (GeoIdList.size() == 2) {
01266                     const Part::Geometry *geom1 = geo[GeoIdList[0]];
01267                     const Part::Geometry *geom2 = geo[GeoIdList[1]];
01268                     if (geom1->getTypeId() == Part::GeomLineSegment::getClassTypeId() &&
01269                         geom2->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
01270                         const Part::GeomLineSegment *lineSeg1 = dynamic_cast<const Part::GeomLineSegment *>(geom1);
01271                         const Part::GeomLineSegment *lineSeg2 = dynamic_cast<const Part::GeomLineSegment *>(geom2);
01272                                         Base::Vector3d dir1 = lineSeg1->getEndPoint() - lineSeg1->getStartPoint();
01273                                         Base::Vector3d dir2 = lineSeg2->getEndPoint() - lineSeg2->getStartPoint();
01274                         if (PosIdList[0] == Sketcher::end)
01275                             dir1 *= -1;
01276                         if (PosIdList[1] == Sketcher::end)
01277                             dir2 *= -1;
01278                         double l1 = dir1.Length();
01279                         double l2 = dir2.Length();
01280                         double angle = dir1.GetAngle(dir2);
01281                         radius = (l1 < l2 ? l1 : l2) * 0.2 * sin(angle/2);
01282                     }
01283                 }
01284                 if (radius < 0)
01285                     return false;
01286 
01287                 // create fillet at point
01288                 Gui::Command::openCommand("Create fillet");
01289                 Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.fillet(%d,%d,%f)",
01290                           sketchgui->getObject()->getNameInDocument(),
01291                           GeoId, PosId, radius);
01292                 Gui::Command::commitCommand();
01293                 Gui::Command::updateActive();
01294             }
01295             return true;
01296         }
01297 
01298         int GeoId = sketchgui->getPreselectCurve();
01299         if (GeoId > -1) {
01300             const std::vector<Part::Geometry *> &geo = sketchgui->getSketchObject()->Geometry.getValues();
01301             const Part::Geometry *geom = geo[GeoId];
01302             if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
01303                 if (Mode==STATUS_SEEK_First) {
01304                     firstCurve = GeoId;
01305                     firstPos = onSketchPos;
01306                     Mode = STATUS_SEEK_Second;
01307                     // add the line to the selection
01308                     std::stringstream ss;
01309                     ss << "Edge" << firstCurve;
01310                     Gui::Selection().addSelection(sketchgui->getSketchObject()->getDocument()->getName()
01311                                                  ,sketchgui->getSketchObject()->getNameInDocument()
01312                                                  ,ss.str().c_str()
01313                                                  ,onSketchPos.fX
01314                                                  ,onSketchPos.fY
01315                                                  ,0.f);
01316                 }
01317                 else if (Mode==STATUS_SEEK_Second) {
01318                     int secondCurve = GeoId;
01319                     Base::Vector2D secondPos = onSketchPos;
01320 
01321                     // guess fillet radius
01322                     const Part::GeomLineSegment *lineSeg1 = dynamic_cast<const Part::GeomLineSegment *>(geo[firstCurve]);
01323                     const Part::GeomLineSegment *lineSeg2 = dynamic_cast<const Part::GeomLineSegment *>(geo[secondCurve]);
01324                     Base::Vector3d refPnt1(firstPos.fX, firstPos.fY, 0.f);
01325                     Base::Vector3d refPnt2(secondPos.fX, secondPos.fY, 0.f);
01326                     double radius = Part::suggestFilletRadius(lineSeg1, lineSeg2, refPnt1, refPnt2);
01327                     if (radius < 0)
01328                         return false;
01329 
01330                     // create fillet between lines
01331                     Gui::Command::openCommand("Create fillet");
01332                     Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.fillet(%d,%d,App.Vector(%f,%f,0),App.Vector(%f,%f,0),%f)",
01333                               sketchgui->getObject()->getNameInDocument(),
01334                               firstCurve, secondCurve,
01335                               firstPos.fX, firstPos.fY,
01336                               secondPos.fX, secondPos.fY, radius);
01337                     Gui::Command::commitCommand();
01338                     Gui::Command::updateActive();
01339 
01340                     Gui::Selection().clearSelection();
01341                     Mode = STATUS_SEEK_First;
01342                 }
01343             }
01344         }
01345 
01346         if (VtId < 0 && GeoId < 0) // exit the fillet tool if the user clicked on empty space
01347             sketchgui->purgeHandler(); // no code after this line, Handler get deleted in ViewProvider
01348 
01349         return true;
01350     }
01351 
01352 protected:
01353     SelectMode Mode;
01354     int firstCurve;
01355     Base::Vector2D firstPos;
01356 };
01357 
01358 DEF_STD_CMD_A(CmdSketcherCreateFillet);
01359 
01360 CmdSketcherCreateFillet::CmdSketcherCreateFillet()
01361   : Command("Sketcher_CreateFillet")
01362 {
01363     sAppModule      = "Sketcher";
01364     sGroup          = QT_TR_NOOP("Sketcher");
01365     sMenuText       = QT_TR_NOOP("Create fillet");
01366     sToolTipText    = QT_TR_NOOP("Create a fillet between to lines or at a coincident point");
01367     sWhatsThis      = sToolTipText;
01368     sStatusTip      = sToolTipText;
01369     sPixmap         = "Sketcher_CreateFillet";
01370     sAccel          = "F";
01371     eType           = ForEdit;
01372 }
01373 
01374 void CmdSketcherCreateFillet::activated(int iMsg)
01375 {
01376     ActivateHandler(getActiveGuiDocument(), new DrawSketchHandlerFillet());
01377 }
01378 
01379 bool CmdSketcherCreateFillet::isActive(void)
01380 {
01381     return isCreateGeoActive(getActiveGuiDocument());
01382 }
01383 // ======================================================================================
01384 
01385 namespace SketcherGui {
01386     class TrimmingSelection : public Gui::SelectionFilterGate
01387     {
01388         App::DocumentObject* object;
01389     public:
01390         TrimmingSelection(App::DocumentObject* obj)
01391             : Gui::SelectionFilterGate((Gui::SelectionFilter*)0), object(obj)
01392         {}
01393 
01394         bool allow(App::Document *pDoc, App::DocumentObject *pObj, const char *sSubName)
01395         {
01396             if (pObj != this->object)
01397                 return false;
01398             if (!sSubName || sSubName[0] == '\0')
01399                 return false;
01400             std::string element(sSubName);
01401             if (element.substr(0,4) == "Edge") {
01402                 int index=std::atoi(element.substr(4,4000).c_str());
01403                 Sketcher::SketchObject *Sketch = static_cast<Sketcher::SketchObject*>(object);
01404                 const std::vector<Part::Geometry *> &geo = Sketch->Geometry.getValues();
01405                 const Part::Geometry *geom = geo[index];
01406                 if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId() ||
01407                     geom->getTypeId() == Part::GeomCircle::getClassTypeId()||
01408                     geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId())
01409                     return true;
01410             }
01411             return  false;
01412         }
01413     };
01414 };
01415 
01416 /* XPM */
01417 static const char *cursor_trimming[]={
01418 "32 32 3 1",
01419 "+ c white",
01420 "* c red",
01421 ". c None",
01422 "......+.........................",
01423 "......+.........................",
01424 "......+.........................",
01425 "......+.........................",
01426 "......+.........................",
01427 "................................",
01428 "+++++...+++++...................",
01429 "................................",
01430 "......+.........................",
01431 "......+.........................",
01432 "......+......................*..",
01433 "......+....................**...",
01434 "......+...................**....",
01435 ".*..............................",
01436 "..*.....................*.......",
01437 "...*..................**........",
01438 ".....*...............**.........",
01439 "......*.........................",
01440 ".......*..........*.............",
01441 ".........*......**..............",
01442 "..........*....**...............",
01443 "...........****.................",
01444 "............*.*.................",
01445 "............***.................",
01446 "..........*....*................",
01447 ".........*.......*..............",
01448 ".......*..........*.............",
01449 "......*............*............",
01450 "....*................*..........",
01451 "...*..................*.........",
01452 ".*.....................*........",
01453 ".........................*......"};
01454 
01455 class DrawSketchHandlerTrimming: public DrawSketchHandler
01456 {
01457 public:
01458     DrawSketchHandlerTrimming() {}
01459     virtual ~DrawSketchHandlerTrimming()
01460     {
01461         Gui::Selection().rmvSelectionGate();
01462     }
01463 
01464     virtual void activated(ViewProviderSketch *sketchgui)
01465     {
01466         Gui::Selection().clearSelection();
01467         Gui::Selection().rmvSelectionGate();
01468         Gui::Selection().addSelectionGate(new TrimmingSelection(sketchgui->getObject()));
01469         setCursor(QPixmap(cursor_trimming),7,7);
01470     }
01471 
01472     virtual void mouseMove(Base::Vector2D onSketchPos)
01473     {
01474     }
01475 
01476     virtual bool pressButton(Base::Vector2D onSketchPos)
01477     {
01478         return true;
01479     }
01480 
01481     virtual bool releaseButton(Base::Vector2D onSketchPos)
01482     {
01483         int GeoId = sketchgui->getPreselectCurve();
01484         if (GeoId > -1) {
01485             const std::vector<Part::Geometry *> &geo = sketchgui->getSketchObject()->Geometry.getValues();
01486             const Part::Geometry *geom = geo[GeoId];
01487             if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId() ||
01488                 geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() ||
01489                 geom->getTypeId() == Part::GeomCircle::getClassTypeId()
01490             ) {
01491                 try {
01492                     Gui::Command::openCommand("Trim edge");
01493                     Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.trim(%d,App.Vector(%f,%f,0))",
01494                               sketchgui->getObject()->getNameInDocument(),
01495                               GeoId, onSketchPos.fX, onSketchPos.fY);
01496                     Gui::Command::commitCommand();
01497                     Gui::Command::updateActive();
01498                 }
01499                 catch (const Base::Exception& e) {
01500                     Base::Console().Error("%s\n", e.what());
01501                 }
01502             }
01503         }
01504         else // exit the trimming tool if the user clicked on empty space
01505             sketchgui->purgeHandler(); // no code after this line, Handler get deleted in ViewProvider
01506 
01507         return true;
01508     }
01509 };
01510 
01511 DEF_STD_CMD_A(CmdSketcherTrimming);
01512 
01513 CmdSketcherTrimming::CmdSketcherTrimming()
01514   : Command("Sketcher_Trimming")
01515 {
01516     sAppModule      = "Sketcher";
01517     sGroup          = QT_TR_NOOP("Sketcher");
01518     sMenuText       = QT_TR_NOOP("Trim edge");
01519     sToolTipText    = QT_TR_NOOP("Trims an edge with respect to the picked position");
01520     sWhatsThis      = sToolTipText;
01521     sStatusTip      = sToolTipText;
01522     sPixmap         = "Sketcher_Trimming";
01523     sAccel          = "T";
01524     eType           = ForEdit;
01525 }
01526 
01527 void CmdSketcherTrimming::activated(int iMsg)
01528 {
01529     ActivateHandler(getActiveGuiDocument(), new DrawSketchHandlerTrimming());
01530 }
01531 
01532 bool CmdSketcherTrimming::isActive(void)
01533 {
01534     return isCreateGeoActive(getActiveGuiDocument());
01535 }
01536 
01537 
01538 void CreateSketcherCommandsCreateGeo(void)
01539 {
01540     Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager();
01541 
01542     //rcCmdMgr.addCommand(new CmdSketcherCreatePoint());
01543     rcCmdMgr.addCommand(new CmdSketcherCreateArc());
01544     rcCmdMgr.addCommand(new CmdSketcherCreateCircle());
01545     rcCmdMgr.addCommand(new CmdSketcherCreateLine());
01546     rcCmdMgr.addCommand(new CmdSketcherCreatePolyline());
01547     rcCmdMgr.addCommand(new CmdSketcherCreateRectangle());
01548     rcCmdMgr.addCommand(new CmdSketcherCreateFillet());
01549     //rcCmdMgr.addCommand(new CmdSketcherCreateText());
01550     //rcCmdMgr.addCommand(new CmdSketcherCreateDraftLine());
01551     rcCmdMgr.addCommand(new CmdSketcherTrimming());
01552 }

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