diff --git a/file.cpp b/file.cpp index 64cc6c1..2362b15 100644 --- a/file.cpp +++ b/file.cpp @@ -308,6 +308,9 @@ bool SolveSpace::LoadFromFile(char *filename) { return false; } + UndoClearStack(&redo); + UndoClearStack(&undo); + constraint.Clear(); request.Clear(); group.Clear(); diff --git a/graphicswin.cpp b/graphicswin.cpp index 95409c1..a4a2e9c 100644 --- a/graphicswin.cpp +++ b/graphicswin.cpp @@ -1,5 +1,3 @@ -#include - #include "solvespace.h" #define mView (&GraphicsWindow::MenuView) @@ -64,8 +62,6 @@ const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = { { 1, "&Arc of a Circle\tA", MNU_ARC, 'A', mReq }, { 1, "&Cubic Segment\t3", MNU_CUBIC, '3', mReq }, { 1, NULL, 0, NULL }, -{ 1, "Sym&bolic Variable\tB", 0, 'B', mReq }, -{ 1, NULL, 0, NULL }, { 1, "To&ggle Construction\tG", MNU_CONSTRUCTION, 'G', mReq }, { 0, "&Constrain", 0, NULL }, @@ -85,8 +81,6 @@ const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = { { 1, "Para&llel\tShift+L", MNU_PARALLEL, 'L'|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 }, { 1, "Solve Once Now\tSpace", MNU_SOLVE_NOW, ' ', mCon }, { 0, "&Help", 0, NULL }, @@ -97,10 +91,10 @@ const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = { void GraphicsWindow::Init(void) { memset(this, 0, sizeof(*this)); - offset.x = offset.y = offset.z = 0; scale = 5; - projRight.x = 1; projRight.y = projRight.z = 0; - projUp.y = 1; projUp.z = projUp.x = 0; + offset = Vector::From(0, 0, 0); + projRight = Vector::From(1, 0, 0); + projUp = Vector::From(0, 1, 0); // And with the latest visible group active, or failing that the first // group after the references @@ -238,6 +232,7 @@ void GraphicsWindow::ZoomToFit(void) { if(dy != 0) scaley = 0.9*height/dy; scale = min(100, min(scalex, scaley)); } + scale = max(0.001, scale); } void GraphicsWindow::MenuView(int id) { diff --git a/sketch.h b/sketch.h index d238913..04fa75b 100644 --- a/sketch.h +++ b/sketch.h @@ -407,7 +407,6 @@ class Constraint { public: static const hConstraint NO_CONSTRAINT; - static const int USER_EQUATION = 10; static const int POINTS_COINCIDENT = 20; static const int PT_PT_DISTANCE = 30; static const int PT_PLANE_DISTANCE = 31; diff --git a/solvespace.cpp b/solvespace.cpp index 55e81a6..8490107 100644 --- a/solvespace.cpp +++ b/solvespace.cpp @@ -98,6 +98,12 @@ void SolveSpace::AfterNewFile(void) { unsaved = false; GenerateAll(0, INT_MAX); later.showTW = true; + + int w, h; + GetGraphicsWindowSize(&w, &h); + GW.width = w; + GW.height = h; + GW.ZoomToFit(); } void SolveSpace::MarkGroupDirtyByEntity(hEntity he) { diff --git a/solvespace.h b/solvespace.h index dd0012a..8e4253a 100644 --- a/solvespace.h +++ b/solvespace.h @@ -71,6 +71,7 @@ void ShowTextWindow(BOOL visible); void InvalidateText(void); void InvalidateGraphics(void); void PaintGraphics(void); +void GetGraphicsWindowSize(int *w, int *h); SDWORD GetMilliseconds(void); void dbp(char *str, ...); diff --git a/textwin.cpp b/textwin.cpp index 55fd1ea..c4780cb 100644 --- a/textwin.cpp +++ b/textwin.cpp @@ -237,7 +237,8 @@ void TextWindow::DescribeSelection(void) { if(gs.n == 1 && (gs.points == 1 || gs.entities == 1)) { e = SS.GetEntity(gs.points == 1 ? gs.point[0] : gs.entity[0]); -#define COP SS.GW.ToString(p.x), SS.GW.ToString(p.y), SS.GW.ToString(p.z) +#define COSTR(p) \ + SS.GW.ToString((p).x), SS.GW.ToString((p).y), SS.GW.ToString((p).z) #define PT_AS_STR "(%Fi%s%E, %Fi%s%E, %Fi%s%E)" #define PT_AS_NUM "(%Fi%3%E, %Fi%3%E, %Fi%3%E)" switch(e->type) { @@ -248,7 +249,7 @@ void TextWindow::DescribeSelection(void) { case Entity::POINT_N_COPY: case Entity::POINT_N_ROT_AA: p = e->PointGetNum(); - Printf(false, "%FtPOINT%E at " PT_AS_STR, COP); + Printf(false, "%FtPOINT%E at " PT_AS_STR, COSTR(p)); break; case Entity::NORMAL_IN_3D: @@ -259,7 +260,7 @@ void TextWindow::DescribeSelection(void) { Quaternion q = e->NormalGetNum(); p = q.RotationN(); Printf(false, "%FtNORMAL / COORDINATE SYSTEM%E"); - Printf(true, " basis n = " PT_AS_NUM, CO(p)); + Printf(true, " basis n = " PT_AS_NUM, CO(p)); p = q.RotationU(); Printf(false, " u = " PT_AS_NUM, CO(p)); p = q.RotationV(); @@ -269,7 +270,7 @@ void TextWindow::DescribeSelection(void) { case Entity::WORKPLANE: { p = SS.GetEntity(e->point[0])->PointGetNum(); Printf(false, "%FtWORKPLANE%E"); - Printf(true, " origin = " PT_AS_STR, COP); + Printf(true, " origin = " PT_AS_STR, COSTR(p)); Quaternion q = e->Normal()->NormalGetNum(); p = q.RotationN(); Printf(true, " normal = " PT_AS_NUM, CO(p)); @@ -279,30 +280,30 @@ void TextWindow::DescribeSelection(void) { Vector p0 = SS.GetEntity(e->point[0])->PointGetNum(); p = p0; Printf(false, "%FtLINE SEGMENT%E"); - Printf(true, " thru " PT_AS_STR, COP); + Printf(true, " thru " PT_AS_STR, COSTR(p)); Vector p1 = SS.GetEntity(e->point[1])->PointGetNum(); p = p1; - Printf(false, " " PT_AS_STR, COP); + Printf(false, " " PT_AS_STR, COSTR(p)); Printf(true, " len = %Fi%s%E", SS.GW.ToString((p1.Minus(p0).Magnitude()))); break; } case Entity::CUBIC: - p = SS.GetEntity(e->point[0])->PointGetNum(); Printf(false, "%FtCUBIC BEZIER CURVE%E"); for(i = 0; i <= 3; i++) { p = SS.GetEntity(e->point[i])->PointGetNum(); - Printf((i==0), " p%c = " PT_AS_STR, '0'+i, COP); + Printf((i==0), " p%c = " PT_AS_STR, '0'+i, COSTR(p)); } break; + case Entity::ARC_OF_CIRCLE: { Printf(false, "%FtARC OF A CIRCLE%E"); p = SS.GetEntity(e->point[0])->PointGetNum(); - Printf(true, " center = " PT_AS_STR, COP); + Printf(true, " center = " PT_AS_STR, COSTR(p)); p = SS.GetEntity(e->point[1])->PointGetNum(); - Printf(true," endpoints = " PT_AS_STR, COP); + Printf(true, " endpoints = " PT_AS_STR, COSTR(p)); p = SS.GetEntity(e->point[2])->PointGetNum(); - Printf(false," " PT_AS_STR, COP); + Printf(false, " " PT_AS_STR, COSTR(p)); double r = e->CircleGetRadiusNum(); Printf(true, " diameter = %Fi%s", SS.GW.ToString(r*2)); Printf(false, " radius = %Fi%s", SS.GW.ToString(r)); @@ -311,9 +312,9 @@ void TextWindow::DescribeSelection(void) { case Entity::CIRCLE: { Printf(false, "%FtCIRCLE%E"); p = SS.GetEntity(e->point[0])->PointGetNum(); - Printf(true, " center = " PT_AS_STR, COP); + Printf(true, " center = " PT_AS_STR, COSTR(p)); double r = e->CircleGetRadiusNum(); - Printf(true, " diameter = %Fi%s", SS.GW.ToString(r*2)); + Printf(true, " diameter = %Fi%s", SS.GW.ToString(r*2)); Printf(false, " radius = %Fi%s", SS.GW.ToString(r)); break; } @@ -321,10 +322,10 @@ void TextWindow::DescribeSelection(void) { case Entity::FACE_XPROD: case Entity::FACE_N_ROT_TRANS: Printf(false, "%FtPLANE FACE%E"); - p = e->FaceGetPointNum(); - Printf(true, " through = " PT_AS_STR, COP); p = e->FaceGetNormalNum(); - Printf(false, " normal = " PT_AS_STR, COP); + Printf(true, " normal = " PT_AS_NUM, CO(p)); + p = e->FaceGetPointNum(); + Printf(false, " thru = " PT_AS_STR, COSTR(p)); break; default: @@ -343,12 +344,33 @@ void TextWindow::DescribeSelection(void) { } } else if(gs.n == 2 && gs.points == 2) { Printf(false, "%FtTWO POINTS"); - Vector p0 = SS.GetEntity(gs.point[0])->PointGetNum(); p = p0; - Printf(true, " at " PT_AS_STR, COP); - Vector p1 = SS.GetEntity(gs.point[1])->PointGetNum(); p = p1; - Printf(false, " " PT_AS_STR, COP); + Vector p0 = SS.GetEntity(gs.point[0])->PointGetNum(); + Printf(true, " at " PT_AS_STR, COSTR(p0)); + Vector p1 = SS.GetEntity(gs.point[1])->PointGetNum(); + Printf(false, " " PT_AS_STR, COSTR(p1)); double d = (p1.Minus(p0)).Magnitude(); Printf(true, " d = %Fi%s", SS.GW.ToString(d)); + } else if(gs.n == 2 && gs.faces == 1 && gs.points == 1) { + Printf(false, "%FtA POINT AND A PLANE FACE"); + Vector pt = SS.GetEntity(gs.point[0])->PointGetNum(); + Printf(true, " point = " PT_AS_STR, COSTR(pt)); + Vector n = SS.GetEntity(gs.face[0])->FaceGetNormalNum(); + Printf(true, " plane normal = " PT_AS_NUM, CO(n)); + Vector pl = SS.GetEntity(gs.face[0])->FaceGetPointNum(); + Printf(false, " plane thru = " PT_AS_STR, COSTR(pl)); + double dd = n.Dot(pl) - n.Dot(pt); + Printf(true, " distance = %Fi%s", SS.GW.ToString(dd)); + } else if(gs.n == 3 && gs.points == 2 && gs.vectors == 1) { + Printf(false, "%FtTWO POINTS AND A VECTOR"); + Vector p0 = SS.GetEntity(gs.point[0])->PointGetNum(); + Printf(true, " pointA = " PT_AS_STR, COSTR(p0)); + Vector p1 = SS.GetEntity(gs.point[1])->PointGetNum(); + Printf(false, " pointB = " PT_AS_STR, COSTR(p1)); + Vector v = SS.GetEntity(gs.vector[0])->VectorGetNum(); + v = v.WithMagnitude(1); + Printf(true, " vector = " PT_AS_NUM, CO(v)); + double d = (p1.Minus(p0)).Dot(v); + Printf(true, " proj_d = %Fi%s", SS.GW.ToString(d)); } else { Printf(true, "%FtSELECTED:%E %d item%s", gs.n, gs.n == 1 ? "" : "s"); } diff --git a/win32/w32main.cpp b/win32/w32main.cpp index 89f8e49..5ff0208 100644 --- a/win32/w32main.cpp +++ b/win32/w32main.cpp @@ -504,12 +504,17 @@ void InvalidateGraphics(void) { InvalidateRect(GraphicsWnd, NULL, FALSE); } -void PaintGraphics(void) +void GetGraphicsWindowSize(int *w, int *h) { RECT r; GetClientRect(GraphicsWnd, &r); - int w = r.right - r.left; - int h = r.bottom - r.top; + *w = r.right - r.left; + *h = r.bottom - r.top; +} +void PaintGraphics(void) +{ + int w, h; + GetGraphicsWindowSize(&w, &h); SS.GW.Paint(w, h); SwapBuffers(GetDC(GraphicsWnd)); diff --git a/wishlist.txt b/wishlist.txt index d65ffe8..b1b0ee3 100644 --- a/wishlist.txt +++ b/wishlist.txt @@ -5,9 +5,9 @@ DXF export partitioned subsystems in the solver TTF font text display with proper formatting/units -more measurements some kind of rounding / chamfer remove back button in browser? clean up user-created workplanes incremental regen of entities? +graphic export