Standardize the behaviour of constraints, by assigning them a
workplane: a free constraint works in three-space (e.g. true distance), and a constraint in a workplane works in that plane (e.g. projected distance). And make the solver go automatically, though solver itself has lots of pieces missing. [git-p4: depot-paths = "//depot/solvespace/": change = 1691]
This commit is contained in:
parent
15476d4732
commit
bfc7109e0c
159
constraint.cpp
159
constraint.cpp
|
@ -2,6 +2,8 @@
|
|||
|
||||
hConstraint Constraint::AddConstraint(Constraint *c) {
|
||||
SS.constraint.AddAndAssignId(c);
|
||||
|
||||
if(SS.GW.solving == GraphicsWindow::SOLVE_ALWAYS) SS.Solve();
|
||||
return c->h;
|
||||
}
|
||||
|
||||
|
@ -9,22 +11,24 @@ void Constraint::ConstrainCoincident(hEntity ptA, hEntity ptB) {
|
|||
Constraint c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
c.group = SS.GW.activeGroup;
|
||||
c.workplane = SS.GW.activeWorkplane;
|
||||
c.type = Constraint::POINTS_COINCIDENT;
|
||||
c.ptA = ptA;
|
||||
c.ptB = ptB;
|
||||
SS.constraint.AddAndAssignId(&c);
|
||||
AddConstraint(&c);
|
||||
}
|
||||
|
||||
void Constraint::MenuConstrain(int id) {
|
||||
Constraint c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
c.group = SS.GW.activeGroup;
|
||||
c.workplane = SS.GW.activeWorkplane;
|
||||
|
||||
SS.GW.GroupSelection();
|
||||
#define gs (SS.GW.gs)
|
||||
|
||||
switch(id) {
|
||||
case GraphicsWindow::MNU_DISTANCE_DIA:
|
||||
case GraphicsWindow::MNU_DISTANCE_DIA: {
|
||||
if(gs.points == 2 && gs.n == 2) {
|
||||
c.type = PT_PT_DISTANCE;
|
||||
c.ptA = gs.point[0];
|
||||
|
@ -38,11 +42,16 @@ void Constraint::MenuConstrain(int id) {
|
|||
Error("Bad selection for distance / diameter constraint.");
|
||||
return;
|
||||
}
|
||||
c.disp.offset = Vector::MakeFrom(50, 50, 50);
|
||||
Vector n = SS.GW.projRight.Cross(SS.GW.projUp);
|
||||
Vector a = SS.GetEntity(c.ptA)->PointGetCoords();
|
||||
Vector b = SS.GetEntity(c.ptB)->PointGetCoords();
|
||||
|
||||
c.disp.offset = n.Cross(a.Minus(b)).WithMagnitude(50);
|
||||
c.exprA = Expr::FromString("0")->DeepCopyKeep();
|
||||
c.ModifyToSatisfy();
|
||||
AddConstraint(&c);
|
||||
break;
|
||||
}
|
||||
|
||||
case GraphicsWindow::MNU_ON_ENTITY:
|
||||
if(gs.points == 2 && gs.n == 2) {
|
||||
|
@ -75,6 +84,10 @@ void Constraint::MenuConstrain(int id) {
|
|||
case GraphicsWindow::MNU_VERTICAL:
|
||||
case GraphicsWindow::MNU_HORIZONTAL: {
|
||||
hEntity ha, hb;
|
||||
if(c.workplane.v == Entity::FREE_IN_3D.v) {
|
||||
Error("Select workplane before constraining horiz/vert.");
|
||||
return;
|
||||
}
|
||||
if(gs.lineSegments == 1 && gs.n == 1) {
|
||||
c.entityA = gs.entity[0];
|
||||
Entity *e = SS.GetEntity(c.entityA);
|
||||
|
@ -87,24 +100,6 @@ void Constraint::MenuConstrain(int id) {
|
|||
Error("Bad selection for horizontal / vertical constraint.");
|
||||
return;
|
||||
}
|
||||
Entity *ea = SS.GetEntity(ha);
|
||||
Entity *eb = SS.GetEntity(hb);
|
||||
if(ea->workplane.v == Entity::FREE_IN_3D.v &&
|
||||
eb->workplane.v == Entity::FREE_IN_3D.v)
|
||||
{
|
||||
Error("Horizontal/vertical constraint applies only to "
|
||||
"entities drawn in a 2d coordinate system.");
|
||||
return;
|
||||
}
|
||||
if(eb->workplane.v == SS.GW.activeWorkplane.v) {
|
||||
// We are constraining two points in two different wrkpls; so
|
||||
// we have two choices for the definitons of the coordinate
|
||||
// directions. ptA's gets chosen, so make sure that's the
|
||||
// active workplane.
|
||||
hEntity t = c.ptA;
|
||||
c.ptA = c.ptB;
|
||||
c.ptB = t;
|
||||
}
|
||||
if(id == GraphicsWindow::MNU_HORIZONTAL) {
|
||||
c.type = HORIZONTAL;
|
||||
} else {
|
||||
|
@ -118,6 +113,15 @@ void Constraint::MenuConstrain(int id) {
|
|||
SS.Solve();
|
||||
return;
|
||||
|
||||
case GraphicsWindow::MNU_SOLVE_AUTO:
|
||||
if(SS.GW.solving == GraphicsWindow::SOLVE_ALWAYS) {
|
||||
SS.GW.solving = GraphicsWindow::DONT_SOLVE;
|
||||
} else {
|
||||
SS.GW.solving = GraphicsWindow::SOLVE_ALWAYS;
|
||||
}
|
||||
SS.GW.EnsureValidActives();
|
||||
break;
|
||||
|
||||
default: oops();
|
||||
}
|
||||
|
||||
|
@ -125,33 +129,31 @@ void Constraint::MenuConstrain(int id) {
|
|||
InvalidateGraphics();
|
||||
}
|
||||
|
||||
Expr *Constraint::Distance(hEntity hpa, hEntity hpb) {
|
||||
Expr *Constraint::Distance(hEntity wrkpl, hEntity hpa, hEntity hpb) {
|
||||
Entity *pa = SS.GetEntity(hpa);
|
||||
Entity *pb = SS.GetEntity(hpb);
|
||||
|
||||
if(!(pa->IsPoint() && pb->IsPoint())) oops();
|
||||
|
||||
if(pa->type == Entity::POINT_IN_2D &&
|
||||
pb->type == Entity::POINT_IN_2D &&
|
||||
pa->workplane.v == pb->workplane.v)
|
||||
{
|
||||
// A nice case; they are both in the same workplane, so I can write
|
||||
// the equation in terms of the basis vectors in that csys.
|
||||
Expr *du = Expr::FromParam(pa->param[0])->Minus(
|
||||
Expr::FromParam(pb->param[0]));
|
||||
Expr *dv = Expr::FromParam(pa->param[1])->Minus(
|
||||
Expr::FromParam(pb->param[1]));
|
||||
if(wrkpl.v == Entity::FREE_IN_3D.v) {
|
||||
// This is true distance
|
||||
ExprVector ea, eb, eab;
|
||||
ea = pa->PointGetExprs();
|
||||
eb = pb->PointGetExprs();
|
||||
eab = ea.Minus(eb);
|
||||
|
||||
return eab.Magnitude();
|
||||
} else {
|
||||
// This is projected distance, in the given workplane.
|
||||
Expr *au, *av, *bu, *bv;
|
||||
|
||||
pa->PointGetExprsInWorkplane(wrkpl, &au, &av);
|
||||
pb->PointGetExprsInWorkplane(wrkpl, &bu, &bv);
|
||||
|
||||
Expr *du = au->Minus(bu);
|
||||
Expr *dv = av->Minus(bv);
|
||||
|
||||
return ((du->Square())->Plus(dv->Square()))->Sqrt();
|
||||
}
|
||||
|
||||
// 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 eab.Magnitude();
|
||||
}
|
||||
|
||||
void Constraint::ModifyToSatisfy(void) {
|
||||
|
@ -182,59 +184,39 @@ void Constraint::AddEq(IdList<Equation,hEquation> *l, Expr *expr, int index) {
|
|||
void Constraint::Generate(IdList<Equation,hEquation> *l) {
|
||||
switch(type) {
|
||||
case PT_PT_DISTANCE:
|
||||
AddEq(l, Distance(ptA, ptB)->Minus(exprA), 0);
|
||||
AddEq(l, Distance(workplane, ptA, ptB)->Minus(exprA), 0);
|
||||
break;
|
||||
|
||||
case EQUAL_LENGTH_LINES: {
|
||||
Entity *a = SS.GetEntity(entityA);
|
||||
Entity *b = SS.GetEntity(entityB);
|
||||
AddEq(l, Distance(a->point[0], a->point[1])->Minus(
|
||||
Distance(b->point[0], b->point[1])), 0);
|
||||
AddEq(l, Distance(workplane, a->point[0], a->point[1])->Minus(
|
||||
Distance(workplane, b->point[0], b->point[1])), 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case POINTS_COINCIDENT: {
|
||||
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()) &&
|
||||
(a->workplane.v == b->workplane.v))
|
||||
{
|
||||
// Both in same workplane, nice.
|
||||
AddEq(l, Expr::FromParam(a->param[0])->Minus(
|
||||
Expr::FromParam(b->param[0])), 0);
|
||||
AddEq(l, Expr::FromParam(a->param[1])->Minus(
|
||||
Expr::FromParam(b->param[1])), 1);
|
||||
if(workplane.v == Entity::FREE_IN_3D.v) {
|
||||
ExprVector pa = a->PointGetExprs();
|
||||
ExprVector pb = b->PointGetExprs();
|
||||
AddEq(l, pa.x->Minus(pb.x), 0);
|
||||
AddEq(l, pa.y->Minus(pb.y), 1);
|
||||
AddEq(l, pa.z->Minus(pb.z), 2);
|
||||
} else {
|
||||
// Either two 2 DOF points in different planes, or one
|
||||
// 3 DOF point and one 2 DOF point. Either way, write two
|
||||
// equations on the projection of a into b's plane.
|
||||
ExprVector p3;
|
||||
p3 = a->PointGetExprs();
|
||||
Entity *w = SS.GetEntity(b->workplane);
|
||||
ExprVector offset = w->WorkplaneGetOffsetExprs();
|
||||
p3 = p3.Minus(offset);
|
||||
ExprVector u, v;
|
||||
w->WorkplaneGetBasisExprs(&u, &v);
|
||||
AddEq(l, Expr::FromParam(b->param[0])->Minus(p3.Dot(u)), 0);
|
||||
AddEq(l, Expr::FromParam(b->param[1])->Minus(p3.Dot(v)), 1);
|
||||
Expr *au, *av;
|
||||
Expr *bu, *bv;
|
||||
a->PointGetExprsInWorkplane(workplane, &au, &av);
|
||||
b->PointGetExprsInWorkplane(workplane, &bu, &bv);
|
||||
AddEq(l, au->Minus(bu), 0);
|
||||
AddEq(l, av->Minus(bv), 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PT_IN_PLANE: {
|
||||
// This one works the same, whether projected or not.
|
||||
ExprVector p, n;
|
||||
Expr *d;
|
||||
p = SS.GetEntity(ptA)->PointGetExprs();
|
||||
|
@ -256,25 +238,12 @@ void Constraint::Generate(IdList<Equation,hEquation> *l) {
|
|||
}
|
||||
Entity *a = SS.GetEntity(ha);
|
||||
Entity *b = SS.GetEntity(hb);
|
||||
if(a->workplane.v == Entity::FREE_IN_3D.v) {
|
||||
Entity *t = a;
|
||||
a = b;
|
||||
b = t;
|
||||
}
|
||||
|
||||
if(a->workplane.v == b->workplane.v) {
|
||||
int i = (type == HORIZONTAL) ? 1 : 0;
|
||||
AddEq(l, Expr::FromParam(a->param[i])->Minus(
|
||||
Expr::FromParam(b->param[i])), 0);
|
||||
} else {
|
||||
Entity *w = SS.GetEntity(a->workplane);
|
||||
ExprVector u, v;
|
||||
w->WorkplaneGetBasisExprs(&u, &v);
|
||||
ExprVector norm = (type == HORIZONTAL) ? v : u;
|
||||
ExprVector pa = a->PointGetExprs();
|
||||
ExprVector pb = b->PointGetExprs();
|
||||
AddEq(l, (pa.Minus(pb)).Dot(norm), 0);
|
||||
}
|
||||
Expr *au, *av, *bu, *bv;
|
||||
a->PointGetExprsInWorkplane(workplane, &au, &av);
|
||||
b->PointGetExprsInWorkplane(workplane, &bu, &bv);
|
||||
|
||||
AddEq(l, (type == HORIZONTAL) ? av->Minus(bv) : au->Minus(bu), 0);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
41
entity.cpp
41
entity.cpp
|
@ -196,6 +196,43 @@ ExprVector Entity::PointGetExprs(void) {
|
|||
return r;
|
||||
}
|
||||
|
||||
void Entity::PointGetExprsInWorkplane(hEntity wrkpl, Expr **u, Expr **v) {
|
||||
if(type == POINT_IN_2D && workplane.v == wrkpl.v) {
|
||||
// They want our coordinates in the form that we've written them,
|
||||
// very nice.
|
||||
*u = Expr::FromParam(param[0]);
|
||||
*v = Expr::FromParam(param[1]);
|
||||
} else {
|
||||
// Get the offset and basis vectors for this weird exotic csys.
|
||||
Entity *w = SS.GetEntity(wrkpl);
|
||||
ExprVector wp = w->WorkplaneGetOffsetExprs();
|
||||
ExprVector wu, wv;
|
||||
w->WorkplaneGetBasisExprs(&wu, &wv);
|
||||
|
||||
// Get our coordinates in three-space, and project them into that
|
||||
// coordinate system.
|
||||
ExprVector ev = PointGetExprs();
|
||||
ev = ev.Minus(wp);
|
||||
*u = ev.Dot(wu);
|
||||
*v = ev.Dot(wv);
|
||||
}
|
||||
}
|
||||
|
||||
bool Entity::PointIsLocked(void) {
|
||||
// A point is locked if none of its coordinates get assumed.
|
||||
if(type == POINT_IN_3D) {
|
||||
if(SS.GetParam(param[0])->assumed) return false;
|
||||
if(SS.GetParam(param[1])->assumed) return false;
|
||||
if(SS.GetParam(param[2])->assumed) return false;
|
||||
} else if(type == POINT_IN_2D) {
|
||||
if(SS.GetParam(param[0])->assumed) return false;
|
||||
if(SS.GetParam(param[1])->assumed) return false;
|
||||
} else {
|
||||
oops();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Entity::LineDrawOrGetDistance(Vector a, Vector b) {
|
||||
if(dogd.drawing) {
|
||||
glBegin(GL_LINE_STRIP);
|
||||
|
@ -272,7 +309,9 @@ void Entity::DrawOrGetDistance(int order) {
|
|||
glEnd();
|
||||
} else {
|
||||
Point2d pp = SS.GW.ProjectPoint(v);
|
||||
dogd.dmin = pp.DistanceTo(dogd.mp) - 5;
|
||||
// Make a free point slightly easier to select, so that with
|
||||
// coincident points, we select the free one.
|
||||
dogd.dmin = pp.DistanceTo(dogd.mp) - (PointIsLocked() ? 3 : 4);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
1
file.cpp
1
file.cpp
|
@ -75,6 +75,7 @@ const SolveSpace::SaveTable SolveSpace::SAVED[] = {
|
|||
{ 'c', "Constraint.h.v", 'x', &(SS.sv.c.h.v) },
|
||||
{ 'c', "Constraint.type", 'd', &(SS.sv.c.type) },
|
||||
{ 'c', "Constraint.group.v", 'x', &(SS.sv.c.group.v) },
|
||||
{ 'c', "Constraint.workplane.v", 'x', &(SS.sv.c.workplane.v) },
|
||||
{ 'c', "Constraint.exprA", 'E', &(SS.sv.c.exprA) },
|
||||
{ 'c', "Constraint.exprB", 'E', &(SS.sv.c.exprB) },
|
||||
{ 'c', "Constraint.ptA.v", 'x', &(SS.sv.c.ptA.v) },
|
||||
|
|
|
@ -31,6 +31,8 @@ const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = {
|
|||
{ 1, "Zoom &Out\t-", MNU_ZOOM_OUT, '-', mView },
|
||||
{ 1, "Zoom To &Fit\tF", MNU_ZOOM_TO_FIT, 'F', mView },
|
||||
{ 1, NULL, 0, NULL },
|
||||
{ 1, "Show Text &Window\tTab", MNU_SHOW_TEXT_WND, '\t', mView },
|
||||
{ 1, NULL, 0, NULL },
|
||||
{ 1, "Dimensions in &Inches", MNU_UNITS_INCHES, 0, mView },
|
||||
{ 1, "Dimensions in &Millimeters", MNU_UNITS_MM, 0, mView },
|
||||
|
||||
|
@ -80,6 +82,7 @@ const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = {
|
|||
{ 1, NULL, 0, NULL },
|
||||
{ 1, "Sym&bolic Equation\tShift+B", 0, 'B'|S, NULL },
|
||||
{ 1, NULL, 0, NULL },
|
||||
{ 1, "Sol&ve Automatically\tShift+Tab", MNU_SOLVE_AUTO, '\t'|S, mCon },
|
||||
{ 1, "Solve Once Now\tSpace", MNU_SOLVE_NOW, ' ', mCon },
|
||||
|
||||
{ 0, "&Help", 0, NULL },
|
||||
|
@ -106,6 +109,11 @@ void GraphicsWindow::Init(void) {
|
|||
showPoints = true;
|
||||
showAllGroups = true;
|
||||
showConstraints = true;
|
||||
|
||||
solving = SOLVE_ALWAYS;
|
||||
|
||||
showTextWindow = true;
|
||||
ShowTextWindow(showTextWindow);
|
||||
}
|
||||
|
||||
void GraphicsWindow::NormalizeProjectionVectors(void) {
|
||||
|
@ -174,6 +182,11 @@ void GraphicsWindow::MenuView(int id) {
|
|||
case MNU_ZOOM_TO_FIT:
|
||||
break;
|
||||
|
||||
case MNU_SHOW_TEXT_WND:
|
||||
SS.GW.showTextWindow = !SS.GW.showTextWindow;
|
||||
SS.GW.EnsureValidActives();
|
||||
break;
|
||||
|
||||
case MNU_UNITS_MM:
|
||||
SS.GW.viewUnits = UNIT_MM;
|
||||
SS.GW.EnsureValidActives();
|
||||
|
@ -228,6 +241,11 @@ void GraphicsWindow::EnsureValidActives(void) {
|
|||
}
|
||||
CheckMenuById(MNU_UNITS_MM, viewUnits == UNIT_MM);
|
||||
CheckMenuById(MNU_UNITS_INCHES, viewUnits == UNIT_INCHES);
|
||||
|
||||
ShowTextWindow(SS.GW.showTextWindow);
|
||||
CheckMenuById(MNU_SHOW_TEXT_WND, SS.GW.showTextWindow);
|
||||
|
||||
CheckMenuById(MNU_SOLVE_AUTO, (SS.GW.solving == SOLVE_ALWAYS));
|
||||
}
|
||||
|
||||
void GraphicsWindow::MenuEdit(int id) {
|
||||
|
@ -415,7 +433,9 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
|
|||
UpdateDraggedPoint(&(c->disp.offset), x, y);
|
||||
} else if(leftDown && pendingOperation == DRAGGING_POINT) {
|
||||
UpdateDraggedEntity(pendingPoint, x, y);
|
||||
HitTestMakeSelection(mp);
|
||||
if(solving == SOLVE_ALWAYS) {
|
||||
SS.Solve();
|
||||
}
|
||||
}
|
||||
|
||||
// No buttons pressed.
|
||||
|
@ -543,6 +563,9 @@ hRequest GraphicsWindow::AddRequest(int type) {
|
|||
r.type = type;
|
||||
SS.request.AddAndAssignId(&r);
|
||||
SS.GenerateAll();
|
||||
|
||||
if(solving == SOLVE_ALWAYS) SS.Solve();
|
||||
|
||||
return r.h;
|
||||
}
|
||||
|
||||
|
@ -707,6 +730,7 @@ void GraphicsWindow::EditControlDone(char *s) {
|
|||
Expr::FreeKeep(&(c->exprA));
|
||||
c->exprA = e->DeepCopyKeep();
|
||||
HideGraphicsEditControl();
|
||||
if(SS.GW.solving == SOLVE_ALWAYS) SS.Solve();
|
||||
} else {
|
||||
Error("Not a valid number or expression: '%s'", s);
|
||||
}
|
||||
|
|
5
sketch.h
5
sketch.h
|
@ -167,8 +167,10 @@ public:
|
|||
bool IsPoint(void);
|
||||
bool IsPointIn3d(void);
|
||||
// Applies for any of the point types
|
||||
bool PointIsLocked(void);
|
||||
Vector PointGetCoords(void);
|
||||
ExprVector PointGetExprs(void);
|
||||
void PointGetExprsInWorkplane(hEntity wrkpl, Expr **u, Expr **v);
|
||||
void PointForceTo(Vector v);
|
||||
bool PointIsFromReferences(void);
|
||||
bool PointIsKnown(void);
|
||||
|
@ -204,6 +206,7 @@ public:
|
|||
|
||||
double val;
|
||||
bool known;
|
||||
bool assumed;
|
||||
};
|
||||
|
||||
|
||||
|
@ -287,7 +290,7 @@ public:
|
|||
// Some helpers when generating symbolic constraint equations
|
||||
void ModifyToSatisfy(void);
|
||||
void AddEq(IdList<Equation,hEquation> *l, Expr *expr, int index);
|
||||
static Expr *Distance(hEntity pa, hEntity pb);
|
||||
static Expr *Distance(hEntity workplane, hEntity pa, hEntity pb);
|
||||
|
||||
static void ConstrainCoincident(hEntity ptA, hEntity ptB);
|
||||
};
|
||||
|
|
|
@ -20,6 +20,7 @@ void SolveSpace::Init(char *cmdLine) {
|
|||
void SolveSpace::GenerateAll(void) {
|
||||
int i;
|
||||
|
||||
// Don't lose our numerical guesses when we regenerate.
|
||||
IdList<Param,hParam> prev;
|
||||
param.MoveSelfInto(&prev);
|
||||
|
||||
|
@ -28,10 +29,12 @@ void SolveSpace::GenerateAll(void) {
|
|||
request.elem[i].Generate(&entity, ¶m);
|
||||
}
|
||||
|
||||
// Restore the numerical guesses.
|
||||
for(i = 0; i < param.n; i++) {
|
||||
Param *p = prev.FindByIdNoOops(param.elem[i].h);
|
||||
if(p) {
|
||||
param.elem[i].val = p->val;
|
||||
param.elem[i].assumed = p->assumed;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,10 +40,11 @@ void ShowGraphicsEditControl(int x, int y, char *s);
|
|||
void HideGraphicsEditControl(void);
|
||||
BOOL GraphicsEditControlIsVisible(void);
|
||||
|
||||
void InvalidateGraphics(void);
|
||||
void ShowTextWindow(BOOL visible);
|
||||
void InvalidateText(void);
|
||||
SDWORD GetMilliseconds(void);
|
||||
void InvalidateGraphics(void);
|
||||
void PaintGraphics(void);
|
||||
SDWORD GetMilliseconds(void);
|
||||
|
||||
void dbp(char *str, ...);
|
||||
void Error(char *str, ...);
|
||||
|
|
25
system.cpp
25
system.cpp
|
@ -181,9 +181,6 @@ bool System::NewtonSolve(int tag) {
|
|||
// Take the Newton step;
|
||||
// J(x_n) (x_{n+1} - x_n) = 0 - F(x_n)
|
||||
for(i = 0; i < mat.m; i++) {
|
||||
dbp("mat.X[%d] = %.3f", i, mat.X[i]);
|
||||
dbp("modifying param %08x, now %.3f", mat.param[i],
|
||||
param.FindById(mat.param[i])->val);
|
||||
(param.FindById(mat.param[i]))->val -= mat.X[i];
|
||||
}
|
||||
|
||||
|
@ -210,10 +207,10 @@ bool System::NewtonSolve(int tag) {
|
|||
|
||||
bool System::Solve(void) {
|
||||
int i, j;
|
||||
dbp("%d equations", eq.n);
|
||||
/* dbp("%d equations", eq.n);
|
||||
for(i = 0; i < eq.n; i++) {
|
||||
dbp(" %s = 0", eq.elem[i].e->Print());
|
||||
}
|
||||
} */
|
||||
|
||||
param.ClearTags();
|
||||
eq.ClearTags();
|
||||
|
@ -221,23 +218,30 @@ bool System::Solve(void) {
|
|||
WriteJacobian(0, 0);
|
||||
EvalJacobian();
|
||||
|
||||
/*
|
||||
for(i = 0; i < mat.m; i++) {
|
||||
for(j = 0; j < mat.n; j++) {
|
||||
dbp("A[%d][%d] = %.3f", i, j, mat.A.num[i][j]);
|
||||
}
|
||||
}
|
||||
} */
|
||||
|
||||
GaussJordan();
|
||||
|
||||
dbp("bound states:");
|
||||
/* dbp("bound states:");
|
||||
for(j = 0; j < mat.n; j++) {
|
||||
dbp(" param %08x: %d", mat.param[j], mat.bound[j]);
|
||||
}
|
||||
} */
|
||||
|
||||
// Fix any still-free variables wherever they are now.
|
||||
for(j = 0; j < mat.n; j++) {
|
||||
if(mat.bound[j]) continue;
|
||||
param.FindById(mat.param[j])->tag = ASSUMED;
|
||||
Param *p = param.FindByIdNoOops(mat.param[j]);
|
||||
if(!p) {
|
||||
// This is parameter does not occur in this group, so it's
|
||||
// not available to assume.
|
||||
continue;
|
||||
}
|
||||
p->tag = ASSUMED;
|
||||
}
|
||||
|
||||
bool ok = NewtonSolve(0);
|
||||
|
@ -250,6 +254,9 @@ bool System::Solve(void) {
|
|||
Param *pp = SS.GetParam(p->h);
|
||||
pp->val = p->val;
|
||||
pp->known = true;
|
||||
// The main param table keeps track of what was assumed, to
|
||||
// choose which point to drag so that it actually moves.
|
||||
pp->assumed = (p->tag == ASSUMED);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
13
ui.h
13
ui.h
|
@ -4,8 +4,8 @@
|
|||
|
||||
class TextWindow {
|
||||
public:
|
||||
static const int MAX_COLS = 150;
|
||||
static const int MAX_ROWS = 300;
|
||||
static const int MAX_COLS = 100;
|
||||
static const int MAX_ROWS = 200;
|
||||
|
||||
#ifndef RGB
|
||||
#define RGB(r, g, b) ((r) | ((g) << 8) | ((b) << 16))
|
||||
|
@ -87,11 +87,12 @@ public:
|
|||
MNU_ZOOM_IN,
|
||||
MNU_ZOOM_OUT,
|
||||
MNU_ZOOM_TO_FIT,
|
||||
MNU_UNSELECT_ALL,
|
||||
MNU_SHOW_TEXT_WND,
|
||||
MNU_UNITS_INCHES,
|
||||
MNU_UNITS_MM,
|
||||
// Edit
|
||||
MNU_DELETE,
|
||||
MNU_UNSELECT_ALL,
|
||||
// Request
|
||||
MNU_SEL_WORKPLANE,
|
||||
MNU_FREE_IN_3D,
|
||||
|
@ -105,6 +106,7 @@ public:
|
|||
MNU_ON_ENTITY,
|
||||
MNU_HORIZONTAL,
|
||||
MNU_VERTICAL,
|
||||
MNU_SOLVE_AUTO,
|
||||
MNU_SOLVE_NOW,
|
||||
} MenuId;
|
||||
typedef void MenuHandler(int id);
|
||||
|
@ -201,9 +203,14 @@ public:
|
|||
bool showPoints;
|
||||
bool showAllGroups;
|
||||
bool showConstraints;
|
||||
bool showTextWindow;
|
||||
static void ToggleBool(int link, DWORD v);
|
||||
static void ToggleAnyDatumShown(int link, DWORD v);
|
||||
|
||||
static const int DONT_SOLVE = 0;
|
||||
static const int SOLVE_ALWAYS = 1;
|
||||
int solving;
|
||||
|
||||
void UpdateDraggedPoint(Vector *pos, double mx, double my);
|
||||
void UpdateDraggedEntity(hEntity hp, double mx, double my);
|
||||
|
||||
|
|
|
@ -332,6 +332,7 @@ static BOOL ProcessKeyDown(WPARAM wParam)
|
|||
case VK_OEM_5: c = '\\'; break;
|
||||
case VK_SPACE: c = ' '; break;
|
||||
case VK_DELETE: c = 127; break;
|
||||
case VK_TAB: c = '\t'; break;
|
||||
|
||||
default:
|
||||
c = wParam;
|
||||
|
@ -351,6 +352,11 @@ static BOOL ProcessKeyDown(WPARAM wParam)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
void ShowTextWindow(BOOL visible)
|
||||
{
|
||||
ShowWindow(TextWnd, visible ? SW_SHOWNOACTIVATE : SW_HIDE);
|
||||
}
|
||||
|
||||
static HGLRC CreateGlContext(HDC hdc)
|
||||
{
|
||||
PIXELFORMATDESCRIPTOR pfd;
|
||||
|
|
Loading…
Reference in New Issue
Block a user