From 549565958ff310c89de5a83552f7a79a7cc86216 Mon Sep 17 00:00:00 2001 From: whitequark Date: Fri, 24 May 2019 15:06:53 +0000 Subject: [PATCH] Skip creating an automatic H/V constraint if it would be redundant. This means that automatically added H/V constraints now will never cause the sketch to become overconstrained, which currently makes that feature almost unusable. --- CHANGELOG.md | 2 ++ src/constraint.cpp | 21 +++++++++++++-------- src/mouse.cpp | 21 ++++++++++++--------- src/sketch.h | 13 +++++++------ 4 files changed, 34 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9308aa02..b079743e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,8 @@ New constraint features: Values are edited in the configured unit regardless of label format. * It is now possible to turn off automatic creation of horizontal/vertical constraints on line segments. + * Automatic creation of constraints no longer happens if the constraint + would have been redundant with other ones. New export/import features: * Three.js: allow configuring projection for exported model, and initially diff --git a/src/constraint.cpp b/src/constraint.cpp index a48ef10e..eaaedf9a 100644 --- a/src/constraint.cpp +++ b/src/constraint.cpp @@ -75,10 +75,6 @@ void Constraint::DeleteAllConstraintsFor(Constraint::Type type, hEntity entityA, SS.GW.hover.Clear(); } -hConstraint Constraint::AddConstraint(Constraint *c) { - return AddConstraint(c, /*rememberForUndo=*/true); -} - hConstraint Constraint::AddConstraint(Constraint *c, bool rememberForUndo) { if(rememberForUndo) SS.UndoRemember(); @@ -91,8 +87,8 @@ hConstraint Constraint::AddConstraint(Constraint *c, bool rememberForUndo) { } hConstraint Constraint::Constrain(Constraint::Type type, hEntity ptA, hEntity ptB, - hEntity entityA, hEntity entityB, - bool other, bool other2) + hEntity entityA, hEntity entityB, + bool other, bool other2) { Constraint c = {}; c.group = SS.GW.activeGroup; @@ -107,8 +103,17 @@ hConstraint Constraint::Constrain(Constraint::Type type, hEntity ptA, hEntity pt return AddConstraint(&c, /*rememberForUndo=*/false); } -hConstraint Constraint::Constrain(Constraint::Type type, hEntity ptA, hEntity ptB, hEntity entityA){ - return Constrain(type, ptA, ptB, entityA, Entity::NO_ENTITY, /*other=*/false, /*other2=*/false); +hConstraint Constraint::TryConstrain(Constraint::Type type, hEntity ptA, hEntity ptB, + hEntity entityA, hEntity entityB, + bool other, bool other2) { + SolveResult solvedBefore = SS.TestRankForGroup(SS.GW.activeGroup); + hConstraint hc = Constrain(type, ptA, ptB, entityA, entityB, other, other2); + SolveResult solvedAfter = SS.TestRankForGroup(SS.GW.activeGroup); + if(solvedBefore == SolveResult::OKAY && solvedAfter == SolveResult::REDUNDANT_OKAY) { + SK.constraint.RemoveById(hc); + hc = {}; + } + return hc; } hConstraint Constraint::ConstrainCoincident(hEntity ptA, hEntity ptB) { diff --git a/src/mouse.cpp b/src/mouse.cpp index 4e1c3fcd..028b1f94 100644 --- a/src/mouse.cpp +++ b/src/mouse.cpp @@ -526,7 +526,7 @@ void GraphicsWindow::MouseRightUp(double x, double y) { if(context.active) return; if(pending.operation == Pending::DRAGGING_NEW_LINE_POINT && pending.hasSuggestion) { - Constraint::Constrain(SS.GW.pending.suggestion, + Constraint::TryConstrain(SS.GW.pending.suggestion, Entity::NO_ENTITY, Entity::NO_ENTITY, pending.request.entity(0)); } @@ -943,7 +943,8 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) { } // This will be clobbered by MouseMoved below. - bool hasConstraintSuggestion = SS.GW.pending.hasSuggestion; + bool hasConstraintSuggestion = pending.hasSuggestion; + Constraint::Type constraintSuggestion = pending.suggestion; // Make sure the hover is up to date. MouseMoved(mx, my, /*leftDown=*/false, /*middleDown=*/false, /*rightDown=*/false, @@ -1223,12 +1224,6 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) { } case Pending::DRAGGING_NEW_LINE_POINT: { - // Constrain the line segment horizontal or vertical if close enough - if(hasConstraintSuggestion) { - Constraint::Constrain(SS.GW.pending.suggestion, - Entity::NO_ENTITY, Entity::NO_ENTITY, pending.request.entity(0)); - } - if(hover.entity.v) { Entity *e = SK.GetEntity(hover.entity); if(e->IsPoint()) { @@ -1246,7 +1241,15 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) { } } - if(ConstrainPointByHovered(pending.point, &mouse)) { + bool doneDragging = ConstrainPointByHovered(pending.point, &mouse); + + // Constrain the line segment horizontal or vertical if close enough + if(hasConstraintSuggestion) { + Constraint::TryConstrain(constraintSuggestion, + Entity::NO_ENTITY, Entity::NO_ENTITY, pending.request.entity(0)); + } + + if(doneDragging) { ClearPending(); break; } diff --git a/src/sketch.h b/src/sketch.h index 1657bb93..49db229e 100644 --- a/src/sketch.h +++ b/src/sketch.h @@ -727,16 +727,17 @@ public: std::string DescriptionString() const; - static hConstraint AddConstraint(Constraint *c, bool rememberForUndo); - static hConstraint AddConstraint(Constraint *c); + static hConstraint AddConstraint(Constraint *c, bool rememberForUndo = true); static void MenuConstrain(Command id); static void DeleteAllConstraintsFor(Constraint::Type type, hEntity entityA, hEntity ptA); static hConstraint ConstrainCoincident(hEntity ptA, hEntity ptB); - static hConstraint Constrain(Constraint::Type type, hEntity ptA, hEntity ptB, hEntity entityA); - static hConstraint Constrain(Constraint::Type type, hEntity ptA, hEntity ptB, - hEntity entityA, hEntity entityB, - bool other, bool other2); + static hConstraint Constrain(Constraint::Type type, hEntity ptA, hEntity ptB, hEntity entityA, + hEntity entityB = Entity::NO_ENTITY, bool other = false, + bool other2 = false); + static hConstraint TryConstrain(Constraint::Type type, hEntity ptA, hEntity ptB, + hEntity entityA, hEntity entityB = Entity::NO_ENTITY, + bool other = false, bool other2 = false); }; class hEquation {