171 lines
4.6 KiB
C++
171 lines
4.6 KiB
C++
#include "solvespace.h"
|
|
|
|
SolveSpace SS;
|
|
|
|
void SolveSpace::Init(char *cmdLine) {
|
|
if(strlen(cmdLine) == 0) {
|
|
NewFile();
|
|
} else {
|
|
LoadFromFile(cmdLine);
|
|
}
|
|
|
|
TW.Init();
|
|
GW.Init();
|
|
|
|
GenerateAll(false);
|
|
|
|
TW.Show();
|
|
}
|
|
|
|
void SolveSpace::GenerateAll(bool andSolve) {
|
|
int i, j;
|
|
|
|
// Don't lose our numerical guesses when we regenerate.
|
|
IdList<Param,hParam> prev;
|
|
param.MoveSelfInto(&prev);
|
|
entity.Clear();
|
|
|
|
for(i = 0; i < group.n; i++) {
|
|
group.elem[i].solved = false;
|
|
}
|
|
|
|
// For now, solve the groups in given order; should discover the
|
|
// correct order later.
|
|
for(i = 0; i < group.n; i++) {
|
|
Group *g = &(group.elem[i]);
|
|
|
|
for(j = 0; j < request.n; j++) {
|
|
Request *r = &(request.elem[j]);
|
|
if(r->group.v != g->h.v) continue;
|
|
|
|
r->Generate(&entity, ¶m);
|
|
}
|
|
|
|
g->Generate(&entity, ¶m);
|
|
|
|
// Use the previous values for params that we've seen before, as
|
|
// initial guesses for the solver.
|
|
for(j = 0; j < param.n; j++) {
|
|
Param *newp = &(param.elem[j]);
|
|
if(newp->known) continue;
|
|
|
|
Param *prevp = prev.FindByIdNoOops(newp->h);
|
|
if(prevp) newp->val = prevp->val;
|
|
}
|
|
|
|
if(g->h.v == Group::HGROUP_REFERENCES.v) {
|
|
ForceReferences();
|
|
group.elem[0].solved = true;
|
|
} else {
|
|
// Solve this group.
|
|
if(andSolve) SolveGroup(g->h);
|
|
}
|
|
|
|
g->MakePolygons();
|
|
}
|
|
|
|
prev.Clear();
|
|
InvalidateGraphics();
|
|
}
|
|
|
|
void SolveSpace::ForceReferences(void) {
|
|
// Force the values of the paramters that define the three reference
|
|
// coordinate systems.
|
|
static const struct {
|
|
hRequest hr;
|
|
Quaternion q;
|
|
} Quat[] = {
|
|
{ Request::HREQUEST_REFERENCE_XY, { 1, 0, 0, 0, } },
|
|
{ Request::HREQUEST_REFERENCE_YZ, { 0.5, 0.5, 0.5, 0.5, } },
|
|
{ Request::HREQUEST_REFERENCE_ZX, { 0.5, -0.5, -0.5, -0.5, } },
|
|
};
|
|
for(int i = 0; i < 3; i++) {
|
|
hRequest hr = Quat[i].hr;
|
|
Entity *wrkpl = GetEntity(hr.entity(0));
|
|
// The origin for our coordinate system, always zero
|
|
Entity *origin = GetEntity(wrkpl->point[0]);
|
|
origin->PointForceTo(Vector::MakeFrom(0, 0, 0));
|
|
GetParam(origin->param[0])->known = true;
|
|
GetParam(origin->param[1])->known = true;
|
|
GetParam(origin->param[2])->known = true;
|
|
// The quaternion that defines the rotation, from the table.
|
|
Entity *normal = GetEntity(wrkpl->normal);
|
|
normal->NormalForceTo(Quat[i].q);
|
|
GetParam(normal->param[0])->known = true;
|
|
GetParam(normal->param[1])->known = true;
|
|
GetParam(normal->param[2])->known = true;
|
|
GetParam(normal->param[3])->known = true;
|
|
}
|
|
}
|
|
|
|
bool SolveSpace::SolveGroup(hGroup hg) {
|
|
int i;
|
|
// Clear out the system to be solved.
|
|
sys.entity.Clear();
|
|
sys.param.Clear();
|
|
sys.eq.Clear();
|
|
// And generate all the params for requests in this group
|
|
for(i = 0; i < request.n; i++) {
|
|
Request *r = &(request.elem[i]);
|
|
if(r->group.v != hg.v) continue;
|
|
|
|
r->Generate(&(sys.entity), &(sys.param));
|
|
}
|
|
// And for the group itself
|
|
Group *g = SS.GetGroup(hg);
|
|
g->Generate(&(sys.entity), &(sys.param));
|
|
// Set the initial guesses for all the params
|
|
for(i = 0; i < sys.param.n; i++) {
|
|
Param *p = &(sys.param.elem[i]);
|
|
p->known = false;
|
|
p->val = GetParam(p->h)->val;
|
|
}
|
|
// And generate all the equations from constraints in this group
|
|
for(i = 0; i < constraint.n; i++) {
|
|
Constraint *c = &(constraint.elem[i]);
|
|
if(c->group.v != hg.v) continue;
|
|
|
|
c->Generate(&(sys.eq));
|
|
}
|
|
// And the equations from entities
|
|
for(i = 0; i < entity.n; i++) {
|
|
Entity *e = &(entity.elem[i]);
|
|
if(e->group.v != hg.v) continue;
|
|
|
|
e->GenerateEquations(&(sys.eq));
|
|
}
|
|
// And from the groups themselves
|
|
g->GenerateEquations(&(sys.eq));
|
|
|
|
bool r = sys.Solve();
|
|
FreeAllTemporary();
|
|
return r;
|
|
}
|
|
|
|
void SolveSpace::MenuFile(int id) {
|
|
switch(id) {
|
|
case GraphicsWindow::MNU_NEW:
|
|
SS.NewFile();
|
|
SS.GenerateAll(false);
|
|
SS.GW.Init();
|
|
SS.TW.Init();
|
|
SS.TW.Show();
|
|
break;
|
|
|
|
case GraphicsWindow::MNU_OPEN:
|
|
break;
|
|
|
|
case GraphicsWindow::MNU_SAVE:
|
|
SS.SaveToFile("t.slvs");
|
|
break;
|
|
|
|
case GraphicsWindow::MNU_SAVE_AS:
|
|
break;
|
|
|
|
case GraphicsWindow::MNU_EXIT:
|
|
break;
|
|
|
|
default: oops();
|
|
}
|
|
}
|