Make the points locked in 2d csys (expressed as two parameters, for

the plane basis vectors) work, easy. Tweak the text window a bit,
for cosmetics, and start to add the symbolic expression code.

[git-p4: depot-paths = "//depot/solvespace/": change = 1667]
solver
Jonathan Westhues 2008-04-13 06:28:35 -08:00
parent b6bf07ac2c
commit 094e10204d
11 changed files with 172 additions and 31 deletions

View File

@ -16,6 +16,7 @@ SSOBJS = $(OBJDIR)\solvespace.obj \
$(OBJDIR)\entity.obj \ $(OBJDIR)\entity.obj \
$(OBJDIR)\sketch.obj \ $(OBJDIR)\sketch.obj \
$(OBJDIR)\glhelper.obj \ $(OBJDIR)\glhelper.obj \
$(OBJDIR)\expr.obj \
LIBS = user32.lib gdi32.lib comctl32.lib advapi32.lib opengl32.lib glu32.lib LIBS = user32.lib gdi32.lib comctl32.lib advapi32.lib opengl32.lib glu32.lib

View File

@ -1,5 +1,15 @@
#include "solvespace.h" #include "solvespace.h"
void Entity::Get2dCsysBasisVectors(Vector *u, Vector *v) {
double q[4];
for(int i = 0; i < 4; i++) {
q[i] = SS.param.FindById(param(i))->val;
}
*u = Vector::RotationU(q[0], q[1], q[2], q[3]);
*v = Vector::RotationV(q[0], q[1], q[2], q[3]);
}
void Entity::LineDrawOrGetDistance(Vector a, Vector b) { void Entity::LineDrawOrGetDistance(Vector a, Vector b) {
if(dogd.drawing) { if(dogd.drawing) {
glBegin(GL_LINE_STRIP); glBegin(GL_LINE_STRIP);
@ -36,13 +46,8 @@ void Entity::DrawOrGetDistance(void) {
Vector p; Vector p;
p = SS.point.FindById(point(16))->GetCoords(); p = SS.point.FindById(point(16))->GetCoords();
double q[4]; Vector u, v;
for(int i = 0; i < 4; i++) { Get2dCsysBasisVectors(&u, &v);
q[i] = SS.param.FindById(param(i))->val;
}
Vector u = Vector::RotationU(q[0], q[1], q[2], q[3]);
Vector v = Vector::RotationV(q[0], q[1], q[2], q[3]);
double s = (min(SS.GW.width, SS.GW.height))*0.4/SS.GW.scale; double s = (min(SS.GW.width, SS.GW.height))*0.4/SS.GW.scale;

46
expr.cpp Normal file
View File

@ -0,0 +1,46 @@
#include "solvespace.h"
Expr *Expr::FromParam(hParam p) {
Expr *r = AllocExpr();
r->op = PARAM;
r->x.parh = p;
return r;
}
Expr *Expr::FromConstant(double v) {
Expr *r = AllocExpr();
r->op = CONSTANT;
r->x.v = v;
return r;
}
Expr *Expr::AnyOp(int newOp, Expr *b) {
Expr *r = AllocExpr();
r->op = newOp;
r->a = this;
r->b = b;
return r;
}
double Expr::Eval(void) {
switch(op) {
case PARAM: return SS.GetParam(x.parh)->val;
case PARAM_PTR: return (x.parp)->val;
case CONSTANT: return x.v;
case PLUS: return a->Eval() + b->Eval();
case MINUS: return a->Eval() - b->Eval();
case TIMES: return a->Eval() * b->Eval();
case DIV: return a->Eval() / b->Eval();
case NEGATE: return -(a->Eval());
case SQRT: return sqrt(a->Eval());
case SQUARE: { double r = a->Eval(); return r*r; }
case SIN: return sin(a->Eval());
case COS: return cos(a->Eval());
default: oops();
}
}

25
expr.h
View File

@ -32,12 +32,33 @@ public:
Expr *a; Expr *a;
Expr *b; Expr *b;
union { union {
double v;
hParam parh; hParam parh;
double *parp; Param *parp;
hPoint point; hPoint point;
hEntity entity; hEntity entity;
double v;
} x; } x;
static Expr *FromParam(hParam p);
static Expr *FromConstant(double v);
Expr *AnyOp(int op, Expr *b);
inline Expr *Plus (Expr *b) { return AnyOp(PLUS, b); }
inline Expr *Minus(Expr *b) { return AnyOp(MINUS, b); }
inline Expr *Times(Expr *b) { return AnyOp(TIMES, b); }
inline Expr *Div (Expr *b) { return AnyOp(DIV, b); }
inline Expr *Negate(void) { return AnyOp(NEGATE, NULL); }
inline Expr *Sqrt (void) { return AnyOp(SQRT, NULL); }
inline Expr *Square(void) { return AnyOp(SQUARE, NULL); }
inline Expr *Sin (void) { return AnyOp(SIN, NULL); }
inline Expr *Cos (void) { return AnyOp(COS, NULL); }
Expr *PartialWrt(hParam p);
double Eval(void);
void ParamsToPointers(void);
void Print(void);
}; };
#endif #endif

View File

@ -125,12 +125,7 @@ void GraphicsWindow::MenuView(MenuId id) {
SS.GW.GroupSelection(); SS.GW.GroupSelection();
if(SS.GW.gs.n == 1 && SS.GW.gs.csyss == 1) { if(SS.GW.gs.n == 1 && SS.GW.gs.csyss == 1) {
Entity *e = SS.entity.FindById(SS.GW.gs.entity[0]); Entity *e = SS.entity.FindById(SS.GW.gs.entity[0]);
double q[4]; e->Get2dCsysBasisVectors( &(SS.GW.projRight), &(SS.GW.projUp));
for(int i = 0; i < 4; i++) {
q[i] = SS.param.FindById(e->param(i))->val;
}
SS.GW.projRight = Vector::RotationU(q[0], q[1], q[2], q[3]);
SS.GW.projUp = Vector::RotationV(q[0], q[1], q[2], q[3]);
SS.GW.offset = SS.point.FindById(e->point(16))->GetCoords(); SS.GW.offset = SS.point.FindById(e->point(16))->GetCoords();
SS.GW.ClearSelection(); SS.GW.ClearSelection();
InvalidateGraphics(); InvalidateGraphics();
@ -376,6 +371,7 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
SS.point.FindById(hr.entity(0).point(16))->ForceTo(v); SS.point.FindById(hr.entity(0).point(16))->ForceTo(v);
pendingOperation = PENDING_OPERATION_DRAGGING_POINT; pendingOperation = PENDING_OPERATION_DRAGGING_POINT;
pendingPoint = hr.entity(0).point(16+3); pendingPoint = hr.entity(0).point(16+3);
pendingDescription = "click to place next point of line";
SS.point.FindById(pendingPoint)->ForceTo(v); SS.point.FindById(pendingPoint)->ForceTo(v);
break; break;

View File

@ -100,33 +100,51 @@ void Param::ForceTo(double v) {
known = true; known = true;
} }
void Point::ForceTo(Vector v) { void Point::ForceTo(Vector p) {
switch(type) { switch(type) {
case IN_FREE_SPACE: case IN_FREE_SPACE:
SS.param.FindById(param(0))->ForceTo(v.x); SS.GetParam(param(0))->ForceTo(p.x);
SS.param.FindById(param(1))->ForceTo(v.y); SS.GetParam(param(1))->ForceTo(p.y);
SS.param.FindById(param(2))->ForceTo(v.z); SS.GetParam(param(2))->ForceTo(p.z);
break; break;
case IN_2D_CSYS: {
Entity *c = SS.GetEntity(csys);
Vector u, v;
c->Get2dCsysBasisVectors(&u, &v);
SS.GetParam(param(0))->ForceTo(p.Dot(u));
SS.GetParam(param(1))->ForceTo(p.Dot(v));
break;
}
default: default:
oops(); oops();
} }
} }
Vector Point::GetCoords(void) { Vector Point::GetCoords(void) {
Vector v; Vector p;
switch(type) { switch(type) {
case IN_FREE_SPACE: case IN_FREE_SPACE:
v.x = SS.param.FindById(param(0))->val; p.x = SS.GetParam(param(0))->val;
v.y = SS.param.FindById(param(1))->val; p.y = SS.GetParam(param(1))->val;
v.z = SS.param.FindById(param(2))->val; p.z = SS.GetParam(param(2))->val;
break; break;
case IN_2D_CSYS: {
Entity *c = SS.GetEntity(csys);
Vector u, v;
c->Get2dCsysBasisVectors(&u, &v);
p = u.ScaledBy(SS.GetParam(param(0))->val);
p = p.Plus(v.ScaledBy(SS.GetParam(param(1))->val));
break;
}
default: default:
oops(); oops();
} }
return v; return p;
} }
void Point::Draw(void) { void Point::Draw(void) {

View File

@ -122,6 +122,8 @@ public:
inline hPoint point(int i) inline hPoint point(int i)
{ hPoint r; r.v = ((this->h.v) << 7) | i; return r; } { hPoint r; r.v = ((this->h.v) << 7) | i; return r; }
void Get2dCsysBasisVectors(Vector *u, Vector *v);
struct { struct {
bool drawing; bool drawing;
Point2d mp; Point2d mp;

View File

@ -21,7 +21,7 @@ void SolveSpace::Init(void) {
g.h = Group::HGROUP_REFERENCES; g.h = Group::HGROUP_REFERENCES;
group.Add(&g); group.Add(&g);
g.csys = Entity::NO_CSYS; g.csys.v = Request::HREQUEST_REFERENCE_XY.v << 10;
g.name.strcpy(""); g.name.strcpy("");
group.AddAndAssignId(&g); group.AddAndAssignId(&g);

View File

@ -12,8 +12,13 @@
#define max(x, y) ((x) > (y) ? (x) : (y)) #define max(x, y) ((x) > (y) ? (x) : (y))
#endif #endif
class Expr;
void dbp(char *str, ...); void dbp(char *str, ...);
void Error(char *str, ...); void Error(char *str, ...);
Expr *AllocExpr(void);
void FreeAllExprs(void);
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
@ -22,7 +27,6 @@ void Error(char *str, ...);
#include <gl/gl.h> #include <gl/gl.h>
#include <gl/glu.h> #include <gl/glu.h>
class Expr;
#include "dsc.h" #include "dsc.h"
#include "sketch.h" #include "sketch.h"
#include "ui.h" #include "ui.h"
@ -58,6 +62,9 @@ public:
IdList<Point,hPoint> point; IdList<Point,hPoint> point;
IdList<Param,hParam> param; IdList<Param,hParam> param;
inline Entity *GetEntity(hEntity h) { return entity.FindById(h); }
inline Param *GetParam (hParam h) { return param. FindById(h); }
hGroup activeGroup; hGroup activeGroup;
void GenerateAll(void); void GenerateAll(void);

View File

@ -208,7 +208,7 @@ void TextWindow::ShowHeader(void) {
Printf(""); Printf("");
} else { } else {
// Navigation buttons // Navigation buttons
Printf(" %Lb%f<<%E %Lh%fhome%E group:%s", Printf(" %Lb%f<<%E %Lh%fhome%E %C4 group:%s",
(DWORD)(&TextWindow::ScreenNavigaton), (DWORD)(&TextWindow::ScreenNavigaton),
(DWORD)(&TextWindow::ScreenNavigaton), (DWORD)(&TextWindow::ScreenNavigaton),
SS.group.FindById(SS.GW.activeGroup)->DescriptionString()); SS.group.FindById(SS.GW.activeGroup)->DescriptionString());
@ -245,7 +245,7 @@ void TextWindow::ShowHeader(void) {
} }
void TextWindow::ShowGroupList(void) { void TextWindow::ShowGroupList(void) {
Printf("%C8[[click group to view requests]]%E"); Printf("%C8[[all groups in sketch follow]]%E");
int i; int i;
for(i = 0; i <= SS.group.elems; i++) { for(i = 0; i <= SS.group.elems; i++) {
DWORD v; DWORD v;
@ -275,6 +275,17 @@ void TextWindow::ShowRequestList(void) {
Printf("%C8[[requests in all groups]]%E"); Printf("%C8[[requests in all groups]]%E");
} else { } else {
Group *g = SS.group.FindById(shown->group); Group *g = SS.group.FindById(shown->group);
if(SS.GW.activeGroup.v == shown->group.v) {
Printf("%C8[[this is the active group]]");
} else {
Printf("%C8[[not active; %Llactivate this group%E%C8]]");
}
if(g->csys.v == Entity::NO_CSYS.v) {
Printf("[[points may go anywhere in 3d]]");
} else {
Printf("[[locked into plane %s]]",
SS.request.FindById(g->csys.request())->DescriptionString());
}
Printf("%C8[[requests in group %s]]%E", g->DescriptionString()); Printf("%C8[[requests in group %s]]%E", g->DescriptionString());
} }

View File

@ -53,6 +53,27 @@ void Error(char *str, ...)
MessageBox(h, buf, "SolveSpace Error", MB_OK | MB_ICONERROR); MessageBox(h, buf, "SolveSpace Error", MB_OK | MB_ICONERROR);
} }
//-----------------------------------------------------------------------------
// A separate heap, on which we allocate expressions. Maybe a bit faster,
// since no fragmentation issues whatsoever, and it also makes it possible
// to be sloppy with our memory management, and just free everything at once
// at the end.
//-----------------------------------------------------------------------------
static HANDLE Heap;
Expr *AllocExpr(void)
{
Expr *v = (Expr *)HeapAlloc(Heap, HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY,
sizeof(Expr));
if(!v) oops();
memset(v, 0, sizeof(*v));
return v;
}
void FreeAllExprs(void)
{
if(Heap) HeapDestroy(Heap);
Heap = HeapCreate(HEAP_NO_SERIALIZE, 1024*1024*20, 0);
}
static void PaintTextWnd(HDC hdc) static void PaintTextWnd(HDC hdc)
{ {
RECT rect; RECT rect;
@ -104,9 +125,18 @@ static void PaintTextWnd(HDC hdc)
} else { } else {
SelectObject(backDc, FixedFont); SelectObject(backDc, FixedFont);
} }
TextOut(backDc, 4 + c*TEXT_WIDTH,
(r-TextWndScrollPos)*TEXT_HEIGHT + 1, int x = 4 + c*TEXT_WIDTH;
(char *)&(SS.TW.text[r][c]), 1); int y = (r-TextWndScrollPos)*TEXT_HEIGHT + 1 + (r >= 3 ? 9 : 0);
HBRUSH b = CreateSolidBrush(SS.TW.colors[color].bg);
RECT a;
a.left = x; a.right = x+TEXT_WIDTH;
a.top = y; a.bottom = y+TEXT_HEIGHT;
FillRect(backDc, &a, b);
DeleteObject(b);
TextOut(backDc, x, y, (char *)&(SS.TW.text[r][c]), 1);
} }
} }
@ -166,6 +196,7 @@ LRESULT CALLBACK TextWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
case WM_SIZING: { case WM_SIZING: {
RECT *r = (RECT *)lParam; RECT *r = (RECT *)lParam;
int hc = (r->bottom - r->top) - ClientIsSmallerBy; int hc = (r->bottom - r->top) - ClientIsSmallerBy;
hc += TEXT_HEIGHT/2;
int extra = hc % TEXT_HEIGHT; int extra = hc % TEXT_HEIGHT;
switch(wParam) { switch(wParam) {
case WMSZ_BOTTOM: case WMSZ_BOTTOM:
@ -526,6 +557,9 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
if(!LinkFont) if(!LinkFont)
LinkFont = (HFONT)GetStockObject(SYSTEM_FONT); LinkFont = (HFONT)GetStockObject(SYSTEM_FONT);
// Create the heap that we use to store Exprs.
FreeAllExprs();
// Call in to the platform-independent code, and let them do their init // Call in to the platform-independent code, and let them do their init
SS.Init(); SS.Init();