From b23336b5891d4a7b142bde3c9171b100d943da94 Mon Sep 17 00:00:00 2001 From: ruevs Date: Tue, 27 Oct 2015 12:28:33 +0200 Subject: [PATCH] Add a new length-difference constraint. This constraint requires the lengths of two line segments to differ by a constant. It can be useful to define the tolerances when making joints. --- exposed/DOC.txt | 4 ++++ exposed/VbDemo.vb | 1 + include/slvs.h | 1 + src/constraint.cpp | 18 ++++++++++++++++++ src/constrainteq.cpp | 10 ++++++++++ src/drawconstraint.cpp | 5 ++++- src/graphicswin.cpp | 1 + src/lib.cpp | 1 + src/mouse.cpp | 4 +++- src/sketch.h | 1 + src/solvespace.cpp | 3 ++- src/ui.h | 1 + 12 files changed, 47 insertions(+), 3 deletions(-) diff --git a/exposed/DOC.txt b/exposed/DOC.txt index 5b049509..743349b6 100644 --- a/exposed/DOC.txt +++ b/exposed/DOC.txt @@ -313,6 +313,10 @@ SLVS_C_LENGTH_RATIO* The length of line entityA divided by the length of line entityB is equal to valA. +SLVS_C_LENGTH_DIFFERENCE* + + The lengths of line entityA and line entityB differ by valA. + SLVS_C_EQ_LEN_PT_LINE_D* The length of the line entityA is equal to the distance from point diff --git a/exposed/VbDemo.vb b/exposed/VbDemo.vb index 01eafc73..6781fc46 100644 --- a/exposed/VbDemo.vb +++ b/exposed/VbDemo.vb @@ -511,6 +511,7 @@ Module VbDemo Public Const SLVS_C_PROJ_PT_DISTANCE As Integer = 100030 Public Const SLVS_C_WHERE_DRAGGED As Integer = 100031 Public Const SLVS_C_CURVE_CURVE_TANGENT As Integer = 100032 + Public Const SLVS_C_LENGTH_DIFFERENCE As Integer = 100033 Public Structure Slvs_Constraint Public h As UInteger diff --git a/include/slvs.h b/include/slvs.h index a06ac92a..3181ceb6 100644 --- a/include/slvs.h +++ b/include/slvs.h @@ -112,6 +112,7 @@ typedef struct { #define SLVS_C_PROJ_PT_DISTANCE 100030 #define SLVS_C_WHERE_DRAGGED 100031 #define SLVS_C_CURVE_CURVE_TANGENT 100032 +#define SLVS_C_LENGTH_DIFFERENCE 100033 typedef struct { Slvs_hConstraint h; diff --git a/src/constraint.cpp b/src/constraint.cpp index 8a023979..1627937d 100644 --- a/src/constraint.cpp +++ b/src/constraint.cpp @@ -24,6 +24,7 @@ char *Constraint::DescriptionString(void) { case EQ_LEN_PT_LINE_D: s = "eq-length-and-pt-ln-dist"; break; case EQ_PT_LN_DISTANCES: s = "eq-pt-line-distances"; break; case LENGTH_RATIO: s = "length-ratio"; break; + case LENGTH_DIFFERENCE: s = "length-difference"; break; case SYMMETRIC: s = "symmetric"; break; case SYMMETRIC_HORIZ: s = "symmetric-h"; break; case SYMMETRIC_VERT: s = "symmetric-v"; break; @@ -322,6 +323,23 @@ void Constraint::MenuConstrain(int id) { AddConstraint(&c); break; + case GraphicsWindow::MNU_DIFFERENCE: + if(gs.lineSegments == 2 && gs.n == 2) { + c.type = LENGTH_DIFFERENCE; + c.entityA = gs.entity[0]; + c.entityB = gs.entity[1]; + } else { + Error("Bad selection for length difference constraint. This " + "constraint can apply to:\n\n" + " * two line segments\n"); + return; + } + + c.valA = 0; + c.ModifyToSatisfy(); + AddConstraint(&c); + break; + case GraphicsWindow::MNU_AT_MIDPOINT: if(gs.lineSegments == 1 && gs.points == 1 && gs.n == 2) { c.type = AT_MIDPOINT; diff --git a/src/constrainteq.cpp b/src/constrainteq.cpp index 1c6beb1d..59288260 100644 --- a/src/constrainteq.cpp +++ b/src/constrainteq.cpp @@ -18,6 +18,7 @@ bool ConstraintBase::HasLabel(void) { case PROJ_PT_DISTANCE: case DIAMETER: case LENGTH_RATIO: + case LENGTH_DIFFERENCE: case ANGLE: case COMMENT: return true; @@ -279,6 +280,15 @@ void ConstraintBase::GenerateReal(IdList *l) { break; } + case LENGTH_DIFFERENCE: { + EntityBase *a = SK.GetEntity(entityA); + EntityBase *b = SK.GetEntity(entityB); + Expr *la = Distance(workplane, a->point[0], a->point[1]); + Expr *lb = Distance(workplane, b->point[0], b->point[1]); + AddEq(l, (la->Minus(lb))->Minus(exA), 0); + break; + } + case DIAMETER: { EntityBase *circle = SK.GetEntity(entityA); Expr *r = circle->CircleGetRadiusExpr(); diff --git a/src/drawconstraint.cpp b/src/drawconstraint.cpp index 391ae5cc..82a1708b 100644 --- a/src/drawconstraint.cpp +++ b/src/drawconstraint.cpp @@ -63,6 +63,8 @@ char *Constraint::Label(void) { sprintf(Ret, "%.2f", valA); } else if(type == LENGTH_RATIO) { sprintf(Ret, "%.3f:1", valA); + } else if(type == LENGTH_DIFFERENCE) { + sprintf(Ret, "%.3f", valA); } else if(type == COMMENT) { strcpy(Ret, comment.str); } else if(type == DIAMETER) { @@ -853,6 +855,7 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) { } case LENGTH_RATIO: + case LENGTH_DIFFERENCE: case EQUAL_LENGTH_LINES: { Vector a, b = Vector::From(0, 0, 0); for(int i = 0; i < 2; i++) { @@ -867,7 +870,7 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) { DoEqualLenTicks(a, b, gn); } - if(type == LENGTH_RATIO) { + if((type == LENGTH_RATIO) || (type == LENGTH_DIFFERENCE)) { Vector ref = ((a.Plus(b)).ScaledBy(0.5)).Plus(disp.offset); DoLabel(ref, labelPos, gr, gu); } diff --git a/src/graphicswin.cpp b/src/graphicswin.cpp index 806c32a4..a76b3db7 100644 --- a/src/graphicswin.cpp +++ b/src/graphicswin.cpp @@ -139,6 +139,7 @@ const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = { { 1, "&On Point / Curve / Plane", MNU_ON_ENTITY, 'O', IN, mCon }, { 1, "E&qual Length / Radius / Angle", MNU_EQUAL, 'Q', IN, mCon }, { 1, "Length Ra&tio", MNU_RATIO, 'Z', IN, mCon }, +{ 1, "Length Diff&erence", MNU_DIFFERENCE, 'J', IN, mCon }, { 1, "At &Midpoint", MNU_AT_MIDPOINT, 'M', IN, mCon }, { 1, "S&ymmetric", MNU_SYMMETRIC, 'Y', IN, mCon }, { 1, "Para&llel / Tangent", MNU_PARALLEL, 'L', IN, mCon }, diff --git a/src/lib.cpp b/src/lib.cpp index 67fcb09c..bf9a81e7 100644 --- a/src/lib.cpp +++ b/src/lib.cpp @@ -156,6 +156,7 @@ case SLVS_C_EQ_LEN_PT_LINE_D: t = Constraint::EQ_LEN_PT_LINE_D; break; case SLVS_C_EQ_PT_LN_DISTANCES: t = Constraint::EQ_PT_LN_DISTANCES; break; case SLVS_C_EQUAL_ANGLE: t = Constraint::EQUAL_ANGLE; break; case SLVS_C_EQUAL_LINE_ARC_LEN: t = Constraint::EQUAL_LINE_ARC_LEN; break; +case SLVS_C_LENGTH_DIFFERENCE: t = Constraint::LENGTH_DIFFERENCE; break; case SLVS_C_SYMMETRIC: t = Constraint::SYMMETRIC; break; case SLVS_C_SYMMETRIC_HORIZ: t = Constraint::SYMMETRIC_HORIZ; break; case SLVS_C_SYMMETRIC_VERT: t = Constraint::SYMMETRIC_VERT; break; diff --git a/src/mouse.cpp b/src/mouse.cpp index 9803be99..2a8db0ef 100644 --- a/src/mouse.cpp +++ b/src/mouse.cpp @@ -1155,6 +1155,7 @@ void GraphicsWindow::MouseLeftDoubleClick(double mx, double my) { case Constraint::ANGLE: case Constraint::LENGTH_RATIO: + case Constraint::LENGTH_DIFFERENCE: sprintf(s, "%.3f", c->valA); break; @@ -1206,7 +1207,8 @@ void GraphicsWindow::EditControlDone(const char *s) { case Constraint::PROJ_PT_DISTANCE: case Constraint::PT_LINE_DISTANCE: case Constraint::PT_FACE_DISTANCE: - case Constraint::PT_PLANE_DISTANCE: { + case Constraint::PT_PLANE_DISTANCE: + case Constraint::LENGTH_DIFFERENCE: { // The sign is not displayed to the user, but this is a signed // distance internally. To flip the sign, the user enters a // negative distance. diff --git a/src/sketch.h b/src/sketch.h index 6cf61eb9..a79f472c 100644 --- a/src/sketch.h +++ b/src/sketch.h @@ -555,6 +555,7 @@ public: EQ_PT_LN_DISTANCES = 53, EQUAL_ANGLE = 54, EQUAL_LINE_ARC_LEN = 55, + LENGTH_DIFFERENCE = 56, SYMMETRIC = 60, SYMMETRIC_HORIZ = 61, SYMMETRIC_VERT = 62, diff --git a/src/solvespace.cpp b/src/solvespace.cpp index 94eb3854..e255d45f 100644 --- a/src/solvespace.cpp +++ b/src/solvespace.cpp @@ -560,7 +560,8 @@ void SolveSpaceUI::MenuAnalyze(int id) { SS.TW.shown.dimSteps = 10; SS.TW.shown.dimIsDistance = (c->type != Constraint::ANGLE) && - (c->type != Constraint::LENGTH_RATIO); + (c->type != Constraint::LENGTH_RATIO) && + (c->type != Constraint::LENGTH_DIFFERENCE); SS.TW.shown.constraint = c->h; SS.TW.shown.screen = TextWindow::SCREEN_STEP_DIMENSION; diff --git a/src/ui.h b/src/ui.h index 0bb59e7d..e068dd09 100644 --- a/src/ui.h +++ b/src/ui.h @@ -404,6 +404,7 @@ public: MNU_REFERENCE, MNU_EQUAL, MNU_RATIO, + MNU_DIFFERENCE, MNU_ON_ENTITY, MNU_SYMMETRIC, MNU_AT_MIDPOINT,