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.
pull/4/head
ruevs 2015-10-27 12:28:33 +02:00 committed by whitequark
parent 8c2e94a01a
commit b23336b589
12 changed files with 47 additions and 3 deletions

View File

@ -313,6 +313,10 @@ SLVS_C_LENGTH_RATIO*
The length of line entityA divided by the length of line entityB is The length of line entityA divided by the length of line entityB is
equal to valA. 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* SLVS_C_EQ_LEN_PT_LINE_D*
The length of the line entityA is equal to the distance from point The length of the line entityA is equal to the distance from point

View File

@ -511,6 +511,7 @@ Module VbDemo
Public Const SLVS_C_PROJ_PT_DISTANCE As Integer = 100030 Public Const SLVS_C_PROJ_PT_DISTANCE As Integer = 100030
Public Const SLVS_C_WHERE_DRAGGED As Integer = 100031 Public Const SLVS_C_WHERE_DRAGGED As Integer = 100031
Public Const SLVS_C_CURVE_CURVE_TANGENT As Integer = 100032 Public Const SLVS_C_CURVE_CURVE_TANGENT As Integer = 100032
Public Const SLVS_C_LENGTH_DIFFERENCE As Integer = 100033
<StructLayout(LayoutKind.Sequential)> Public Structure Slvs_Constraint <StructLayout(LayoutKind.Sequential)> Public Structure Slvs_Constraint
Public h As UInteger Public h As UInteger

View File

@ -112,6 +112,7 @@ typedef struct {
#define SLVS_C_PROJ_PT_DISTANCE 100030 #define SLVS_C_PROJ_PT_DISTANCE 100030
#define SLVS_C_WHERE_DRAGGED 100031 #define SLVS_C_WHERE_DRAGGED 100031
#define SLVS_C_CURVE_CURVE_TANGENT 100032 #define SLVS_C_CURVE_CURVE_TANGENT 100032
#define SLVS_C_LENGTH_DIFFERENCE 100033
typedef struct { typedef struct {
Slvs_hConstraint h; Slvs_hConstraint h;

View File

@ -24,6 +24,7 @@ char *Constraint::DescriptionString(void) {
case EQ_LEN_PT_LINE_D: s = "eq-length-and-pt-ln-dist"; break; 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 EQ_PT_LN_DISTANCES: s = "eq-pt-line-distances"; break;
case LENGTH_RATIO: s = "length-ratio"; break; case LENGTH_RATIO: s = "length-ratio"; break;
case LENGTH_DIFFERENCE: s = "length-difference"; break;
case SYMMETRIC: s = "symmetric"; break; case SYMMETRIC: s = "symmetric"; break;
case SYMMETRIC_HORIZ: s = "symmetric-h"; break; case SYMMETRIC_HORIZ: s = "symmetric-h"; break;
case SYMMETRIC_VERT: s = "symmetric-v"; break; case SYMMETRIC_VERT: s = "symmetric-v"; break;
@ -322,6 +323,23 @@ void Constraint::MenuConstrain(int id) {
AddConstraint(&c); AddConstraint(&c);
break; 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: case GraphicsWindow::MNU_AT_MIDPOINT:
if(gs.lineSegments == 1 && gs.points == 1 && gs.n == 2) { if(gs.lineSegments == 1 && gs.points == 1 && gs.n == 2) {
c.type = AT_MIDPOINT; c.type = AT_MIDPOINT;

View File

@ -18,6 +18,7 @@ bool ConstraintBase::HasLabel(void) {
case PROJ_PT_DISTANCE: case PROJ_PT_DISTANCE:
case DIAMETER: case DIAMETER:
case LENGTH_RATIO: case LENGTH_RATIO:
case LENGTH_DIFFERENCE:
case ANGLE: case ANGLE:
case COMMENT: case COMMENT:
return true; return true;
@ -279,6 +280,15 @@ void ConstraintBase::GenerateReal(IdList<Equation,hEquation> *l) {
break; 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: { case DIAMETER: {
EntityBase *circle = SK.GetEntity(entityA); EntityBase *circle = SK.GetEntity(entityA);
Expr *r = circle->CircleGetRadiusExpr(); Expr *r = circle->CircleGetRadiusExpr();

View File

@ -63,6 +63,8 @@ char *Constraint::Label(void) {
sprintf(Ret, "%.2f", valA); sprintf(Ret, "%.2f", valA);
} else if(type == LENGTH_RATIO) { } else if(type == LENGTH_RATIO) {
sprintf(Ret, "%.3f:1", valA); sprintf(Ret, "%.3f:1", valA);
} else if(type == LENGTH_DIFFERENCE) {
sprintf(Ret, "%.3f", valA);
} else if(type == COMMENT) { } else if(type == COMMENT) {
strcpy(Ret, comment.str); strcpy(Ret, comment.str);
} else if(type == DIAMETER) { } else if(type == DIAMETER) {
@ -853,6 +855,7 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) {
} }
case LENGTH_RATIO: case LENGTH_RATIO:
case LENGTH_DIFFERENCE:
case EQUAL_LENGTH_LINES: { case EQUAL_LENGTH_LINES: {
Vector a, b = Vector::From(0, 0, 0); Vector a, b = Vector::From(0, 0, 0);
for(int i = 0; i < 2; i++) { for(int i = 0; i < 2; i++) {
@ -867,7 +870,7 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) {
DoEqualLenTicks(a, b, gn); 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); Vector ref = ((a.Plus(b)).ScaledBy(0.5)).Plus(disp.offset);
DoLabel(ref, labelPos, gr, gu); DoLabel(ref, labelPos, gr, gu);
} }

View File

@ -139,6 +139,7 @@ const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = {
{ 1, "&On Point / Curve / Plane", MNU_ON_ENTITY, 'O', IN, mCon }, { 1, "&On Point / Curve / Plane", MNU_ON_ENTITY, 'O', IN, mCon },
{ 1, "E&qual Length / Radius / Angle", MNU_EQUAL, 'Q', IN, mCon }, { 1, "E&qual Length / Radius / Angle", MNU_EQUAL, 'Q', IN, mCon },
{ 1, "Length Ra&tio", MNU_RATIO, 'Z', 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, "At &Midpoint", MNU_AT_MIDPOINT, 'M', IN, mCon },
{ 1, "S&ymmetric", MNU_SYMMETRIC, 'Y', IN, mCon }, { 1, "S&ymmetric", MNU_SYMMETRIC, 'Y', IN, mCon },
{ 1, "Para&llel / Tangent", MNU_PARALLEL, 'L', IN, mCon }, { 1, "Para&llel / Tangent", MNU_PARALLEL, 'L', IN, mCon },

View File

@ -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_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_ANGLE: t = Constraint::EQUAL_ANGLE; break;
case SLVS_C_EQUAL_LINE_ARC_LEN: t = Constraint::EQUAL_LINE_ARC_LEN; 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: t = Constraint::SYMMETRIC; break;
case SLVS_C_SYMMETRIC_HORIZ: t = Constraint::SYMMETRIC_HORIZ; break; case SLVS_C_SYMMETRIC_HORIZ: t = Constraint::SYMMETRIC_HORIZ; break;
case SLVS_C_SYMMETRIC_VERT: t = Constraint::SYMMETRIC_VERT; break; case SLVS_C_SYMMETRIC_VERT: t = Constraint::SYMMETRIC_VERT; break;

View File

@ -1155,6 +1155,7 @@ void GraphicsWindow::MouseLeftDoubleClick(double mx, double my) {
case Constraint::ANGLE: case Constraint::ANGLE:
case Constraint::LENGTH_RATIO: case Constraint::LENGTH_RATIO:
case Constraint::LENGTH_DIFFERENCE:
sprintf(s, "%.3f", c->valA); sprintf(s, "%.3f", c->valA);
break; break;
@ -1206,7 +1207,8 @@ void GraphicsWindow::EditControlDone(const char *s) {
case Constraint::PROJ_PT_DISTANCE: case Constraint::PROJ_PT_DISTANCE:
case Constraint::PT_LINE_DISTANCE: case Constraint::PT_LINE_DISTANCE:
case Constraint::PT_FACE_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 // The sign is not displayed to the user, but this is a signed
// distance internally. To flip the sign, the user enters a // distance internally. To flip the sign, the user enters a
// negative distance. // negative distance.

View File

@ -555,6 +555,7 @@ public:
EQ_PT_LN_DISTANCES = 53, EQ_PT_LN_DISTANCES = 53,
EQUAL_ANGLE = 54, EQUAL_ANGLE = 54,
EQUAL_LINE_ARC_LEN = 55, EQUAL_LINE_ARC_LEN = 55,
LENGTH_DIFFERENCE = 56,
SYMMETRIC = 60, SYMMETRIC = 60,
SYMMETRIC_HORIZ = 61, SYMMETRIC_HORIZ = 61,
SYMMETRIC_VERT = 62, SYMMETRIC_VERT = 62,

View File

@ -560,7 +560,8 @@ void SolveSpaceUI::MenuAnalyze(int id) {
SS.TW.shown.dimSteps = 10; SS.TW.shown.dimSteps = 10;
SS.TW.shown.dimIsDistance = SS.TW.shown.dimIsDistance =
(c->type != Constraint::ANGLE) && (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.constraint = c->h;
SS.TW.shown.screen = TextWindow::SCREEN_STEP_DIMENSION; SS.TW.shown.screen = TextWindow::SCREEN_STEP_DIMENSION;

View File

@ -404,6 +404,7 @@ public:
MNU_REFERENCE, MNU_REFERENCE,
MNU_EQUAL, MNU_EQUAL,
MNU_RATIO, MNU_RATIO,
MNU_DIFFERENCE,
MNU_ON_ENTITY, MNU_ON_ENTITY,
MNU_SYMMETRIC, MNU_SYMMETRIC,
MNU_AT_MIDPOINT, MNU_AT_MIDPOINT,