Change the workplanes a bit. Now the active workplane is per group,

so e.g. a new extrude starts in free space, which is likely what
you want. And default to an in-workplane group, and tweak the
display of workplanes.

[git-p4: depot-paths = "//depot/solvespace/": change = 1748]
solver
Jonathan Westhues 2008-05-26 18:22:20 -08:00
parent dd70cb55a2
commit ecee90965e
8 changed files with 144 additions and 135 deletions

View File

@ -19,7 +19,7 @@ void Constraint::Constrain(int type, hEntity ptA, hEntity ptB, hEntity entityA)
Constraint c; Constraint c;
memset(&c, 0, sizeof(c)); memset(&c, 0, sizeof(c));
c.group = SS.GW.activeGroup; c.group = SS.GW.activeGroup;
c.workplane = SS.GW.activeWorkplane; c.workplane = SS.GW.ActiveWorkplane();
c.type = type; c.type = type;
c.ptA = ptA; c.ptA = ptA;
c.ptB = ptB; c.ptB = ptB;
@ -35,7 +35,7 @@ void Constraint::MenuConstrain(int id) {
Constraint c; Constraint c;
memset(&c, 0, sizeof(c)); memset(&c, 0, sizeof(c));
c.group = SS.GW.activeGroup; c.group = SS.GW.activeGroup;
c.workplane = SS.GW.activeWorkplane; c.workplane = SS.GW.ActiveWorkplane();
SS.GW.GroupSelection(); SS.GW.GroupSelection();
#define gs (SS.GW.gs) #define gs (SS.GW.gs)

View File

@ -695,32 +695,42 @@ void Entity::DrawOrGetDistance(int order) {
Vector u = Normal()->NormalU(); Vector u = Normal()->NormalU();
Vector v = Normal()->NormalV(); Vector v = Normal()->NormalV();
double s = (min(SS.GW.width, SS.GW.height))*0.4/SS.GW.scale; double s = (min(SS.GW.width, SS.GW.height))*0.45/SS.GW.scale;
Vector us = u.ScaledBy(s); Vector us = u.ScaledBy(s);
Vector vs = v.ScaledBy(s); Vector vs = v.ScaledBy(s);
Vector pp = p.Plus (us).Plus (vs); Vector pp = p.Plus (us).Plus (vs);
Vector pm = p.Plus (us).Minus(vs); Vector pm = p.Plus (us).Minus(vs);
Vector mm = p.Minus(us).Minus(vs); Vector mm = p.Minus(us).Minus(vs), mm2 = mm;
Vector mp = p.Minus(us).Plus (vs); Vector mp = p.Minus(us).Plus (vs);
glxColor3d(0, 0.3, 0.3); glxColor3d(0, 0.3, 0.3);
glEnable(GL_LINE_STIPPLE); glEnable(GL_LINE_STIPPLE);
glLineStipple(3, 0x1111); glLineStipple(3, 0x1111);
if(!h.isFromRequest()) {
mm = mm.Plus(v.ScaledBy(60/SS.GW.scale));
mm2 = mm2.Plus(u.ScaledBy(60/SS.GW.scale));
LineDrawOrGetDistance(mm2, mm);
}
LineDrawOrGetDistance(pp, pm); LineDrawOrGetDistance(pp, pm);
LineDrawOrGetDistance(pm, mm); LineDrawOrGetDistance(pm, mm2);
LineDrawOrGetDistance(mm, mp); LineDrawOrGetDistance(mm, mp);
LineDrawOrGetDistance(mp, pp); LineDrawOrGetDistance(mp, pp);
glDisable(GL_LINE_STIPPLE); glDisable(GL_LINE_STIPPLE);
char *str = DescriptionString()+5;
if(dogd.drawing) { if(dogd.drawing) {
glPushMatrix(); glPushMatrix();
glxTranslatev(mm); glxTranslatev(mm2);
glxOntoWorkplane(u, v); glxOntoWorkplane(u, v);
glxWriteText(DescriptionString()); glxWriteText(str);
glPopMatrix(); glPopMatrix();
} else { } else {
Vector pos = mm2.Plus(u.ScaledBy(glxStrWidth(str)/2)).Plus(
v.ScaledBy(glxStrHeight()/2));
Point2d pp = SS.GW.ProjectPoint(pos);
dogd.dmin = min(dogd.dmin, pp.DistanceTo(dogd.mp) - 10);
// If a line lies in a plane, then select the line, not // If a line lies in a plane, then select the line, not
// the plane. // the plane.
dogd.dmin += 3; dogd.dmin += 3;

View File

@ -17,11 +17,6 @@ void SolveSpace::NewFile(void) {
g.h = Group::HGROUP_REFERENCES; g.h = Group::HGROUP_REFERENCES;
group.Add(&g); group.Add(&g);
// And an empty group, for the first stuff the user draws.
g.name.strcpy("drawing");
group.AddAndAssignId(&g);
// Let's create three two-d coordinate systems, for the coordinate // Let's create three two-d coordinate systems, for the coordinate
// planes; these are our references, present in every sketch. // planes; these are our references, present in every sketch.
Request r; Request r;
@ -41,13 +36,23 @@ void SolveSpace::NewFile(void) {
r.name.strcpy("#ZX"); r.name.strcpy("#ZX");
r.h = Request::HREQUEST_REFERENCE_ZX; r.h = Request::HREQUEST_REFERENCE_ZX;
request.Add(&r); request.Add(&r);
}
// And an empty group, for the first stuff the user draws.
g.type = Group::DRAWING_WORKPLANE;
g.subtype = Group::WORKPLANE_BY_POINT_ORTHO;
g.wrkpl.q = Quaternion::MakeFrom(1, 0, 0, 0);
hRequest hr = Request::HREQUEST_REFERENCE_XY;
g.wrkpl.origin = hr.entity(1);
g.name.strcpy("draw-in-plane");
group.AddAndAssignId(&g);
SS.GetGroup(g.h)->activeWorkplane = g.h.entity(0);
}
const SolveSpace::SaveTable SolveSpace::SAVED[] = { const SolveSpace::SaveTable SolveSpace::SAVED[] = {
{ 'g', "Group.h.v", 'x', &(SS.sv.g.h.v) }, { 'g', "Group.h.v", 'x', &(SS.sv.g.h.v) },
{ 'g', "Group.type", 'd', &(SS.sv.g.type) }, { 'g', "Group.type", 'd', &(SS.sv.g.type) },
{ 'g', "Group.name", 'N', &(SS.sv.g.name) }, { 'g', "Group.name", 'N', &(SS.sv.g.name) },
{ 'g', "Group.activeWorkplane.v", 'x', &(SS.sv.g.activeWorkplane.v) },
{ 'g', "Group.opA.v", 'x', &(SS.sv.g.opA.v) }, { 'g', "Group.opA.v", 'x', &(SS.sv.g.opA.v) },
{ 'g', "Group.opB.v", 'x', &(SS.sv.g.opB.v) }, { 'g', "Group.opB.v", 'x', &(SS.sv.g.opB.v) },
{ 'g', "Group.subtype", 'd', &(SS.sv.g.subtype) }, { 'g', "Group.subtype", 'd', &(SS.sv.g.subtype) },

View File

@ -31,7 +31,6 @@ const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = {
{ 1, "Zoom &In\t+", MNU_ZOOM_IN, '+', mView }, { 1, "Zoom &In\t+", MNU_ZOOM_IN, '+', mView },
{ 1, "Zoom &Out\t-", MNU_ZOOM_OUT, '-', mView }, { 1, "Zoom &Out\t-", MNU_ZOOM_OUT, '-', mView },
{ 1, "Zoom To &Fit\tF", MNU_ZOOM_TO_FIT, 'F', mView }, { 1, "Zoom To &Fit\tF", MNU_ZOOM_TO_FIT, 'F', mView },
{ 1, "Onto Othe&r Side\tCtrl+O", MNU_OTHER_SIDE, 'R'|C, mView },
{ 1, NULL, 0, NULL }, { 1, NULL, 0, NULL },
{ 1, "Show Text &Window\tTab", MNU_SHOW_TEXT_WND, '\t', mView }, { 1, "Show Text &Window\tTab", MNU_SHOW_TEXT_WND, '\t', mView },
{ 1, NULL, 0, NULL }, { 1, NULL, 0, NULL },
@ -102,15 +101,11 @@ void GraphicsWindow::Init(void) {
projRight.x = 1; projRight.y = projRight.z = 0; projRight.x = 1; projRight.y = projRight.z = 0;
projUp.y = 1; projUp.z = projUp.x = 0; projUp.y = 1; projUp.z = projUp.x = 0;
// Start locked on to the XY plane.
hRequest r = Request::HREQUEST_REFERENCE_XY;
activeWorkplane = r.entity(0);
// And with the latest visible group active // And with the latest visible group active
int i; int i;
for(i = 0; i < SS.group.n; i++) { for(i = 0; i < SS.group.n; i++) {
Group *g = &(SS.group.elem[i]); Group *g = &(SS.group.elem[i]);
if(g->visible) activeGroup = g->h; if(i == 0 || g->visible) activeGroup = g->h;
} }
EnsureValidActives(); EnsureValidActives();
@ -145,7 +140,13 @@ Point2d GraphicsWindow::ProjectPoint(Vector p) {
return r; return r;
} }
void GraphicsWindow::AnimateOnto(Quaternion quatf, Vector offsetf) { void GraphicsWindow::AnimateOntoWorkplane(void) {
if(!LockedInWorkplane()) return;
Entity *w = SS.GetEntity(ActiveWorkplane());
Quaternion quatf = w->Normal()->NormalGetNum();
Vector offsetf = (SS.GetEntity(w->point[0])->PointGetNum()).ScaledBy(-1);
// Get our initial orientation and translation. // Get our initial orientation and translation.
Quaternion quat0 = Quaternion::MakeFrom(projRight, projUp); Quaternion quat0 = Quaternion::MakeFrom(projRight, projUp);
Vector offset0 = offset; Vector offset0 = offset;
@ -197,15 +198,6 @@ void GraphicsWindow::MenuView(int id) {
case MNU_ZOOM_TO_FIT: case MNU_ZOOM_TO_FIT:
break; break;
case MNU_OTHER_SIDE: {
Quaternion quatf = Quaternion::MakeFrom(
SS.GW.projRight.ScaledBy(-1), SS.GW.projUp.ScaledBy(1));
Vector ru = quatf.RotationU();
Vector rv = quatf.RotationV();
SS.GW.AnimateOnto(quatf, SS.GW.offset);
break;
}
case MNU_SHOW_TEXT_WND: case MNU_SHOW_TEXT_WND:
SS.GW.showTextWindow = !SS.GW.showTextWindow; SS.GW.showTextWindow = !SS.GW.showTextWindow;
SS.GW.EnsureValidActives(); SS.GW.EnsureValidActives();
@ -243,25 +235,25 @@ void GraphicsWindow::EnsureValidActives(void) {
} }
// The active coordinate system must also exist. // The active coordinate system must also exist.
if(activeWorkplane.v != Entity::FREE_IN_3D.v) { if(LockedInWorkplane()) {
Entity *e = SS.entity.FindByIdNoOops(activeWorkplane); Entity *e = SS.entity.FindByIdNoOops(ActiveWorkplane());
if(e) { if(e) {
hGroup hgw = e->group; hGroup hgw = e->group;
if(hgw.v != activeGroup.v && SS.GroupsInOrder(activeGroup, hgw)) { if(hgw.v != activeGroup.v && SS.GroupsInOrder(activeGroup, hgw)) {
// The active workplane is in a group that comes after the // The active workplane is in a group that comes after the
// active group; so any request or constraint will fail. // active group; so any request or constraint will fail.
activeWorkplane = Entity::FREE_IN_3D; SetWorkplaneFreeIn3d();
change = true; change = true;
} }
} else { } else {
activeWorkplane = Entity::FREE_IN_3D; SetWorkplaneFreeIn3d();
change = true; change = true;
} }
} }
bool in3d = (activeWorkplane.v == Entity::FREE_IN_3D.v); bool locked = LockedInWorkplane();
CheckMenuById(MNU_FREE_IN_3D, in3d); CheckMenuById(MNU_FREE_IN_3D, !locked);
CheckMenuById(MNU_SEL_WORKPLANE, !in3d); CheckMenuById(MNU_SEL_WORKPLANE, locked);
// And update the checked state for various menus // And update the checked state for various menus
switch(viewUnits) { switch(viewUnits) {
@ -282,6 +274,16 @@ void GraphicsWindow::EnsureValidActives(void) {
if(change) SS.TW.Show(); if(change) SS.TW.Show();
} }
void GraphicsWindow::SetWorkplaneFreeIn3d(void) {
SS.GetGroup(activeGroup)->activeWorkplane = Entity::FREE_IN_3D;
}
hEntity GraphicsWindow::ActiveWorkplane(void) {
return SS.GetGroup(activeGroup)->activeWorkplane;
}
bool GraphicsWindow::LockedInWorkplane(void) {
return (SS.GW.ActiveWorkplane().v != Entity::FREE_IN_3D.v);
}
void GraphicsWindow::GeneratePerSolving(void) { void GraphicsWindow::GeneratePerSolving(void) {
SS.GenerateAll(solving == SOLVE_ALWAYS); SS.GenerateAll(solving == SOLVE_ALWAYS);
} }
@ -336,25 +338,23 @@ void GraphicsWindow::MenuRequest(int id) {
case MNU_SEL_WORKPLANE: { case MNU_SEL_WORKPLANE: {
SS.GW.GroupSelection(); SS.GW.GroupSelection();
if(SS.GW.gs.n == 1 && SS.GW.gs.workplanes == 1) { if(SS.GW.gs.n == 1 && SS.GW.gs.workplanes == 1) {
SS.GW.activeWorkplane = SS.GW.gs.entity[0]; SS.GetGroup(SS.GW.activeGroup)->activeWorkplane =
SS.GW.gs.entity[0];
} }
if(SS.GW.activeWorkplane.v == Entity::FREE_IN_3D.v) { if(!SS.GW.LockedInWorkplane()) {
Error("Select workplane (e.g., the XY plane) " Error("Select workplane (e.g., the XY plane) "
"before locking on."); "before locking on.");
break; break;
} }
// Align the view with the selected workplane // Align the view with the selected workplane
Entity *e = SS.GetEntity(SS.GW.activeWorkplane); SS.GW.AnimateOntoWorkplane();
Quaternion quatf = e->Normal()->NormalGetNum();
Vector offsetf = (e->WorkplaneGetOffset()).ScaledBy(-1);
SS.GW.AnimateOnto(quatf, offsetf);
SS.GW.ClearSuper(); SS.GW.ClearSuper();
SS.TW.Show(); SS.TW.Show();
break; break;
} }
case MNU_FREE_IN_3D: case MNU_FREE_IN_3D:
SS.GW.activeWorkplane = Entity::FREE_IN_3D; SS.GW.SetWorkplaneFreeIn3d();
SS.GW.EnsureValidActives(); SS.GW.EnsureValidActives();
SS.TW.Show(); SS.TW.Show();
break; break;
@ -800,7 +800,7 @@ hRequest GraphicsWindow::AddRequest(int type) {
Request r; Request r;
memset(&r, 0, sizeof(r)); memset(&r, 0, sizeof(r));
r.group = activeGroup; r.group = activeGroup;
r.workplane = activeWorkplane; r.workplane = ActiveWorkplane();
r.type = type; r.type = type;
SS.request.AddAndAssignId(&r); SS.request.AddAndAssignId(&r);
@ -878,7 +878,7 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
break; break;
case MNU_RECTANGLE: { case MNU_RECTANGLE: {
if(SS.GW.activeWorkplane.v == Entity::FREE_IN_3D.v) { if(!SS.GW.LockedInWorkplane()) {
Error("Can't draw rectangle in 3d; select a workplane first."); Error("Can't draw rectangle in 3d; select a workplane first.");
break; break;
} }
@ -922,7 +922,7 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
break; break;
case MNU_ARC: case MNU_ARC:
if(SS.GW.activeWorkplane.v == Entity::FREE_IN_3D.v) { if(!SS.GW.LockedInWorkplane()) {
Error("Can't draw arc in 3d; select a workplane first."); Error("Can't draw arc in 3d; select a workplane first.");
ClearPending(); ClearPending();
break; break;

View File

@ -74,7 +74,7 @@ void Group::MenuGroup(int id) {
case GraphicsWindow::MNU_GROUP_EXTRUDE: case GraphicsWindow::MNU_GROUP_EXTRUDE:
g.type = EXTRUDE; g.type = EXTRUDE;
g.opA = SS.GW.activeGroup; g.opA = SS.GW.activeGroup;
g.wrkpl.entityB = SS.GW.activeWorkplane; g.wrkpl.entityB = SS.GW.ActiveWorkplane();
g.subtype = EXTRUDE_ONE_SIDED; g.subtype = EXTRUDE_ONE_SIDED;
g.name.strcpy("extrude"); g.name.strcpy("extrude");
break; break;
@ -92,12 +92,9 @@ void Group::MenuGroup(int id) {
SS.GenerateAll(SS.GW.solving == GraphicsWindow::SOLVE_ALWAYS); SS.GenerateAll(SS.GW.solving == GraphicsWindow::SOLVE_ALWAYS);
SS.GW.activeGroup = g.h; SS.GW.activeGroup = g.h;
if(g.type == DRAWING_WORKPLANE) { if(g.type == DRAWING_WORKPLANE) {
SS.GW.activeWorkplane = g.h.entity(0); SS.GetGroup(g.h)->activeWorkplane = g.h.entity(0);
Entity *e = SS.GetEntity(SS.GW.activeWorkplane);
Quaternion quatf = e->Normal()->NormalGetNum();
Vector offsetf = (e->WorkplaneGetOffset()).ScaledBy(-1);
SS.GW.AnimateOnto(quatf, offsetf);
} }
SS.GW.AnimateOntoWorkplane();
TextWindow::ScreenSelectGroup(0, g.h.v); TextWindow::ScreenSelectGroup(0, g.h.v);
SS.TW.Show(); SS.TW.Show();
} }

View File

@ -88,6 +88,7 @@ public:
hGroup opA; hGroup opA;
hGroup opB; hGroup opB;
bool visible; bool visible;
hEntity activeWorkplane;
static const int SOLVED_OKAY = 0; static const int SOLVED_OKAY = 0;
static const int DIDNT_CONVERGE = 10; static const int DIDNT_CONVERGE = 10;

View File

@ -223,15 +223,15 @@ void TextWindow::ScreenNavigation(int link, DWORD v) {
void TextWindow::ShowHeader(void) { void TextWindow::ShowHeader(void) {
ClearScreen(); ClearScreen();
char *cd = (SS.GW.activeWorkplane.v == Entity::FREE_IN_3D.v) ? char *cd = SS.GW.LockedInWorkplane() ?
"free in 3d" : SS.GetEntity(SS.GW.ActiveWorkplane())->DescriptionString() :
SS.GetEntity(SS.GW.activeWorkplane)->DescriptionString(); "free in 3d";
// Navigation buttons // Navigation buttons
if(SS.GW.pending.description) { if(SS.GW.pending.description) {
Printf(false, " %Bt%Ft workplane:%Fd %s", cd); Printf(false, " %Bt%Ft wrkpl:%Fd %s", cd);
} else { } else {
Printf(false, " %Lb%f<<%E %Lh%fhome%E %Bt%Ft workplane:%Fd %s", Printf(false, " %Lb%f<<%E %Lh%fhome%E %Bt%Ft wrkpl:%Fd %s",
(&TextWindow::ScreenNavigation), (&TextWindow::ScreenNavigation),
(&TextWindow::ScreenNavigation), (&TextWindow::ScreenNavigation),
cd); cd);
@ -299,11 +299,6 @@ void TextWindow::ScreenActivateGroup(int link, DWORD v) {
Group *g = SS.GetGroup(hg); Group *g = SS.GetGroup(hg);
g->visible = true; g->visible = true;
SS.GW.activeGroup.v = v; SS.GW.activeGroup.v = v;
if(g->type == Group::DRAWING_WORKPLANE) {
// If we're activating an in-workplane drawing, then activate that
// workplane too.
SS.GW.activeWorkplane = g->h.entity(0);
}
SS.GW.ClearSuper(); SS.GW.ClearSuper();
} }
void TextWindow::ReportHowGroupSolved(hGroup hg) { void TextWindow::ReportHowGroupSolved(hGroup hg) {

9
ui.h
View File

@ -101,7 +101,6 @@ public:
MNU_ZOOM_IN, MNU_ZOOM_IN,
MNU_ZOOM_OUT, MNU_ZOOM_OUT,
MNU_ZOOM_TO_FIT, MNU_ZOOM_TO_FIT,
MNU_OTHER_SIDE,
MNU_SHOW_TEXT_WND, MNU_SHOW_TEXT_WND,
MNU_UNITS_INCHES, MNU_UNITS_INCHES,
MNU_UNITS_MM, MNU_UNITS_MM,
@ -177,7 +176,7 @@ public:
void NormalizeProjectionVectors(void); void NormalizeProjectionVectors(void);
Point2d ProjectPoint(Vector p); Point2d ProjectPoint(Vector p);
void AnimateOnto(Quaternion quatf, Vector offsetf); void AnimateOntoWorkplane(void);
Vector VectorFromProjs(double right, double up, double forward); Vector VectorFromProjs(double right, double up, double forward);
typedef enum { typedef enum {
@ -187,8 +186,10 @@ public:
Unit viewUnits; Unit viewUnits;
hGroup activeGroup; hGroup activeGroup;
hEntity activeWorkplane; void EnsureValidActives(void);
void EnsureValidActives(); bool LockedInWorkplane(void);
void SetWorkplaneFreeIn3d(void);
hEntity ActiveWorkplane(void);
// Operations that must be completed by doing something with the mouse // Operations that must be completed by doing something with the mouse
// are noted here. These occupy the same space as the menu ids. // are noted here. These occupy the same space as the menu ids.