Add a convenience command to draw a rectangle (as four line

segments), add the toggle construction command, and color the lines
differently depending on what group you're in.

Also change dynamic memory stuff to use a Win32 heap for everything
(no malloc), and validate that often. I think I've seen it crash,
though I can't reproduce it.

[git-p4: depot-paths = "//depot/solvespace/": change = 1708]
This commit is contained in:
Jonathan Westhues 2008-05-06 20:17:29 -08:00
parent c767d55c71
commit 6b264a6ba6
11 changed files with 119 additions and 17 deletions

View File

@ -18,12 +18,23 @@ void Constraint::ConstrainCoincident(hEntity ptA, hEntity ptB) {
memset(&c, 0, sizeof(c)); memset(&c, 0, sizeof(c));
c.group = SS.GW.activeGroup; c.group = SS.GW.activeGroup;
c.workplane = SS.GW.activeWorkplane; c.workplane = SS.GW.activeWorkplane;
c.type = Constraint::POINTS_COINCIDENT; c.type = POINTS_COINCIDENT;
c.ptA = ptA; c.ptA = ptA;
c.ptB = ptB; c.ptB = ptB;
AddConstraint(&c); AddConstraint(&c);
} }
void Constraint::ConstrainHorizVert(bool horiz, hEntity ls) {
Constraint c;
memset(&c, 0, sizeof(c));
c.group = SS.GW.activeGroup;
c.workplane = SS.GW.activeWorkplane;
if(c.workplane.v == Entity::FREE_IN_3D.v) oops();
c.type = (horiz ? HORIZONTAL : VERTICAL);
c.entityA = ls;
AddConstraint(&c);
}
void Constraint::MenuConstrain(int id) { void Constraint::MenuConstrain(int id) {
Constraint c; Constraint c;
memset(&c, 0, sizeof(c)); memset(&c, 0, sizeof(c));

View File

@ -31,6 +31,8 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) {
// If the group is hidden, then the constraints are hidden and not // If the group is hidden, then the constraints are hidden and not
// able to be selected. // able to be selected.
if(!(g->visible)) return; if(!(g->visible)) return;
// And likewise if the group is not the active group.
if(g->h.v != SS.GW.activeGroup.v) return;
// Unit vectors that describe our current view of the scene. One pixel // Unit vectors that describe our current view of the scene. One pixel
// long, not one actual unit. // long, not one actual unit.

2
dsc.h
View File

@ -159,7 +159,7 @@ public:
void Clear(void) { void Clear(void) {
elemsAllocated = n = 0; elemsAllocated = n = 0;
if(elem) free(elem); if(elem) MemFree(elem);
elem = NULL; elem = NULL;
} }

View File

@ -288,7 +288,7 @@ void Entity::LineDrawOrGetDistance(Vector a, Vector b) {
void Entity::LineDrawOrGetDistanceOrEdge(Vector a, Vector b) { void Entity::LineDrawOrGetDistanceOrEdge(Vector a, Vector b) {
LineDrawOrGetDistance(a, b); LineDrawOrGetDistance(a, b);
if(dogd.edges) { if(dogd.edges && !construction) {
SEdge edge; SEdge edge;
edge.a = a; edge.b = b; edge.a = a; edge.b = b;
dogd.edges->l.Add(&edge); dogd.edges->l.Add(&edge);
@ -325,7 +325,13 @@ void Entity::DrawOrGetDistance(int order) {
// contribute a distance for the selection, but it still generates edges. // contribute a distance for the selection, but it still generates edges.
if(!(g->visible) && !dogd.edges) return; if(!(g->visible) && !dogd.edges) return;
if(group.v != SS.GW.activeGroup.v) {
glxColor3d(0.5, 0.3, 0.0);
} else if(construction) {
glxColor3d(0.1, 0.7, 0.1);
} else {
glxColor3d(1, 1, 1); glxColor3d(1, 1, 1);
}
switch(type) { switch(type) {
case POINT_XFRMD: case POINT_XFRMD:

View File

@ -67,6 +67,7 @@ const SolveSpace::SaveTable SolveSpace::SAVED[] = {
{ 'e', "Entity.h.v", 'x', &(SS.sv.e.h.v) }, { 'e', "Entity.h.v", 'x', &(SS.sv.e.h.v) },
{ 'e', "Entity.type", 'd', &(SS.sv.e.type) }, { 'e', "Entity.type", 'd', &(SS.sv.e.type) },
{ 'e', "Entity.group.v", 'x', &(SS.sv.e.group.v) }, { 'e', "Entity.group.v", 'x', &(SS.sv.e.group.v) },
{ 'e', "Entity.construction", 'b', &(SS.sv.e.construction) },
{ 'e', "Entity.param[0].v", 'x', &(SS.sv.e.param[0].v) }, { 'e', "Entity.param[0].v", 'x', &(SS.sv.e.param[0].v) },
{ 'e', "Entity.param[1].v", 'x', &(SS.sv.e.param[1].v) }, { 'e', "Entity.param[1].v", 'x', &(SS.sv.e.param[1].v) },
{ 'e', "Entity.param[2].v", 'x', &(SS.sv.e.param[2].v) }, { 'e', "Entity.param[2].v", 'x', &(SS.sv.e.param[2].v) },

View File

@ -65,7 +65,7 @@ const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = {
{ 1, "Sym&bolic Variable\tB", 0, 'B', mReq }, { 1, "Sym&bolic Variable\tB", 0, 'B', mReq },
{ 1, "&Import From File...\tI", 0, 'I', mReq }, { 1, "&Import From File...\tI", 0, 'I', mReq },
{ 1, NULL, 0, NULL }, { 1, NULL, 0, NULL },
{ 1, "To&ggle Construction\tG", 0, 'G', NULL }, { 1, "To&ggle Construction\tG", MNU_CONSTRUCTION, 'G', mReq },
{ 0, "&Constrain", 0, NULL }, { 0, "&Constrain", 0, NULL },
{ 1, "&Distance / Diameter\tShift+D", MNU_DISTANCE_DIA, 'D'|S, mCon }, { 1, "&Distance / Diameter\tShift+D", MNU_DISTANCE_DIA, 'D'|S, mCon },
@ -346,12 +346,27 @@ void GraphicsWindow::MenuRequest(int id) {
case MNU_CUBIC: s = "click first point of cubic segment"; goto c; case MNU_CUBIC: s = "click first point of cubic segment"; goto c;
case MNU_CIRCLE: s = "click center of circle"; goto c; case MNU_CIRCLE: s = "click center of circle"; goto c;
case MNU_WORKPLANE: s = "click origin of workplane"; goto c; case MNU_WORKPLANE: s = "click origin of workplane"; goto c;
case MNU_RECTANGLE: s = "click one corner of rectangular"; goto c;
c: c:
SS.GW.pending.operation = id; SS.GW.pending.operation = id;
SS.GW.pending.description = s; SS.GW.pending.description = s;
SS.TW.Show(); SS.TW.Show();
break; break;
case MNU_CONSTRUCTION: {
SS.GW.GroupSelection();
int i;
for(i = 0; i < SS.GW.gs.entities; i++) {
hEntity he = SS.GW.gs.entity[i];
if(!he.isFromRequest()) continue;
Request *r = SS.GetRequest(he.request());
r->construction = !(r->construction);
}
SS.GW.ClearSelection();
SS.GenerateAll(SS.GW.solving == GraphicsWindow::SOLVE_ALWAYS);
break;
}
default: oops(); default: oops();
} }
} }
@ -687,6 +702,27 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
SS.GetEntity(pending.point)->PointForceTo(v); SS.GetEntity(pending.point)->PointForceTo(v);
break; break;
case MNU_RECTANGLE: {
hRequest lns[4];
int i;
for(i = 0; i < 4; i++) {
lns[i] = AddRequest(Request::LINE_SEGMENT);
}
for(i = 0; i < 4; i++) {
Constraint::ConstrainCoincident(
lns[i].entity(1), lns[(i+1)%4].entity(2));
SS.GetEntity(lns[i].entity(1))->PointForceTo(v);
SS.GetEntity(lns[i].entity(2))->PointForceTo(v);
}
for(i = 0; i < 4; i++) {
Constraint::ConstrainHorizVert((i % 2)==0, lns[i].entity(0));
}
pending.operation = DRAGGING_NEW_POINT;
pending.point = lns[1].entity(2);
pending.description = "click to place other corner of rectangle";
break;
}
case MNU_CIRCLE: case MNU_CIRCLE:
hr = AddRequest(Request::CIRCLE); hr = AddRequest(Request::CIRCLE);
SS.GetEntity(hr.entity(1))->PointForceTo(v); SS.GetEntity(hr.entity(1))->PointForceTo(v);

View File

@ -55,15 +55,17 @@ char *Group::DescriptionString(void) {
void Group::Generate(IdList<Entity,hEntity> *entity, void Group::Generate(IdList<Entity,hEntity> *entity,
IdList<Param,hParam> *param) IdList<Param,hParam> *param)
{ {
Vector gn = (SS.GW.projRight).Cross(SS.GW.projUp);
gn = gn.WithMagnitude(200/SS.GW.scale);
int i; int i;
switch(type) { switch(type) {
case DRAWING: case DRAWING:
return; return;
case EXTRUDE: case EXTRUDE:
AddParam(param, h.param(0), 50); AddParam(param, h.param(0), gn.x);
AddParam(param, h.param(1), 50); AddParam(param, h.param(1), gn.y);
AddParam(param, h.param(2), 50); AddParam(param, h.param(2), gn.z);
for(i = 0; i < entity->n; i++) { for(i = 0; i < entity->n; i++) {
Entity *e = &(entity->elem[i]); Entity *e = &(entity->elem[i]);
if(e->group.v != opA.v) continue; if(e->group.v != opA.v) continue;
@ -138,8 +140,12 @@ void Group::CopyEntity(hEntity in, int a, hParam dx, hParam dy, hParam dz,
if(isExtrusion) { if(isExtrusion) {
if(a != 0) oops(); if(a != 0) oops();
SS.entity.Add(&en); SS.entity.Add(&en);
hEntity np = en.h;
memset(&en, 0, sizeof(en));
en.point[0] = ep->h; en.point[0] = ep->h;
en.point[1] = en.h; en.point[1] = np;
en.group = h;
en.h = Remap(ep->h, 1); en.h = Remap(ep->h, 1);
en.type = Entity::LINE_SEGMENT; en.type = Entity::LINE_SEGMENT;
// And then this line segment gets added // And then this line segment gets added
@ -160,6 +166,10 @@ void Group::CopyEntity(hEntity in, int a, hParam dx, hParam dy, hParam dz,
} }
void Group::MakePolygons(void) { void Group::MakePolygons(void) {
int i;
for(i = 0; i < faces.n; i++) {
(faces.elem[i]).Clear();
}
faces.Clear(); faces.Clear();
if(type == DRAWING) { if(type == DRAWING) {
edges.l.Clear(); edges.l.Clear();
@ -332,6 +342,7 @@ void Request::Generate(IdList<Entity,hEntity> *entity,
e.type = et; e.type = et;
e.group = group; e.group = group;
e.workplane = workplane; e.workplane = workplane;
e.construction = construction;
e.h = h.entity(0); e.h = h.entity(0);
// And generate entities for the points // And generate entities for the points

View File

@ -188,10 +188,15 @@ public:
hGroup group; hGroup group;
hEntity workplane; // or Entity::FREE_IN_3D hEntity workplane; // or Entity::FREE_IN_3D
bool construction;
// For entities that are derived by a transformation, the number of // For entities that are derived by a transformation, the number of
// times to apply the transformation. // times to apply the transformation.
int timesApplied; int timesApplied;
bool HasDirection(void);
ExprVector GetDirection(void);
bool IsWorkplane(void); bool IsWorkplane(void);
// The plane is points P such that P dot (xn, yn, zn) - d = 0 // The plane is points P such that P dot (xn, yn, zn) - d = 0
void WorkplaneGetPlaneExprs(ExprVector *n, Expr **d); void WorkplaneGetPlaneExprs(ExprVector *n, Expr **d);
@ -349,6 +354,7 @@ public:
static ExprVector PointInThreeSpace(hEntity workplane, Expr *u, Expr *v); static ExprVector PointInThreeSpace(hEntity workplane, Expr *u, Expr *v);
static void ConstrainCoincident(hEntity ptA, hEntity ptB); static void ConstrainCoincident(hEntity ptA, hEntity ptB);
static void ConstrainHorizVert(bool horiz, hEntity lineSegment);
}; };
class hEquation { class hEquation {

View File

@ -55,6 +55,7 @@ void FreeAllTemporary(void);
void *MemRealloc(void *p, int n); void *MemRealloc(void *p, int n);
void *MemAlloc(int n); void *MemAlloc(int n);
void MemFree(void *p); void MemFree(void *p);
void vl(void); // debug function to validate
#include "dsc.h" #include "dsc.h"

1
ui.h
View File

@ -107,6 +107,7 @@ public:
MNU_CIRCLE, MNU_CIRCLE,
MNU_RECTANGLE, MNU_RECTANGLE,
MNU_CUBIC, MNU_CUBIC,
MNU_CONSTRUCTION,
// Group // Group
MNU_GROUP_DRAWING, MNU_GROUP_DRAWING,
MNU_GROUP_EXTRUDE, MNU_GROUP_EXTRUDE,

View File

@ -62,23 +62,48 @@ void Error(char *str, ...)
// to be sloppy with our memory management, and just free everything at once // to be sloppy with our memory management, and just free everything at once
// at the end. // at the end.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static HANDLE Heap; static HANDLE Temp;
void *AllocTemporary(int n) void *AllocTemporary(int n)
{ {
Expr *v = (Expr *)HeapAlloc(Heap, HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY, n); void *v = HeapAlloc(Temp, HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY, n);
if(!v) oops(); if(!v) oops();
memset(v, 0, n);
return v; return v;
} }
void FreeAllTemporary(void) void FreeAllTemporary(void)
{ {
if(Heap) HeapDestroy(Heap); if(Temp) HeapDestroy(Temp);
Heap = HeapCreate(HEAP_NO_SERIALIZE, 1024*1024*20, 0); Temp = HeapCreate(HEAP_NO_SERIALIZE, 1024*1024*20, 0);
// This is a good place to validate, because it gets called fairly
// often.
vl();
} }
void *MemRealloc(void *p, int n) { return realloc(p, n); } static HANDLE Perm;
void *MemAlloc(int n) { return malloc(n); } void *MemRealloc(void *p, int n) {
void MemFree(void *p) { free(p); } if(!p) {
return MemAlloc(n);
}
p = HeapReAlloc(Perm, HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY, p, n);
vl();
if(!p) oops();
return p;
}
void *MemAlloc(int n) {
void *p = HeapAlloc(Perm, HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY, n);
vl();
if(!p) oops();
return p;
}
void MemFree(void *p) {
HeapFree(Perm, HEAP_NO_SERIALIZE, p);
vl();
}
void vl(void) {
if(!HeapValidate(Temp, HEAP_NO_SERIALIZE, NULL)) oops();
if(!HeapValidate(Perm, HEAP_NO_SERIALIZE, NULL)) oops();
}
static void PaintTextWnd(HDC hdc) static void PaintTextWnd(HDC hdc)
{ {
@ -750,6 +775,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
ThawWindowPos(TextWnd); ThawWindowPos(TextWnd);
ThawWindowPos(GraphicsWnd); ThawWindowPos(GraphicsWnd);
// Create the heap used for long-lived stuff (that gets freed piecewise).
Perm = HeapCreate(HEAP_NO_SERIALIZE, 1024*1024*20, 0);
// Create the heap that we use to store Exprs and other temp stuff. // Create the heap that we use to store Exprs and other temp stuff.
FreeAllTemporary(); FreeAllTemporary();