Skip to content

Commit a8001ad

Browse files
committed
Add horizontal and vertical constraints. Those have their own 2d/3d
issues, when the points are not all in the same coordinate system. All painful, of course. Also add continuous line drawing, and auto-constraining of line segments as I draw. [git-p4: depot-paths = "//depot/solvespace/": change = 1683]
1 parent 1bf7e3d commit a8001ad

File tree

8 files changed

+259
-43
lines changed

8 files changed

+259
-43
lines changed

constraint.cpp

Lines changed: 101 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,16 @@ hConstraint Constraint::AddConstraint(Constraint *c) {
55
return c->h;
66
}
77

8+
void Constraint::ConstrainCoincident(hEntity ptA, hEntity ptB) {
9+
Constraint c;
10+
memset(&c, 0, sizeof(c));
11+
c.group = SS.GW.activeGroup;
12+
c.type = Constraint::POINTS_COINCIDENT;
13+
c.ptA = ptA;
14+
c.ptB = ptB;
15+
SS.constraint.AddAndAssignId(&c);
16+
}
17+
818
void Constraint::MenuConstrain(int id) {
919
Constraint c;
1020
memset(&c, 0, sizeof(c));
@@ -62,6 +72,48 @@ void Constraint::MenuConstrain(int id) {
6272
AddConstraint(&c);
6373
break;
6474

75+
case GraphicsWindow::MNU_VERTICAL:
76+
case GraphicsWindow::MNU_HORIZONTAL: {
77+
hEntity ha, hb;
78+
if(gs.lineSegments == 1 && gs.n == 1) {
79+
c.entityA = gs.entity[0];
80+
Entity *e = SS.GetEntity(c.entityA);
81+
ha = e->assoc[0];
82+
hb = e->assoc[1];
83+
} else if(gs.points == 2 && gs.n == 2) {
84+
ha = c.ptA = gs.point[0];
85+
hb = c.ptB = gs.point[1];
86+
} else {
87+
Error("Bad selection for horizontal / vertical constraint.");
88+
return;
89+
}
90+
Entity *ea = SS.GetEntity(ha);
91+
Entity *eb = SS.GetEntity(hb);
92+
if(ea->csys.v == Entity::NO_CSYS.v &&
93+
eb->csys.v == Entity::NO_CSYS.v)
94+
{
95+
Error("Horizontal/vertical constraint applies only to "
96+
"entities drawn in a 2d coordinate system.");
97+
return;
98+
}
99+
if(eb->csys.v == SS.GW.activeCsys.v) {
100+
// We are constraining two points in two different csyss; so
101+
// we have two choices for the definitons of the coordinate
102+
// directions. ptA's gets chosen, so make sure that's the
103+
// active csys.
104+
hEntity t = c.ptA;
105+
c.ptA = c.ptB;
106+
c.ptB = t;
107+
}
108+
if(id == GraphicsWindow::MNU_HORIZONTAL) {
109+
c.type = HORIZONTAL;
110+
} else {
111+
c.type = VERTICAL;
112+
}
113+
AddConstraint(&c);
114+
break;
115+
}
116+
65117
case GraphicsWindow::MNU_SOLVE_NOW:
66118
SS.Solve();
67119
return;
@@ -157,24 +209,27 @@ void Constraint::Generate(IdList<Equation,hEquation> *l) {
157209
AddEq(l, eab.x, 0);
158210
AddEq(l, eab.y, 1);
159211
AddEq(l, eab.z, 2);
160-
} else if(a->IsPointIn3d() && !b->IsPointIn3d()) {
161-
// One point has 2 DOF, one has 3; write two eqs, on the
162-
// projection of the 3 DOF point into the 2 DOF point plane.
212+
} else if(!(a->IsPointIn3d() || b->IsPointIn3d()) &&
213+
(a->csys.v == b->csys.v))
214+
{
215+
// Both in same csys, nice.
216+
AddEq(l, Expr::FromParam(a->param.h[0])->Minus(
217+
Expr::FromParam(b->param.h[0])), 0);
218+
AddEq(l, Expr::FromParam(a->param.h[1])->Minus(
219+
Expr::FromParam(b->param.h[1])), 1);
220+
} else {
221+
// Either two 2 DOF points in different planes, or one
222+
// 3 DOF point and one 2 DOF point. Either way, write two
223+
// equations on the projection of a into b's plane.
163224
ExprVector p3;
164225
p3 = a->PointGetExprs();
165226
Entity *csy = SS.GetEntity(b->csys);
227+
ExprVector offset = csy->Csys2dGetOffsetExprs();
228+
p3 = p3.Minus(offset);
166229
ExprVector u, v;
167230
csy->Csys2dGetBasisExprs(&u, &v);
168231
AddEq(l, Expr::FromParam(b->param.h[0])->Minus(p3.Dot(u)), 0);
169232
AddEq(l, Expr::FromParam(b->param.h[1])->Minus(p3.Dot(v)), 1);
170-
} else if(a->csys.v == b->csys.v) {
171-
// Both in same csys, nice.
172-
AddEq(l, Expr::FromParam(a->param.h[0])->Minus(
173-
Expr::FromParam(b->param.h[0])), 0);
174-
AddEq(l, Expr::FromParam(a->param.h[1])->Minus(
175-
Expr::FromParam(b->param.h[1])), 1);
176-
} else {
177-
oops();
178233
}
179234
break;
180235
}
@@ -188,6 +243,41 @@ void Constraint::Generate(IdList<Equation,hEquation> *l) {
188243
break;
189244
}
190245

246+
case HORIZONTAL:
247+
case VERTICAL: {
248+
hEntity ha, hb;
249+
if(entityA.v) {
250+
Entity *e = SS.GetEntity(entityA);
251+
ha = e->assoc[0];
252+
hb = e->assoc[1];
253+
} else {
254+
ha = ptA;
255+
hb = ptB;
256+
}
257+
Entity *a = SS.GetEntity(ha);
258+
Entity *b = SS.GetEntity(hb);
259+
if(a->csys.v == Entity::NO_CSYS.v) {
260+
Entity *t = a;
261+
a = b;
262+
b = t;
263+
}
264+
265+
if(a->csys.v == b->csys.v) {
266+
int i = (type == HORIZONTAL) ? 1 : 0;
267+
AddEq(l, Expr::FromParam(a->param.h[i])->Minus(
268+
Expr::FromParam(b->param.h[i])), 0);
269+
} else {
270+
Entity *csy = SS.GetEntity(a->csys);
271+
ExprVector u, v;
272+
csy->Csys2dGetBasisExprs(&u, &v);
273+
ExprVector norm = (type == HORIZONTAL) ? v : u;
274+
ExprVector pa = a->PointGetExprs();
275+
ExprVector pb = b->PointGetExprs();
276+
AddEq(l, (pa.Minus(pb)).Dot(norm), 0);
277+
}
278+
break;
279+
}
280+
191281
default: oops();
192282
}
193283
}

drawconstraint.cpp

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) {
3333
Vector gu = SS.GW.projUp;
3434
Vector gn = gr.Cross(gu);
3535

36-
glxColor(1, 0.3, 1);
36+
glxColor(1, 0.2, 1);
3737
switch(type) {
3838
case PT_PT_DISTANCE: {
3939
Vector ap = SS.GetEntity(ptA)->PointGetCoords();
@@ -125,6 +125,55 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) {
125125
break;
126126
}
127127

128+
case HORIZONTAL:
129+
case VERTICAL:
130+
if(entityA.v) {
131+
Entity *e = SS.GetEntity(entityA);
132+
Vector a = SS.GetEntity(e->assoc[0])->PointGetCoords();
133+
Vector b = SS.GetEntity(e->assoc[1])->PointGetCoords();
134+
Vector m = (a.ScaledBy(0.5)).Plus(b.ScaledBy(0.5));
135+
136+
if(dogd.drawing) {
137+
glPushMatrix();
138+
glxTranslatev(m);
139+
glxOntoCsys(gr, gu);
140+
glxWriteText(type == HORIZONTAL ? "H" : "V");
141+
glPopMatrix();
142+
} else {
143+
Point2d ref = SS.GW.ProjectPoint(m);
144+
dogd.dmin = min(dogd.dmin, ref.DistanceTo(dogd.mp)-10);
145+
}
146+
} else {
147+
Vector a = SS.GetEntity(ptA)->PointGetCoords();
148+
Vector b = SS.GetEntity(ptB)->PointGetCoords();
149+
Entity *csy = SS.GetEntity(SS.GetEntity(ptA)->csys);
150+
Vector cn = csy->Csys2dGetNormalVector();
151+
152+
int i;
153+
for(i = 0; i < 2; i++) {
154+
Vector o = (i == 0) ? a : b;
155+
Vector d = (i == 0) ? a.Minus(b) : b.Minus(a);
156+
Vector dp = cn.Cross(d);
157+
d = d.WithMagnitude(14/SS.GW.scale);
158+
Vector c = o.Minus(d);
159+
LineDrawOrGetDistance(o, c);
160+
d = d.WithMagnitude(3/SS.GW.scale);
161+
dp = dp.WithMagnitude(2/SS.GW.scale);
162+
if(dogd.drawing) {
163+
glBegin(GL_QUADS);
164+
glxVertex3v((c.Plus(d)).Plus(dp));
165+
glxVertex3v((c.Minus(d)).Plus(dp));
166+
glxVertex3v((c.Minus(d)).Minus(dp));
167+
glxVertex3v((c.Plus(d)).Minus(dp));
168+
glEnd();
169+
} else {
170+
Point2d ref = SS.GW.ProjectPoint(c);
171+
dogd.dmin = min(dogd.dmin, ref.DistanceTo(dogd.mp)-6);
172+
}
173+
}
174+
}
175+
break;
176+
128177
default: oops();
129178
}
130179
}

entity.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ void Entity::Csys2dGetBasisVectors(Vector *u, Vector *v) {
1616
*v = quat.RotationV();
1717
}
1818

19+
Vector Entity::Csys2dGetNormalVector(void) {
20+
Vector u, v;
21+
Csys2dGetBasisVectors(&u, &v);
22+
return u.Cross(v);
23+
}
24+
1925
void Entity::Csys2dGetBasisExprs(ExprVector *u, ExprVector *v) {
2026
Expr *a = Expr::FromParam(param.h[0]);
2127
Expr *b = Expr::FromParam(param.h[1]);
@@ -47,6 +53,10 @@ void Entity::Csys2dGetBasisExprs(ExprVector *u, ExprVector *v) {
4753
v->z = (v->z)->Plus(two->Times(c->Times(d)));
4854
}
4955

56+
ExprVector Entity::Csys2dGetOffsetExprs(void) {
57+
return SS.GetEntity(assoc[0])->PointGetExprs();
58+
}
59+
5060
bool Entity::HasPlane(void) {
5161
switch(type) {
5262
case CSYS_2D:

0 commit comments

Comments
 (0)