@@ -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+
818void 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}
0 commit comments