diff --git a/src/Mod/Sketcher/Gui/CommandConstraints.cpp b/src/Mod/Sketcher/Gui/CommandConstraints.cpp index e6a75e8ac1..a181e3e38c 100644 --- a/src/Mod/Sketcher/Gui/CommandConstraints.cpp +++ b/src/Mod/Sketcher/Gui/CommandConstraints.cpp @@ -2592,6 +2592,347 @@ bool CmdSketcherDimension::isActive(void) return isCommandActive(getActiveGuiDocument()); } +// Comp for horizontal/vertical ============================================= + +class CmdSketcherCompHorizontalVertical : public Gui::GroupCommand +{ +public: + CmdSketcherCompHorizontalVertical() + : GroupCommand("Sketcher_CompHorVer") + { + sAppModule = "Sketcher"; + sGroup = "Sketcher"; + sMenuText = QT_TR_NOOP("Horizontal/Vertical"); + sToolTipText = QT_TR_NOOP("Constrains a single line to either horizontal or vertical."); + sWhatsThis = "Sketcher_CompHorVer"; + sStatusTip = sToolTipText; + eType = ForEdit; + + setCheckable(false); + + addCommand("Sketcher_ConstrainHorVer"); + addCommand("Sketcher_ConstrainHorizontal"); + addCommand("Sketcher_ConstrainVertical"); + } + + const char* className() const override { return "CmdSketcherCompDimensionTools"; } +}; + +// ============================================================================ +bool canHorVerBlock(Sketcher::SketchObject* Obj, int geoId) +{ + const std::vector& vals = Obj->Constraints.getValues(); + + // check if the edge already has a Horizontal/Vertical/Block constraint + for (auto& constr : vals) { + if (constr->Type == Sketcher::Horizontal && constr->First == geoId + && constr->FirstPos == Sketcher::PointPos::none) { + Gui::TranslatedUserWarning( + Obj, + QObject::tr("Double constraint"), + QObject::tr("The selected edge already has a horizontal constraint!")); + return false; + } + if (constr->Type == Sketcher::Vertical && constr->First == geoId + && constr->FirstPos == Sketcher::PointPos::none) { + Gui::TranslatedUserWarning( + Obj, + QObject::tr("Impossible constraint"), + QObject::tr("The selected edge already has a vertical constraint!")); + return false; + } + // check if the edge already has a Block constraint + if (constr->Type == Sketcher::Block && constr->First == geoId + && constr->FirstPos == Sketcher::PointPos::none) { + Gui::TranslatedUserWarning( + Obj, + QObject::tr("Impossible constraint"), + QObject::tr("The selected edge already has a Block constraint!")); + return false; + } + } + return true; +} + +void horVerActivated(CmdSketcherConstraint* cmd, std::string type) +{ + // get the selection + std::vector selection = Gui::Command::getSelection().getSelectionEx(); + + // only one sketch with its subelements are allowed to be selected + if (selection.size() != 1 + || !selection[0].isObjectTypeOf(Sketcher::SketchObject::getClassTypeId())) { + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/Mod/Sketcher"); + bool constraintMode = hGrp->GetBool("ContinuousConstraintMode", true); + + if (constraintMode) { + ActivateHandler(cmd->getActiveGuiDocument(), new DrawSketchHandlerGenConstraint(cmd)); + Gui::Command::getSelection().clearSelection(); + } + else { + Gui::TranslatedUserWarning(cmd->getActiveGuiDocument(), + QObject::tr("Wrong selection"), + QObject::tr("Select an edge from the sketch.")); + } + return; + } + + // get the needed lists and objects + const std::vector& SubNames = selection[0].getSubNames(); + auto* Obj = static_cast(selection[0].getObject()); + const std::vector& vals = Obj->Constraints.getValues(); + + std::vector edgegeoids; + std::vector pointgeoids; + std::vector pointpos; + + int fixedpoints = 0; + + for (auto& name : SubNames) { + int GeoId; + Sketcher::PointPos PosId; + getIdsFromName(name, Obj, GeoId, PosId); + + if (isEdge(GeoId, PosId)) {// it is an edge + const Part::Geometry* geo = Obj->getGeometry(GeoId); + + if (!isLineSegment(*geo)) { + Gui::TranslatedUserWarning(Obj, + QObject::tr("Impossible constraint"), + QObject::tr("The selected edge is not a line segment.")); + return; + } + + if (canHorVerBlock(Obj, GeoId)) { + edgegeoids.push_back(GeoId); + } + } + else if (isVertex(GeoId, PosId)) { + // can be a point, a construction point, an external point or root + + if (isPointOrSegmentFixed(Obj, GeoId)) { + fixedpoints++; + } + + pointgeoids.push_back(GeoId); + pointpos.push_back(PosId); + } + } + + if (edgegeoids.empty() && pointgeoids.empty()) { + Gui::TranslatedUserWarning( + Obj, + QObject::tr("Impossible constraint"), + QObject::tr("The selected item(s) can't accept a horizontal or vertical constraint!")); + return; + } + + // if there is at least one edge selected, ignore the point alignment functionality + if (!edgegeoids.empty()) { + // undo command open + const char* cmdName = type == "Horizontal" ? "Add horizontal constraint" : type == "Vertical" ? "Add vertical constraint" : "Add horizontal/vertical constraint"; + Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", cmdName)); + for (auto& geoId : edgegeoids) { + std::string typeToApply = type; + if (type == "HorVer") { + const Part::Geometry* geo = Obj->getGeometry(geoId); + auto* line = static_cast(geo); + double angle = toVector2d(line->getEndPoint() - line->getStartPoint()).Angle(); + typeToApply = fabs(sin(angle)) < fabs(cos(angle)) ? "Horizontal" : "Vertical"; + } + + Gui::cmdAppObjectArgs(selection[0].getObject(), + "addConstraint(Sketcher.Constraint('%s',%d))", + typeToApply, + geoId); + } + } + else if (fixedpoints <= 1) {// pointgeoids + // undo command open + const char* cmdName = type == "Horizontal" ? "Add horizontal alignment" : type == "Vertical" ? "Add vertical alignment" : "Add horizontal/vertical alignment"; + Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", cmdName)); + std::vector::iterator it; + std::vector::iterator itp; + for (it = pointgeoids.begin(), itp = pointpos.begin(); + it != std::prev(pointgeoids.end()) && itp != std::prev(pointpos.end()); + it++, itp++) { + + std::string typeToApply = type; + if (type == "HorVer") { + auto point1 = Obj->getPoint(*it, *itp); + auto point2 = Obj->getPoint(*std::next(it), *std::next(itp)); + double angle = toVector2d(point2 - point1).Angle(); + typeToApply = fabs(sin(angle)) < fabs(cos(angle)) ? "Horizontal" : "Vertical"; + } + + Gui::cmdAppObjectArgs(selection[0].getObject(), + "addConstraint(Sketcher.Constraint('%s',%d,%d,%d,%d))", + typeToApply, + *it, + static_cast(*itp), + *std::next(it), + static_cast(*std::next(itp))); + } + } + else {// vertex mode, fixedpoints > 1 + Gui::TranslatedUserWarning(Obj, + QObject::tr("Impossible constraint"), + QObject::tr("There are more than one fixed points selected. " + "Select a maximum of one fixed point!")); + return; + } + // finish the transaction and update + Gui::Command::commitCommand(); + + tryAutoRecompute(Obj); + + // clear the selection (convenience) + Gui::Command::getSelection().clearSelection(); +} + +void horVerApplyConstraint(CmdSketcherConstraint* cmd, std::string type, std::vector& selSeq, int seqIndex) +{ + auto* sketchgui = + static_cast(cmd->getActiveGuiDocument()->getInEdit()); + Sketcher::SketchObject* Obj = sketchgui->getSketchObject(); + + switch (seqIndex) { + case 0:// {Edge} + { + // create the constraint + const std::vector& vals = Obj->Constraints.getValues(); + + int CrvId = selSeq.front().GeoId; + if (CrvId != -1) { + const Part::Geometry* geo = Obj->getGeometry(CrvId); + + if (!isLineSegment(*geo)) { + Gui::TranslatedUserWarning( + Obj, + QObject::tr("Impossible constraint"), + QObject::tr("The selected edge is not a line segment.")); + return; + } + + // check if the edge already has a Horizontal/Vertical/Block constraint + if (!canHorVerBlock(Obj, CrvId)) { + return; + } + + std::string typeToApply = type; + if (type == "HorVer") { + const Part::Geometry* geo = Obj->getGeometry(CrvId); + auto* line = static_cast(geo); + double angle = toVector2d(line->getEndPoint() - line->getStartPoint()).Angle(); + typeToApply = fabs(sin(angle)) < fabs(cos(angle)) ? "Horizontal" : "Vertical"; + } + + const char* cmdName = typeToApply == "Horizontal" ? "Add horizontal constraint" : "Add vertical constraint"; + Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", cmdName)); + + // issue the actual commands to create the constraint + Gui::cmdAppObjectArgs(sketchgui->getObject(), + "addConstraint(Sketcher.Constraint('%s',%d))", + typeToApply, + CrvId); + // finish the transaction and update + Gui::Command::commitCommand(); + + tryAutoRecompute(Obj); + } + + break; + } + + case 1:// {SelVertex, SelVertexOrRoot} + case 2:// {SelRoot, SelVertex} + { + int GeoId1, GeoId2; + Sketcher::PointPos PosId1, PosId2; + GeoId1 = selSeq.at(0).GeoId; + GeoId2 = selSeq.at(1).GeoId; + PosId1 = selSeq.at(0).PosId; + PosId2 = selSeq.at(1).PosId; + + if (areBothPointsOrSegmentsFixed(Obj, GeoId1, GeoId2)) { + showNoConstraintBetweenFixedGeometry(Obj); + return; + } + + std::string typeToApply = type; + if (type == "HorVer") { + auto point1 = Obj->getPoint(GeoId1, PosId1); + auto point2 = Obj->getPoint(GeoId2, PosId2); + double angle = toVector2d(point2 - point1).Angle(); + typeToApply = fabs(sin(angle)) < fabs(cos(angle)) ? "Horizontal" : "Vertical"; + } + + // undo command open + const char* cmdName = type == "Horizontal" ? "Add horizontal alignment" : "Add vertical alignment"; + Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", cmdName)); + + // issue the actual commands to create the constraint + Gui::cmdAppObjectArgs(sketchgui->getObject(), + "addConstraint(Sketcher.Constraint('%s',%d,%d,%d,%d))", + typeToApply, + GeoId1, + static_cast(PosId1), + GeoId2, + static_cast(PosId2)); + // finish the transaction and update + Gui::Command::commitCommand(); + + tryAutoRecompute(Obj); + + break; + } + } +} + +class CmdSketcherConstrainHorVer : public CmdSketcherConstraint +{ +public: + CmdSketcherConstrainHorVer(); + ~CmdSketcherConstrainHorVer() override + {} + const char* className() const override + { + return "CmdSketcherConstrainHorVer"; + } + +protected: + void activated(int iMsg) override; + void applyConstraint(std::vector& selSeq, int seqIndex) override; +}; + +CmdSketcherConstrainHorVer::CmdSketcherConstrainHorVer() + : CmdSketcherConstraint("Sketcher_ConstrainHorVer") +{ + sAppModule = "Sketcher"; + sGroup = "Sketcher"; + sMenuText = QT_TR_NOOP("Horizontal/Vertical"); + sToolTipText = QT_TR_NOOP("Constrains a single line to either horizontal or vertical, whichever is closer to current alignment."); + sWhatsThis = "Sketcher_ConstrainHorVer"; + sStatusTip = sToolTipText; + sPixmap = "Constraint_HorVer"; + sAccel = "A"; + eType = ForEdit; + + allowedSelSequences = { {SelEdge}, {SelVertex, SelVertexOrRoot}, {SelRoot, SelVertex} }; +} + +void CmdSketcherConstrainHorVer::activated(int iMsg) +{ + Q_UNUSED(iMsg); + horVerActivated(this, "HorVer"); +} + +void CmdSketcherConstrainHorVer::applyConstraint(std::vector& selSeq, int seqIndex) +{ + horVerApplyConstraint(this, "HorVer", selSeq, seqIndex); +} + // ============================================================================ @@ -2630,255 +2971,12 @@ CmdSketcherConstrainHorizontal::CmdSketcherConstrainHorizontal() void CmdSketcherConstrainHorizontal::activated(int iMsg) { Q_UNUSED(iMsg); - - // get the selection - std::vector selection = getSelection().getSelectionEx(); - - // only one sketch with its subelements are allowed to be selected - if (selection.size() != 1 - || !selection[0].isObjectTypeOf(Sketcher::SketchObject::getClassTypeId())) { - ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath( - "User parameter:BaseApp/Preferences/Mod/Sketcher"); - bool constraintMode = hGrp->GetBool("ContinuousConstraintMode", true); - - if (constraintMode) { - ActivateHandler(getActiveGuiDocument(), new DrawSketchHandlerGenConstraint(this)); - getSelection().clearSelection(); - } - else { - Gui::TranslatedUserWarning(getActiveGuiDocument(), - QObject::tr("Wrong selection"), - QObject::tr("Select an edge from the sketch.")); - } - return; - } - - // get the needed lists and objects - const std::vector& SubNames = selection[0].getSubNames(); - Sketcher::SketchObject* Obj = static_cast(selection[0].getObject()); - const std::vector& vals = Obj->Constraints.getValues(); - - std::vector edgegeoids; - std::vector pointgeoids; - std::vector pointpos; - - int fixedpoints = 0; - // go through the selected subelements - for (std::vector::const_iterator it = SubNames.begin(); it != SubNames.end(); - ++it) { - int GeoId; - Sketcher::PointPos PosId; - getIdsFromName((*it), Obj, GeoId, PosId); - - if (isEdge(GeoId, PosId)) {// it is an edge - const Part::Geometry* geo = Obj->getGeometry(GeoId); - - if (! isLineSegment(*geo)) { - Gui::TranslatedUserWarning(Obj, - QObject::tr("Impossible constraint"), - QObject::tr("The selected edge is not a line segment.")); - return; - } - - // check if the edge already has a Horizontal/Vertical/Block constraint - for (std::vector::const_iterator it = vals.begin(); - it != vals.end(); - ++it) { - if ((*it)->Type == Sketcher::Horizontal && (*it)->First == GeoId - && (*it)->FirstPos == Sketcher::PointPos::none) { - Gui::TranslatedUserWarning( - Obj, - QObject::tr("Double constraint"), - QObject::tr("The selected edge already has a horizontal constraint!")); - return; - } - if ((*it)->Type == Sketcher::Vertical && (*it)->First == GeoId - && (*it)->FirstPos == Sketcher::PointPos::none) { - Gui::TranslatedUserWarning( - Obj, - QObject::tr("Impossible constraint"), - QObject::tr("The selected edge already has a vertical constraint!")); - return; - } - // check if the edge already has a Block constraint - if ((*it)->Type == Sketcher::Block && (*it)->First == GeoId - && (*it)->FirstPos == Sketcher::PointPos::none) { - Gui::TranslatedUserWarning( - Obj, - QObject::tr("Impossible constraint"), - QObject::tr("The selected edge already has a Block constraint!")); - return; - } - } - edgegeoids.push_back(GeoId); - } - else if (isVertex(GeoId, PosId)) { - // can be a point, a construction point, an external point or root - - if (isPointOrSegmentFixed(Obj, GeoId)) { - fixedpoints++; - } - - pointgeoids.push_back(GeoId); - pointpos.push_back(PosId); - } - } - - if (edgegeoids.empty() && pointgeoids.empty()) { - Gui::TranslatedUserWarning( - Obj, - QObject::tr("Impossible constraint"), - QObject::tr("The selected item(s) can't accept a horizontal constraint!")); - return; - } - - // if there is at least one edge selected, ignore the point alignment functionality - if (!edgegeoids.empty()) { - // undo command open - openCommand(QT_TRANSLATE_NOOP("Command", "Add horizontal constraint")); - for (std::vector::iterator it = edgegeoids.begin(); it != edgegeoids.end(); it++) { - // issue the actual commands to create the constraint - Gui::cmdAppObjectArgs(selection[0].getObject(), - "addConstraint(Sketcher.Constraint('Horizontal',%d))", - *it); - } - } - else if (fixedpoints <= 1) {// pointgeoids - // undo command open - openCommand(QT_TRANSLATE_NOOP("Command", "Add horizontal alignment")); - std::vector::iterator it; - std::vector::iterator itp; - for (it = pointgeoids.begin(), itp = pointpos.begin(); - it != std::prev(pointgeoids.end()) && itp != std::prev(pointpos.end()); - it++, itp++) { - // issue the actual commands to create the constraint - Gui::cmdAppObjectArgs(selection[0].getObject(), - "addConstraint(Sketcher.Constraint('Horizontal',%d,%d,%d,%d))", - *it, - static_cast(*itp), - *std::next(it), - static_cast(*std::next(itp))); - } - } - else {// vertex mode, fixedpoints > 1 - Gui::TranslatedUserWarning(Obj, - QObject::tr("Impossible constraint"), - QObject::tr("There are more than one fixed points selected. " - "Select a maximum of one fixed point!")); - return; - } - // finish the transaction and update - commitCommand(); - - tryAutoRecompute(Obj); - - // clear the selection (convenience) - getSelection().clearSelection(); + horVerActivated(this, "Horizontal"); } void CmdSketcherConstrainHorizontal::applyConstraint(std::vector& selSeq, int seqIndex) { - SketcherGui::ViewProviderSketch* sketchgui = - static_cast(getActiveGuiDocument()->getInEdit()); - Sketcher::SketchObject* Obj = sketchgui->getSketchObject(); - - switch (seqIndex) { - case 0:// {Edge} - { - // create the constraint - const std::vector& vals = Obj->Constraints.getValues(); - - int CrvId = selSeq.front().GeoId; - if (CrvId != -1) { - const Part::Geometry* geo = Obj->getGeometry(CrvId); - - if (! isLineSegment(*geo)) { - Gui::TranslatedUserWarning( - Obj, - QObject::tr("Impossible constraint"), - QObject::tr("The selected edge is not a line segment.")); - return; - } - - // check if the edge already has a Horizontal/Vertical/Block constraint - for (std::vector::const_iterator it = vals.begin(); - it != vals.end(); - ++it) { - if ((*it)->Type == Sketcher::Horizontal && (*it)->First == CrvId - && (*it)->FirstPos == Sketcher::PointPos::none) { - Gui::TranslatedUserWarning( - Obj, - QObject::tr("Double constraint"), - QObject::tr("The selected edge already has a horizontal constraint!")); - return; - } - if ((*it)->Type == Sketcher::Vertical && (*it)->First == CrvId - && (*it)->FirstPos == Sketcher::PointPos::none) { - Gui::TranslatedUserWarning( - Obj, - QObject::tr("Impossible constraint"), - QObject::tr("The selected edge already has a vertical constraint!")); - return; - } - // check if the edge already has a Block constraint - if ((*it)->Type == Sketcher::Block && (*it)->First == CrvId - && (*it)->FirstPos == Sketcher::PointPos::none) { - Gui::TranslatedUserWarning( - Obj, - QObject::tr("Impossible constraint"), - QObject::tr("The selected edge already has a Block constraint!")); - return; - } - } - - // undo command open - Gui::Command::openCommand( - QT_TRANSLATE_NOOP("Command", "Add horizontal constraint")); - // issue the actual commands to create the constraint - Gui::cmdAppObjectArgs(sketchgui->getObject(), - "addConstraint(Sketcher.Constraint('Horizontal',%d))", - CrvId); - // finish the transaction and update - Gui::Command::commitCommand(); - - tryAutoRecompute(Obj); - } - - break; - } - - case 1:// {SelVertex, SelVertexOrRoot} - case 2:// {SelRoot, SelVertex} - { - int GeoId1, GeoId2; - Sketcher::PointPos PosId1, PosId2; - GeoId1 = selSeq.at(0).GeoId; - GeoId2 = selSeq.at(1).GeoId; - PosId1 = selSeq.at(0).PosId; - PosId2 = selSeq.at(1).PosId; - - if (areBothPointsOrSegmentsFixed(Obj, GeoId1, GeoId2)) { - showNoConstraintBetweenFixedGeometry(Obj); - return; - } - - // undo command open - Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Add horizontal alignment")); - // issue the actual commands to create the constraint - Gui::cmdAppObjectArgs(sketchgui->getObject(), - "addConstraint(Sketcher.Constraint('Horizontal',%d,%d,%d,%d))", - GeoId1, - static_cast(PosId1), - GeoId2, - static_cast(PosId2)); - // finish the transaction and update - Gui::Command::commitCommand(); - - tryAutoRecompute(Obj); - - break; - } - } + horVerApplyConstraint(this, "Horizontal", selSeq, seqIndex); } // ================================================================================ @@ -2918,253 +3016,12 @@ CmdSketcherConstrainVertical::CmdSketcherConstrainVertical() void CmdSketcherConstrainVertical::activated(int iMsg) { Q_UNUSED(iMsg); - - // get the selection - std::vector selection = getSelection().getSelectionEx(); - - // only one sketch with its subelements are allowed to be selected - if (selection.size() != 1 - || !selection[0].isObjectTypeOf(Sketcher::SketchObject::getClassTypeId())) { - ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath( - "User parameter:BaseApp/Preferences/Mod/Sketcher"); - bool constraintMode = hGrp->GetBool("ContinuousConstraintMode", true); - - if (constraintMode) { - ActivateHandler(getActiveGuiDocument(), new DrawSketchHandlerGenConstraint(this)); - getSelection().clearSelection(); - } - else { - Gui::TranslatedUserWarning(getActiveGuiDocument(), - QObject::tr("Wrong selection"), - QObject::tr("Select an edge from the sketch.")); - } - return; - } - - // get the needed lists and objects - const std::vector& SubNames = selection[0].getSubNames(); - Sketcher::SketchObject* Obj = static_cast(selection[0].getObject()); - const std::vector& vals = Obj->Constraints.getValues(); - - std::vector edgegeoids; - std::vector pointgeoids; - std::vector pointpos; - - int fixedpoints = 0; - // go through the selected subelements - for (std::vector::const_iterator it = SubNames.begin(); it != SubNames.end(); - ++it) { - int GeoId; - Sketcher::PointPos PosId; - getIdsFromName((*it), Obj, GeoId, PosId); - - if (isEdge(GeoId, PosId)) {// it is an edge - const Part::Geometry* geo = Obj->getGeometry(GeoId); - - if (! isLineSegment(*geo)) { - Gui::TranslatedUserWarning(Obj, - QObject::tr("Impossible constraint"), - QObject::tr("The selected edge is not a line segment.")); - return; - } - - // check if the edge already has a Horizontal/Vertical/Block constraint - for (std::vector::const_iterator it = vals.begin(); - it != vals.end(); - ++it) { - if ((*it)->Type == Sketcher::Vertical && (*it)->First == GeoId - && (*it)->FirstPos == Sketcher::PointPos::none) { - Gui::TranslatedUserWarning( - Obj, - QObject::tr("Double constraint"), - QObject::tr("The selected edge already has a horizontal constraint!")); - return; - } - if ((*it)->Type == Sketcher::Horizontal && (*it)->First == GeoId - && (*it)->FirstPos == Sketcher::PointPos::none) { - Gui::TranslatedUserWarning( - Obj, - QObject::tr("Impossible constraint"), - QObject::tr("The selected edge already has a horizontal constraint!")); - return; - } - // check if the edge already has a Block constraint - if ((*it)->Type == Sketcher::Block && (*it)->First == GeoId - && (*it)->FirstPos == Sketcher::PointPos::none) { - Gui::TranslatedUserWarning( - Obj, - QObject::tr("Impossible constraint"), - QObject::tr("The selected edge already has a Block constraint!")); - return; - } - } - edgegeoids.push_back(GeoId); - } - else if (isVertex(GeoId, PosId)) { - // can be a point, a construction point, an external point, root or a blocked geometry - if (isPointOrSegmentFixed(Obj, GeoId)) { - fixedpoints++; - } - - pointgeoids.push_back(GeoId); - pointpos.push_back(PosId); - } - } - - if (edgegeoids.empty() && pointgeoids.empty()) { - Gui::TranslatedUserWarning( - Obj, - QObject::tr("Impossible constraint"), - QObject::tr("The selected item(s) can't accept a vertical constraint!")); - return; - } - - // if there is at least one edge selected, ignore the point alignment functionality - if (!edgegeoids.empty()) { - // undo command open - openCommand(QT_TRANSLATE_NOOP("Command", "Add vertical constraint")); - for (std::vector::iterator it = edgegeoids.begin(); it != edgegeoids.end(); it++) { - // issue the actual commands to create the constraint - Gui::cmdAppObjectArgs(selection[0].getObject(), - "addConstraint(Sketcher.Constraint('Vertical',%d))", - *it); - } - } - else if (fixedpoints <= 1) {// vertex mode, maximum one fixed point - // undo command open - openCommand(QT_TRANSLATE_NOOP("Command", "Add vertical alignment")); - std::vector::iterator it; - std::vector::iterator itp; - for (it = pointgeoids.begin(), itp = pointpos.begin(); - it != std::prev(pointgeoids.end()) && itp != std::prev(pointpos.end()); - it++, itp++) { - // issue the actual commands to create the constraint - Gui::cmdAppObjectArgs(selection[0].getObject(), - "addConstraint(Sketcher.Constraint('Vertical',%d,%d,%d,%d))", - *it, - static_cast(*itp), - *std::next(it), - static_cast(*std::next(itp))); - } - } - else {// vertex mode, fixedpoints > 1 - Gui::TranslatedUserWarning(Obj, - QObject::tr("Impossible constraint"), - QObject::tr("There are more than one fixed points selected. " - "Select a maximum of one fixed point!")); - return; - } - - // finish the transaction and update - commitCommand(); - - tryAutoRecompute(Obj); - - // clear the selection (convenience) - getSelection().clearSelection(); + horVerActivated(this, "Vertical"); } void CmdSketcherConstrainVertical::applyConstraint(std::vector& selSeq, int seqIndex) { - SketcherGui::ViewProviderSketch* sketchgui = - static_cast(getActiveGuiDocument()->getInEdit()); - Sketcher::SketchObject* Obj = sketchgui->getSketchObject(); - - switch (seqIndex) { - case 0:// {Edge} - { - // create the constraint - const std::vector& vals = Obj->Constraints.getValues(); - - int CrvId = selSeq.front().GeoId; - if (CrvId != -1) { - const Part::Geometry* geo = Obj->getGeometry(CrvId); - - if (! isLineSegment(*geo)) { - Gui::TranslatedUserWarning( - Obj, - QObject::tr("Impossible constraint"), - QObject::tr("The selected edge is not a line segment.")); - return; - } - - // check if the edge already has a Horizontal or Vertical constraint - for (std::vector::const_iterator it = vals.begin(); - it != vals.end(); - ++it) { - if ((*it)->Type == Sketcher::Horizontal && (*it)->First == CrvId - && (*it)->FirstPos == Sketcher::PointPos::none) { - Gui::TranslatedUserWarning( - Obj, - QObject::tr("Impossible constraint"), - QObject::tr("The selected edge already has a horizontal constraint!")); - return; - } - if ((*it)->Type == Sketcher::Vertical && (*it)->First == CrvId - && (*it)->FirstPos == Sketcher::PointPos::none) { - Gui::TranslatedUserWarning( - Obj, - QObject::tr("Double constraint"), - QObject::tr("The selected edge already has a vertical constraint!")); - return; - } - // check if the edge already has a Block constraint - if ((*it)->Type == Sketcher::Block && (*it)->First == CrvId - && (*it)->FirstPos == Sketcher::PointPos::none) { - Gui::TranslatedUserWarning( - Obj, - QObject::tr("Impossible constraint"), - QObject::tr("The selected edge already has a Block constraint!")); - return; - } - } - - // undo command open - Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Add vertical constraint")); - // issue the actual commands to create the constraint - Gui::cmdAppObjectArgs(sketchgui->getObject(), - "addConstraint(Sketcher.Constraint('Vertical',%d))", - CrvId); - // finish the transaction and update - Gui::Command::commitCommand(); - tryAutoRecompute(Obj); - } - - break; - } - - case 1:// {SelVertex, SelVertexOrRoot} - case 2:// {SelRoot, SelVertex} - { - int GeoId1, GeoId2; - Sketcher::PointPos PosId1, PosId2; - GeoId1 = selSeq.at(0).GeoId; - GeoId2 = selSeq.at(1).GeoId; - PosId1 = selSeq.at(0).PosId; - PosId2 = selSeq.at(1).PosId; - - if (areBothPointsOrSegmentsFixed(Obj, GeoId1, GeoId2)) { - showNoConstraintBetweenFixedGeometry(Obj); - return; - } - - // undo command open - Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Add horizontal alignment")); - // issue the actual commands to create the constraint - Gui::cmdAppObjectArgs(sketchgui->getObject(), - "addConstraint(Sketcher.Constraint('Vertical',%d,%d,%d,%d))", - GeoId1, - static_cast(PosId1), - GeoId2, - static_cast(PosId2)); - // finish the transaction and update - Gui::Command::commitCommand(); - - tryAutoRecompute(Obj); - - break; - } - } + horVerApplyConstraint(this, "Vertical", selSeq, seqIndex); } // ====================================================================================== @@ -10069,6 +9926,8 @@ void CreateSketcherCommandsConstraints() rcCmdMgr.addCommand(new CmdSketcherConstrainHorizontal()); rcCmdMgr.addCommand(new CmdSketcherConstrainVertical()); + rcCmdMgr.addCommand(new CmdSketcherConstrainHorVer()); + rcCmdMgr.addCommand(new CmdSketcherCompHorizontalVertical()); rcCmdMgr.addCommand(new CmdSketcherConstrainLock()); rcCmdMgr.addCommand(new CmdSketcherConstrainBlock()); rcCmdMgr.addCommand(new CmdSketcherConstrainCoincident()); diff --git a/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc b/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc index a0929e01ab..fdae83de0c 100644 --- a/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc +++ b/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc @@ -20,6 +20,7 @@ icons/constraints/Constraint_Horizontal.svg icons/constraints/Constraint_HorizontalDistance.svg icons/constraints/Constraint_HorizontalDistance_Driven.svg + icons/constraints/Constraint_HorVer.svg icons/constraints/Constraint_InternalAlignment.svg icons/constraints/Constraint_InternalAlignment_Ellipse_Focus1.svg icons/constraints/Constraint_InternalAlignment_Ellipse_Focus2.svg diff --git a/src/Mod/Sketcher/Gui/Resources/icons/constraints/Constraint_HorVer.svg b/src/Mod/Sketcher/Gui/Resources/icons/constraints/Constraint_HorVer.svg new file mode 100644 index 0000000000..d9dddf9be6 --- /dev/null +++ b/src/Mod/Sketcher/Gui/Resources/icons/constraints/Constraint_HorVer.svg @@ -0,0 +1,215 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + [wmayer] + + + 2011-10-10 + https://www.freecad.org/wiki/index.php?title=Artwork + + + FreeCAD + + + FreeCAD/src/Mod/Sketcher/Gui/Resources/icons/Constraint_Horizontal.svg + + + FreeCAD LGPL2+ + + + https://www.gnu.org/copyleft/lesser.html + + + [agryson] Alexander Gryson + + + + + + + + + + + + + + diff --git a/src/Mod/Sketcher/Gui/Utils.h b/src/Mod/Sketcher/Gui/Utils.h index 0d5dd5c073..d1f3454fb2 100644 --- a/src/Mod/Sketcher/Gui/Utils.h +++ b/src/Mod/Sketcher/Gui/Utils.h @@ -211,6 +211,12 @@ inline Base::Vector3d toVector3d(const Base::Vector2d& vector2d) return Base::Vector3d(vector2d.x, vector2d.y, 0.); } +/// converts a 3D vector in the XY plane into a 2D vector +inline Base::Vector2d toVector2d(const Base::Vector3d& vector3d) +{ + return Base::Vector2d(vector3d.x, vector3d.y); +} + template auto toPointerVector(const std::vector>& vector) diff --git a/src/Mod/Sketcher/Gui/Workbench.cpp b/src/Mod/Sketcher/Gui/Workbench.cpp index 80256ebba0..bfdf659f1d 100644 --- a/src/Mod/Sketcher/Gui/Workbench.cpp +++ b/src/Mod/Sketcher/Gui/Workbench.cpp @@ -432,6 +432,7 @@ inline void SketcherAddWorkbenchConstraints(Gui::MenuItem& cons) << "Sketcher_ConstrainPointOnObject" << "Sketcher_ConstrainVertical" << "Sketcher_ConstrainHorizontal" + << "Sketcher_ConstrainHorVer" << "Sketcher_ConstrainParallel" << "Sketcher_ConstrainPerpendicular" << "Sketcher_ConstrainTangent" @@ -462,8 +463,7 @@ inline void SketcherAddWorkbenchConstraints(Gui::ToolBarItem& cons << "Sketcher_ConstrainCoincident" << "Sketcher_ConstrainPointOnObject" - << "Sketcher_ConstrainVertical" - << "Sketcher_ConstrainHorizontal" + << "Sketcher_CompHorVer" << "Sketcher_ConstrainParallel" << "Sketcher_ConstrainPerpendicular" << "Sketcher_ConstrainTangent"