diff --git a/constraint.cpp b/constraint.cpp index 94f2bf20..c706d05e 100644 --- a/constraint.cpp +++ b/constraint.cpp @@ -92,16 +92,14 @@ Expr *Constraint::Distance(hEntity hpa, hEntity hpb) { return ((du->Square())->Plus(dv->Square()))->Sqrt(); } - Expr *ax, *ay, *az; - Expr *bx, *by, *bz; - pa->PointGetExprs(&ax, &ay, &az); - pb->PointGetExprs(&bx, &by, &bz); - Expr *dx2 = (ax->Minus(bx))->Square(); - Expr *dy2 = (ay->Minus(by))->Square(); - Expr *dz2 = (az->Minus(bz))->Square(); + // The usual case, just write it in terms of the coordinates + ExprVector ea, eb, eab; + ea = pa->PointGetExprs(); + eb = pb->PointGetExprs(); + eab = ea.Minus(eb); - return (dx2->Plus(dy2->Plus(dz2)))->Sqrt(); + return eab.Magnitude(); } void Constraint::ModifyToSatisfy(void) { @@ -144,24 +142,49 @@ void Constraint::Generate(IdList *l) { } case POINTS_COINCIDENT: { - Expr *ax, *ay, *az; - Expr *bx, *by, *bz; - SS.GetEntity(ptA)->PointGetExprs(&ax, &ay, &az); - SS.GetEntity(ptB)->PointGetExprs(&bx, &by, &bz); - AddEq(l, ax->Minus(bx), 0); - AddEq(l, ay->Minus(by), 1); - AddEq(l, az->Minus(bz), 2); + Entity *a = SS.GetEntity(ptA); + Entity *b = SS.GetEntity(ptB); + if(!a->IsPointIn3d() && b->IsPointIn3d()) { + Entity *t = a; + a = b; b = t; + } + if(a->IsPointIn3d() && b->IsPointIn3d()) { + // Easy case: both points have 3 DOF, so write three eqs. + ExprVector ea, eb, eab; + ea = a->PointGetExprs(); + eb = b->PointGetExprs(); + eab = ea.Minus(eb); + AddEq(l, eab.x, 0); + AddEq(l, eab.y, 1); + AddEq(l, eab.z, 2); + } else if(a->IsPointIn3d() && !b->IsPointIn3d()) { + // One point has 2 DOF, one has 3; write two eqs, on the + // projection of the 3 DOF point into the 2 DOF point plane. + ExprVector p3; + p3 = a->PointGetExprs(); + Entity *csy = SS.GetEntity(b->csys); + ExprVector u, v; + csy->Csys2dGetBasisExprs(&u, &v); + AddEq(l, Expr::FromParam(b->param.h[0])->Minus(p3.Dot(u)), 0); + AddEq(l, Expr::FromParam(b->param.h[1])->Minus(p3.Dot(v)), 1); + } else if(a->csys.v == b->csys.v) { + // Both in same csys, nice. + AddEq(l, Expr::FromParam(a->param.h[0])->Minus( + Expr::FromParam(b->param.h[0])), 0); + AddEq(l, Expr::FromParam(a->param.h[1])->Minus( + Expr::FromParam(b->param.h[1])), 1); + } else { + oops(); + } break; } case PT_IN_PLANE: { - Expr *px, *py, *pz; - Expr *nx, *ny, *nz, *d; - SS.GetEntity(ptA)->PointGetExprs(&px, &py, &pz); - SS.GetEntity(entityA)->PlaneGetExprs(&nx, &ny, &nz, &d); - AddEq(l, - ((px->Times(nx))->Plus((py->Times(ny)->Plus(pz->Times(nz))))) - ->Minus(d), 0); + ExprVector p, n; + Expr *d; + p = SS.GetEntity(ptA)->PointGetExprs(); + SS.GetEntity(entityA)->PlaneGetExprs(&n, &d); + AddEq(l, (p.Dot(n))->Minus(d), 0); break; } diff --git a/entity.cpp b/entity.cpp index 1a3aeb14..d1c9faab 100644 --- a/entity.cpp +++ b/entity.cpp @@ -16,7 +16,7 @@ void Entity::Csys2dGetBasisVectors(Vector *u, Vector *v) { *v = quat.RotationV(); } -void Entity::Csys2dGetBasisExprs(Expr **u, Expr **v) { +void Entity::Csys2dGetBasisExprs(ExprVector *u, ExprVector *v) { Expr *a = Expr::FromParam(param.h[0]); Expr *b = Expr::FromParam(param.h[1]); Expr *c = Expr::FromParam(param.h[2]); @@ -24,23 +24,27 @@ void Entity::Csys2dGetBasisExprs(Expr **u, Expr **v) { Expr *two = Expr::FromConstant(2); - u[0] = a->Square(); - u[0] = (u[0])->Plus(b->Square()); - u[0] = (u[0])->Minus(c->Square()); - u[0] = (u[0])->Minus(d->Square()); - u[1] = two->Times(a->Times(d)); - u[1] = (u[1])->Plus(two->Times(b->Times(c))); - u[2] = two->Times(b->Times(d)); - u[2] = (u[2])->Minus(two->Times(a->Times(c))); + u->x = a->Square(); + u->x = (u->x)->Plus(b->Square()); + u->x = (u->x)->Minus(c->Square()); + u->x = (u->x)->Minus(d->Square()); - v[0] = two->Times(b->Times(c)); - v[0] = (v[0])->Minus(two->Times(a->Times(d))); - v[1] = a->Square(); - v[1] = (v[1])->Minus(b->Square()); - v[1] = (v[1])->Plus(c->Square()); - v[1] = (v[1])->Minus(d->Square()); - v[2] = two->Times(a->Times(b)); - v[2] = (v[2])->Plus(two->Times(c->Times(d))); + u->y = two->Times(a->Times(d)); + u->y = (u->y)->Plus(two->Times(b->Times(c))); + + u->z = two->Times(b->Times(d)); + u->z = (u->z)->Minus(two->Times(a->Times(c))); + + v->x = two->Times(b->Times(c)); + v->x = (v->x)->Minus(two->Times(a->Times(d))); + + v->y = a->Square(); + v->y = (v->y)->Minus(b->Square()); + v->y = (v->y)->Plus(c->Square()); + v->y = (v->y)->Minus(d->Square()); + + v->z = two->Times(a->Times(b)); + v->z = (v->z)->Plus(two->Times(c->Times(d))); } bool Entity::HasPlane(void) { @@ -52,32 +56,33 @@ bool Entity::HasPlane(void) { } } -void Entity::PlaneGetExprs(Expr **x, Expr **y, Expr **z, Expr **dn) { - Expr *a = Expr::FromParam(param.h[0]); - Expr *b = Expr::FromParam(param.h[1]); - Expr *c = Expr::FromParam(param.h[2]); - Expr *d = Expr::FromParam(param.h[3]); +void Entity::PlaneGetExprs(ExprVector *n, Expr **dn) { + if(type == CSYS_2D) { + Expr *a = Expr::FromParam(param.h[0]); + Expr *b = Expr::FromParam(param.h[1]); + Expr *c = Expr::FromParam(param.h[2]); + Expr *d = Expr::FromParam(param.h[3]); - Expr *two = Expr::FromConstant(2); + Expr *two = Expr::FromConstant(2); - // Convert the quaternion to our plane's normal vector. - *x = two->Times(a->Times(c)); - *x = (*x)->Plus (two->Times(b->Times(d))); - *y = two->Times(c->Times(d)); - *y = (*y)->Minus(two->Times(a->Times(b))); - *z = a->Square(); - *z = (*z)->Minus(b->Square()); - *z = (*z)->Minus(c->Square()); - *z = (*z)->Plus (d->Square()); + // Convert the quaternion to our plane's normal vector. + n->x = two->Times(a->Times(c)); + n->x = (n->x)->Plus (two->Times(b->Times(d))); + n->y = two->Times(c->Times(d)); + n->y = (n->y)->Minus(two->Times(a->Times(b))); + n->z = a->Square(); + n->z = (n->z)->Minus(b->Square()); + n->z = (n->z)->Minus(c->Square()); + n->z = (n->z)->Plus (d->Square()); - Expr *x0, *y0, *z0; - SS.GetEntity(assoc[0])->PointGetExprs(&x0, &y0, &z0); - // The plane is n dot (p - p0) = 0, or - // n dot p - n dot p0 = 0 - // so dn = n dot p0 - *dn = x0->Times(*x); - *dn = (*dn)->Plus(y0->Times(*y)); - *dn = (*dn)->Plus(z0->Times(*z)); + ExprVector p0 = SS.GetEntity(assoc[0])->PointGetExprs(); + // The plane is n dot (p - p0) = 0, or + // n dot p - n dot p0 = 0 + // so dn = n dot p0 + *dn = p0.Dot(*n); + } else { + oops(); + } } bool Entity::IsPoint(void) { @@ -90,6 +95,15 @@ bool Entity::IsPoint(void) { } } +bool Entity::IsPointIn3d(void) { + switch(type) { + case POINT_IN_3D: + return true; + default: + return false; + } +} + bool Entity::PointIsKnown(void) { switch(type) { case POINT_IN_3D: @@ -149,31 +163,27 @@ Vector Entity::PointGetCoords(void) { return p; } -void Entity::PointGetExprs(Expr **x, Expr **y, Expr **z) { +ExprVector Entity::PointGetExprs(void) { + ExprVector r; switch(type) { case POINT_IN_3D: - *x = Expr::FromParam(param.h[0]); - *y = Expr::FromParam(param.h[1]); - *z = Expr::FromParam(param.h[2]); + r.x = Expr::FromParam(param.h[0]); + r.y = Expr::FromParam(param.h[1]); + r.z = Expr::FromParam(param.h[2]); break; case POINT_IN_2D: { Entity *c = SS.GetEntity(csys); - Expr *u[3], *v[3]; - c->Csys2dGetBasisExprs(u, v); + ExprVector u, v; + c->Csys2dGetBasisExprs(&u, &v); - *x = Expr::FromParam(param.h[0])->Times(u[0]); - *x = (*x)->Plus(Expr::FromParam(param.h[1])->Times(v[0])); - - *y = Expr::FromParam(param.h[0])->Times(u[1]); - *y = (*y)->Plus(Expr::FromParam(param.h[1])->Times(v[1])); - - *z = Expr::FromParam(param.h[0])->Times(u[2]); - *z = (*z)->Plus(Expr::FromParam(param.h[1])->Times(v[2])); + r = u.ScaledBy(Expr::FromParam(param.h[0])); + r = r.Plus(v.ScaledBy(Expr::FromParam(param.h[1]))); break; } default: oops(); } + return r; } void Entity::LineDrawOrGetDistance(Vector a, Vector b) { @@ -226,17 +236,15 @@ void Entity::DrawOrGetDistance(int order) { Vector d = SS.GW.projUp.ScaledBy(s/SS.GW.scale); glxColor(0, 0.8, 0); - glDisable(GL_LINE_SMOOTH); glBegin(GL_QUADS); glxVertex3v(v.Plus (r).Plus (d)); glxVertex3v(v.Plus (r).Minus(d)); glxVertex3v(v.Minus(r).Minus(d)); glxVertex3v(v.Minus(r).Plus (d)); glEnd(); - glEnable(GL_LINE_SMOOTH); } else { Point2d pp = SS.GW.ProjectPoint(v); - dogd.dmin = pp.DistanceTo(dogd.mp) - 7; + dogd.dmin = pp.DistanceTo(dogd.mp) - 5; } break; } diff --git a/expr.cpp b/expr.cpp index 9af47e17..136eac57 100644 --- a/expr.cpp +++ b/expr.cpp @@ -1,5 +1,52 @@ #include "solvespace.h" +ExprVector ExprVector::FromExprs(Expr *x, Expr *y, Expr *z) { + ExprVector r = { x, y, z}; + return r; +} + +ExprVector ExprVector::Minus(ExprVector b) { + ExprVector r; + r.x = x->Minus(b.x); + r.y = y->Minus(b.y); + r.z = z->Minus(b.z); + return r; +} + +ExprVector ExprVector::Plus(ExprVector b) { + ExprVector r; + r.x = x->Plus(b.x); + r.y = y->Plus(b.y); + r.z = z->Plus(b.z); + return r; +} + +Expr *ExprVector::Dot(ExprVector b) { + Expr *r; + r = x->Times(b.x); + r = r->Plus(y->Times(b.y)); + r = r->Plus(z->Times(b.z)); + return r; +} + +ExprVector ExprVector::ScaledBy(Expr *s) { + ExprVector r; + r.x = x->Times(s); + r.y = y->Times(s); + r.z = z->Times(s); + return r; +} + +Expr *ExprVector::Magnitude(void) { + Expr *r; + r = x->Square(); + r = r->Plus(y->Square()); + r = r->Plus(z->Square()); + return r->Sqrt(); +} + + + Expr *Expr::FromParam(hParam p) { Expr *r = AllocExpr(); r->op = PARAM; diff --git a/expr.h b/expr.h index 326789e3..80a3beed 100644 --- a/expr.h +++ b/expr.h @@ -111,4 +111,17 @@ public: static void Parse(void); }; +class ExprVector { +public: + Expr *x, *y, *z; + + static ExprVector FromExprs(Expr *x, Expr *y, Expr *z); + + ExprVector Plus(ExprVector b); + ExprVector Minus(ExprVector b); + Expr *Dot(ExprVector b); + ExprVector ScaledBy(Expr *s); + Expr *Magnitude(void); +}; + #endif diff --git a/graphicswin.cpp b/graphicswin.cpp index ade8c034..05cc836f 100644 --- a/graphicswin.cpp +++ b/graphicswin.cpp @@ -34,8 +34,8 @@ const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = { { 1, "&Onto Plane / Coordinate System\tO", MNU_ORIENT_ONTO, 'O', mView }, { 1, "&Lock Orientation\tL", MNU_LOCK_VIEW, 'L', mView }, { 1, NULL, 0, NULL }, -{ 1, "Dimensions in &Inches", 0, NULL }, -{ 1, "Dimensions in &Millimeters", 0, NULL }, +{ 1, "Dimensions in &Inches", MNU_UNITS_INCHES, 0, mView }, +{ 1, "Dimensions in &Millimeters", MNU_UNITS_MM, 0, mView }, { 0, "&Group", 0, 0, NULL }, { 1, "New &Drawing Group", 0, 0, NULL }, @@ -139,7 +139,7 @@ void GraphicsWindow::MenuView(int id) { case MNU_LOCK_VIEW: SS.GW.viewLocked = !SS.GW.viewLocked; - CheckMenuById(MNU_LOCK_VIEW, SS.GW.viewLocked); + SS.GW.EnsureValidActives(); break; case MNU_ORIENT_ONTO: { @@ -200,6 +200,16 @@ void GraphicsWindow::MenuView(int id) { break; } + case MNU_UNITS_MM: + SS.GW.viewUnits = UNIT_MM; + SS.GW.EnsureValidActives(); + break; + + case MNU_UNITS_INCHES: + SS.GW.viewUnits = UNIT_INCHES; + SS.GW.EnsureValidActives(); + break; + default: oops(); } InvalidateGraphics(); @@ -233,6 +243,18 @@ void GraphicsWindow::EnsureValidActives(void) { bool in3d = (activeCsys.v == Entity::NO_CSYS.v); CheckMenuById(MNU_NO_CSYS, in3d); CheckMenuById(MNU_SEL_CSYS, !in3d); + + // And update the checked state for various menus + CheckMenuById(MNU_LOCK_VIEW, viewLocked); + switch(viewUnits) { + case UNIT_MM: + case UNIT_INCHES: + break; + default: + viewUnits = UNIT_MM; + } + CheckMenuById(MNU_UNITS_MM, viewUnits == UNIT_MM); + CheckMenuById(MNU_UNITS_INCHES, viewUnits == UNIT_INCHES); } void GraphicsWindow::MenuEdit(int id) { @@ -242,6 +264,7 @@ void GraphicsWindow::MenuEdit(int id) { SS.GW.ClearSelection(); SS.GW.pendingOperation = 0; SS.GW.pendingDescription = NULL; + SS.TW.ScreenNavigation('h', 0); SS.TW.Show(); break; diff --git a/sketch.h b/sketch.h index f781b54d..061573eb 100644 --- a/sketch.h +++ b/sketch.h @@ -96,10 +96,9 @@ public: int type; hEntity csys; // or Entity::NO_CSYS - hGroup group; - NameStr name; + bool construction; // When a request generates entities from entities, and the source // entities may have come from multiple requests, it's necessary to @@ -141,12 +140,13 @@ public: // Applies only for a CSYS_2D type void Csys2dGetBasisVectors(Vector *u, Vector *v); - void Csys2dGetBasisExprs(Expr **u, Expr **v); + void Csys2dGetBasisExprs(ExprVector *u, ExprVector *v); bool IsPoint(void); + bool IsPointIn3d(void); // Applies for any of the point types - void PointGetExprs(Expr **x, Expr **y, Expr **z); Vector PointGetCoords(void); + ExprVector PointGetExprs(void); void PointForceTo(Vector v); bool PointIsFromReferences(void); bool PointIsKnown(void); @@ -154,7 +154,7 @@ public: // Applies for anything that comes with a plane bool HasPlane(void); // The plane is points P such that P dot (xn, yn, zn) - d = 0 - void PlaneGetExprs(Expr **xn, Expr **yn, Expr **zn, Expr **d); + void PlaneGetExprs(ExprVector *n, Expr **d); // Routines to draw and hit-test the representation of the entity // on-screen. diff --git a/solvespace.h b/solvespace.h index 827b7a76..2fd9b6dd 100644 --- a/solvespace.h +++ b/solvespace.h @@ -26,6 +26,7 @@ typedef signed long SDWORD; #include class Expr; +class ExprVector; // From the platform-specific code. int SaveFileYesNoCancel(void); diff --git a/textwin.cpp b/textwin.cpp index 01a8b2e9..9a90071d 100644 --- a/textwin.cpp +++ b/textwin.cpp @@ -176,7 +176,7 @@ void TextWindow::OneScreenForward(void) { history++; } -void TextWindow::ScreenNavigaton(int link, DWORD v) { +void TextWindow::ScreenNavigation(int link, DWORD v) { switch(link) { default: case 'h': @@ -216,8 +216,8 @@ void TextWindow::ShowHeader(void) { cd = SS.GetEntity(SS.GW.activeCsys)->DescriptionString(); } Printf(" %Lb%f<<%E %Lh%fhome%E %C4 csys:%C5 %s", - (DWORD)(&TextWindow::ScreenNavigaton), - (DWORD)(&TextWindow::ScreenNavigaton), + (DWORD)(&TextWindow::ScreenNavigation), + (DWORD)(&TextWindow::ScreenNavigation), cd); } diff --git a/ui.h b/ui.h index 3a08bb92..0cc0d702 100644 --- a/ui.h +++ b/ui.h @@ -65,7 +65,7 @@ public: void OneScreenForward(void); static void ScreenSelectGroup(int link, DWORD v); - static void ScreenNavigaton(int link, DWORD v); + static void ScreenNavigation(int link, DWORD v); }; class GraphicsWindow { @@ -87,6 +87,8 @@ public: MNU_ORIENT_ONTO, MNU_LOCK_VIEW, MNU_UNSELECT_ALL, + MNU_UNITS_INCHES, + MNU_UNITS_MM, // Edit MNU_DELETE, // Request @@ -134,6 +136,12 @@ public: void NormalizeProjectionVectors(void); Point2d ProjectPoint(Vector p); + typedef enum { + UNIT_MM = 0, + UNIT_INCHES, + } Unit; + Unit viewUnits; + hGroup activeGroup; hEntity activeCsys; void EnsureValidActives(); diff --git a/win32/w32main.cpp b/win32/w32main.cpp index 0a8c5625..ec754b03 100644 --- a/win32/w32main.cpp +++ b/win32/w32main.cpp @@ -405,9 +405,9 @@ void ShowGraphicsEditControl(int x, int y, char *s) // (x, y) are the bottom left, but the edit control is placed by its // top left corner - y -= 21; + y -= 20; - MoveWindow(GraphicsEditControl, x, y, 120, 21, TRUE); + MoveWindow(GraphicsEditControl, x, y, 220, 21, TRUE); ShowWindow(GraphicsEditControl, SW_SHOW); SendMessage(GraphicsEditControl, WM_SETTEXT, 0, (LPARAM)s); SendMessage(GraphicsEditControl, EM_SETSEL, 0, strlen(s));