From 582317a4051cb15fadf4e157cb145f8c5911a902 Mon Sep 17 00:00:00 2001 From: donovaly Date: Sun, 6 Jun 2021 05:33:23 +0200 Subject: [PATCH] [sketch] rework the slot command In practical work it turned out that the slot command is not as convenient as it should because one cannot snap to a proper endpoint and one is restricted to work perpendicular to the sketch axes This PR fixes this by setting the second snap point to the center of the second arc and removing the perpendicularity. Benefits: when you want to get the slot at a line, edge or sketch axis, set the two center points accordingly. The line does not have to be parallel to one of the sketch axes when you want to define the slot using 2 points in the sketch you can do this now --- src/Mod/Sketcher/Gui/CommandCreateGeo.cpp | 159 ++++++++++++---------- 1 file changed, 87 insertions(+), 72 deletions(-) diff --git a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp index 37f77b9ea8..f096f4aa06 100644 --- a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp +++ b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp @@ -6979,16 +6979,16 @@ namespace SketcherGui { /** * Create Slot */ -class DrawSketchHandlerSlot: public DrawSketchHandler +class DrawSketchHandlerSlot : public DrawSketchHandler { public: DrawSketchHandlerSlot() - : Mode(STATUS_SEEK_First) - , lx(0), ly(0), r(0), a(0) - , EditCurve(36) + : Mode(STATUS_SEEK_First) + , dx(0), dy(0), r(0) + , EditCurve(35) { } - virtual ~DrawSketchHandlerSlot(){} + virtual ~DrawSketchHandlerSlot() {} /// mode table enum BoxMode { STATUS_SEEK_First, /**< enum value ----. */ @@ -6996,7 +6996,7 @@ public: STATUS_End }; - virtual void activated(ViewProviderSketch *) + virtual void activated(ViewProviderSketch*) { setCrosshairCursor("Sketcher_Pointer_Slot"); } @@ -7004,48 +7004,57 @@ public: virtual void mouseMove(Base::Vector2d onSketchPos) { - if (Mode==STATUS_SEEK_First) { + if (Mode == STATUS_SEEK_First) { setPositionText(onSketchPos); - if (seekAutoConstraint(sugConstr1, onSketchPos, Base::Vector2d(0.f,0.f))) { + if (seekAutoConstraint(sugConstr1, onSketchPos, Base::Vector2d(0.f, 0.f))) { renderSuggestConstraintsCursor(sugConstr1); return; } } - else if (Mode==STATUS_SEEK_Second) { - float dx = onSketchPos.x - StartPos.x; - float dy = onSketchPos.y - StartPos.y; + else if (Mode == STATUS_SEEK_Second) { + dx = onSketchPos.x - StartPos.x; + dy = onSketchPos.y - StartPos.y; - lx = 0; ly = 0; a = 0; + double a = 0; double rev = 0; if (fabs(dx) > fabs(dy)) { - lx = dx; - r = dy; + r = fabs(dx) / 4; rev = Base::sgn(dx); } else { - ly = dy; - r = dx; + r = fabs(dy) / 4; a = 8; rev = Base::sgn(dy); } + // draw the arcs with each 16 segments for (int i = 0; i < 17; i++) { + // first get the position at the arc + // if a is 0, the end points of the arc are at the y-axis, if it is 8, they are on the x-axis double angle = (i + a) * M_PI / 16.0; - double rx = -fabs(r) * rev * sin(angle); - double ry = fabs(r) * rev * cos(angle); + double rx = -r * rev * sin(angle); + double ry = r * rev * cos(angle); + // now apply the rotation matrix according to the angle between StartPos and onSketchPos + if (!(dx == 0 || dy == 0)) { + double rotAngle = atan(dy / dx); + if (a > 0) + rotAngle = -atan(dx / dy); + double rxRot = rx * cos(rotAngle) - ry * sin(rotAngle); + double ryRot = rx * sin(rotAngle) + ry * cos(rotAngle); + rx = rxRot; + ry = ryRot; + } EditCurve[i] = Base::Vector2d(StartPos.x + rx, StartPos.y + ry); - EditCurve[18 + i] = Base::Vector2d(StartPos.x - rx + lx, StartPos.y - ry + ly); + EditCurve[17 + i] = Base::Vector2d(StartPos.x + dx - rx, StartPos.y + dy - ry); } - EditCurve[17] = EditCurve[16] + Base::Vector2d(lx,ly); - EditCurve[35] = EditCurve[0] ; + EditCurve[34] = EditCurve[0]; SbString text; - text.sprintf(" (%.1fR %.1fL)", r,lx); + text.sprintf(" (%.1fR %.1fL)", r, sqrt(dx * dx + dy * dy)); setPositionText(onSketchPos, text); sketchgui->drawEdit(EditCurve); - if (seekAutoConstraint(sugConstr2, onSketchPos, Base::Vector2d(0.f,0.f), - AutoConstraint::CURVE)) { + if (seekAutoConstraint(sugConstr2, onSketchPos, Base::Vector2d(0.f, 0.f))) { renderSuggestConstraintsCursor(sugConstr2); return; } @@ -7055,7 +7064,7 @@ public: virtual bool pressButton(Base::Vector2d onSketchPos) { - if (Mode==STATUS_SEEK_First){ + if (Mode == STATUS_SEEK_First) { StartPos = onSketchPos; Mode = STATUS_SEEK_Second; } @@ -7068,25 +7077,33 @@ public: virtual bool releaseButton(Base::Vector2d onSketchPos) { Q_UNUSED(onSketchPos); - if (Mode==STATUS_End){ + if (Mode == STATUS_End) { unsetCursor(); resetPositionText(); int firstCurve = getHighestCurveIndex() + 1; // add the geometry to the sketch + // first determine the rotation angle for the first arc double start, end; - if (fabs(lx) > fabs(ly)) { - start = M_PI / 2; - end = -M_PI / 2; + if (fabs(dx) > fabs(dy)) { + if (dx > 0) { + start = 0.5 * M_PI; + end = 1.5 * M_PI; + } + else { + start = 1.5 * M_PI; + end = 0.5 * M_PI; + } } else { - start = 0; - end = M_PI; - } - if (ly > 0 || lx < 0) { - double temp = start; - start = end; - end = temp; + if (dy > 0) { + start = -M_PI; + end = 0; + } + else { + start = 0; + end = -M_PI; + } } try { @@ -7094,67 +7111,65 @@ public: Gui::Command::doCommand(Gui::Command::Doc, "geoList = []\n" "geoList.append(Part.ArcOfCircle(Part.Circle(App.Vector(%f, %f, 0), App.Vector(0, 0, 1), %f), %f, %f))\n" - "geoList.append(Part.ArcOfCircle(Part.Circle(App.Vector(%f, %f, 0), App.Vector(0, 0, 1), %f), %f, %f))\n" + "geoList.append(Part.ArcOfCircle(Part.Circle(App.Vector(%f, %f ,0), App.Vector(0, 0, 1), %f), %f, %f))\n" "geoList.append(Part.LineSegment(App.Vector(%f, %f, 0), App.Vector(%f, %f, 0)))\n" "geoList.append(Part.LineSegment(App.Vector(%f, %f, 0), App.Vector(%f, %f, 0)))\n" "%s.addGeometry(geoList, %s)\n" "conList = []\n" - "conList.append(Sketcher.Constraint('Tangent', %i, 1, %i, 1))\n" "conList.append(Sketcher.Constraint('Tangent', %i, 2, %i, 1))\n" "conList.append(Sketcher.Constraint('Tangent', %i, 2, %i, 1))\n" - "conList.append(Sketcher.Constraint('Tangent', %i, 2, %i, 2))\n" - "conList.append(Sketcher.Constraint('%s', %i))\n" + "conList.append(Sketcher.Constraint('Tangent', %i, 2, %i, 1))\n" + "conList.append(Sketcher.Constraint('Tangent', %i, 2, %i, 1))\n" "conList.append(Sketcher.Constraint('Equal', %i, %i))\n" "%s.addConstraint(conList)\n", - StartPos.x, StartPos.y, // center of the arc1 - fabs(r), // radius arc1 - start, end, // start and end angle of arc1 - StartPos.x + lx, StartPos.y + ly, // center of the arc2 - fabs(r), // radius arc2 - end, start, // start and end angle of arc2 + StartPos.x, StartPos.y, // center of the arc1 + r, // radius arc1 + start, end, // start and end angle of arc1 + StartPos.x + dx, StartPos.y + dy, // center of the arc2 + r, // radius arc2 + end, end + M_PI, // start and end angle of arc2 EditCurve[16].x, EditCurve[16].y, EditCurve[17].x, EditCurve[17].y, // line1 - EditCurve[0].x, EditCurve[0].y, EditCurve[34].x, EditCurve[34].y, // line2 + EditCurve[33].x, EditCurve[33].y, EditCurve[34].x, EditCurve[34].y, // line2 Gui::Command::getObjectCmd(sketchgui->getObject()).c_str(), // the sketch geometryCreationMode == Construction ? "True" : "False", // geometry as construction or not - firstCurve, firstCurve + 3, // tangent1 - firstCurve, firstCurve + 2, // tangent2 - firstCurve + 2, firstCurve + 1, // tangent3 - firstCurve + 3, firstCurve + 1, // tangent4 - (fabs(lx) > fabs(ly)) ? "Horizontal" : "Vertical", firstCurve + 2, // vertical or horizontal constraint - firstCurve, firstCurve + 1, // equal constraint + firstCurve, firstCurve + 2, // tangent1 + firstCurve + 2, firstCurve + 1, // tangent2 + firstCurve + 1, firstCurve + 3, // tangent3 + firstCurve + 3, firstCurve, // tangent4 + firstCurve, firstCurve + 1, // equal constraint Gui::Command::getObjectCmd(sketchgui->getObject()).c_str()); // the sketch Gui::Command::commitCommand(); - // add auto constraints at the start of the first side + // add auto constraints at the center of the first arc if (sugConstr1.size() > 0) { - createAutoConstraints(sugConstr1, getHighestCurveIndex() - 3 , Sketcher::mid); + createAutoConstraints(sugConstr1, getHighestCurveIndex() - 3, Sketcher::mid); sugConstr1.clear(); } - // add auto constraints at the end of the second side + // add auto constraints at the center of the second arc if (sugConstr2.size() > 0) { - createAutoConstraints(sugConstr2, getHighestCurveIndex() - 2, Sketcher::end); + createAutoConstraints(sugConstr2, getHighestCurveIndex() - 2, Sketcher::mid); sugConstr2.clear(); } - tryAutoRecomputeIfNotSolve(static_cast(sketchgui->getObject())); + tryAutoRecomputeIfNotSolve(static_cast(sketchgui->getObject())); } catch (const Base::Exception& e) { Base::Console().Error("Failed to add slot: %s\n", e.what()); Gui::Command::abortCommand(); - tryAutoRecompute(static_cast(sketchgui->getObject())); + tryAutoRecompute(static_cast(sketchgui->getObject())); } ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Sketcher"); - bool continuousMode = hGrp->GetBool("ContinuousCreationMode",true); + bool continuousMode = hGrp->GetBool("ContinuousCreationMode", true); if (continuousMode) { // This code enables the continuous creation mode. Mode = STATUS_SEEK_First; EditCurve.clear(); sketchgui->drawEdit(EditCurve); - EditCurve.resize(36); + EditCurve.resize(35); applyCursor(); /* this is ok not to call to purgeHandler * in continuous creation mode because the @@ -7170,7 +7185,7 @@ public: protected: BoxMode Mode; Base::Vector2d StartPos; - double lx, ly, r, a; + double dx, dy, r; std::vector EditCurve; std::vector sugConstr1, sugConstr2; }; @@ -7178,17 +7193,17 @@ protected: DEF_STD_CMD_AU(CmdSketcherCreateSlot) CmdSketcherCreateSlot::CmdSketcherCreateSlot() - : Command("Sketcher_CreateSlot") + : Command("Sketcher_CreateSlot") { - sAppModule = "Sketcher"; - sGroup = QT_TR_NOOP("Sketcher"); - sMenuText = QT_TR_NOOP("Create slot"); - sToolTipText = QT_TR_NOOP("Create a slot in the sketch"); - sWhatsThis = "Sketcher_CreateSlot"; - sStatusTip = sToolTipText; - sPixmap = "Sketcher_CreateSlot"; - sAccel = ""; - eType = ForEdit; + sAppModule = "Sketcher"; + sGroup = QT_TR_NOOP("Sketcher"); + sMenuText = QT_TR_NOOP("Create slot"); + sToolTipText = QT_TR_NOOP("Create a slot in the sketch"); + sWhatsThis = "Sketcher_CreateSlot"; + sStatusTip = sToolTipText; + sPixmap = "Sketcher_CreateSlot"; + sAccel = ""; + eType = ForEdit; } void CmdSketcherCreateSlot::activated(int iMsg)