From 64054d13c4c48951fdb0d88116919bdfcbbee47d Mon Sep 17 00:00:00 2001 From: PaddleStroke Date: Mon, 25 Mar 2024 16:27:29 +0100 Subject: [PATCH] Sketcher: Add line mid-point auto-constraint --- .../Sketcher/Gui/DrawSketchDefaultHandler.h | 11 +++ src/Mod/Sketcher/Gui/DrawSketchHandler.cpp | 93 +++++++++++-------- 2 files changed, 63 insertions(+), 41 deletions(-) diff --git a/src/Mod/Sketcher/Gui/DrawSketchDefaultHandler.h b/src/Mod/Sketcher/Gui/DrawSketchDefaultHandler.h index 580781019d..da16ac413f 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchDefaultHandler.h +++ b/src/Mod/Sketcher/Gui/DrawSketchDefaultHandler.h @@ -720,6 +720,17 @@ protected: AutoConstraints.push_back(std::move(c)); } } break; + case Sketcher::Symmetric: { + auto c = std::make_unique(); + c->Type = Sketcher::Symmetric; + c->First = geoId2; + c->FirstPos = Sketcher::PointPos::start; + c->Second = geoId2; + c->SecondPos = Sketcher::PointPos::end; + c->Third = geoId1; + c->ThirdPos = posId1; + AutoConstraints.push_back(std::move(c)); + } break; // In special case of Horizontal/Vertical constraint, geoId2 is normally unused // and should be 'Constraint::GeoUndef' However it can be used as a way to // require the function to apply these constraints on another geometry In this diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandler.cpp b/src/Mod/Sketcher/Gui/DrawSketchHandler.cpp index 8b9ff87809..04cde7998c 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandler.cpp +++ b/src/Mod/Sketcher/Gui/DrawSketchHandler.cpp @@ -600,11 +600,9 @@ DrawSketchHandler::suggestedConstraintsPixmaps(std::vector& sugg { std::vector pixmaps; // Iterate through AutoConstraints types and get their pixmaps - std::vector::iterator it = suggestedConstraints.begin(); - int i = 0; - for (; it != suggestedConstraints.end(); ++it, i++) { + for (auto& autoCstr : suggestedConstraints) { QString iconType; - switch (it->Type) { + switch (autoCstr.Type) { case Horizontal: iconType = QString::fromLatin1("Constraint_Horizontal"); break; @@ -617,6 +615,9 @@ DrawSketchHandler::suggestedConstraintsPixmaps(std::vector& sugg case PointOnObject: iconType = QString::fromLatin1("Constraint_PointOnObject"); break; + case Symmetric: + iconType = QString::fromLatin1("Constraint_Symmetric"); + break; case Tangent: iconType = QString::fromLatin1("Constraint_Tangent"); break; @@ -644,15 +645,13 @@ int DrawSketchHandler::seekAutoConstraint(std::vector& suggested AutoConstraint::TargetType type) { suggestedConstraints.clear(); + SketchObject* obj = sketchgui->getSketchObject(); if (!sketchgui->Autoconstraints.getValue()) { return 0; // If Autoconstraints property is not set quit } - - Base::Vector3d hitShapeDir = - Base::Vector3d(0, - 0, - 0); // direction of hit shape (if it is a line, the direction of the line) + // direction of hit shape (if it is a line, the direction of the line) + Base::Vector3d hitShapeDir = Base::Vector3d(0, 0, 0); // Get Preselection int preSelPnt = getPreselectPoint(); @@ -660,13 +659,13 @@ int DrawSketchHandler::seekAutoConstraint(std::vector& suggested int preSelCrs = getPreselectCross(); int GeoId = GeoEnum::GeoUndef; - Sketcher::PointPos PosId = Sketcher::PointPos::none; + PointPos PosId = PointPos::none; if (preSelPnt != -1) { - sketchgui->getSketchObject()->getGeoVertexIndex(preSelPnt, GeoId, PosId); + obj->getGeoVertexIndex(preSelPnt, GeoId, PosId); } else if (preSelCrv != -1) { - const Part::Geometry* geom = sketchgui->getSketchObject()->getGeometry(preSelCrv); + const Part::Geometry* geom = obj->getGeometry(preSelCrv); // ensure geom exists in case object was called before preselection is updated if (geom) { @@ -679,7 +678,7 @@ int DrawSketchHandler::seekAutoConstraint(std::vector& suggested } else if (preSelCrs == 0) { // root point GeoId = Sketcher::GeoEnum::RtPnt; - PosId = Sketcher::PointPos::start; + PosId = PointPos::start; } else if (preSelCrs == 1) { // x axis GeoId = Sketcher::GeoEnum::HAxis; @@ -696,18 +695,33 @@ int DrawSketchHandler::seekAutoConstraint(std::vector& suggested constr.Type = Sketcher::None; constr.GeoId = GeoId; constr.PosId = PosId; - if ((type == AutoConstraint::VERTEX || type == AutoConstraint::VERTEX_NO_TANGENCY) - && PosId != Sketcher::PointPos::none) { - constr.Type = Sketcher::Coincident; + if (type == AutoConstraint::VERTEX || type == AutoConstraint::VERTEX_NO_TANGENCY) { + if (PosId == PointPos::none) { + bool lineCenter = false; + auto* geo = obj->getGeometry(GeoId); + if (geo->is()) { + auto* line = static_cast(geo); + + Base::Vector2d startPoint = toVector2d(line->getStartPoint()); + Base::Vector2d endPoint = toVector2d(line->getEndPoint()); + Base::Vector2d midPoint = (startPoint + endPoint) / 2; + + // Check if we are at middle of the line + if ((Pos - midPoint).Length() < (endPoint - startPoint).Length() * 0.05) { + lineCenter = true; + } + } + + constr.Type = lineCenter ? Sketcher::Symmetric : Sketcher::PointOnObject; + } + else { + constr.Type = Sketcher::Coincident; + } } - else if (type == AutoConstraint::CURVE && PosId != Sketcher::PointPos::none) { + else if (type == AutoConstraint::CURVE && PosId != PointPos::none) { constr.Type = Sketcher::PointOnObject; } - else if ((type == AutoConstraint::VERTEX || type == AutoConstraint::VERTEX_NO_TANGENCY) - && PosId == Sketcher::PointPos::none) { - constr.Type = Sketcher::PointOnObject; - } - else if (type == AutoConstraint::CURVE && PosId == Sketcher::PointPos::none) { + else if (type == AutoConstraint::CURVE && PosId == PointPos::none) { constr.Type = Sketcher::Tangent; } @@ -750,7 +764,7 @@ int DrawSketchHandler::seekAutoConstraint(std::vector& suggested AutoConstraint constr; constr.Type = Sketcher::None; constr.GeoId = GeoEnum::GeoUndef; - constr.PosId = Sketcher::PointPos::none; + constr.PosId = PointPos::none; double angle = std::abs(atan2(Dir.y, Dir.x)); if (angle < angleDevRad || (M_PI - angle) < angleDevRad) { // Suggest horizontal constraint @@ -779,20 +793,18 @@ int DrawSketchHandler::seekAutoConstraint(std::vector& suggested double tangDeviation = 0.1 * sketchgui->getScaleFactor(); // Get geometry list - const std::vector geomlist = - sketchgui->getSketchObject()->getCompleteGeometry(); + const std::vector geomlist = obj->getCompleteGeometry(); Base::Vector3d tmpPos(Pos.x, Pos.y, 0.f); // Current cursor point Base::Vector3d tmpDir(Dir.x, Dir.y, 0.f); // Direction of line Base::Vector3d tmpStart(Pos.x - Dir.x, Pos.y - Dir.y, 0.f); // Start point - // Iterate through geometry - int i = 0; - for (std::vector::const_iterator it = geomlist.begin(); it != geomlist.end(); - ++it, i++) { + int i = -1; + for (auto* geo : geomlist) { + i++; - if ((*it)->is()) { - const Part::GeomCircle* circle = static_cast((*it)); + if (geo->is()) { + auto* circle = static_cast(geo); Base::Vector3d center = circle->getCenter(); @@ -813,9 +825,8 @@ int DrawSketchHandler::seekAutoConstraint(std::vector& suggested tangDeviation = projDist; } } - else if ((*it)->is()) { - - const Part::GeomEllipse* ellipse = static_cast((*it)); + else if (geo->is()) { + auto* ellipse = static_cast(geo); Base::Vector3d center = ellipse->getCenter(); @@ -832,8 +843,8 @@ int DrawSketchHandler::seekAutoConstraint(std::vector& suggested double distancetoline = norm * (tmpPos - focus1P); // distance focus1 to line - Base::Vector3d focus1PMirrored = - focus1P + 2 * distancetoline * norm; // mirror of focus1 with respect to the line + // mirror of focus1 with respect to the line + Base::Vector3d focus1PMirrored = focus1P + 2 * distancetoline * norm; double error = fabs((focus1PMirrored - focus2P).Length() - 2 * a); @@ -842,8 +853,8 @@ int DrawSketchHandler::seekAutoConstraint(std::vector& suggested tangDeviation = error; } } - else if ((*it)->is()) { - const Part::GeomArcOfCircle* arc = static_cast((*it)); + else if (geo->is()) { + auto* arc = static_cast(geo); Base::Vector3d center = arc->getCenter(); double radius = arc->getRadius(); @@ -873,8 +884,8 @@ int DrawSketchHandler::seekAutoConstraint(std::vector& suggested } } } - else if ((*it)->is()) { - const Part::GeomArcOfEllipse* aoe = static_cast((*it)); + else if (geo->is()) { + auto* aoe = static_cast(geo); Base::Vector3d center = aoe->getCenter(); @@ -934,7 +945,7 @@ int DrawSketchHandler::seekAutoConstraint(std::vector& suggested // Suggest vertical constraint constr.Type = Tangent; constr.GeoId = tangId; - constr.PosId = Sketcher::PointPos::none; + constr.PosId = PointPos::none; suggestedConstraints.push_back(constr); }