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
parent
b6bf07ac2c
commit
094e10204d
1
Makefile
1
Makefile
|
@ -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
|
||||||
|
|
19
entity.cpp
19
entity.cpp
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
25
expr.h
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
36
sketch.cpp
36
sketch.cpp
|
@ -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) {
|
||||||
|
|
2
sketch.h
2
sketch.h
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
15
textwin.cpp
15
textwin.cpp
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue