CommandConstraints.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 # include <QMessageBox>
00027 #endif
00028 
00029 #include <Gui/Application.h>
00030 #include <Gui/Document.h>
00031 #include <Gui/Selection.h>
00032 #include <Gui/Command.h>
00033 #include <Gui/MainWindow.h>
00034 #include <Gui/DlgEditFileIncludeProptertyExternal.h>
00035 
00036 #include <Mod/Part/App/Geometry.h>
00037 #include <Mod/Sketcher/App/SketchObject.h>
00038 
00039 #include "ViewProviderSketch.h"
00040 
00041 using namespace std;
00042 using namespace SketcherGui;
00043 using namespace Sketcher;
00044 
00045 bool isCreateConstraintActive(Gui::Document *doc)
00046 {
00047     if (doc)
00048         // checks if a Sketch Viewprovider is in Edit and is in no special mode
00049         if (doc->getInEdit() && doc->getInEdit()->isDerivedFrom(SketcherGui::ViewProviderSketch::getClassTypeId()))
00050             if (dynamic_cast<SketcherGui::ViewProviderSketch*>(doc->getInEdit())
00051                 ->getSketchMode() == ViewProviderSketch::STATUS_NONE)
00052                 if (Gui::Selection().countObjectsOfType(Sketcher::SketchObject::getClassTypeId()) > 0)
00053                     return true;
00054     return false;
00055 }
00056 
00057 void updateDatumDistance(Gui::Document *doc, Constraint *constr)
00058 {
00059     float sf = 1.f;
00060     if (doc && doc->getInEdit() && doc->getInEdit()->isDerivedFrom(SketcherGui::ViewProviderSketch::getClassTypeId())) {
00061         SketcherGui::ViewProviderSketch *vp = dynamic_cast<SketcherGui::ViewProviderSketch*>(doc->getInEdit());
00062         sf = vp->getScaleFactor();
00063 
00064         constr->LabelDistance = 2. * sf;
00065         vp->draw(); // Redraw
00066     }
00067 }
00068 
00069 namespace SketcherGui {
00070 
00071 struct SketchSelection{
00072     enum GeoType {
00073         Point,
00074         Line,
00075         Circle,
00076         Arc
00077     };
00078     int setUp(void);
00079     struct SketchSelectionItem {
00080         GeoType type;
00081         int GeoId;
00082         bool Extern;
00083     };
00084     std::list<SketchSelectionItem> Items;
00085     QString ErrorMsg;
00086 };
00087 
00088 int SketchSelection::setUp(void)
00089 {
00090     std::vector<Gui::SelectionObject> selection = Gui::Selection().getSelectionEx();
00091 
00092     Sketcher::SketchObject *SketchObj=0;
00093     Part::Feature          *SupportObj=0;
00094     std::vector<std::string> SketchSubNames;
00095     std::vector<std::string> SupportSubNames;
00096 
00097     // only one sketch with its subelements are allowed to be selected
00098     if (selection.size() == 1) {
00099         // if one selectetd, only sketch allowed. should be done by activity of command
00100         if(!selection[0].getObject()->getTypeId().isDerivedFrom(Sketcher::SketchObject::getClassTypeId()))
00101         {
00102             ErrorMsg = QObject::tr("Only sketch and its support is allowed to select");
00103             return -1;
00104         }
00105 
00106         SketchObj = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject());
00107         SketchSubNames = selection[0].getSubNames();
00108     } else if(selection.size() == 2) {
00109         if(selection[0].getObject()->getTypeId().isDerivedFrom(Sketcher::SketchObject::getClassTypeId())){
00110             SketchObj = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject());
00111             // check if the none sketch object is the support of the sketch
00112             if(selection[1].getObject() != SketchObj->Support.getValue()){
00113                 ErrorMsg = QObject::tr("Only sketch and its support is allowed to select");
00114                 return-1;
00115             }
00116             // assume always a Part::Feature derived object as support
00117             assert(selection[1].getObject()->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId()));
00118             SupportObj = dynamic_cast<Part::Feature*>(selection[1].getObject());
00119             SketchSubNames  = selection[0].getSubNames();
00120             SupportSubNames = selection[1].getSubNames();
00121 
00122         } else if (selection[1].getObject()->getTypeId().isDerivedFrom(Sketcher::SketchObject::getClassTypeId())) {
00123             SketchObj = dynamic_cast<Sketcher::SketchObject*>(selection[1].getObject());
00124             // check if the none sketch object is the support of the sketch
00125             if(selection[0].getObject() != SketchObj->Support.getValue()){
00126                 ErrorMsg = QObject::tr("Only sketch and its support is allowed to select");
00127                 return -1;
00128             }
00129             // assume always a Part::Feature derived object as support
00130             assert(selection[0].getObject()->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId()));
00131             SupportObj = dynamic_cast<Part::Feature*>(selection[0].getObject());
00132             SketchSubNames  = selection[1].getSubNames();
00133             SupportSubNames = selection[0].getSubNames();
00134 
00135         } else {
00136             ErrorMsg = QObject::tr("One of the selected has to be on the sketch");
00137             return -1;
00138         }
00139     }
00140 
00141     // colect Sketch geos
00142     for ( std::vector<std::string>::const_iterator it= SketchSubNames.begin();it!=SketchSubNames.end();++it){
00143 
00144 
00145     }
00146 
00147 
00148     return Items.size();
00149 }
00150 
00151 } // namespace SketcherGui
00152 
00153 
00154 
00155 /* Constrain commands =======================================================*/
00156 DEF_STD_CMD_A(CmdSketcherConstrainHorizontal);
00157 
00158 CmdSketcherConstrainHorizontal::CmdSketcherConstrainHorizontal()
00159     :Command("Sketcher_ConstrainHorizontal")
00160 {
00161     sAppModule      = "Sketcher";
00162     sGroup          = QT_TR_NOOP("Sketcher");
00163     sMenuText       = QT_TR_NOOP("Constrain horizontally");
00164     sToolTipText    = QT_TR_NOOP("Create a horizontal constraint on the selected item");
00165     sWhatsThis      = sToolTipText;
00166     sStatusTip      = sToolTipText;
00167     sPixmap         = "Constraint_Horizontal";
00168     sAccel          = "H";
00169     eType           = ForEdit;
00170 }
00171 
00172 void CmdSketcherConstrainHorizontal::activated(int iMsg)
00173 {
00174     // get the selection
00175     std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx();
00176 
00177     // only one sketch with its subelements are allowed to be selected
00178     if (selection.size() != 1) {
00179         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
00180             QObject::tr("Select an edge from the sketch."));
00181         return;
00182     }
00183 
00184     // get the needed lists and objects
00185     const std::vector<std::string> &SubNames = selection[0].getSubNames();
00186     Sketcher::SketchObject* Obj = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject());
00187     const std::vector< Sketcher::Constraint * > &vals = Obj->Constraints.getValues();
00188     const std::vector<Part::Geometry *> &geomlist = Obj->Geometry.getValues();
00189 
00190     std::vector<int> ids;
00191     // go through the selected subelements
00192     for(std::vector<std::string>::const_iterator it=SubNames.begin();it!=SubNames.end();++it){
00193         // only handle edges
00194         if (it->size() > 4 && it->substr(0,4) == "Edge") {
00195             int index=std::atoi(it->substr(4,4000).c_str());
00196 
00197             Part::Geometry *geo = geomlist[index];
00198             if (geo->getTypeId() != Part::GeomLineSegment::getClassTypeId()) {
00199                 QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Impossible constraint"),
00200                                      QObject::tr("The selected edge is not a line segment"));
00201                 return;
00202             }
00203 
00204             // check if the edge has already a Horizontal or Vertical constraint
00205             for (std::vector< Sketcher::Constraint * >::const_iterator it= vals.begin();
00206                  it != vals.end(); ++it) {
00207                 if ((*it)->Type == Sketcher::Horizontal && (*it)->First == index){
00208                     QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Double constraint"),
00209                         QObject::tr("The selected edge has already a horizontal constraint!"));
00210                     return;
00211                 }
00212                 if ((*it)->Type == Sketcher::Vertical && (*it)->First == index) {
00213                     QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Impossible constraint"),
00214                                          QObject::tr("The selected edge has already a vertical constraint!"));
00215                     return;
00216                 }
00217             }
00218             ids.push_back(index);
00219         }
00220     }
00221     // undo command open
00222     openCommand("add horizontal constraint");
00223 
00224     for (std::vector<int>::iterator it=ids.begin(); it != ids.end(); it++) {
00225         // issue the actual commands to create the constraint
00226         doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Horizontal',%d)) "
00227                  ,selection[0].getFeatName(),*it);
00228     }
00229     // finish the transaction and update
00230     commitCommand();
00231     updateActive();
00232 
00233     // clear the selection (convenience)
00234     getSelection().clearSelection();
00235 }
00236 
00237 bool CmdSketcherConstrainHorizontal::isActive(void)
00238 {
00239     return isCreateConstraintActive( getActiveGuiDocument() );
00240 }
00241 
00242 
00243 DEF_STD_CMD_A(CmdSketcherConstrainVertical);
00244 
00245 CmdSketcherConstrainVertical::CmdSketcherConstrainVertical()
00246     :Command("Sketcher_ConstrainVertical")
00247 {
00248     sAppModule      = "Sketcher";
00249     sGroup          = QT_TR_NOOP("Sketcher");
00250     sMenuText       = QT_TR_NOOP("Constrain vertically");
00251     sToolTipText    = QT_TR_NOOP("Create a vertical constraint on the selected item");
00252     sWhatsThis      = sToolTipText;
00253     sStatusTip      = sToolTipText;
00254     sPixmap         = "Constraint_Vertical";
00255     sAccel          = "V";
00256     eType           = ForEdit;
00257 }
00258 
00259 void CmdSketcherConstrainVertical::activated(int iMsg)
00260 {
00261     // get the selection
00262     std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx();
00263 
00264     // only one sketch with its subelements are allowed to be selected
00265     if (selection.size() != 1) {
00266         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
00267             QObject::tr("Select an edge from the sketch."));
00268         return;
00269     }
00270 
00271     // get the needed lists and objects
00272     const std::vector<std::string> &SubNames = selection[0].getSubNames();
00273     Sketcher::SketchObject* Obj = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject());
00274     const std::vector< Sketcher::Constraint * > &vals = Obj->Constraints.getValues();
00275     const std::vector<Part::Geometry *> &geomlist = Obj->Geometry.getValues();
00276 
00277      std::vector<int> ids;
00278 
00279     // go through the selected subelements
00280     for(std::vector<std::string>::const_iterator it=SubNames.begin();it!=SubNames.end();++it){
00281         // only handle edges
00282         if (it->size() > 4 && it->substr(0,4) == "Edge") {
00283             int index=std::atoi(it->substr(4,4000).c_str());
00284 
00285             Part::Geometry *geo = geomlist[index];
00286             if (geo->getTypeId() != Part::GeomLineSegment::getClassTypeId()) {
00287                 QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Impossible constraint"),
00288                                      QObject::tr("The selected edge is not a line segment"));
00289                 return;
00290             }
00291 
00292             // check if the edge has already a Horizontal or Vertical constraint
00293             for (std::vector< Sketcher::Constraint * >::const_iterator it= vals.begin();
00294                  it != vals.end(); ++it) {
00295                 if ((*it)->Type == Sketcher::Horizontal && (*it)->First == index) {
00296                     QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Impossible constraint"),
00297                         QObject::tr("The selected edge has already a horizontal constraint!"));
00298                     return;
00299                 }
00300                 if ((*it)->Type == Sketcher::Vertical && (*it)->First == index) {
00301                     QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Double constraint"),
00302                         QObject::tr("The selected edge has already a vertical constraint!"));
00303                     return;
00304                 }
00305             }
00306             ids.push_back(index);
00307         }
00308     }
00309 
00310     // undo command open
00311     openCommand("add vertical constraint");
00312     for (std::vector<int>::iterator it=ids.begin(); it != ids.end(); it++) {
00313         // issue the actual command to create the constraint
00314         doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Vertical',%d))"
00315                  ,selection[0].getFeatName(),*it);
00316     }
00317     // finish the transaction and update
00318     commitCommand();
00319     updateActive();
00320 
00321     // clear the selection (convenience)
00322     getSelection().clearSelection();
00323 }
00324 
00325 bool CmdSketcherConstrainVertical::isActive(void)
00326 {
00327     return isCreateConstraintActive( getActiveGuiDocument() );
00328 }
00329 
00330 
00331 DEF_STD_CMD_A(CmdSketcherConstrainLock);
00332 
00333 CmdSketcherConstrainLock::CmdSketcherConstrainLock()
00334     :Command("Sketcher_ConstrainLock")
00335 {
00336     sAppModule      = "Sketcher";
00337     sGroup          = QT_TR_NOOP("Sketcher");
00338     sMenuText       = QT_TR_NOOP("Constrain lock");
00339     sToolTipText    = QT_TR_NOOP("Create a lock constraint on the selected item");
00340     sWhatsThis      = sToolTipText;
00341     sStatusTip      = sToolTipText;
00342     sPixmap         = "Sketcher_ConstrainLock";
00343     eType           = ForEdit;
00344 }
00345 
00346 void CmdSketcherConstrainLock::activated(int iMsg)
00347 {
00348     // get the selection
00349     std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx();
00350 
00351     // only one sketch with its subelements are allowed to be selected
00352     if (selection.size() != 1) {
00353         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
00354             QObject::tr("Select entities from the sketch."));
00355         return;
00356     }
00357 
00358     // get the needed lists and objects
00359     const std::vector<std::string> &SubNames = selection[0].getSubNames();
00360     Sketcher::SketchObject* Obj = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject());
00361 
00362     if (SubNames.size() != 1) {
00363         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
00364             QObject::tr("Select exactly one entity from the sketch."));
00365         return;
00366     }
00367 
00368     int GeoId;
00369     Sketcher::PointPos PosId=Sketcher::none;
00370     if (SubNames[0].size() > 6 && SubNames[0].substr(0,6) == "Vertex") {
00371         int VtId = std::atoi(SubNames[0].substr(6,4000).c_str());
00372         Obj->getGeoVertexIndex(VtId,GeoId,PosId);
00373     }
00374     else if (SubNames[0].size() > 4 && SubNames[0].substr(0,4) == "Edge")
00375         GeoId = std::atoi(SubNames[0].substr(4,4000).c_str());
00376     else {
00377         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
00378             QObject::tr("Select exactly one entity from the sketch."));
00379         return;
00380     }
00381 
00382     Base::Vector3d pnt = Obj->getPoint(GeoId,PosId);
00383 
00384     // undo command open
00385     openCommand("add fixed constraint");
00386     Gui::Command::doCommand(
00387         Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('DistanceX',%d,%d,%f)) ",
00388         selection[0].getFeatName(),GeoId,PosId,pnt.x);
00389     Gui::Command::doCommand(
00390         Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('DistanceY',%d,%d,%f)) ",
00391         selection[0].getFeatName(),GeoId,PosId,pnt.y);
00392 
00393     // finish the transaction and update
00394     commitCommand();
00395     updateActive();
00396 
00397     // clear the selection (convenience)
00398     getSelection().clearSelection();
00399 }
00400 
00401 bool CmdSketcherConstrainLock::isActive(void)
00402 {
00403     return isCreateConstraintActive( getActiveGuiDocument() );
00404 }
00405 
00406 
00407 DEF_STD_CMD_A(CmdSketcherConstrainCoincident);
00408 
00409 CmdSketcherConstrainCoincident::CmdSketcherConstrainCoincident()
00410     :Command("Sketcher_ConstrainCoincident")
00411 {
00412     sAppModule      = "Sketcher";
00413     sGroup          = QT_TR_NOOP("Sketcher");
00414     sMenuText       = QT_TR_NOOP("Constrain coincident");
00415     sToolTipText    = QT_TR_NOOP("Create a coincident constraint on the selected item");
00416     sWhatsThis      = sToolTipText;
00417     sStatusTip      = sToolTipText;
00418     sPixmap         = "Constraint_PointOnPoint";
00419     sAccel          = "C";
00420     eType           = ForEdit;
00421 }
00422 
00423 void CmdSketcherConstrainCoincident::activated(int iMsg)
00424 {
00425     // get the selection
00426     std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx();
00427 
00428     // only one sketch with its subelements are allowed to be selected
00429     if (selection.size() != 1) {
00430         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
00431             QObject::tr("Select vertexes from the sketch."));
00432         return;
00433     }
00434 
00435     // get the needed lists and objects
00436     const std::vector<std::string> &SubNames = selection[0].getSubNames();
00437     Sketcher::SketchObject* Obj = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject());
00438 
00439     if (SubNames.size() != 2) {
00440         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
00441             QObject::tr("Select exactly two vertexes from the sketch."));
00442         return;
00443     }
00444 
00445     int index1,index2;
00446     // get first vertex index
00447     if (SubNames[0].size() > 6 && SubNames[0].substr(0,6) == "Vertex")
00448         index1 = std::atoi(SubNames[0].substr(6,4000).c_str());
00449     else {
00450         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
00451             QObject::tr("Select exactly two vertexes from the sketch."));
00452         return;
00453     }
00454 
00455     // get second vertex index
00456     if (SubNames[1].size() > 6 && SubNames[1].substr(0,6) == "Vertex")
00457         index2 = std::atoi(SubNames[1].substr(6,4000).c_str());
00458     else {
00459         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
00460             QObject::tr("Select exactly two vertexes from the sketch."));
00461         return;
00462     }
00463     int GeoId1,GeoId2;
00464     Sketcher::PointPos Pt1,Pt2;
00465     Obj->getGeoVertexIndex(index1,GeoId1,Pt1);
00466     Obj->getGeoVertexIndex(index2,GeoId2,Pt2);
00467 
00468     // undo command open
00469     openCommand("add coincident constraint");
00470     Gui::Command::doCommand(
00471         Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Coincident',%d,%d,%d,%d)) ",
00472         selection[0].getFeatName(),GeoId1,Pt1,GeoId2,Pt2);
00473 
00474     // finish the transaction and update
00475     commitCommand();
00476     updateActive();
00477 
00478     // clear the selection (convenience)
00479     getSelection().clearSelection();
00480 }
00481 
00482 bool CmdSketcherConstrainCoincident::isActive(void)
00483 {
00484     return isCreateConstraintActive( getActiveGuiDocument() );
00485 }
00486 
00487 
00488 DEF_STD_CMD_A(CmdSketcherConstrainDistance);
00489 
00490 CmdSketcherConstrainDistance::CmdSketcherConstrainDistance()
00491     :Command("Sketcher_ConstrainDistance")
00492 {
00493     sAppModule      = "Sketcher";
00494     sGroup          = QT_TR_NOOP("Sketcher");
00495     sMenuText       = QT_TR_NOOP("Constrain distance");
00496     sToolTipText    = QT_TR_NOOP("Fix a length of a line or the distance between a line and a vertex");
00497     sWhatsThis      = sToolTipText;
00498     sStatusTip      = sToolTipText;
00499     sPixmap         = "Constraint_Length";
00500     sAccel          = "D";
00501     eType           = ForEdit;
00502 }
00503 
00504 void CmdSketcherConstrainDistance::activated(int iMsg)
00505 {
00506 #if 0
00507 
00508     SketchSelection selection;
00509 
00510     int num = selection.setUp();
00511 
00512 #else
00513     // get the selection
00514     std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx();
00515 
00516     // only one sketch with its subelements are allowed to be selected
00517     if (selection.size() != 1) {
00518         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
00519             QObject::tr("Select vertexes from the sketch."));
00520         return;
00521     }
00522 
00523     // get the needed lists and objects
00524     const std::vector<std::string> &SubNames = selection[0].getSubNames();
00525     Sketcher::SketchObject* Obj = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject());
00526     const std::vector<Part::Geometry *> &geo = Obj->Geometry.getValues();
00527 
00528     if (SubNames.size() < 1 || SubNames.size() > 2) {
00529         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
00530             QObject::tr("Select exactly one line or one point and one line or two points from the sketch."));
00531         return;
00532     }
00533 
00534     int GeoId1=Constraint::GeoUndef, VtId1=-1, GeoId2=Constraint::GeoUndef, VtId2=-1;
00535     if (SubNames.size() >= 1) {
00536         if (SubNames[0].size() > 4 && SubNames[0].substr(0,4) == "Edge")
00537             GeoId1 = std::atoi(SubNames[0].substr(4,4000).c_str());
00538         else if (SubNames[0].size() > 6 && SubNames[0].substr(0,6) == "Vertex")
00539             VtId1 = std::atoi(SubNames[0].substr(6,4000).c_str());
00540     }
00541     if (SubNames.size() == 2) {
00542         if (SubNames[1].size() > 4 && SubNames[1].substr(0,4) == "Edge")
00543             GeoId2 = std::atoi(SubNames[1].substr(4,4000).c_str());
00544         else if (SubNames[1].size() > 6 && SubNames[1].substr(0,6) == "Vertex")
00545             VtId2 = std::atoi(SubNames[1].substr(6,4000).c_str());
00546     }
00547 
00548     if (VtId1 >= 0 && VtId2 >= 0) { // point to point distance
00549         Sketcher::PointPos PosId1,PosId2;
00550         Obj->getGeoVertexIndex(VtId1,GeoId1,PosId1);
00551         Obj->getGeoVertexIndex(VtId2,GeoId2,PosId2);
00552         Base::Vector3d pnt1 = Obj->getPoint(GeoId1,PosId1);
00553         Base::Vector3d pnt2 = Obj->getPoint(GeoId2,PosId2);
00554 
00555         openCommand("add point to point distance constraint");
00556         Gui::Command::doCommand(
00557             Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Distance',%d,%d,%d,%d,%f)) ",
00558             selection[0].getFeatName(),GeoId1,PosId1,GeoId2,PosId2,(pnt2-pnt1).Length());
00559         commitCommand();
00560 
00561         // Get the latest constraint
00562         const std::vector<Sketcher::Constraint *> &ConStr = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject())->Constraints.getValues();
00563         Sketcher::Constraint *constr = ConStr[ConStr.size() -1];
00564 
00565         updateDatumDistance(getActiveGuiDocument(), constr);
00566 
00567         //updateActive();
00568         getSelection().clearSelection();
00569         return;
00570     }
00571     else if ((VtId1 >= 0 && GeoId2 >= 0) || (VtId2 >= 0 && GeoId1 >= 0))  { // point to line distance
00572         if (VtId2 >= 0 && GeoId1 >= 0) {
00573             std::swap(VtId1,VtId2);
00574             std::swap(GeoId1,GeoId2);
00575         }
00576         Sketcher::PointPos PosId1;
00577         Obj->getGeoVertexIndex(VtId1,GeoId1,PosId1);
00578         Base::Vector3d pnt = Obj->getPoint(GeoId1,PosId1);
00579         const Part::Geometry *geom = geo[GeoId2];
00580         if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
00581             const Part::GeomLineSegment *lineSeg;
00582             lineSeg = dynamic_cast<const Part::GeomLineSegment*>(geom);
00583             Base::Vector3d pnt1 = lineSeg->getStartPoint();
00584             Base::Vector3d pnt2 = lineSeg->getEndPoint();
00585             Base::Vector3d d = pnt2-pnt1;
00586             double ActDist = std::abs(-pnt.x*d.y+pnt.y*d.x+pnt1.x*pnt2.y-pnt2.x*pnt1.y) / d.Length();
00587 
00588             openCommand("add point to line Distance constraint");
00589             Gui::Command::doCommand(
00590                 Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Distance',%d,%d,%d,%f)) ",
00591                 selection[0].getFeatName(),GeoId1,PosId1,GeoId2,ActDist);
00592             commitCommand();
00593 
00594             // Get the latest constraint
00595             const std::vector<Sketcher::Constraint *> &ConStr = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject())->Constraints.getValues();
00596             Sketcher::Constraint *constr = ConStr[ConStr.size() -1];
00597 
00598             updateDatumDistance(getActiveGuiDocument(), constr);
00599 
00600             //updateActive();
00601             getSelection().clearSelection();
00602             return;
00603         }
00604     }
00605     else if (GeoId1 >= 0) { // line length
00606         const Part::Geometry *geom = geo[GeoId1];
00607         if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
00608             const Part::GeomLineSegment *lineSeg;
00609             lineSeg = dynamic_cast<const Part::GeomLineSegment*>(geom);
00610             double ActLength = (lineSeg->getEndPoint()-lineSeg->getStartPoint()).Length();
00611 
00612             openCommand("add length constraint");
00613             Gui::Command::doCommand(
00614                 Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Distance',%d,%f)) ",
00615                 selection[0].getFeatName(),GeoId1,ActLength);
00616             commitCommand();
00617 
00618             // Get the latest created constraint
00619             const std::vector<Sketcher::Constraint *> &ConStr = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject())->Constraints.getValues();
00620             Sketcher::Constraint *constr = ConStr[ConStr.size() -1];
00621 
00622             updateDatumDistance(getActiveGuiDocument(), constr);
00623 
00624             //updateActive();
00625             getSelection().clearSelection();
00626             return;
00627         }
00628     }
00629 
00630     QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
00631         QObject::tr("Select exactly one line or one point and one line or two points from the sketch."));
00632     return;
00633 #endif
00634 }
00635 
00636 bool CmdSketcherConstrainDistance::isActive(void)
00637 {
00638     return isCreateConstraintActive( getActiveGuiDocument() );
00639 }
00640 
00641 
00642 DEF_STD_CMD_A(CmdSketcherConstrainPointOnObject);
00643 
00644 CmdSketcherConstrainPointOnObject::CmdSketcherConstrainPointOnObject()
00645     :Command("Sketcher_ConstrainPointOnObject")
00646 {
00647     sAppModule      = "Sketcher";
00648     sGroup          = QT_TR_NOOP("Sketcher");
00649     sMenuText       = QT_TR_NOOP("Constrain point onto object");
00650     sToolTipText    = QT_TR_NOOP("Fix a point onto an object");
00651     sWhatsThis      = sToolTipText;
00652     sStatusTip      = sToolTipText;
00653     sPixmap         = "Constraint_PointOnObject";
00654     sAccel          = "O";
00655     eType           = ForEdit;
00656 }
00657 
00658 void CmdSketcherConstrainPointOnObject::activated(int iMsg)
00659 {
00660     // get the selection
00661     std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx();
00662 
00663     // only one sketch with its subelements are allowed to be selected
00664     if (selection.size() != 1) {
00665         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
00666             QObject::tr("Select vertexes from the sketch."));
00667         return;
00668     }
00669 
00670     // get the needed lists and objects
00671     const std::vector<std::string> &SubNames = selection[0].getSubNames();
00672     Sketcher::SketchObject* Obj = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject());
00673     const std::vector<Part::Geometry *> &geo = Obj->Geometry.getValues();
00674 
00675     if (SubNames.size() < 1 || SubNames.size() > 2) {
00676         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
00677             QObject::tr("Select exactly one point and one object from the sketch."));
00678         return;
00679     }
00680 
00681     int GeoId1=Constraint::GeoUndef, VtId1=-1, GeoId2=Constraint::GeoUndef, VtId2=-1;
00682 
00683     if (SubNames.size() >= 1) {
00684         if (SubNames[0].size() > 4 && SubNames[0].substr(0,4) == "Edge")
00685             GeoId1 = std::atoi(SubNames[0].substr(4,4000).c_str());
00686         else if (SubNames[0].size() > 6 && SubNames[0].substr(0,6) == "Vertex")
00687             VtId1 = std::atoi(SubNames[0].substr(6,4000).c_str());
00688     }
00689     if (SubNames.size() == 2) {
00690         if (SubNames[1].size() > 4 && SubNames[1].substr(0,4) == "Edge")
00691             GeoId2 = std::atoi(SubNames[1].substr(4,4000).c_str());
00692         else if (SubNames[1].size() > 6 && SubNames[1].substr(0,6) == "Vertex")
00693             VtId2 = std::atoi(SubNames[1].substr(6,4000).c_str());
00694     }
00695 
00696     if ((VtId1 >= 0 && GeoId2 >= 0) || (VtId2 >= 0 && GeoId1 >= 0)) {
00697         if (VtId2 >= 0 && GeoId1 >= 0) {
00698             std::swap(VtId1,VtId2);
00699             std::swap(GeoId1,GeoId2);
00700         }
00701 
00702         Sketcher::PointPos PosId1;
00703         Obj->getGeoVertexIndex(VtId1,GeoId1,PosId1);
00704 
00705         const Part::Geometry *geom = geo[GeoId2];
00706 
00707         // Currently only accepts line segments and circles
00708         if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId() ||
00709             geom->getTypeId() == Part::GeomCircle::getClassTypeId() ||
00710             geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() ) {
00711 
00712             openCommand("add point on object constraint");
00713             Gui::Command::doCommand(
00714                 Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('PointOnObject',%d,%d,%d)) ",
00715                 selection[0].getFeatName(),GeoId1,PosId1,GeoId2);
00716             commitCommand();
00717             //updateActive();
00718             getSelection().clearSelection();
00719             return;
00720         }
00721     }
00722 
00723     QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
00724         QObject::tr("Select exactly one point and one object from the sketch."));
00725     return;
00726 }
00727 
00728 bool CmdSketcherConstrainPointOnObject::isActive(void)
00729 {
00730     return isCreateConstraintActive( getActiveGuiDocument() );
00731 }
00732 
00733 DEF_STD_CMD_A(CmdSketcherConstrainDistanceX);
00734 
00735 CmdSketcherConstrainDistanceX::CmdSketcherConstrainDistanceX()
00736     :Command("Sketcher_ConstrainDistanceX")
00737 {
00738     sAppModule      = "Sketcher";
00739     sGroup          = QT_TR_NOOP("Sketcher");
00740     sMenuText       = QT_TR_NOOP("Constrain horizontal distance");
00741     sToolTipText    = QT_TR_NOOP("Fix the horizontal distance between two points or line ends");
00742     sWhatsThis      = sToolTipText;
00743     sStatusTip      = sToolTipText;
00744     sPixmap         = "Constraint_HorizontalDistance";
00745     sAccel          = "D";
00746     eType           = ForEdit;
00747 }
00748 
00749 void CmdSketcherConstrainDistanceX::activated(int iMsg)
00750 {
00751     // get the selection
00752     std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx();
00753 
00754     // only one sketch with its subelements are allowed to be selected
00755     if (selection.size() != 1) {
00756         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
00757             QObject::tr("Select vertexes from the sketch."));
00758         return;
00759     }
00760 
00761     // get the needed lists and objects
00762     const std::vector<std::string> &SubNames = selection[0].getSubNames();
00763     Sketcher::SketchObject* Obj = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject());
00764     const std::vector<Part::Geometry *> &geo = Obj->Geometry.getValues();
00765 
00766     if (SubNames.size() < 1 || SubNames.size() > 2) {
00767         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
00768             QObject::tr("Select exactly one line or up to two points from the sketch."));
00769         return;
00770     }
00771 
00772     int GeoId1=Constraint::GeoUndef, VtId1=-1, GeoId2=Constraint::GeoUndef, VtId2=-1;
00773     if (SubNames.size() >= 1) {
00774         if (SubNames[0].size() > 4 && SubNames[0].substr(0,4) == "Edge")
00775             GeoId1 = std::atoi(SubNames[0].substr(4,4000).c_str());
00776         else if (SubNames[0].size() > 6 && SubNames[0].substr(0,6) == "Vertex")
00777             VtId1 = std::atoi(SubNames[0].substr(6,4000).c_str());
00778     }
00779     if (SubNames.size() == 2) {
00780         if (SubNames[1].size() > 4 && SubNames[1].substr(0,4) == "Edge")
00781             GeoId2 = std::atoi(SubNames[1].substr(4,4000).c_str());
00782         else if (SubNames[1].size() > 6 && SubNames[1].substr(0,6) == "Vertex")
00783             VtId2 = std::atoi(SubNames[1].substr(6,4000).c_str());
00784     }
00785 
00786     if (VtId1 >= 0 && VtId2 >= 0) { // point to point horizontal distance
00787         Sketcher::PointPos PosId1,PosId2;
00788         Obj->getGeoVertexIndex(VtId1,GeoId1,PosId1);
00789         Obj->getGeoVertexIndex(VtId2,GeoId2,PosId2);
00790         Base::Vector3d pnt1 = Obj->getPoint(GeoId1,PosId1);
00791         Base::Vector3d pnt2 = Obj->getPoint(GeoId2,PosId2);
00792         double ActLength = pnt2.x-pnt1.x;
00793 
00794         openCommand("add point to point horizontal distance constraint");
00795         Gui::Command::doCommand(
00796             Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('DistanceX',%d,%d,%d,%d,%f)) ",
00797             selection[0].getFeatName(),GeoId1,PosId1,GeoId2,PosId2,ActLength);
00798         commitCommand();
00799 
00800         // Get the latest created constraint
00801         const std::vector<Sketcher::Constraint *> &ConStr = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject())->Constraints.getValues();
00802         Sketcher::Constraint *constr = ConStr[ConStr.size() -1];
00803 
00804         updateDatumDistance(getActiveGuiDocument(), constr);
00805 
00806         //updateActive();
00807         getSelection().clearSelection();
00808         return;
00809     }
00810     else if (GeoId1 >= 0 && GeoId2 < 0 && VtId2 < 0)  { // horizontal length of a line
00811         const Part::Geometry *geom = geo[GeoId1];
00812         if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
00813             const Part::GeomLineSegment *lineSeg;
00814             lineSeg = dynamic_cast<const Part::GeomLineSegment*>(geom);
00815             double ActLength = lineSeg->getEndPoint().x-lineSeg->getStartPoint().x;
00816 
00817             openCommand("add horizontal length constraint");
00818             Gui::Command::doCommand(
00819                 Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('DistanceX',%d,%f)) ",
00820                 selection[0].getFeatName(),GeoId1,ActLength);
00821             commitCommand();
00822 
00823             // Get the latest created constraint
00824             const std::vector<Sketcher::Constraint *> &ConStr = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject())->Constraints.getValues();
00825             Sketcher::Constraint *constr = ConStr[ConStr.size() -1];
00826 
00827             updateDatumDistance(getActiveGuiDocument(), constr);
00828 
00829             //updateActive();
00830             getSelection().clearSelection();
00831             return;
00832         }
00833     }
00834     else if (VtId1 >= 0) { // point on fixed x-coordinate
00835         Sketcher::PointPos PosId1;
00836         Obj->getGeoVertexIndex(VtId1,GeoId1,PosId1);
00837         Base::Vector3d pnt = Obj->getPoint(GeoId1,PosId1);
00838         double ActX = pnt.x;
00839 
00840         openCommand("add fixed x-coordinate constraint");
00841         Gui::Command::doCommand(
00842             Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('DistanceX',%d,%d,%f)) ",
00843             selection[0].getFeatName(),GeoId1,PosId1,ActX);
00844         commitCommand();
00845 
00846         // Get the latest created constraint
00847         const std::vector<Sketcher::Constraint *> &ConStr = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject())->Constraints.getValues();
00848         Sketcher::Constraint *constr = ConStr[ConStr.size() -1];
00849 
00850         updateDatumDistance(getActiveGuiDocument(), constr);
00851 
00852         //updateActive();
00853         getSelection().clearSelection();
00854         return;
00855     }
00856 
00857     QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
00858         QObject::tr("Select exactly one line or up to two points from the sketch."));
00859     return;
00860 }
00861 
00862 bool CmdSketcherConstrainDistanceX::isActive(void)
00863 {
00864     return isCreateConstraintActive( getActiveGuiDocument() );
00865 }
00866 
00867 
00868 DEF_STD_CMD_A(CmdSketcherConstrainDistanceY);
00869 
00870 CmdSketcherConstrainDistanceY::CmdSketcherConstrainDistanceY()
00871     :Command("Sketcher_ConstrainDistanceY")
00872 {
00873     sAppModule      = "Sketcher";
00874     sGroup          = QT_TR_NOOP("Sketcher");
00875     sMenuText       = QT_TR_NOOP("Constrain horizontal distance");
00876     sToolTipText    = QT_TR_NOOP("Fix the vertical distance between two points or line ends");
00877     sWhatsThis      = sToolTipText;
00878     sStatusTip      = sToolTipText;
00879     sPixmap         = "Constraint_VerticalDistance";
00880     sAccel          = "D";
00881     eType           = ForEdit;
00882 }
00883 
00884 void CmdSketcherConstrainDistanceY::activated(int iMsg)
00885 {
00886     // get the selection
00887     std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx();
00888 
00889     // only one sketch with its subelements are allowed to be selected
00890     if (selection.size() != 1) {
00891         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
00892             QObject::tr("Select vertexes from the sketch."));
00893         return;
00894     }
00895 
00896     // get the needed lists and objects
00897     const std::vector<std::string> &SubNames = selection[0].getSubNames();
00898     Sketcher::SketchObject* Obj = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject());
00899     const std::vector<Part::Geometry *> &geo = Obj->Geometry.getValues();
00900 
00901     if (SubNames.size() < 1 || SubNames.size() > 2) {
00902         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
00903             QObject::tr("Select exactly one line or up to two points from the sketch."));
00904         return;
00905     }
00906 
00907     int GeoId1=Constraint::GeoUndef, VtId1=-1, GeoId2=Constraint::GeoUndef, VtId2=-1;
00908     if (SubNames.size() >= 1) {
00909         if (SubNames[0].size() > 4 && SubNames[0].substr(0,4) == "Edge")
00910             GeoId1 = std::atoi(SubNames[0].substr(4,4000).c_str());
00911         else if (SubNames[0].size() > 6 && SubNames[0].substr(0,6) == "Vertex")
00912             VtId1 = std::atoi(SubNames[0].substr(6,4000).c_str());
00913     }
00914     if (SubNames.size() == 2) {
00915         if (SubNames[1].size() > 4 && SubNames[1].substr(0,4) == "Edge")
00916             GeoId2 = std::atoi(SubNames[1].substr(4,4000).c_str());
00917         else if (SubNames[1].size() > 6 && SubNames[1].substr(0,6) == "Vertex")
00918             VtId2 = std::atoi(SubNames[1].substr(6,4000).c_str());
00919     }
00920 
00921     if (VtId1 >= 0 && VtId2 >= 0) { // point to point horizontal distance
00922         Sketcher::PointPos PosId1,PosId2;
00923         Obj->getGeoVertexIndex(VtId1,GeoId1,PosId1);
00924         Obj->getGeoVertexIndex(VtId2,GeoId2,PosId2);
00925         Base::Vector3d pnt1 = Obj->getPoint(GeoId1,PosId1);
00926         Base::Vector3d pnt2 = Obj->getPoint(GeoId2,PosId2);
00927         double ActLength = pnt2.y-pnt1.y;
00928 
00929         openCommand("add point to point vertical distance constraint");
00930         Gui::Command::doCommand(
00931             Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('DistanceY',%d,%d,%d,%d,%f)) ",
00932             selection[0].getFeatName(),GeoId1,PosId1,GeoId2,PosId2,ActLength);
00933         commitCommand();
00934 
00935         // Get the latest created constraint
00936         const std::vector<Sketcher::Constraint *> &ConStr = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject())->Constraints.getValues();
00937         Sketcher::Constraint *constr = ConStr[ConStr.size() -1];
00938 
00939         updateDatumDistance(getActiveGuiDocument(), constr);
00940 
00941         //updateActive();
00942         getSelection().clearSelection();
00943         return;
00944     }
00945     else if (GeoId1 >= 0 && GeoId2 < 0 && VtId2 < 0)  { // horizontal length of a line
00946         const Part::Geometry *geom = geo[GeoId1];
00947         if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
00948             const Part::GeomLineSegment *lineSeg;
00949             lineSeg = dynamic_cast<const Part::GeomLineSegment*>(geom);
00950             double ActLength = lineSeg->getEndPoint().y-lineSeg->getStartPoint().y;
00951 
00952             openCommand("add vertical length constraint");
00953             Gui::Command::doCommand(
00954                 Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('DistanceY',%d,%f)) ",
00955                 selection[0].getFeatName(),GeoId1,ActLength);
00956             commitCommand();
00957 
00958             // Get the latest created constraint
00959             const std::vector<Sketcher::Constraint *> &ConStr = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject())->Constraints.getValues();
00960             Sketcher::Constraint *constr = ConStr[ConStr.size() -1];
00961 
00962             updateDatumDistance(getActiveGuiDocument(), constr);
00963 
00964             //updateActive();
00965             getSelection().clearSelection();
00966             return;
00967         }
00968     }
00969     else if (VtId1 >= 0) { // point on fixed y-coordinate
00970         Sketcher::PointPos PosId1;
00971         Obj->getGeoVertexIndex(VtId1,GeoId1,PosId1);
00972         Base::Vector3d pnt = Obj->getPoint(GeoId1,PosId1);
00973         double ActY = pnt.y;
00974 
00975         openCommand("add fixed y-coordinate constraint");
00976         Gui::Command::doCommand(
00977             Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('DistanceY',%d,%d,%f)) ",
00978             selection[0].getFeatName(),GeoId1,PosId1,ActY);
00979         commitCommand();
00980 
00981         // Get the latest created constraint
00982         const std::vector<Sketcher::Constraint *> &ConStr = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject())->Constraints.getValues();
00983         Sketcher::Constraint *constr = ConStr[ConStr.size() -1];
00984 
00985         updateDatumDistance(getActiveGuiDocument(), constr);
00986 
00987         //updateActive();
00988         getSelection().clearSelection();
00989         return;
00990     }
00991 
00992     QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
00993         QObject::tr("Select exactly one line or up to two points from the sketch."));
00994     return;
00995 }
00996 
00997 bool CmdSketcherConstrainDistanceY::isActive(void)
00998 {
00999     return isCreateConstraintActive( getActiveGuiDocument() );
01000 }
01001 
01002 
01003 DEF_STD_CMD_A(CmdSketcherConstrainParallel);
01004 
01005 CmdSketcherConstrainParallel::CmdSketcherConstrainParallel()
01006     :Command("Sketcher_ConstrainParallel")
01007 {
01008     sAppModule      = "Sketcher";
01009     sGroup          = QT_TR_NOOP("Sketcher");
01010     sMenuText       = QT_TR_NOOP("Constrain parallel");
01011     sToolTipText    = QT_TR_NOOP("Create a parallel constraint between two lines");
01012     sWhatsThis      = sToolTipText;
01013     sStatusTip      = sToolTipText;
01014     sPixmap         = "Constraint_Parallel";
01015     sAccel          = "P";
01016     eType           = ForEdit;
01017 }
01018 
01019 void CmdSketcherConstrainParallel::activated(int iMsg)
01020 {
01021     // get the selection
01022     std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx();
01023 
01024     // only one sketch with its subelements are allowed to be selected
01025     if (selection.size() != 1) {
01026         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
01027             QObject::tr("Select two or more lines from the sketch."));
01028         return;
01029     }
01030 
01031     // get the needed lists and objects
01032     const std::vector<std::string> &SubNames = selection[0].getSubNames();
01033     Sketcher::SketchObject* Obj = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject());
01034     const std::vector< Sketcher::Constraint * > &vals = Obj->Constraints.getValues();
01035     const std::vector<Part::Geometry *> &geomlist = Obj->Geometry.getValues();
01036 
01037 
01038     // go through the selected subelements
01039 
01040     if (SubNames.size() < 2) {
01041         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
01042             QObject::tr("Select at least two lines from the sketch."));
01043         return;
01044     }
01045 
01046     std::vector<int> ids;
01047     for (std::vector<std::string>::const_iterator it=SubNames.begin();it!=SubNames.end();++it) {
01048         int index;
01049         std::string subName = *it;
01050         if (subName.size() > 4 && subName.substr(0,4) == "Edge")
01051             index = std::atoi(subName.substr(4,4000).c_str());
01052         else {
01053             QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
01054                                  QObject::tr("Select a valid line"));
01055             return;
01056         }
01057 
01058         // Check that the curve is a line segment
01059         Part::Geometry *geo = geomlist[index];
01060         if (geo->getTypeId() != Part::GeomLineSegment::getClassTypeId()) {
01061             QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
01062                                 QObject::tr("The selected edge is not a valid line"));
01063             return;
01064         }
01065         ids.push_back(index);
01066     }
01067 
01068     // undo command open
01069     openCommand("add parallel constraint");
01070     int i = 0;
01071     for (std::vector<int>::iterator it = ids.begin(); it!=ids.end();++it, i++) {
01072         if(i == ids.size() - 1)
01073             break;
01074 
01075         Gui::Command::doCommand(
01076             Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Parallel',%d,%d)) ",
01077             selection[0].getFeatName(),ids[i],ids[i+1]);
01078     }
01079 
01080     // finish the transaction and update
01081     commitCommand();
01082     updateActive();
01083 
01084     // clear the selection (convenience)
01085     getSelection().clearSelection();
01086 }
01087 
01088 bool CmdSketcherConstrainParallel::isActive(void)
01089 {
01090     return isCreateConstraintActive( getActiveGuiDocument() );
01091 }
01092 
01093 
01094 DEF_STD_CMD_A(CmdSketcherConstrainPerpendicular);
01095 
01096 CmdSketcherConstrainPerpendicular::CmdSketcherConstrainPerpendicular()
01097     :Command("Sketcher_ConstrainPerpendicular")
01098 {
01099     sAppModule      = "Sketcher";
01100     sGroup          = QT_TR_NOOP("Sketcher");
01101     sMenuText       = QT_TR_NOOP("Constrain perpendicular");
01102     sToolTipText    = QT_TR_NOOP("Create a Perpendicular constraint between two lines");
01103     sWhatsThis      = sToolTipText;
01104     sStatusTip      = sToolTipText;
01105     sPixmap         = "Constraint_Perpendicular";
01106     sAccel          = "N";
01107     eType           = ForEdit;
01108 }
01109 
01110 void CmdSketcherConstrainPerpendicular::activated(int iMsg)
01111 {
01112     // get the selection
01113     std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx();
01114 
01115     // only one sketch with its subelements are allowed to be selected
01116     if (selection.size() != 1) {
01117         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
01118             QObject::tr("Select two lines from the sketch."));
01119         return;
01120     }
01121 
01122     // get the needed lists and objects
01123     const std::vector<std::string> &SubNames = selection[0].getSubNames();
01124     Sketcher::SketchObject* Obj = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject());
01125     const std::vector< Sketcher::Constraint * > &vals = Obj->Constraints.getValues();
01126     const std::vector<Part::Geometry *> &geomlist = Obj->Geometry.getValues();
01127 
01128     if (SubNames.size() != 2) {
01129         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
01130             QObject::tr("Select exactly two lines from the sketch."));
01131         return;
01132     }
01133 
01134     int GeoId1,GeoId2;
01135     if (SubNames[0].size() > 4 && SubNames[0].substr(0,4) == "Edge")
01136         GeoId1 = std::atoi(SubNames[0].substr(4,4000).c_str());
01137     else {
01138         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
01139             QObject::tr("Select exactly two lines from the sketch."));
01140         return;
01141     }
01142 
01143     if (SubNames[1].size() > 4 && SubNames[1].substr(0,4) == "Edge")
01144         GeoId2 = std::atoi(SubNames[1].substr(4,4000).c_str());
01145     else {
01146         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
01147             QObject::tr("Select exactly two lines from the sketch."));
01148         return;
01149     }
01150 
01151     Part::Geometry *geo1 = geomlist[GeoId1];
01152     Part::Geometry *geo2 = geomlist[GeoId2];
01153 
01154     if (geo1->getTypeId() != Part::GeomLineSegment::getClassTypeId() ||
01155         geo2->getTypeId() != Part::GeomLineSegment::getClassTypeId()) {
01156 
01157         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
01158         QObject::tr("Select exactly two lines from the sketch."));
01159         return;
01160     }
01161 
01162     // undo command open
01163     openCommand("add perpendicular constraint");
01164     Gui::Command::doCommand(
01165         Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Perpendicular',%d,%d)) ",
01166         selection[0].getFeatName(),GeoId1,GeoId2);
01167 
01168     // finish the transaction and update
01169     commitCommand();
01170     updateActive();
01171 
01172     // clear the selection (convenience)
01173     getSelection().clearSelection();
01174 }
01175 
01176 bool CmdSketcherConstrainPerpendicular::isActive(void)
01177 {
01178     return isCreateConstraintActive( getActiveGuiDocument() );
01179 }
01180 
01181 
01182 DEF_STD_CMD_A(CmdSketcherConstrainTangent);
01183 
01184 CmdSketcherConstrainTangent::CmdSketcherConstrainTangent()
01185     :Command("Sketcher_ConstrainTangent")
01186 {
01187     sAppModule      = "Sketcher";
01188     sGroup          = QT_TR_NOOP("Sketcher");
01189     sMenuText       = QT_TR_NOOP("Constrain tangent");
01190     sToolTipText    = QT_TR_NOOP("Create a tangent constraint between two entities");
01191     sWhatsThis      = sToolTipText;
01192     sStatusTip      = sToolTipText;
01193     sPixmap         = "Constraint_Tangent";
01194     sAccel          = "T";
01195     eType           = ForEdit;
01196 }
01197 
01198 void CmdSketcherConstrainTangent::activated(int iMsg)
01199 {
01200     // get the selection
01201     std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx();
01202 
01203     // only one sketch with its subelements are allowed to be selected
01204     if (selection.size() != 1) {
01205         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
01206             QObject::tr("Select two entities from the sketch."));
01207         return;
01208     }
01209 
01210     // get the needed lists and objects
01211     const std::vector<std::string> &SubNames = selection[0].getSubNames();
01212     Sketcher::SketchObject* Obj = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject());
01213 
01214     if (SubNames.size() != 2) {
01215         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
01216             QObject::tr("Select exactly two entities from the sketch."));
01217         return;
01218     }
01219 
01220     int GeoId1=Constraint::GeoUndef, VtId1=-1, GeoId2=Constraint::GeoUndef, VtId2=-1;
01221     if (SubNames[0].size() > 4 && SubNames[0].substr(0,4) == "Edge")
01222         GeoId1 = std::atoi(SubNames[0].substr(4,4000).c_str());
01223     else if (SubNames[0].size() > 6 && SubNames[0].substr(0,6) == "Vertex")
01224         VtId1 = std::atoi(SubNames[0].substr(6,4000).c_str());
01225 
01226     if (SubNames[1].size() > 4 && SubNames[1].substr(0,4) == "Edge")
01227         GeoId2 = std::atoi(SubNames[1].substr(4,4000).c_str());
01228     else if (SubNames[1].size() > 6 && SubNames[1].substr(0,6) == "Vertex")
01229         VtId2 = std::atoi(SubNames[1].substr(6,4000).c_str());
01230 
01231     Sketcher::PointPos PosId1,PosId2;
01232     if (VtId1 >= 0 && VtId2 >= 0) { // tangency at common point
01233         Obj->getGeoVertexIndex(VtId1,GeoId1,PosId1);
01234         Obj->getGeoVertexIndex(VtId2,GeoId2,PosId2);
01235         openCommand("add tangent constraint");
01236         Gui::Command::doCommand(
01237             Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Tangent',%d,%d,%d,%d)) ",
01238             selection[0].getFeatName(),GeoId1,PosId1,GeoId2,PosId2);
01239         commitCommand();
01240         updateActive();
01241         getSelection().clearSelection();
01242         return;
01243     }
01244     else if ((VtId1 >= 0 && GeoId2 >= 0) || (VtId2 >= 0 && GeoId1 >= 0)) { // VtId1 is a tangency point
01245         if (VtId2 >= 0 && GeoId1 >= 0) {
01246             VtId1 = VtId2;
01247             VtId2 = -1;
01248             GeoId2 = GeoId1;
01249             GeoId1 = -1;
01250         }
01251         Obj->getGeoVertexIndex(VtId1,GeoId1,PosId1);
01252         openCommand("add tangent constraint");
01253         Gui::Command::doCommand(
01254             Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Tangent',%d,%d,%d)) ",
01255             selection[0].getFeatName(),GeoId1,PosId1,GeoId2);
01256         commitCommand();
01257         updateActive();
01258         getSelection().clearSelection();
01259         return;
01260     }
01261     else if (GeoId1 >= 0 && GeoId2 >= 0) { // simple tangency between GeoId1 and GeoId2
01262         openCommand("add tangent constraint");
01263         Gui::Command::doCommand(
01264             Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Tangent',%d,%d)) ",
01265             selection[0].getFeatName(),GeoId1,GeoId2);
01266         commitCommand();
01267         updateActive();
01268         getSelection().clearSelection();
01269         return;
01270     }
01271     QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
01272         QObject::tr("Select exactly two entities from the sketch."));
01273     return;
01274 }
01275 
01276 bool CmdSketcherConstrainTangent::isActive(void)
01277 {
01278     return isCreateConstraintActive( getActiveGuiDocument() );
01279 }
01280 
01281 
01282 DEF_STD_CMD_A(CmdSketcherConstrainRadius);
01283 
01284 CmdSketcherConstrainRadius::CmdSketcherConstrainRadius()
01285     :Command("Sketcher_ConstrainRadius")
01286 {
01287     sAppModule      = "Sketcher";
01288     sGroup          = QT_TR_NOOP("Sketcher");
01289     sMenuText       = QT_TR_NOOP("Constrain radius");
01290     sToolTipText    = QT_TR_NOOP("Fix the radius of a circle or an arc");
01291     sWhatsThis      = sToolTipText;
01292     sStatusTip      = sToolTipText;
01293     sPixmap         = "Constraint_Radius";
01294     sAccel          = "R";
01295     eType           = ForEdit;
01296 }
01297 
01298 void CmdSketcherConstrainRadius::activated(int iMsg)
01299 {
01300     // get the selection
01301     std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx();
01302 
01303     // only one sketch with its subelements are allowed to be selected
01304     if (selection.size() != 1) {
01305         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
01306             QObject::tr("Select exactly one arc or circle from the sketch."));
01307         return;
01308     }
01309 
01310     // get the needed lists and objects
01311     const std::vector<std::string> &SubNames = selection[0].getSubNames();
01312     Sketcher::SketchObject* Obj = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject());
01313     const std::vector<Part::Geometry *> &geo = Obj->Geometry.getValues();
01314 
01315     if (SubNames.size() != 1) {
01316         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
01317             QObject::tr("Select exactly one arc or circle from the sketch."));
01318         return;
01319     }
01320 
01321     if (SubNames[0].size() > 4 && SubNames[0].substr(0,4) == "Edge") {
01322         int GeoId = std::atoi(SubNames[0].substr(4,4000).c_str());
01323 
01324         const Part::Geometry *geom = geo[GeoId];
01325         if (geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) {
01326             const Part::GeomArcOfCircle *arc = dynamic_cast<const Part::GeomArcOfCircle *>(geom);
01327             double ActRadius = arc->getRadius();
01328 
01329             openCommand("add radius constraint");
01330             Gui::Command::doCommand(
01331                 Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Radius',%d,%f)) ",
01332                 selection[0].getFeatName(),GeoId,ActRadius);
01333             commitCommand();
01334             //updateActive();
01335             getSelection().clearSelection();
01336             return;
01337         }
01338         else if (geom->getTypeId() == Part::GeomCircle::getClassTypeId()) {
01339             const Part::GeomCircle *circle = dynamic_cast<const Part::GeomCircle *>(geom);
01340             double ActRadius = circle->getRadius();
01341 
01342             openCommand("add radius constraint");
01343             Gui::Command::doCommand(
01344                 Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Radius',%d,%f)) ",
01345                 selection[0].getFeatName(),GeoId,ActRadius);
01346             commitCommand();
01347             //updateActive();
01348             getSelection().clearSelection();
01349             return;
01350         }
01351     }
01352 
01353     QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
01354         QObject::tr("Select exactly one arc or circle from the sketch."));
01355     return;
01356 }
01357 
01358 bool CmdSketcherConstrainRadius::isActive(void)
01359 {
01360     return isCreateConstraintActive( getActiveGuiDocument() );
01361 }
01362 
01363 
01364 DEF_STD_CMD_A(CmdSketcherConstrainAngle);
01365 
01366 CmdSketcherConstrainAngle::CmdSketcherConstrainAngle()
01367     :Command("Sketcher_ConstrainAngle")
01368 {
01369     sAppModule      = "Sketcher";
01370     sGroup          = QT_TR_NOOP("Sketcher");
01371     sMenuText       = QT_TR_NOOP("Constrain angle");
01372     sToolTipText    = QT_TR_NOOP("Fix the angle of a line or the angle between two lines");
01373     sWhatsThis      = sToolTipText;
01374     sStatusTip      = sToolTipText;
01375     sPixmap         = "Constraint_InternalAngle";
01376     sAccel          = "A";
01377     eType           = ForEdit;
01378 }
01379 
01380 void CmdSketcherConstrainAngle::activated(int iMsg)
01381 {
01382     // get the selection
01383     std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx();
01384 
01385     // only one sketch with its subelements are allowed to be selected
01386     if (selection.size() != 1) {
01387         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
01388             QObject::tr("Select vertexes from the sketch."));
01389         return;
01390     }
01391 
01392     // get the needed lists and objects
01393     const std::vector<std::string> &SubNames = selection[0].getSubNames();
01394     Sketcher::SketchObject* Obj = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject());
01395     const std::vector<Part::Geometry *> &geo = Obj->Geometry.getValues();
01396 
01397     if (SubNames.size() < 1 || SubNames.size() > 2) {
01398         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
01399             QObject::tr("Select exactly one or two lines from the sketch."));
01400         return;
01401     }
01402 
01403     int GeoId1=Constraint::GeoUndef, GeoId2=Constraint::GeoUndef;
01404     if (SubNames[0].size() > 4 && SubNames[0].substr(0,4) == "Edge")
01405         GeoId1 = std::atoi(SubNames[0].substr(4,4000).c_str());
01406     if (SubNames.size() == 2) {
01407         if (SubNames[1].size() > 4 && SubNames[1].substr(0,4) == "Edge")
01408             GeoId2 = std::atoi(SubNames[1].substr(4,4000).c_str());
01409     }
01410 
01411     if (GeoId2 >= 0) { // line to line angle
01412         const Part::Geometry *geom1 = geo[GeoId1];
01413         const Part::Geometry *geom2 = geo[GeoId2];
01414         if (geom1->getTypeId() == Part::GeomLineSegment::getClassTypeId() &&
01415             geom2->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
01416             const Part::GeomLineSegment *lineSeg1 = dynamic_cast<const Part::GeomLineSegment*>(geom1);
01417             const Part::GeomLineSegment *lineSeg2 = dynamic_cast<const Part::GeomLineSegment*>(geom2);
01418 
01419             // find the two closest line ends
01420             Sketcher::PointPos PosId1,PosId2;
01421             Base::Vector3d p1a = lineSeg1->getStartPoint();
01422             Base::Vector3d p1b = lineSeg1->getEndPoint();
01423             Base::Vector3d p2a = lineSeg2->getStartPoint();
01424             Base::Vector3d p2b = lineSeg2->getEndPoint();
01425             double length = 1e10;
01426             for (int i=0; i <= 1; i++)
01427                 for (int j=0; j <= 1; j++) {
01428                     double tmp = ((j?p2a:p2b)-(i?p1a:p1b)).Length();
01429                     if (tmp < length) {
01430                         length = tmp;
01431                         PosId1 = i ? Sketcher::start : Sketcher::end;
01432                         PosId2 = j ? Sketcher::start : Sketcher::end;
01433                     }
01434                 }
01435 
01436             Base::Vector3d dir1 = ((PosId1 == Sketcher::start) ? 1. : -1.) *
01437                                   (lineSeg1->getEndPoint()-lineSeg1->getStartPoint());
01438             Base::Vector3d dir2 = ((PosId2 == Sketcher::start) ? 1. : -1.) *
01439                                   (lineSeg2->getEndPoint()-lineSeg2->getStartPoint());
01440 
01441             double ActAngle = atan2(-dir1.y*dir2.x+dir1.x*dir2.y,
01442                                     dir1.x*dir2.x+dir1.y*dir2.y);
01443             if (ActAngle < 0) {
01444                 ActAngle *= -1;
01445                 std::swap(GeoId1,GeoId2);
01446                 std::swap(PosId1,PosId2);
01447             }
01448 
01449             openCommand("add angle constraint");
01450             Gui::Command::doCommand(
01451                 Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Angle',%d,%d,%d,%d,%f)) ",
01452                 selection[0].getFeatName(),GeoId1,PosId1,GeoId2,PosId2,ActAngle);
01453             commitCommand();
01454 
01455             // Get the latest created constraint
01456             const std::vector<Sketcher::Constraint *> &ConStr = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject())->Constraints.getValues();
01457             Sketcher::Constraint *constr = ConStr[ConStr.size() -1];
01458 
01459             updateDatumDistance(getActiveGuiDocument(), constr);
01460 
01461             //updateActive();
01462             getSelection().clearSelection();
01463             return;
01464         }
01465     } else if (GeoId1 >= 0) { // line angle
01466         const Part::Geometry *geom = geo[GeoId1];
01467         if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
01468             const Part::GeomLineSegment *lineSeg;
01469             lineSeg = dynamic_cast<const Part::GeomLineSegment*>(geom);
01470             Base::Vector3d dir = lineSeg->getEndPoint()-lineSeg->getStartPoint();
01471             double ActAngle = atan2(dir.y,dir.x);
01472 
01473             openCommand("add angle constraint");
01474             Gui::Command::doCommand(
01475                 Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Angle',%d,%f)) ",
01476                 selection[0].getFeatName(),GeoId1,ActAngle);
01477             commitCommand();
01478 
01479             // Get the latest constraint
01480             const std::vector<Sketcher::Constraint *> &ConStr = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject())->Constraints.getValues();
01481             Sketcher::Constraint *constr = ConStr[ConStr.size() -1];
01482 
01483             float sf = 1.f;
01484             Gui::Document *doc = getActiveGuiDocument();
01485             if (doc && doc->getInEdit() && doc->getInEdit()->isDerivedFrom(SketcherGui::ViewProviderSketch::getClassTypeId())) {
01486                 SketcherGui::ViewProviderSketch *vp = dynamic_cast<SketcherGui::ViewProviderSketch*>(doc->getInEdit());
01487                 sf = vp->getScaleFactor();
01488 
01489                 constr->LabelDistance = 2. * sf;
01490                 vp->draw(); // Redraw
01491             }
01492 
01493             //updateActive();
01494             getSelection().clearSelection();
01495             return;
01496         }
01497     }
01498 
01499     QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
01500         QObject::tr("Select exactly one or two lines from the sketch."));
01501     return;
01502 }
01503 
01504 bool CmdSketcherConstrainAngle::isActive(void)
01505 {
01506     return isCreateConstraintActive( getActiveGuiDocument() );
01507 }
01508 
01509 
01510 DEF_STD_CMD_A(CmdSketcherConstrainEqual);
01511 
01512 CmdSketcherConstrainEqual::CmdSketcherConstrainEqual()
01513     :Command("Sketcher_ConstrainEqual")
01514 {
01515     sAppModule      = "Sketcher";
01516     sGroup          = QT_TR_NOOP("Sketcher");
01517     sMenuText       = QT_TR_NOOP("Constrain equal");
01518     sToolTipText    = QT_TR_NOOP("Create an equality constraint between two lines or between circles and arcs");
01519     sWhatsThis      = sToolTipText;
01520     sStatusTip      = sToolTipText;
01521     sPixmap         = "Constraint_EqualLength";
01522     sAccel          = "E";
01523     eType           = ForEdit;
01524 }
01525 
01526 void CmdSketcherConstrainEqual::activated(int iMsg)
01527 {
01528     // get the selection
01529     std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx();
01530 
01531     // only one sketch with its subelements are allowed to be selected
01532     if (selection.size() != 1) {
01533         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
01534             QObject::tr("Select two edges from the sketch."));
01535         return;
01536     }
01537 
01538     // get the needed lists and objects
01539     const std::vector<std::string> &SubNames = selection[0].getSubNames();
01540     Sketcher::SketchObject* Obj = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject());
01541     const std::vector< Sketcher::Constraint * > &vals = Obj->Constraints.getValues();
01542     const std::vector<Part::Geometry *> &geomlist = Obj->Geometry.getValues();
01543 
01544     // go through the selected subelements
01545 
01546     if (SubNames.size() < 2) {
01547         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
01548             QObject::tr("Select atleast two lines from the sketch."));
01549         return;
01550     }
01551 
01552     std::vector<int> ids;
01553     bool lineSel = false, arcSel = false, circSel = false;
01554 
01555     for (std::vector<std::string>::const_iterator it=SubNames.begin(); it != SubNames.end(); ++it) {
01556         int index;
01557         std::string subName = *it;
01558         if (subName.size() > 4 && subName.substr(0,4) == "Edge")
01559             index = std::atoi(subName.substr(4,4000).c_str());
01560         else {
01561             QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
01562                                  QObject::tr("Select exactly two same geometries"));
01563             return;
01564         }
01565 
01566         Part::Geometry *geo = geomlist[index];
01567         if (geo->getTypeId() != Part::GeomLineSegment::getClassTypeId()) {
01568             lineSel = true;
01569         } else if (geo->getTypeId() != Part::GeomArcOfCircle::getClassTypeId()) {
01570             arcSel = true;
01571         } else if (geo->getTypeId() != Part::GeomCircle::getClassTypeId()) {
01572             circSel = true;
01573         } else {
01574             QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
01575             QObject::tr("Select valid geometries"));
01576             return;
01577         }
01578 
01579         ids.push_back(index);
01580     }
01581 
01582     if (lineSel && (arcSel || circSel)) {
01583         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
01584         QObject::tr("Select geometry of similar type"));
01585         return;
01586     }
01587 
01588     // undo command open
01589     openCommand("add equality constraint");
01590     int i = 0;
01591     for (std::vector<int>::iterator it = ids.begin(); it!=ids.end();it++, i++) {
01592         if( i == ids.size() - 1)
01593             break;
01594         Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Equal',%d,%d)) ",
01595             selection[0].getFeatName(),ids[i],ids[i+1]);
01596     }
01597     // finish the transaction and update
01598     commitCommand();
01599     updateActive();
01600 
01601     // clear the selection (convenience)
01602     getSelection().clearSelection();
01603 }
01604 
01605 bool CmdSketcherConstrainEqual::isActive(void)
01606 {
01607     return isCreateConstraintActive( getActiveGuiDocument() );
01608 }
01609 
01610 
01611 DEF_STD_CMD_A(CmdSketcherConstrainSymmetric);
01612 
01613 CmdSketcherConstrainSymmetric::CmdSketcherConstrainSymmetric()
01614     :Command("Sketcher_ConstrainSymmetric")
01615 {
01616     sAppModule      = "Sketcher";
01617     sGroup          = QT_TR_NOOP("Sketcher");
01618     sMenuText       = QT_TR_NOOP("Constrain symmetrical");
01619     sToolTipText    = QT_TR_NOOP("Create an symmetry constraint between two points with respect to a line");
01620     sWhatsThis      = sToolTipText;
01621     sStatusTip      = sToolTipText;
01622     sPixmap         = "Constraint_Symmetric";
01623     sAccel          = "S";
01624     eType           = ForEdit;
01625 }
01626 
01627 void CmdSketcherConstrainSymmetric::activated(int iMsg)
01628 {
01629     // get the selection
01630     std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx();
01631     Sketcher::SketchObject* Obj = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject());
01632     const std::vector<Part::Geometry *> &geo = Obj->Geometry.getValues();
01633 
01634     // only one sketch with its subelements are allowed to be selected
01635     if (selection.size() != 1) {
01636         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
01637             QObject::tr("Select two points and one line from the sketch."));
01638         return;
01639     }
01640 
01641     // get the needed lists and objects
01642     const std::vector<std::string> &SubNames = selection[0].getSubNames();
01643 
01644     if (SubNames.size() != 3) {
01645         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
01646             QObject::tr("Select two points and one line from the sketch."));
01647         return;
01648     }
01649 
01650     int GeoId1=Constraint::GeoUndef, VtId1=-1,
01651         GeoId2=Constraint::GeoUndef, VtId2=-1,
01652         GeoId3=Constraint::GeoUndef, VtId3=-1;
01653     if (SubNames.size() >= 1) {
01654         if (SubNames[0].size() > 4 && SubNames[0].substr(0,4) == "Edge")
01655             GeoId1 = std::atoi(SubNames[0].substr(4,4000).c_str());
01656         else if (SubNames[0].size() > 6 && SubNames[0].substr(0,6) == "Vertex")
01657             VtId1 = std::atoi(SubNames[0].substr(6,4000).c_str());
01658         if (SubNames[1].size() > 4 && SubNames[1].substr(0,4) == "Edge")
01659             GeoId2 = std::atoi(SubNames[1].substr(4,4000).c_str());
01660         else if (SubNames[1].size() > 6 && SubNames[1].substr(0,6) == "Vertex")
01661             VtId2 = std::atoi(SubNames[1].substr(6,4000).c_str());
01662         if (SubNames[2].size() > 4 && SubNames[2].substr(0,4) == "Edge")
01663             GeoId3 = std::atoi(SubNames[2].substr(4,4000).c_str());
01664         else if (SubNames[2].size() > 6 && SubNames[2].substr(0,6) == "Vertex")
01665             VtId3 = std::atoi(SubNames[2].substr(6,4000).c_str());
01666     }
01667 
01668     if (GeoId1 != Constraint::GeoUndef && GeoId3 == Constraint::GeoUndef) {
01669         std::swap(GeoId1,GeoId3);
01670         std::swap(VtId1,VtId3);
01671     }
01672     else if (GeoId2 != Constraint::GeoUndef && GeoId3 == Constraint::GeoUndef) {
01673         std::swap(GeoId2,GeoId3);
01674         std::swap(VtId2,VtId3);
01675     }
01676 
01677     if (VtId1 >= 0 && VtId2 >= 0 && GeoId3 != Constraint::GeoUndef) {
01678         Sketcher::PointPos PosId1,PosId2;
01679         Obj->getGeoVertexIndex(VtId1,GeoId1,PosId1);
01680         Obj->getGeoVertexIndex(VtId2,GeoId2,PosId2);
01681         const Part::Geometry *geom = geo[GeoId3];
01682         if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
01683             // undo command open
01684             openCommand("add symmetric constraint");
01685             Gui::Command::doCommand(
01686                 Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Symmetric',%d,%d,%d,%d,%d)) ",
01687                 selection[0].getFeatName(),GeoId1,PosId1,GeoId2,PosId2,GeoId3);
01688 
01689             // finish the transaction and update
01690             commitCommand();
01691             updateActive();
01692 
01693             // clear the selection (convenience)
01694             getSelection().clearSelection();
01695             return;
01696         }
01697     }
01698     QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
01699         QObject::tr("Select two points and one line from the sketch."));
01700 }
01701 
01702 bool CmdSketcherConstrainSymmetric::isActive(void)
01703 {
01704     return isCreateConstraintActive( getActiveGuiDocument() );
01705 }
01706 
01707 
01708 
01709 void CreateSketcherCommandsConstraints(void)
01710 {
01711     Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager();
01712 
01713     rcCmdMgr.addCommand(new CmdSketcherConstrainHorizontal());
01714     rcCmdMgr.addCommand(new CmdSketcherConstrainVertical());
01715     rcCmdMgr.addCommand(new CmdSketcherConstrainLock());
01716     rcCmdMgr.addCommand(new CmdSketcherConstrainCoincident());
01717     rcCmdMgr.addCommand(new CmdSketcherConstrainParallel());
01718     rcCmdMgr.addCommand(new CmdSketcherConstrainPerpendicular());
01719     rcCmdMgr.addCommand(new CmdSketcherConstrainTangent());
01720     rcCmdMgr.addCommand(new CmdSketcherConstrainDistance());
01721     rcCmdMgr.addCommand(new CmdSketcherConstrainDistanceX());
01722     rcCmdMgr.addCommand(new CmdSketcherConstrainDistanceY());
01723     rcCmdMgr.addCommand(new CmdSketcherConstrainRadius());
01724     rcCmdMgr.addCommand(new CmdSketcherConstrainAngle());
01725     rcCmdMgr.addCommand(new CmdSketcherConstrainEqual());
01726     rcCmdMgr.addCommand(new CmdSketcherConstrainPointOnObject());
01727     rcCmdMgr.addCommand(new CmdSketcherConstrainSymmetric());
01728  }

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