Add reference dimensions, add user-programmable lighting, and add a
configuration screen where all this can be specified. [git-p4: depot-paths = "//depot/solvespace/": change = 1783]
This commit is contained in:
parent
f2645029b8
commit
d471872830
|
@ -233,6 +233,22 @@ void Constraint::MenuConstrain(int id) {
|
|||
} else {
|
||||
c.type = SYMMETRIC_VERT;
|
||||
}
|
||||
if(gs.lineSegments == 1) {
|
||||
// If this line segment is already constrained horiz or
|
||||
// vert, then auto-remove that redundant constraint.
|
||||
SS.constraint.ClearTags();
|
||||
for(int i = 0; i < SS.constraint.n; i++) {
|
||||
Constraint *ct = &(SS.constraint.elem[i]);
|
||||
if(ct->type != HORIZONTAL && ct->type != VERTICAL) {
|
||||
continue;
|
||||
}
|
||||
if(ct->entityA.v != (gs.entity[0]).v) continue;
|
||||
ct->tag = 1;
|
||||
}
|
||||
SS.constraint.RemoveTagged();
|
||||
// And no need to do anything special, since nothing
|
||||
// ever depends on a constraint.
|
||||
}
|
||||
} else {
|
||||
// Symmetry with a symmetry plane specified explicitly.
|
||||
c.type = SYMMETRIC;
|
||||
|
@ -290,7 +306,20 @@ void Constraint::MenuConstrain(int id) {
|
|||
}
|
||||
}
|
||||
Error("Must select an angle constraint.");
|
||||
return;
|
||||
|
||||
case GraphicsWindow::MNU_REFERENCE:
|
||||
if(gs.constraints == 1 && gs.n == 0) {
|
||||
Constraint *c = SS.GetConstraint(gs.constraint[0]);
|
||||
if(c->HasLabel()) {
|
||||
(c->reference) = !(c->reference);
|
||||
SS.GetGroup(c->group)->clean = false;
|
||||
SS.GenerateAll();
|
||||
break;
|
||||
}
|
||||
}
|
||||
Error("Must select a constraint with associated label.");
|
||||
return;
|
||||
|
||||
case GraphicsWindow::MNU_ANGLE:
|
||||
if(gs.vectors == 2 && gs.n == 2) {
|
||||
|
@ -456,9 +485,9 @@ void Constraint::ModifyToSatisfy(void) {
|
|||
// that means no extra work.
|
||||
IdList<Equation,hEquation> l;
|
||||
// An uninit IdList could lead us to free some random address, bad.
|
||||
memset(&l, 0, sizeof(l));
|
||||
|
||||
Generate(&l);
|
||||
ZERO(&l);
|
||||
// Generate the equations even if this is a reference dimension
|
||||
GenerateReal(&l);
|
||||
if(l.n != 1) oops();
|
||||
|
||||
// These equations are written in the form f(...) - d = 0, where
|
||||
|
@ -480,6 +509,11 @@ void Constraint::AddEq(IdList<Equation,hEquation> *l, Expr *expr, int index) {
|
|||
}
|
||||
|
||||
void Constraint::Generate(IdList<Equation,hEquation> *l) {
|
||||
if(!reference) {
|
||||
GenerateReal(l);
|
||||
}
|
||||
}
|
||||
void Constraint::GenerateReal(IdList<Equation,hEquation> *l) {
|
||||
Expr *exA = NULL;
|
||||
if(exprA) exA = exprA->DeepCopy();
|
||||
|
||||
|
|
24
draw.cpp
24
draw.cpp
|
@ -759,12 +759,12 @@ void GraphicsWindow::HitTestMakeSelection(Point2d mp) {
|
|||
}
|
||||
}
|
||||
|
||||
Vector GraphicsWindow::VectorFromProjs(double right, double up, double fwd) {
|
||||
Vector GraphicsWindow::VectorFromProjs(Vector rightUpForward) {
|
||||
Vector n = projRight.Cross(projUp);
|
||||
Vector r = offset.ScaledBy(-1);
|
||||
r = r.Plus(projRight.ScaledBy(right));
|
||||
r = r.Plus(projUp.ScaledBy(up));
|
||||
r = r.Plus(n.ScaledBy(fwd));
|
||||
|
||||
Vector r = (projRight.ScaledBy(rightUpForward.x));
|
||||
r = r.Plus(projUp.ScaledBy(rightUpForward.y));
|
||||
r = r.Plus(n.ScaledBy(rightUpForward.z));
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -810,21 +810,25 @@ void GraphicsWindow::Paint(int w, int h) {
|
|||
glClearDepth(1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// Let's use two lights
|
||||
// Let's use two lights, at the user-specified locations
|
||||
GLfloat f;
|
||||
glEnable(GL_LIGHT0);
|
||||
GLfloat li0[] = { 0.8f, 0.8f, 0.8f, 1.0f };
|
||||
f = (GLfloat)SS.lightIntensity[0];
|
||||
GLfloat li0[] = { f, f, f, 1.0f };
|
||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, li0);
|
||||
glLightfv(GL_LIGHT0, GL_SPECULAR, li0);
|
||||
|
||||
glEnable(GL_LIGHT1);
|
||||
GLfloat li1[] = { 0.4f, 0.4f, 0.4f, 1.0f };
|
||||
f = (GLfloat)SS.lightIntensity[1];
|
||||
GLfloat li1[] = { f, f, f, 1.0f };
|
||||
glLightfv(GL_LIGHT1, GL_DIFFUSE, li1);
|
||||
glLightfv(GL_LIGHT1, GL_SPECULAR, li1);
|
||||
|
||||
Vector lp;
|
||||
lp = VectorFromProjs(-0.49*w/scale, 0.49*h/scale, 0);
|
||||
lp = VectorFromProjs(SS.lightPos[0]);
|
||||
GLfloat lp0[4] = { (GLfloat)lp.x, (GLfloat)lp.y, (GLfloat)lp.z, 0 };
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, lp0);
|
||||
lp = VectorFromProjs(0.49*w/scale, 0.10*h/scale, 0);
|
||||
lp = VectorFromProjs(SS.lightPos[1]);
|
||||
GLfloat lp1[4] = { (GLfloat)lp.x, (GLfloat)lp.y, (GLfloat)lp.z, 0 };
|
||||
glLightfv(GL_LIGHT1, GL_POSITION, lp1);
|
||||
|
||||
|
|
|
@ -40,8 +40,24 @@ double Constraint::EllipticalInterpolation(double rx, double ry, double theta) {
|
|||
return v;
|
||||
}
|
||||
|
||||
char *Constraint::Label(void) {
|
||||
static char Ret[1024];
|
||||
if(type == ANGLE) {
|
||||
sprintf(Ret, "%.2f", exprA->Eval());
|
||||
} else if(type == LENGTH_RATIO) {
|
||||
sprintf(Ret, "%.3f:1", exprA->Eval());
|
||||
} else {
|
||||
// exprA has units of distance
|
||||
strcpy(Ret, SS.GW.ToString(exprA->Eval()));
|
||||
}
|
||||
if(reference) {
|
||||
strcat(Ret, " REF");
|
||||
}
|
||||
return Ret;
|
||||
}
|
||||
|
||||
void Constraint::DoLabel(Vector ref, Vector *labelPos, Vector gr, Vector gu) {
|
||||
char *s = exprA->Print();
|
||||
char *s = Label();
|
||||
if(labelPos) {
|
||||
// labelPos is from the top left corner (for the text box used to
|
||||
// edit things), but ref is from the center.
|
||||
|
@ -188,7 +204,7 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) {
|
|||
|
||||
double theta = atan2(disp.offset.Dot(gu), disp.offset.Dot(gr));
|
||||
double adj = EllipticalInterpolation(
|
||||
glxStrWidth(exprA->Print())/2, glxStrHeight()/2, theta);
|
||||
glxStrWidth(Label())/2, glxStrHeight()/2, theta);
|
||||
|
||||
Vector mark = ref.Minus(center);
|
||||
mark = mark.WithMagnitude(mark.Magnitude()-r);
|
||||
|
@ -333,7 +349,7 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) {
|
|||
|
||||
double tl = atan2(rm.Dot(gu), rm.Dot(gr));
|
||||
double adj = EllipticalInterpolation(
|
||||
glxStrWidth(exprA->Print())/2, glxStrHeight()/2, tl);
|
||||
glxStrWidth(Label())/2, glxStrHeight()/2, tl);
|
||||
ref = ref.Plus(rm.WithMagnitude(adj + 3/SS.GW.scale));
|
||||
} else {
|
||||
// The lines are skew; no wonderful way to illustrate that.
|
||||
|
|
|
@ -4,7 +4,9 @@ void Entity::LineDrawOrGetDistance(Vector a, Vector b) {
|
|||
if(dogd.drawing) {
|
||||
// glPolygonOffset works only on polys, not lines, so do it myself
|
||||
Vector adj = SS.GW.projRight.Cross(SS.GW.projUp);
|
||||
adj = adj.ScaledBy(5/SS.GW.scale);
|
||||
// Draw lines from active group in front of those from previous
|
||||
int delta = (group.v == SS.GW.activeGroup.v) ? 10 : 5;
|
||||
adj = adj.ScaledBy(delta/SS.GW.scale);
|
||||
glBegin(GL_LINES);
|
||||
glxVertex3v(a.Plus(adj));
|
||||
glxVertex3v(b.Plus(adj));
|
||||
|
@ -14,6 +16,8 @@ void Entity::LineDrawOrGetDistance(Vector a, Vector b) {
|
|||
Point2d bp = SS.GW.ProjectPoint(b);
|
||||
|
||||
double d = dogd.mp.DistanceToLine(ap, bp.Minus(ap), true);
|
||||
// A little bit easier to select in the active group
|
||||
if(group.v == SS.GW.activeGroup.v) d -= 1;
|
||||
dogd.dmin = min(dogd.dmin, d);
|
||||
}
|
||||
dogd.refp = (a.Plus(b)).ScaledBy(0.5);
|
||||
|
@ -164,9 +168,7 @@ void Entity::DrawOrGetDistance(void) {
|
|||
glPolygonOffset(0, 0);
|
||||
} else {
|
||||
Point2d pp = SS.GW.ProjectPoint(v);
|
||||
// Make a free point slightly easier to select, so that with
|
||||
// coincident points, we select the free one.
|
||||
dogd.dmin = pp.DistanceTo(dogd.mp) - 4;
|
||||
dogd.dmin = pp.DistanceTo(dogd.mp) - 6;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -292,7 +294,7 @@ void Entity::DrawOrGetDistance(void) {
|
|||
Vector p1 = SS.GetEntity(point[1])->PointGetNum();
|
||||
Vector p2 = SS.GetEntity(point[2])->PointGetNum();
|
||||
Vector p3 = SS.GetEntity(point[3])->PointGetNum();
|
||||
int i, n = 20;
|
||||
int i, n = (int)(15/sqrt(SS.meshTol));
|
||||
Vector prev = p0;
|
||||
for(i = 1; i <= n; i++) {
|
||||
double t = ((double)i)/n;
|
||||
|
@ -307,7 +309,6 @@ void Entity::DrawOrGetDistance(void) {
|
|||
break;
|
||||
}
|
||||
|
||||
#define CIRCLE_SIDES(r) (7 + (int)(sqrt(r*SS.GW.scale)))
|
||||
case ARC_OF_CIRCLE: {
|
||||
Vector c = SS.GetEntity(point[0])->PointGetNum();
|
||||
Vector pa = SS.GetEntity(point[1])->PointGetNum();
|
||||
|
@ -321,7 +322,7 @@ void Entity::DrawOrGetDistance(void) {
|
|||
double thetaa, thetab, dtheta;
|
||||
ArcGetAngles(&thetaa, &thetab, &dtheta);
|
||||
|
||||
int i, n = 3 + (int)(CIRCLE_SIDES(ra)*dtheta/(2*PI));
|
||||
int i, n = 3 + (int)(SS.CircleSides(ra)*dtheta/(2*PI));
|
||||
Vector prev = pa;
|
||||
for(i = 1; i <= n; i++) {
|
||||
double theta = thetaa + (dtheta*i)/n;
|
||||
|
@ -340,7 +341,7 @@ void Entity::DrawOrGetDistance(void) {
|
|||
Vector center = SS.GetEntity(point[0])->PointGetNum();
|
||||
Vector u = q.RotationU(), v = q.RotationV();
|
||||
|
||||
int i, c = CIRCLE_SIDES(r);
|
||||
int i, c = SS.CircleSides(r);
|
||||
Vector prev = u.ScaledBy(r).Plus(center);
|
||||
for(i = 1; i <= c; i++) {
|
||||
double phi = (2*PI*i)/c;
|
||||
|
|
1
file.cpp
1
file.cpp
|
@ -140,6 +140,7 @@ const SolveSpace::SaveTable SolveSpace::SAVED[] = {
|
|||
{ 'c', "Constraint.entityA.v", 'x', &(SS.sv.c.entityA.v) },
|
||||
{ 'c', "Constraint.entityB.v", 'x', &(SS.sv.c.entityB.v) },
|
||||
{ 'c', "Constraint.otherAngle", 'b', &(SS.sv.c.otherAngle) },
|
||||
{ 'c', "Constraint.reference", 'b', &(SS.sv.c.reference) },
|
||||
{ 'c', "Constraint.disp.offset.x", 'f', &(SS.sv.c.disp.offset.x) },
|
||||
{ 'c', "Constraint.disp.offset.y", 'f', &(SS.sv.c.disp.offset.y) },
|
||||
{ 'c', "Constraint.disp.offset.z", 'f', &(SS.sv.c.disp.offset.z) },
|
||||
|
|
|
@ -175,9 +175,7 @@ void glxFillMesh(int specColor, SMesh *m, DWORD h, DWORD s1, DWORD s2)
|
|||
color = specColor;
|
||||
}
|
||||
if(color != prevColor) {
|
||||
GLfloat mpf[] = { ((color >> 0) & 0xff) / 255.0f,
|
||||
((color >> 8) & 0xff) / 255.0f,
|
||||
((color >> 16) & 0xff) / 255.0f, 1.0 };
|
||||
GLfloat mpf[] = { REDf(color), GREENf(color), BLUEf(color), 1.0 };
|
||||
glEnd();
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mpf);
|
||||
prevColor = color;
|
||||
|
|
|
@ -65,7 +65,6 @@ const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = {
|
|||
{ 1, "&Cubic Segment\t3", MNU_CUBIC, '3', mReq },
|
||||
{ 1, NULL, 0, NULL },
|
||||
{ 1, "Sym&bolic Variable\tB", 0, 'B', mReq },
|
||||
{ 1, "&Import From File...\tI", 0, 'I', mReq },
|
||||
{ 1, NULL, 0, NULL },
|
||||
{ 1, "To&ggle Construction\tG", MNU_CONSTRUCTION, 'G', mReq },
|
||||
|
||||
|
@ -73,6 +72,7 @@ const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = {
|
|||
{ 1, "&Distance / Diameter\tShift+D", MNU_DISTANCE_DIA, 'D'|S, mCon },
|
||||
{ 1, "A&ngle\tShift+N", MNU_ANGLE, 'N'|S, mCon },
|
||||
{ 1, "Other S&upplementary Angle\tShift+U", MNU_OTHER_ANGLE, 'U'|S, mCon },
|
||||
{ 1, "Toggle &Reference Dim\tShift+R", MNU_REFERENCE, 'R'|S, mCon },
|
||||
{ 1, NULL, 0, NULL },
|
||||
{ 1, "&Horizontal\tShift+H", MNU_HORIZONTAL, 'H'|S, mCon },
|
||||
{ 1, "&Vertical\tShift+V", MNU_VERTICAL, 'V'|S, mCon },
|
||||
|
@ -83,7 +83,7 @@ const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = {
|
|||
{ 1, "At &Midpoint\tShift+M", MNU_AT_MIDPOINT, 'M'|S, mCon },
|
||||
{ 1, "S&ymmetric\tShift+Y", MNU_SYMMETRIC, 'Y'|S, mCon },
|
||||
{ 1, "Para&llel\tShift+L", MNU_PARALLEL, 'L'|S, mCon },
|
||||
{ 1, "Same O&rientation\tShift+R", MNU_ORIENTED_SAME, 'R'|S, mCon },
|
||||
{ 1, "Same Orient&ation\tShift+A", MNU_ORIENTED_SAME, 'A'|S, mCon },
|
||||
{ 1, NULL, 0, NULL },
|
||||
{ 1, "Sym&bolic Equation\tShift+B", 0, 'B'|S, NULL },
|
||||
{ 1, NULL, 0, NULL },
|
||||
|
@ -187,6 +187,59 @@ void GraphicsWindow::AnimateOntoWorkplane(void) {
|
|||
InvalidateGraphics();
|
||||
}
|
||||
|
||||
void GraphicsWindow::HandlePointForZoomToFit(Vector p,
|
||||
Point2d *pmax, Point2d *pmin)
|
||||
{
|
||||
Point2d p2 = ProjectPoint(p);
|
||||
pmax->x = max(pmax->x, p2.x);
|
||||
pmax->y = max(pmax->y, p2.y);
|
||||
pmin->x = min(pmin->x, p2.x);
|
||||
pmin->y = min(pmin->y, p2.y);
|
||||
}
|
||||
void GraphicsWindow::ZoomToFit(void) {
|
||||
int i, j;
|
||||
Point2d pmax = { -1e12, -1e12 }, pmin = { 1e12, 1e12 };
|
||||
|
||||
HandlePointForZoomToFit(Vector::From(0, 0, 0), &pmax, &pmin);
|
||||
|
||||
for(i = 0; i < SS.entity.n; i++) {
|
||||
Entity *e = &(SS.entity.elem[i]);
|
||||
if(!e->IsPoint()) continue;
|
||||
if(!e->IsVisible()) continue;
|
||||
HandlePointForZoomToFit(e->PointGetNum(), &pmax, &pmin);
|
||||
}
|
||||
Group *g = SS.GetGroup(activeGroup);
|
||||
for(i = 0; i < g->mesh.l.n; i++) {
|
||||
STriangle *tr = &(g->mesh.l.elem[i]);
|
||||
HandlePointForZoomToFit(tr->a, &pmax, &pmin);
|
||||
HandlePointForZoomToFit(tr->b, &pmax, &pmin);
|
||||
HandlePointForZoomToFit(tr->c, &pmax, &pmin);
|
||||
}
|
||||
for(i = 0; i < g->poly.l.n; i++) {
|
||||
SContour *sc = &(g->poly.l.elem[i]);
|
||||
for(j = 0; j < sc->l.n; j++) {
|
||||
HandlePointForZoomToFit(sc->l.elem[j].p, &pmax, &pmin);
|
||||
}
|
||||
}
|
||||
|
||||
pmax = pmax.ScaledBy(1/scale);
|
||||
pmin = pmin.ScaledBy(1/scale);
|
||||
double xm = (pmax.x + pmin.x)/2, ym = (pmax.y + pmin.y)/2;
|
||||
double dx = pmax.x - pmin.x, dy = pmax.y - pmin.y;
|
||||
|
||||
offset = offset.Plus(projRight.ScaledBy(-xm)).Plus(
|
||||
projUp. ScaledBy(-ym));
|
||||
|
||||
if(dx == 0 && dy == 0) {
|
||||
scale = 5;
|
||||
} else {
|
||||
double scalex = 1e12, scaley = 1e12;
|
||||
if(dx != 0) scalex = 0.9*width /dx;
|
||||
if(dy != 0) scaley = 0.9*height/dy;
|
||||
scale = min(100, min(scalex, scaley));
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsWindow::MenuView(int id) {
|
||||
switch(id) {
|
||||
case MNU_ZOOM_IN:
|
||||
|
@ -198,6 +251,7 @@ void GraphicsWindow::MenuView(int id) {
|
|||
break;
|
||||
|
||||
case MNU_ZOOM_TO_FIT:
|
||||
SS.GW.ZoomToFit();
|
||||
break;
|
||||
|
||||
case MNU_SHOW_TEXT_WND:
|
||||
|
|
|
@ -123,7 +123,17 @@ void Group::GenerateMesh(void) {
|
|||
Vector axis = SS.GetEntity(predef.entityB)->VectorGetNum();
|
||||
axis = axis.WithMagnitude(1);
|
||||
|
||||
int n = 20;
|
||||
// Calculate the max radius, to determine fineness of mesh
|
||||
double r, rmax = 0;
|
||||
for(i = 0; i < edges.l.n; i++) {
|
||||
SEdge *edge = &(edges.l.elem[i]);
|
||||
r = (edge->a).DistanceToLine(orig, axis);
|
||||
rmax = max(r, rmax);
|
||||
r = (edge->b).DistanceToLine(orig, axis);
|
||||
rmax = max(r, rmax);
|
||||
}
|
||||
|
||||
int n = SS.CircleSides(rmax);
|
||||
for(a = 0; a <= n; a++) {
|
||||
double thetai = (2*PI*WRAP(a-1, n))/n, thetaf = (2*PI*a)/n;
|
||||
for(i = 0; i < edges.l.n; i++) {
|
||||
|
@ -139,18 +149,23 @@ void Group::GenerateMesh(void) {
|
|||
|
||||
Vector ab = (edge->b).Minus(edge->a);
|
||||
Vector out = ((src->poly).normal).Cross(ab);
|
||||
// This is a vector, not a point, so no origin for rotation
|
||||
out = out.RotatedAbout(axis, thetai);
|
||||
|
||||
// The line sweeps out a quad, so two triangles
|
||||
STriangle quad1 = STriangle::From(meta, ai, bi, af),
|
||||
quad2 = STriangle::From(meta, af, bi, bf);
|
||||
|
||||
// Could be only one of the triangles has area; be sure
|
||||
// to use that one for normal checking, then.
|
||||
Vector n1 = quad1.Normal(), n2 = quad2.Normal();
|
||||
Vector n = (n1.Magnitude() > n2.Magnitude()) ? n1 : n2;
|
||||
if(n.Dot(out) < 0) {
|
||||
quad1.FlipNormal();
|
||||
quad2.FlipNormal();
|
||||
}
|
||||
// If one of the endpoints lies on the axis of rotation,
|
||||
// then the quad is just a single triangle
|
||||
// One or both of the endpoints might lie on the axis of
|
||||
// rotation, in which case its triangle is zero-area.
|
||||
if(da >= LENGTH_EPS) outm.AddTriangle(&quad1);
|
||||
if(db >= LENGTH_EPS) outm.AddTriangle(&quad2);
|
||||
}
|
||||
|
|
3
mesh.cpp
3
mesh.cpp
|
@ -220,7 +220,6 @@ void SMesh::MakeFromUnion(SMesh *a, SMesh *b) {
|
|||
}
|
||||
|
||||
void SMesh::MakeFromDifference(SMesh *a, SMesh *b) {
|
||||
SDWORD in = GetMilliseconds();
|
||||
SBsp3 *bspa = SBsp3::FromMesh(a);
|
||||
SBsp3 *bspb = SBsp3::FromMesh(b);
|
||||
|
||||
|
@ -231,8 +230,6 @@ void SMesh::MakeFromDifference(SMesh *a, SMesh *b) {
|
|||
flipNormal = false;
|
||||
keepCoplanar = false;
|
||||
AddAgainstBsp(a, bspb);
|
||||
dbp("dt = %d", GetMilliseconds() - in);
|
||||
dbp("tris = %d", l.n);
|
||||
}
|
||||
|
||||
bool SMesh::MakeFromInterferenceCheck(SMesh *srca, SMesh *srcb, SMesh *error) {
|
||||
|
|
2
sketch.h
2
sketch.h
|
@ -461,6 +461,7 @@ public:
|
|||
void LineDrawOrGetDistance(Vector a, Vector b);
|
||||
void DrawOrGetDistance(Vector *labelPos);
|
||||
double EllipticalInterpolation(double rx, double ry, double theta);
|
||||
char *Label(void);
|
||||
void DoLabel(Vector ref, Vector *labelPos, Vector gr, Vector gu);
|
||||
void DoProjectedPoint(Vector *p);
|
||||
|
||||
|
@ -472,6 +473,7 @@ public:
|
|||
bool HasLabel(void);
|
||||
|
||||
void Generate(IdList<Equation,hEquation> *l);
|
||||
void GenerateReal(IdList<Equation,hEquation> *l);
|
||||
// Some helpers when generating symbolic constraint equations
|
||||
void ModifyToSatisfy(void);
|
||||
void AddEq(IdList<Equation,hEquation> *l, Expr *expr, int index);
|
||||
|
|
|
@ -3,9 +3,41 @@
|
|||
SolveSpace SS;
|
||||
|
||||
void SolveSpace::Init(char *cmdLine) {
|
||||
int i;
|
||||
// Default list of colors for the model material
|
||||
modelColor[0] = CnfThawDWORD(RGB(150, 150, 150), "ModelColor_0");
|
||||
modelColor[1] = CnfThawDWORD(RGB(100, 100, 100), "ModelColor_1");
|
||||
modelColor[2] = CnfThawDWORD(RGB( 30, 30, 30), "ModelColor_2");
|
||||
modelColor[3] = CnfThawDWORD(RGB(150, 0, 0), "ModelColor_3");
|
||||
modelColor[4] = CnfThawDWORD(RGB( 0, 100, 0), "ModelColor_4");
|
||||
modelColor[5] = CnfThawDWORD(RGB( 0, 80, 80), "ModelColor_5");
|
||||
modelColor[6] = CnfThawDWORD(RGB( 0, 0, 130), "ModelColor_6");
|
||||
modelColor[7] = CnfThawDWORD(RGB( 80, 0, 80), "ModelColor_7");
|
||||
// Light intensities
|
||||
lightIntensity[0] = ((int)CnfThawDWORD( 700, "LightIntensity_0"))/1000.0;
|
||||
lightIntensity[1] = ((int)CnfThawDWORD( 400, "LightIntensity_1"))/1000.0;
|
||||
// Light positions
|
||||
lightPos[0].x = ((int)CnfThawDWORD(-500, "LightPos_0_Right" ))/1000.0;
|
||||
lightPos[0].y = ((int)CnfThawDWORD( 500, "LightPos_0_Up" ))/1000.0;
|
||||
lightPos[0].z = ((int)CnfThawDWORD( 0, "LightPos_0_Forward" ))/1000.0;
|
||||
lightPos[1].x = ((int)CnfThawDWORD( 500, "LightPos_1_Right" ))/1000.0;
|
||||
lightPos[1].y = ((int)CnfThawDWORD( 0, "LightPos_1_Up" ))/1000.0;
|
||||
lightPos[1].z = ((int)CnfThawDWORD( 0, "LightPos_1_Forward" ))/1000.0;
|
||||
// Mesh tolerance
|
||||
meshTol = ((int)CnfThawDWORD(1000, "MeshTolerance"))/1000.0;
|
||||
// Recent files menus
|
||||
for(i = 0; i < MAX_RECENT; i++) {
|
||||
char name[100];
|
||||
sprintf(name, "RecentFile_%d", i);
|
||||
strcpy(RecentFile[i], "");
|
||||
CnfThawString(RecentFile[i], MAX_PATH, name);
|
||||
}
|
||||
RefreshRecentMenus();
|
||||
|
||||
// Start with either an empty file, or the file specified on the
|
||||
// command line.
|
||||
NewFile();
|
||||
AfterNewFile();
|
||||
|
||||
if(strlen(cmdLine) != 0) {
|
||||
if(LoadFromFile(cmdLine)) {
|
||||
strcpy(saveFile, cmdLine);
|
||||
|
@ -13,16 +45,49 @@ void SolveSpace::Init(char *cmdLine) {
|
|||
NewFile();
|
||||
}
|
||||
}
|
||||
|
||||
AfterNewFile();
|
||||
}
|
||||
|
||||
void SolveSpace::Exit(void) {
|
||||
int i;
|
||||
char name[100];
|
||||
// Recent files
|
||||
for(i = 0; i < MAX_RECENT; i++) {
|
||||
sprintf(name, "RecentFile_%d", i);
|
||||
CnfFreezeString(RecentFile[i], name);
|
||||
}
|
||||
// Model colors
|
||||
for(i = 0; i < MODEL_COLORS; i++) {
|
||||
sprintf(name, "ModelColor_%d", i);
|
||||
CnfFreezeDWORD(modelColor[i], name);
|
||||
}
|
||||
// Light intensities
|
||||
CnfFreezeDWORD((int)(lightIntensity[0]*1000), "LightIntensity_0");
|
||||
CnfFreezeDWORD((int)(lightIntensity[1]*1000), "LightIntensity_1");
|
||||
// Light positions
|
||||
CnfFreezeDWORD((int)(lightPos[0].x*1000), "LightPos_0_Right");
|
||||
CnfFreezeDWORD((int)(lightPos[0].y*1000), "LightPos_0_Up");
|
||||
CnfFreezeDWORD((int)(lightPos[0].z*1000), "LightPos_0_Forward");
|
||||
CnfFreezeDWORD((int)(lightPos[1].x*1000), "LightPos_1_Right");
|
||||
CnfFreezeDWORD((int)(lightPos[1].y*1000), "LightPos_1_Up");
|
||||
CnfFreezeDWORD((int)(lightPos[1].z*1000), "LightPos_1_Forward");
|
||||
// Mesh tolerance
|
||||
CnfFreezeDWORD((int)(meshTol*1000), "MeshTolerance");
|
||||
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
void SolveSpace::DoLater(void) {
|
||||
if(later.generateAll) GenerateAll();
|
||||
if(later.showTW) TW.Show();
|
||||
ZERO(&later);
|
||||
}
|
||||
|
||||
int SolveSpace::CircleSides(double r) {
|
||||
int s = 7 + (int)(sqrt(r*SS.GW.scale/meshTol));
|
||||
return min(s, 40);
|
||||
}
|
||||
|
||||
void SolveSpace::AfterNewFile(void) {
|
||||
ReloadAllImported();
|
||||
GenerateAll(-1, -1);
|
||||
|
@ -249,6 +314,14 @@ void SolveSpace::GenerateAll(int first, int last) {
|
|||
}
|
||||
}
|
||||
|
||||
// And update any reference dimensions with their new values
|
||||
for(i = 0; i < constraint.n; i++) {
|
||||
Constraint *c = &(constraint.elem[i]);
|
||||
if(c->reference) {
|
||||
c->ModifyToSatisfy();
|
||||
}
|
||||
}
|
||||
|
||||
prev.Clear();
|
||||
InvalidateGraphics();
|
||||
|
||||
|
@ -459,7 +532,7 @@ void SolveSpace::MenuFile(int id) {
|
|||
|
||||
case GraphicsWindow::MNU_EXIT:
|
||||
if(!SS.OkayToStartNewFile()) break;
|
||||
ExitNow();
|
||||
SS.Exit();
|
||||
break;
|
||||
|
||||
default: oops();
|
||||
|
|
17
solvespace.h
17
solvespace.h
|
@ -80,6 +80,10 @@ void dbp(char *str, ...);
|
|||
|
||||
void Error(char *str, ...);
|
||||
void ExitNow(void);
|
||||
void CnfFreezeString(char *str, char *name);
|
||||
void CnfFreezeDWORD(DWORD v, char *name);
|
||||
void CnfThawString(char *str, int maxLen, char *name);
|
||||
DWORD CnfThawDWORD(DWORD v, char *name);
|
||||
|
||||
void *AllocTemporary(int n);
|
||||
void FreeAllTemporary(void);
|
||||
|
@ -242,10 +246,21 @@ public:
|
|||
void UndoClearState(UndoState *ut);
|
||||
void UndoClearStack(UndoStack *uk);
|
||||
|
||||
// Little bits of extra configuration state
|
||||
static const int MODEL_COLORS = 8;
|
||||
int modelColor[MODEL_COLORS];
|
||||
Vector lightPos[2];
|
||||
double lightIntensity[2];
|
||||
double meshTol;
|
||||
|
||||
void Init(char *cmdLine);
|
||||
void Exit(void);
|
||||
|
||||
int CircleSides(double r);
|
||||
|
||||
// File load/save routines, including the additional files that get
|
||||
// loaded when we have import groups.
|
||||
FILE *fh;
|
||||
void Init(char *cmdLine);
|
||||
void AfterNewFile(void);
|
||||
static void RemoveFromRecentList(char *file);
|
||||
static void AddToRecentList(char *file);
|
||||
|
|
170
textwin.cpp
170
textwin.cpp
|
@ -31,16 +31,6 @@ void TextWindow::ClearSuper(void) {
|
|||
shown = &(showns[shownIndex]);
|
||||
ClearScreen();
|
||||
Show();
|
||||
|
||||
// Default list of colors for the model material
|
||||
modelColor[0] = RGB(150, 150, 150);
|
||||
modelColor[1] = RGB(100, 100, 100);
|
||||
modelColor[2] = RGB( 30, 30, 30);
|
||||
modelColor[3] = RGB(150, 0, 0);
|
||||
modelColor[4] = RGB( 0, 100, 0);
|
||||
modelColor[5] = RGB( 0, 80, 80);
|
||||
modelColor[6] = RGB( 0, 0, 130);
|
||||
modelColor[7] = RGB( 80, 0, 80);
|
||||
}
|
||||
|
||||
void TextWindow::ClearScreen(void) {
|
||||
|
@ -97,6 +87,16 @@ void TextWindow::Printf(bool halfLine, char *fmt, ...) {
|
|||
sprintf(buf, "%08x", v);
|
||||
break;
|
||||
}
|
||||
case '@': {
|
||||
double v = va_arg(vl, double);
|
||||
sprintf(buf, "%.2f", v);
|
||||
break;
|
||||
}
|
||||
case '2': {
|
||||
double v = va_arg(vl, double);
|
||||
sprintf(buf, "%s%.2f", v < 0 ? "" : " ", v);
|
||||
break;
|
||||
}
|
||||
case '3': {
|
||||
double v = va_arg(vl, double);
|
||||
sprintf(buf, "%s%.3f", v < 0 ? "" : " ", v);
|
||||
|
@ -201,10 +201,12 @@ void TextWindow::Show(void) {
|
|||
if(SS.GW.pending.description) {
|
||||
// A pending operation (that must be completed with the mouse in
|
||||
// the graphics window) will preempt our usual display.
|
||||
HideTextEditControl();
|
||||
ShowHeader(false);
|
||||
Printf(false, "");
|
||||
Printf(false, "%s", SS.GW.pending.description);
|
||||
} else if(gs.n > 0) {
|
||||
HideTextEditControl();
|
||||
ShowHeader(false);
|
||||
DescribeSelection();
|
||||
} else {
|
||||
|
@ -216,6 +218,7 @@ void TextWindow::Show(void) {
|
|||
case SCREEN_LIST_OF_GROUPS: ShowListOfGroups(); break;
|
||||
case SCREEN_GROUP_INFO: ShowGroupInfo(); break;
|
||||
case SCREEN_GROUP_SOLVE_INFO: ShowGroupSolveInfo(); break;
|
||||
case SCREEN_CONFIGURATION: ShowConfiguration(); break;
|
||||
}
|
||||
}
|
||||
InvalidateText();
|
||||
|
@ -437,15 +440,12 @@ void TextWindow::ScreenToggleGroupShown(int link, DWORD v) {
|
|||
}
|
||||
void TextWindow::ScreenShowGroupsSpecial(int link, DWORD v) {
|
||||
int i;
|
||||
bool before = true;
|
||||
for(i = 0; i < SS.group.n; i++) {
|
||||
Group *g = &(SS.group.elem[i]);
|
||||
|
||||
if(g->h.v == SS.GW.activeGroup.v) {
|
||||
before = false;
|
||||
} else if(before && link == 's') {
|
||||
if(link == 's') {
|
||||
g->visible = true;
|
||||
} else if(!before && link == 'h') {
|
||||
} else {
|
||||
g->visible = false;
|
||||
}
|
||||
}
|
||||
|
@ -471,6 +471,9 @@ void TextWindow::ScreenHowGroupSolved(int link, DWORD v) {
|
|||
SS.TW.OneScreenForwardTo(SCREEN_GROUP_SOLVE_INFO);
|
||||
SS.TW.shown->group.v = v;
|
||||
}
|
||||
void TextWindow::ScreenShowConfiguration(int link, DWORD v) {
|
||||
SS.TW.OneScreenForwardTo(SCREEN_CONFIGURATION);
|
||||
}
|
||||
void TextWindow::ShowListOfGroups(void) {
|
||||
Printf(true, "%Ftactv show ok group-name%E");
|
||||
int i;
|
||||
|
@ -508,10 +511,11 @@ void TextWindow::ShowListOfGroups(void) {
|
|||
if(active) afterActive = true;
|
||||
}
|
||||
|
||||
Printf(true, " %Fl%Ls%fshow all groups before active%E",
|
||||
&(TextWindow::ScreenShowGroupsSpecial));
|
||||
Printf(false, " %Fl%Lh%fhide all groups after active%E",
|
||||
Printf(true, " %Fl%Ls%fshow all%E / %Fl%Lh%fhide all%E",
|
||||
&(TextWindow::ScreenShowGroupsSpecial),
|
||||
&(TextWindow::ScreenShowGroupsSpecial));
|
||||
Printf(false, " %Fl%Ls%fconfiguration%E",
|
||||
&(TextWindow::ScreenShowConfiguration));
|
||||
}
|
||||
|
||||
|
||||
|
@ -569,8 +573,8 @@ void TextWindow::ScreenColor(int link, DWORD v) {
|
|||
SS.UndoRemember();
|
||||
|
||||
Group *g = SS.GetGroup(SS.TW.shown->group);
|
||||
if(v < 0 || v >= MODEL_COLORS) return;
|
||||
g->color = SS.TW.modelColor[v];
|
||||
if(v < 0 || v >= SS.MODEL_COLORS) return;
|
||||
g->color = SS.modelColor[v];
|
||||
SS.MarkGroupDirty(g->h);
|
||||
SS.GenerateAll();
|
||||
SS.GW.ClearSuper();
|
||||
|
@ -610,7 +614,7 @@ void TextWindow::ShowGroupInfo(void) {
|
|||
Printf(true, "%FtGROUP %E%s", g->DescriptionString());
|
||||
} else {
|
||||
Printf(true, "%FtGROUP %E%s "
|
||||
"(%Fl%Ll%D%frename%E / %Fl%Ll%D%fdel%E)",
|
||||
"[%Fl%Ll%D%frename%E/%Fl%Ll%D%fdel%E]",
|
||||
g->DescriptionString(),
|
||||
g->h.v, &TextWindow::ScreenChangeGroupName,
|
||||
g->h.v, &TextWindow::ScreenDeleteGroup);
|
||||
|
@ -646,7 +650,7 @@ void TextWindow::ShowGroupInfo(void) {
|
|||
|
||||
if(g->type == Group::ROTATE || g->type == Group::TRANSLATE) {
|
||||
int times = (int)(g->exprA->Eval());
|
||||
Printf(true, "%Ft%s%E %d time%s %Fl%Ll%D%f(change)%E",
|
||||
Printf(true, "%Ft%s%E %d time%s %Fl%Ll%D%f[change]%E",
|
||||
s2, times, times == 1 ? "" : "s",
|
||||
g->h.v, &TextWindow::ScreenChangeExprA);
|
||||
}
|
||||
|
@ -681,14 +685,14 @@ void TextWindow::ShowGroupInfo(void) {
|
|||
if(g->type == Group::EXTRUDE || g->type == Group::LATHE) {
|
||||
#define TWOX(v) v v
|
||||
Printf(true, "%FtM_COLOR%E " TWOX(TWOX(TWOX("%Bp%D%f%Ln %Bd%E "))),
|
||||
0x80000000 | modelColor[0], 0, &TextWindow::ScreenColor,
|
||||
0x80000000 | modelColor[1], 1, &TextWindow::ScreenColor,
|
||||
0x80000000 | modelColor[2], 2, &TextWindow::ScreenColor,
|
||||
0x80000000 | modelColor[3], 3, &TextWindow::ScreenColor,
|
||||
0x80000000 | modelColor[4], 4, &TextWindow::ScreenColor,
|
||||
0x80000000 | modelColor[5], 5, &TextWindow::ScreenColor,
|
||||
0x80000000 | modelColor[6], 6, &TextWindow::ScreenColor,
|
||||
0x80000000 | modelColor[7], 7, &TextWindow::ScreenColor);
|
||||
0x80000000 | SS.modelColor[0], 0, &TextWindow::ScreenColor,
|
||||
0x80000000 | SS.modelColor[1], 1, &TextWindow::ScreenColor,
|
||||
0x80000000 | SS.modelColor[2], 2, &TextWindow::ScreenColor,
|
||||
0x80000000 | SS.modelColor[3], 3, &TextWindow::ScreenColor,
|
||||
0x80000000 | SS.modelColor[4], 4, &TextWindow::ScreenColor,
|
||||
0x80000000 | SS.modelColor[5], 5, &TextWindow::ScreenColor,
|
||||
0x80000000 | SS.modelColor[6], 6, &TextWindow::ScreenColor,
|
||||
0x80000000 | SS.modelColor[7], 7, &TextWindow::ScreenColor);
|
||||
}
|
||||
|
||||
Printf(true, "%Ftrequests in group");
|
||||
|
@ -727,13 +731,15 @@ void TextWindow::ShowGroupInfo(void) {
|
|||
|
||||
void TextWindow::ShowGroupSolveInfo(void) {
|
||||
Group *g = SS.group.FindById(shown->group);
|
||||
if(g->solved.how == Group::SOLVED_OKAY) {
|
||||
// Go back to the default group info screen
|
||||
shown->screen = SCREEN_GROUP_INFO;
|
||||
Show();
|
||||
return;
|
||||
}
|
||||
|
||||
Printf(true, "%FtGROUP %E%s", g->DescriptionString());
|
||||
|
||||
switch(g->solved.how) {
|
||||
case Group::SOLVED_OKAY:
|
||||
Printf(true, " %Fsgroup solved okay%E");
|
||||
break;
|
||||
|
||||
case Group::DIDNT_CONVERGE:
|
||||
Printf(true, " %FxSOLVE FAILED!%Fd no convergence");
|
||||
break;
|
||||
|
@ -757,6 +763,69 @@ void TextWindow::ShowGroupSolveInfo(void) {
|
|||
}
|
||||
}
|
||||
|
||||
void TextWindow::ScreenChangeLightPosition(int link, DWORD v) {
|
||||
char str[1024];
|
||||
sprintf(str, "%.2f, %.2f, %.2f", CO(SS.lightPos[v]));
|
||||
ShowTextEditControl(29+2*v, 8, str);
|
||||
SS.TW.edit.meaning = EDIT_LIGHT_POSITION;
|
||||
SS.TW.edit.i = v;
|
||||
}
|
||||
void TextWindow::ScreenChangeLightIntensity(int link, DWORD v) {
|
||||
char str[1024];
|
||||
sprintf(str, "%.2f", SS.lightIntensity[v]);
|
||||
ShowTextEditControl(29+2*v, 30, str);
|
||||
SS.TW.edit.meaning = EDIT_LIGHT_INTENSITY;
|
||||
SS.TW.edit.i = v;
|
||||
}
|
||||
void TextWindow::ScreenChangeColor(int link, DWORD v) {
|
||||
char str[1024];
|
||||
sprintf(str, "%.2f, %.2f, %.2f",
|
||||
REDf(SS.modelColor[v]),
|
||||
GREENf(SS.modelColor[v]),
|
||||
BLUEf(SS.modelColor[v]));
|
||||
ShowTextEditControl(9+2*v, 12, str);
|
||||
SS.TW.edit.meaning = EDIT_COLOR;
|
||||
SS.TW.edit.i = v;
|
||||
}
|
||||
void TextWindow::ScreenChangeMeshTolerance(int link, DWORD v) {
|
||||
char str[1024];
|
||||
sprintf(str, "%.2f", SS.meshTol);
|
||||
ShowTextEditControl(37, 3, str);
|
||||
SS.TW.edit.meaning = EDIT_MESH_TOLERANCE;
|
||||
}
|
||||
void TextWindow::ShowConfiguration(void) {
|
||||
int i;
|
||||
Printf(true, "%Ft material color-(r, g, b)");
|
||||
|
||||
for(i = 0; i < SS.MODEL_COLORS; i++) {
|
||||
Printf(false, "%Bp #%d: %Bp %Bp (%@, %@, %@) %f%D%Ll%Fl[change]%E",
|
||||
(i & 1) ? 'd' : 'a',
|
||||
i, 0x80000000 | SS.modelColor[i],
|
||||
(i & 1) ? 'd' : 'a',
|
||||
REDf(SS.modelColor[i]),
|
||||
GREENf(SS.modelColor[i]),
|
||||
BLUEf(SS.modelColor[i]),
|
||||
&ScreenChangeColor, i);
|
||||
}
|
||||
|
||||
Printf(false, "");
|
||||
Printf(false, "%Ft light position intensity");
|
||||
for(i = 0; i < 2; i++) {
|
||||
Printf(false, "%Bp #%d (%2,%2,%2)%Fl%D%f%Ll[c]%E "
|
||||
"%2 %Fl%D%f%Ll[c]%E",
|
||||
(i & 1) ? 'd' : 'a', i,
|
||||
CO(SS.lightPos[i]), i, &ScreenChangeLightPosition,
|
||||
SS.lightIntensity[i], i, &ScreenChangeLightIntensity);
|
||||
}
|
||||
|
||||
Printf(false, "");
|
||||
Printf(false, "%Ft mesh tolerance (smaller is finer)%E");
|
||||
Printf(false, "%Ba %2 %Fl%Ll%f%D[change]%E; now %d triangles",
|
||||
SS.meshTol,
|
||||
&ScreenChangeMeshTolerance, 0,
|
||||
SS.group.elem[SS.group.n-1].mesh.l.n);
|
||||
}
|
||||
|
||||
void TextWindow::EditControlDone(char *s) {
|
||||
switch(edit.meaning) {
|
||||
case EDIT_TIMES_REPEATED: {
|
||||
|
@ -770,7 +839,6 @@ void TextWindow::EditControlDone(char *s) {
|
|||
|
||||
SS.MarkGroupDirty(g->h);
|
||||
SS.later.generateAll = true;
|
||||
SS.later.showTW = true;
|
||||
} else {
|
||||
Error("Not a valid number or expression: '%s'", s);
|
||||
}
|
||||
|
@ -792,11 +860,39 @@ void TextWindow::EditControlDone(char *s) {
|
|||
Group *g = SS.GetGroup(edit.group);
|
||||
g->name.strcpy(s);
|
||||
}
|
||||
SS.later.showTW = true;
|
||||
SS.unsaved = true;
|
||||
break;
|
||||
}
|
||||
case EDIT_LIGHT_INTENSITY:
|
||||
SS.lightIntensity[edit.i] = min(1, max(0, atof(s)));
|
||||
InvalidateGraphics();
|
||||
break;
|
||||
case EDIT_LIGHT_POSITION: {
|
||||
double x, y, z;
|
||||
if(sscanf(s, "%lf, %lf, %lf", &x, &y, &z)==3) {
|
||||
SS.lightPos[edit.i] = Vector::From(x, y, z);
|
||||
} else {
|
||||
Error("Bad format: specify coordinates as x, y, z");
|
||||
}
|
||||
InvalidateGraphics();
|
||||
break;
|
||||
}
|
||||
case EDIT_COLOR: {
|
||||
double r, g, b;
|
||||
if(sscanf(s, "%lf, %lf, %lf", &r, &g, &b)==3) {
|
||||
SS.modelColor[edit.i] = RGB(r*255, g*255, b*255);
|
||||
} else {
|
||||
Error("Bad format: specify color as r, g, b");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EDIT_MESH_TOLERANCE: {
|
||||
SS.meshTol = min(10, max(0.1, atof(s)));
|
||||
SS.GenerateAll(0, INT_MAX);
|
||||
break;
|
||||
}
|
||||
}
|
||||
SS.later.showTW = true;
|
||||
HideTextEditControl();
|
||||
edit.meaning = EDIT_NOTHING;
|
||||
}
|
||||
|
|
25
ui.h
25
ui.h
|
@ -10,6 +10,9 @@ public:
|
|||
#ifndef RGB
|
||||
#define RGB(r, g, b) ((r) | ((g) << 8) | ((b) << 16))
|
||||
#endif
|
||||
#define REDf(v) ((((v) >> 0) & 0xff) / 255.0f)
|
||||
#define GREENf(v) ((((v) >> 8) & 0xff) / 255.0f)
|
||||
#define BLUEf(v) ((((v) >> 16) & 0xff) / 255.0f)
|
||||
typedef struct {
|
||||
char c;
|
||||
int color;
|
||||
|
@ -17,9 +20,6 @@ public:
|
|||
static const Color fgColors[];
|
||||
static const Color bgColors[];
|
||||
|
||||
static const int MODEL_COLORS = 8;
|
||||
int modelColor[MODEL_COLORS];
|
||||
|
||||
BYTE text[MAX_ROWS][MAX_COLS];
|
||||
typedef void LinkFunction(int link, DWORD v);
|
||||
static const int NOT_A_LINK = 0;
|
||||
|
@ -45,6 +45,7 @@ public:
|
|||
static const int SCREEN_LIST_OF_GROUPS = 0;
|
||||
static const int SCREEN_GROUP_INFO = 1;
|
||||
static const int SCREEN_GROUP_SOLVE_INFO = 2;
|
||||
static const int SCREEN_CONFIGURATION = 3;
|
||||
typedef struct {
|
||||
int screen;
|
||||
hGroup group;
|
||||
|
@ -58,8 +59,13 @@ public:
|
|||
static const int EDIT_NOTHING = 0;
|
||||
static const int EDIT_TIMES_REPEATED = 1;
|
||||
static const int EDIT_GROUP_NAME = 2;
|
||||
static const int EDIT_LIGHT_POSITION = 3;
|
||||
static const int EDIT_LIGHT_INTENSITY = 4;
|
||||
static const int EDIT_COLOR = 5;
|
||||
static const int EDIT_MESH_TOLERANCE = 6;
|
||||
struct {
|
||||
int meaning;
|
||||
int i;
|
||||
hGroup group;
|
||||
} edit;
|
||||
|
||||
|
@ -73,6 +79,7 @@ public:
|
|||
void ShowListOfGroups(void);
|
||||
void ShowGroupInfo(void);
|
||||
void ShowGroupSolveInfo(void);
|
||||
void ShowConfiguration(void);
|
||||
// Special screen, based on selection
|
||||
void DescribeSelection(void);
|
||||
|
||||
|
@ -90,18 +97,23 @@ public:
|
|||
static void ScreenHoverRequest(int link, DWORD v);
|
||||
static void ScreenSelectRequest(int link, DWORD v);
|
||||
static void ScreenSelectConstraint(int link, DWORD v);
|
||||
static void ScreenUnselectAll(int link, DWORD v);
|
||||
|
||||
static void ScreenChangeOneOrTwoSides(int link, DWORD v);
|
||||
static void ScreenChangeMeshCombine(int link, DWORD v);
|
||||
static void ScreenColor(int link, DWORD v);
|
||||
|
||||
static void ScreenUnselectAll(int link, DWORD v);
|
||||
static void ScreenShowConfiguration(int link, DWORD v);
|
||||
|
||||
static void ScreenNavigation(int link, DWORD v);
|
||||
|
||||
// These ones do stuff with the edit control
|
||||
static void ScreenChangeExprA(int link, DWORD v);
|
||||
static void ScreenChangeGroupName(int link, DWORD v);
|
||||
static void ScreenChangeLightPosition(int link, DWORD v);
|
||||
static void ScreenChangeLightIntensity(int link, DWORD v);
|
||||
static void ScreenChangeColor(int link, DWORD v);
|
||||
static void ScreenChangeMeshTolerance(int link, DWORD v);
|
||||
|
||||
void EditControlDone(char *s);
|
||||
};
|
||||
|
@ -155,6 +167,7 @@ public:
|
|||
MNU_DISTANCE_DIA,
|
||||
MNU_ANGLE,
|
||||
MNU_OTHER_ANGLE,
|
||||
MNU_REFERENCE,
|
||||
MNU_EQUAL,
|
||||
MNU_RATIO,
|
||||
MNU_ON_ENTITY,
|
||||
|
@ -203,7 +216,9 @@ public:
|
|||
void NormalizeProjectionVectors(void);
|
||||
Point2d ProjectPoint(Vector p);
|
||||
void AnimateOntoWorkplane(void);
|
||||
Vector VectorFromProjs(double right, double up, double forward);
|
||||
Vector VectorFromProjs(Vector rightUpForward);
|
||||
void HandlePointForZoomToFit(Vector p, Point2d *pmax, Point2d *pmin);
|
||||
void ZoomToFit(void);
|
||||
|
||||
typedef enum {
|
||||
UNIT_MM = 0,
|
||||
|
|
|
@ -71,6 +71,23 @@ void ExitNow(void) {
|
|||
PostQuitMessage(0);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helpers so that we can read/write registry keys from the platform-
|
||||
// independent code.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CnfFreezeString(char *str, char *name)
|
||||
{ FreezeStringF(str, FREEZE_SUBKEY, name); }
|
||||
|
||||
void CnfFreezeDWORD(DWORD v, char *name)
|
||||
{ FreezeDWORDF(v, FREEZE_SUBKEY, name); }
|
||||
|
||||
void CnfThawString(char *str, int maxLen, char *name)
|
||||
{ ThawStringF(str, maxLen, FREEZE_SUBKEY, name); }
|
||||
|
||||
DWORD CnfThawDWORD(DWORD v, char *name)
|
||||
{ return ThawDWORDF(v, FREEZE_SUBKEY, name); }
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A separate heap, on which we allocate expressions. Maybe a bit faster,
|
||||
// since no fragmentation issues whatsoever, and it also makes it possible
|
||||
|
@ -877,13 +894,6 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
|||
|
||||
InitCommonControls();
|
||||
|
||||
int i;
|
||||
for(i = 0; i < MAX_RECENT; i++) {
|
||||
char name[100];
|
||||
sprintf(name, "RecentFile_%d", i);
|
||||
ThawStringF(RecentFile[i], MAX_PATH, FREEZE_SUBKEY, name);
|
||||
}
|
||||
|
||||
// A monospaced font
|
||||
FixedFont = CreateFont(TEXT_HEIGHT-4, TEXT_WIDTH, 0, 0, FW_REGULAR, FALSE,
|
||||
FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
|
||||
|
@ -936,11 +946,5 @@ done:
|
|||
// Write everything back to the registry
|
||||
FreezeWindowPos(TextWnd);
|
||||
FreezeWindowPos(GraphicsWnd);
|
||||
for(i = 0; i < MAX_RECENT; i++) {
|
||||
char name[100];
|
||||
sprintf(name, "RecentFile_%d", i);
|
||||
FreezeStringF(RecentFile[i], FREEZE_SUBKEY, name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
10
wishlist.txt
10
wishlist.txt
|
@ -1,17 +1,15 @@
|
|||
|
||||
|
||||
STL check for meshes, and T intersection removal
|
||||
STL export
|
||||
better triangle combining (Simplify()) for meshes
|
||||
DXF export
|
||||
compress file format (binary?)
|
||||
partitioned subsystems in the solver
|
||||
arbitrary color specification
|
||||
specify tolerance for meshing
|
||||
specify light positions (all on one configuration screen)
|
||||
TTF font text
|
||||
display with proper formatting/units
|
||||
more measurements
|
||||
reference dimensions (just to look at, no equations)
|
||||
some kind of rounding
|
||||
some kind of rounding / chamfer
|
||||
auto-constrain translate in then-active workplane
|
||||
remove back button in browser?
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user