[Sketcher] Auto horizontal/vertical (#11330)

* Refactor sketcher horizontal / vertical constraints and adds a horizontal/vertical command.

* Sketcher : HorVer : change tool icon.

---------

Co-authored-by: Paddle <PaddleStroke@users.noreply.github.com>
This commit is contained in:
PaddleStroke
2023-11-20 18:00:22 +01:00
committed by GitHub
parent 0148cbaac1
commit cce89e4fec
5 changed files with 571 additions and 490 deletions

View File

@@ -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<Sketcher::Constraint*>& 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<Gui::SelectionObject> 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<std::string>& SubNames = selection[0].getSubNames();
auto* Obj = static_cast<Sketcher::SketchObject*>(selection[0].getObject());
const std::vector<Sketcher::Constraint*>& vals = Obj->Constraints.getValues();
std::vector<int> edgegeoids;
std::vector<int> pointgeoids;
std::vector<Sketcher::PointPos> 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<const Part::GeomLineSegment*>(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<int>::iterator it;
std::vector<Sketcher::PointPos>::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<int>(*itp),
*std::next(it),
static_cast<int>(*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<SelIdPair>& selSeq, int seqIndex)
{
auto* sketchgui =
static_cast<SketcherGui::ViewProviderSketch*>(cmd->getActiveGuiDocument()->getInEdit());
Sketcher::SketchObject* Obj = sketchgui->getSketchObject();
switch (seqIndex) {
case 0:// {Edge}
{
// create the constraint
const std::vector<Sketcher::Constraint*>& 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<const Part::GeomLineSegment*>(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<int>(PosId1),
GeoId2,
static_cast<int>(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<SelIdPair>& 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<SelIdPair>& 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<Gui::SelectionObject> 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<std::string>& SubNames = selection[0].getSubNames();
Sketcher::SketchObject* Obj = static_cast<Sketcher::SketchObject*>(selection[0].getObject());
const std::vector<Sketcher::Constraint*>& vals = Obj->Constraints.getValues();
std::vector<int> edgegeoids;
std::vector<int> pointgeoids;
std::vector<Sketcher::PointPos> pointpos;
int fixedpoints = 0;
// go through the selected subelements
for (std::vector<std::string>::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<Sketcher::Constraint*>::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<int>::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<int>::iterator it;
std::vector<Sketcher::PointPos>::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<int>(*itp),
*std::next(it),
static_cast<int>(*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<SelIdPair>& selSeq, int seqIndex)
{
SketcherGui::ViewProviderSketch* sketchgui =
static_cast<SketcherGui::ViewProviderSketch*>(getActiveGuiDocument()->getInEdit());
Sketcher::SketchObject* Obj = sketchgui->getSketchObject();
switch (seqIndex) {
case 0:// {Edge}
{
// create the constraint
const std::vector<Sketcher::Constraint*>& 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<Sketcher::Constraint*>::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<int>(PosId1),
GeoId2,
static_cast<int>(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<Gui::SelectionObject> 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<std::string>& SubNames = selection[0].getSubNames();
Sketcher::SketchObject* Obj = static_cast<Sketcher::SketchObject*>(selection[0].getObject());
const std::vector<Sketcher::Constraint*>& vals = Obj->Constraints.getValues();
std::vector<int> edgegeoids;
std::vector<int> pointgeoids;
std::vector<Sketcher::PointPos> pointpos;
int fixedpoints = 0;
// go through the selected subelements
for (std::vector<std::string>::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<Sketcher::Constraint*>::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<int>::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<int>::iterator it;
std::vector<Sketcher::PointPos>::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<int>(*itp),
*std::next(it),
static_cast<int>(*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<SelIdPair>& selSeq, int seqIndex)
{
SketcherGui::ViewProviderSketch* sketchgui =
static_cast<SketcherGui::ViewProviderSketch*>(getActiveGuiDocument()->getInEdit());
Sketcher::SketchObject* Obj = sketchgui->getSketchObject();
switch (seqIndex) {
case 0:// {Edge}
{
// create the constraint
const std::vector<Sketcher::Constraint*>& 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<Sketcher::Constraint*>::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<int>(PosId1),
GeoId2,
static_cast<int>(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());