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:
parent
c767d55c71
commit
6b264a6ba6
@ -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));
|
||||||
|
@ -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
2
dsc.h
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
10
entity.cpp
10
entity.cpp
@ -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;
|
||||||
|
|
||||||
glxColor3d(1, 1, 1);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case POINT_XFRMD:
|
case POINT_XFRMD:
|
||||||
|
1
file.cpp
1
file.cpp
@ -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) },
|
||||||
|
@ -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);
|
||||||
|
19
sketch.cpp
19
sketch.cpp
@ -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
|
||||||
|
6
sketch.h
6
sketch.h
@ -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 {
|
||||||
|
@ -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
1
ui.h
@ -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,
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user