diff --git a/src/draw.cpp b/src/draw.cpp index 7562018..47d0420 100644 --- a/src/draw.cpp +++ b/src/draw.cpp @@ -716,6 +716,28 @@ nogrid:; SK.constraint.elem[i].Draw(); } + // Draw the "pending" constraint, i.e. a constraint that would be + // placed on a line that is almost horizontal or vertical + if(SS.GW.pending.operation == DRAGGING_NEW_LINE_POINT) { + SuggestedConstraint suggested = + SS.GW.SuggestLineConstraint(SS.GW.pending.request); + if(suggested != GraphicsWindow::SUGGESTED_NONE) { + Constraint c; + ZERO(&c); + c.group = SS.GW.activeGroup; + c.workplane = SS.GW.ActiveWorkplane(); + c.type = suggested; + c.ptA = Entity::NO_ENTITY; + c.ptB = Entity::NO_ENTITY; + c.entityA = SS.GW.pending.request.entity(0); + c.entityB = Entity::NO_ENTITY; + c.other = false; + c.other2 = false; + // Only draw. + c.Draw(); + } + } + // Draw the traced path, if one exists ssglLineWidth(Style::Width(Style::ANALYZE)); ssglColorRGB(Style::Color(Style::ANALYZE)); diff --git a/src/graphicswin.cpp b/src/graphicswin.cpp index fef7f2b..ac44d8b 100644 --- a/src/graphicswin.cpp +++ b/src/graphicswin.cpp @@ -1016,3 +1016,27 @@ void GraphicsWindow::ToggleBool(bool *v) { SS.ScheduleShowTW(); } +GraphicsWindow::SuggestedConstraint GraphicsWindow::SuggestLineConstraint(hRequest request) { + if(LockedInWorkplane()) { + Entity *ptA = SK.GetEntity(request.entity(1)), + *ptB = SK.GetEntity(request.entity(2)); + + Expr *au, *av, *bu, *bv; + + ptA->PointGetExprsInWorkplane(ActiveWorkplane(), &au, &av); + ptB->PointGetExprsInWorkplane(ActiveWorkplane(), &bu, &bv); + + Expr *du = au->Minus(bu); + Expr *dv = av->Minus(bv); + + const double TOLERANCE = 10.0; + if(fabs(du->Eval()) * scale < TOLERANCE) + return SUGGESTED_VERTICAL; + else if(fabs(dv->Eval()) * scale < TOLERANCE) + return SUGGESTED_HORIZONTAL; + else + return SUGGESTED_NONE; + } else { + return SUGGESTED_NONE; + } +} diff --git a/src/mouse.cpp b/src/mouse.cpp index e968147..ef8a4af 100644 --- a/src/mouse.cpp +++ b/src/mouse.cpp @@ -497,6 +497,15 @@ void GraphicsWindow::MouseRightUp(double x, double y) { if(context.active) return; + if(pending.operation == DRAGGING_NEW_LINE_POINT) { + SuggestedConstraint suggested = + SS.GW.SuggestLineConstraint(SS.GW.pending.request); + if(suggested != SUGGESTED_NONE) { + Constraint::Constrain(suggested, + Entity::NO_ENTITY, Entity::NO_ENTITY, pending.request.entity(0)); + } + } + if(pending.operation == DRAGGING_NEW_LINE_POINT || pending.operation == DRAGGING_NEW_CUBIC_POINT) { @@ -806,6 +815,7 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) { ClearSuper(); pending.operation = DRAGGING_NEW_LINE_POINT; + pending.request = hr; pending.point = hr.entity(2); pending.description = "click next point of line, or press Esc"; SK.GetEntity(pending.point)->PointForceTo(v); @@ -1009,6 +1019,14 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) { } case DRAGGING_NEW_LINE_POINT: { + // Constrain the line segment horizontal or vertical if close enough + SuggestedConstraint suggested = + SS.GW.SuggestLineConstraint(SS.GW.pending.request); + if(suggested != SUGGESTED_NONE) { + Constraint::Constrain(suggested, + Entity::NO_ENTITY, Entity::NO_ENTITY, pending.request.entity(0)); + } + if(hover.entity.v) { Entity *e = SK.GetEntity(hover.entity); if(e->IsPoint()) { @@ -1044,6 +1062,7 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) { // And drag an endpoint of the new line segment pending.operation = DRAGGING_NEW_LINE_POINT; + pending.request = hr; pending.point = hr.entity(2); pending.description = "click next point of line, or press Esc"; diff --git a/src/ui.h b/src/ui.h index 65a4a26..f176219 100644 --- a/src/ui.h +++ b/src/ui.h @@ -523,6 +523,7 @@ public: struct { int operation; + hRequest request; hEntity point; List points; hEntity circle; @@ -535,6 +536,13 @@ public: // The constraint that is being edited with the on-screen textbox. hConstraint constraintBeingEdited; + enum SuggestedConstraint { + SUGGESTED_NONE = 0, + SUGGESTED_HORIZONTAL = Constraint::HORIZONTAL, + SUGGESTED_VERTICAL = Constraint::VERTICAL, + }; + SuggestedConstraint SuggestLineConstraint(hRequest lineSegment); + Vector SnapToGrid(Vector p); bool ConstrainPointByHovered(hEntity pt); void DeleteTaggedRequests(void);