Add code to assemble the piecewise linear segments in a group into

a polygon, and to fill that polygon.

[git-p4: depot-paths = "//depot/solvespace/": change = 1686]
solver
Jonathan Westhues 2008-04-24 23:04:09 -08:00
parent 1331457928
commit a7cec38656
13 changed files with 264 additions and 25 deletions

View File

@ -21,6 +21,7 @@ SSOBJS = $(OBJDIR)\solvespace.obj \
$(OBJDIR)\drawconstraint.obj \ $(OBJDIR)\drawconstraint.obj \
$(OBJDIR)\file.obj \ $(OBJDIR)\file.obj \
$(OBJDIR)\system.obj \ $(OBJDIR)\system.obj \
$(OBJDIR)\polygon.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

@ -33,7 +33,7 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) {
Vector gu = SS.GW.projUp; Vector gu = SS.GW.projUp;
Vector gn = gr.Cross(gu); Vector gn = gr.Cross(gu);
glxColor(1, 0.2, 1); glxColor3d(1, 0.2, 1);
switch(type) { switch(type) {
case PT_PT_DISTANCE: { case PT_PT_DISTANCE: {
Vector ap = SS.GetEntity(ptA)->PointGetCoords(); Vector ap = SS.GetEntity(ptA)->PointGetCoords();
@ -86,7 +86,7 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) {
for(int i = 0; i < 2; i++) { for(int i = 0; i < 2; i++) {
Vector p = SS.GetEntity(i == 0 ? ptA : ptB)-> Vector p = SS.GetEntity(i == 0 ? ptA : ptB)->
PointGetCoords(); PointGetCoords();
glxColor(0.4, 0, 0.4); glxColor3d(0.4, 0, 0.4);
glBegin(GL_QUADS); glBegin(GL_QUADS);
glxVertex3v(p.Plus (r).Plus (d)); glxVertex3v(p.Plus (r).Plus (d));
glxVertex3v(p.Plus (r).Minus(d)); glxVertex3v(p.Plus (r).Minus(d));

1
dsc.h
View File

@ -33,6 +33,7 @@ public:
static Vector MakeFrom(double x, double y, double z); static Vector MakeFrom(double x, double y, double z);
bool Equals(Vector v);
Vector Plus(Vector b); Vector Plus(Vector b);
Vector Minus(Vector b); Vector Minus(Vector b);
Vector Negated(void); Vector Negated(void);

View File

@ -211,13 +211,31 @@ void Entity::LineDrawOrGetDistance(Vector a, Vector b) {
} }
} }
void Entity::LineDrawOrGetDistanceOrEdge(Vector a, Vector b) {
LineDrawOrGetDistance(a, b);
if(dogd.edges) {
SEdge edge;
edge.a = a; edge.b = b;
dogd.edges->l.Add(&edge);
}
}
void Entity::Draw(int order) { void Entity::Draw(int order) {
dogd.drawing = true; dogd.drawing = true;
dogd.edges = NULL;
DrawOrGetDistance(order); DrawOrGetDistance(order);
} }
void Entity::GenerateEdges(SEdgeList *el) {
dogd.drawing = false;
dogd.edges = el;
DrawOrGetDistance(-1);
dogd.edges = NULL;
}
double Entity::GetDistance(Point2d mp) { double Entity::GetDistance(Point2d mp) {
dogd.drawing = false; dogd.drawing = false;
dogd.edges = NULL;
dogd.mp = mp; dogd.mp = mp;
dogd.dmin = 1e12; dogd.dmin = 1e12;
@ -227,7 +245,7 @@ double Entity::GetDistance(Point2d mp) {
} }
void Entity::DrawOrGetDistance(int order) { void Entity::DrawOrGetDistance(int order) {
glxColor(1, 1, 1); glxColor3d(1, 1, 1);
switch(type) { switch(type) {
case POINT_IN_3D: case POINT_IN_3D:
@ -245,7 +263,7 @@ void Entity::DrawOrGetDistance(int order) {
Vector r = SS.GW.projRight.ScaledBy(s/SS.GW.scale); Vector r = SS.GW.projRight.ScaledBy(s/SS.GW.scale);
Vector d = SS.GW.projUp.ScaledBy(s/SS.GW.scale); Vector d = SS.GW.projUp.ScaledBy(s/SS.GW.scale);
glxColor(0, 0.8, 0); glxColor3d(0, 0.8, 0);
glBegin(GL_QUADS); glBegin(GL_QUADS);
glxVertex3v(v.Plus (r).Plus (d)); glxVertex3v(v.Plus (r).Plus (d));
glxVertex3v(v.Plus (r).Minus(d)); glxVertex3v(v.Plus (r).Minus(d));
@ -279,7 +297,7 @@ void Entity::DrawOrGetDistance(int order) {
Vector mm = p.Minus(us).Minus(vs); Vector mm = p.Minus(us).Minus(vs);
Vector mp = p.Minus(us).Plus (vs); Vector mp = p.Minus(us).Plus (vs);
glxColor(0, 0.4, 0.4); glxColor3d(0, 0.4, 0.4);
LineDrawOrGetDistance(pp, pm); LineDrawOrGetDistance(pp, pm);
LineDrawOrGetDistance(pm, mm); LineDrawOrGetDistance(pm, mm);
LineDrawOrGetDistance(mm, mp); LineDrawOrGetDistance(mm, mp);
@ -299,7 +317,7 @@ void Entity::DrawOrGetDistance(int order) {
if(order >= 0 && order != 1) break; if(order >= 0 && order != 1) break;
Vector a = SS.GetEntity(assoc[0])->PointGetCoords(); Vector a = SS.GetEntity(assoc[0])->PointGetCoords();
Vector b = SS.GetEntity(assoc[1])->PointGetCoords(); Vector b = SS.GetEntity(assoc[1])->PointGetCoords();
LineDrawOrGetDistance(a, b); LineDrawOrGetDistanceOrEdge(a, b);
break; break;
} }

View File

@ -60,7 +60,7 @@ void glxOntoCsys(Vector u, Vector v)
void glxLockColorTo(double r, double g, double b) void glxLockColorTo(double r, double g, double b)
{ {
ColorLocked = false; ColorLocked = false;
glxColor(r, g, b); glxColor3d(r, g, b);
ColorLocked = true; ColorLocked = true;
} }
@ -69,9 +69,45 @@ void glxUnlockColor(void)
ColorLocked = false; ColorLocked = false;
} }
void glxColor(double r, double g, double b) void glxColor3d(double r, double g, double b)
{ {
if(!ColorLocked) { if(!ColorLocked) glColor3d(r, g, b);
glColor3f((GLfloat)r, (GLfloat)g, (GLfloat)b);
}
} }
void glxColor4d(double r, double g, double b, double a)
{
if(!ColorLocked) glColor4d(r, g, b, a);
}
static void __stdcall Vertex(Vector *p) {
glxVertex3v(*p);
}
void glxFillPolygon(SPolygon *p)
{
int i, j;
GLUtesselator *gt = gluNewTess();
typedef void __stdcall cf(void);
gluTessCallback(gt, GLU_TESS_BEGIN, (cf *)glBegin);
gluTessCallback(gt, GLU_TESS_END, (cf *)glEnd);
gluTessCallback(gt, GLU_TESS_VERTEX, (cf *)Vertex);
gluTessProperty(gt, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
gluTessBeginPolygon(gt, NULL);
for(i = 0; i < p->l.n; i++) {
SContour *sc = &(p->l.elem[i]);
gluTessBeginContour(gt);
for(j = 0; j < (sc->l.n-1); j++) {
SPoint *sp = &(sc->l.elem[j]);
double ap[3];
ap[0] = sp->p.x;
ap[1] = sp->p.y;
ap[2] = sp->p.z;
gluTessVertex(gt, ap, &(sp->p));
}
gluTessEndContour(gt);
}
gluTessEndPolygon(gt);
gluDeleteTess(gt);
}

View File

@ -280,7 +280,21 @@ void GraphicsWindow::MenuEdit(int id) {
if(s->entity.v) { if(s->entity.v) {
r = s->entity.request(); r = s->entity.request();
} }
if(r.v && !r.IsFromReferences()) SS.request.Tag(r, 1); if(r.v && !r.IsFromReferences()) {
SS.request.Tag(r, 1);
int j;
for(j = 0; j < SS.constraint.n; j++) {
Constraint *c = &(SS.constraint.elem[j]);
if(((c->ptA).request().v == r.v) ||
((c->ptB).request().v == r.v) ||
((c->ptC).request().v == r.v) ||
((c->entityA).request().v == r.v) ||
((c->entityB).request().v == r.v))
{
SS.constraint.Tag(c->h, 1);
}
}
}
if(s->constraint.v) { if(s->constraint.v) {
SS.constraint.Tag(s->constraint, 1); SS.constraint.Tag(s->constraint, 1);
} }
@ -561,19 +575,22 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
hRequest hr; hRequest hr;
switch(pendingOperation) { switch(pendingOperation) {
case MNU_DATUM_POINT: case MNU_DATUM_POINT:
ClearSelection(); hover.Clear();
hr = AddRequest(Request::DATUM_POINT); hr = AddRequest(Request::DATUM_POINT);
SS.GetEntity(hr.entity(0))->PointForceTo(v); SS.GetEntity(hr.entity(0))->PointForceTo(v);
ClearSelection(); hover.Clear();
pendingOperation = 0; pendingOperation = 0;
break; break;
case MNU_LINE_SEGMENT: case MNU_LINE_SEGMENT:
ClearSelection(); hover.Clear();
hr = AddRequest(Request::LINE_SEGMENT); hr = AddRequest(Request::LINE_SEGMENT);
SS.GetEntity(hr.entity(1))->PointForceTo(v); SS.GetEntity(hr.entity(1))->PointForceTo(v);
if(hover.entity.v && SS.GetEntity(hover.entity)->IsPoint()) {
Constraint::ConstrainCoincident(hover.entity, hr.entity(1));
}
ClearSelection(); hover.Clear();
pendingOperation = DRAGGING_NEW_LINE_POINT; pendingOperation = DRAGGING_NEW_LINE_POINT;
pendingPoint = hr.entity(2); pendingPoint = hr.entity(2);
@ -776,6 +793,11 @@ void GraphicsWindow::Paint(int w, int h) {
SS.constraint.elem[i].Draw(); SS.constraint.elem[i].Draw();
} }
// Draw the groups; this fills the polygons, if requested.
for(i = 0; i < SS.group.n; i++) {
SS.group.elem[i].Draw();
}
// Then redraw whatever the mouse is hovering over, highlighted. // Then redraw whatever the mouse is hovering over, highlighted.
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glxLockColorTo(1, 1, 0); glxLockColorTo(1, 1, 0);

78
polygon.cpp Normal file
View File

@ -0,0 +1,78 @@
#include "solvespace.h"
bool SEdgeList::AssemblePolygon(SPolygon *dest, SEdge *errorAt) {
dest->Clear();
l.ClearTags();
for(;;) {
Vector first, last;
int i;
for(i = 0; i < l.n; i++) {
if(!l.elem[i].tag) {
first = l.elem[i].a;
last = l.elem[i].b;
l.elem[i].tag = 1;
break;
}
}
if(i >= l.n) {
return true;
}
dest->AddEmptyContour();
dest->AddPoint(first);
dest->AddPoint(last);
do {
for(i = 0; i < l.n; i++) {
SEdge *se = &(l.elem[i]);
if(se->tag) continue;
if(se->a.Equals(last)) {
dest->AddPoint(se->b);
last = se->b;
se->tag = 1;
break;
}
if(se->b.Equals(last)) {
dest->AddPoint(se->a);
last = se->a;
se->tag = 1;
break;
}
}
if(i >= l.n) {
// Couldn't assemble a closed contour; mark where.
errorAt->a = first;
errorAt->b = last;
return false;
}
} while(!last.Equals(first));
}
}
void SPolygon::Clear(void) {
int i;
for(i = 0; i < l.n; i++) {
(l.elem[i]).l.Clear();
}
l.Clear();
}
void SPolygon::AddEmptyContour(void) {
SContour c;
memset(&c, 0, sizeof(c));
l.Add(&c);
}
void SPolygon::AddPoint(Vector p) {
if(l.n < 1) oops();
SPoint sp;
sp.tag = 0;
sp.p = p;
// Add to the last contour in the list
(l.elem[l.n-1]).l.Add(&sp);
}

View File

@ -2,16 +2,40 @@
#ifndef __POLYGON_H #ifndef __POLYGON_H
#define __POLYGON_H #define __POLYGON_H
class SPolygon;
template <class T> template <class T>
class SList { class SList {
public: public:
T *elem; T *elem;
int n; int n;
int elemsAllocated; int elemsAllocated;
void Add(T *t) {
if(n >= elemsAllocated) {
elemsAllocated = (elemsAllocated + 32)*2;
elem = (T *)MemRealloc(elem, elemsAllocated*sizeof(elem[0]));
}
elem[n++] = *t;
}
void ClearTags(void) {
int i;
for(i = 0; i < n; i++) {
elem[i].tag = 0;
}
}
void Clear(void) {
if(elem) MemFree(elem);
elem = NULL;
n = elemsAllocated = 0;
}
}; };
class SEdge { class SEdge {
public: public:
int tag;
Vector a, b; Vector a, b;
}; };
@ -19,16 +43,27 @@ class SEdgeList {
public: public:
SList<SEdge> l; SList<SEdge> l;
bool AssemblePolygon(SPolygon *dest, SEdge *errorAt);
};
class SPoint {
public:
int tag;
Vector p;
}; };
class SContour { class SContour {
public: public:
SList<Vector> l; SList<SPoint> l;
}; };
class SPolygon { class SPolygon {
public: public:
SList<SContour> l; SList<SContour> l;
void AddEmptyContour(void);
void AddPoint(Vector p);
void Clear(void);
}; };
class SPolyhedron { class SPolyhedron {

View File

@ -17,6 +17,34 @@ char *Group::DescriptionString(void) {
return ret; return ret;
} }
void Group::Draw(void) {
edges.l.Clear();
int i;
for(i = 0; i < SS.entity.n; i++) {
Entity *e = &(SS.entity.elem[i]);
hRequest hr = e->h.request();
if(SS.GetRequest(hr)->group.v != h.v) continue;
e->GenerateEdges(&edges);
}
SPolygon poly;
memset(&poly, 0, sizeof(poly));
SEdge error;
if(edges.AssemblePolygon(&poly, &error)) {
glxColor4d(0, 0, 1, 0.15);
glxFillPolygon(&poly);
} else {
glxColor4d(1, 0, 0, 0.3);
glLineWidth(10);
glBegin(GL_LINES);
glxVertex3v(error.a);
glxVertex3v(error.b);
glEnd();
glLineWidth(1);
}
poly.Clear();
}
hParam Request::AddParam(IdList<Param,hParam> *param, hParam hp) { hParam Request::AddParam(IdList<Param,hParam> *param, hParam hp) {
Param pa; Param pa;
memset(&pa, 0, sizeof(pa)); memset(&pa, 0, sizeof(pa));

View File

@ -65,10 +65,15 @@ public:
bool visible; bool visible;
SEdgeList edges;
SPolygon poly;
NameStr name; NameStr name;
char *DescriptionString(void); char *DescriptionString(void);
void Draw(void);
SPolygon GetPolygon(void); SPolygon GetPolygon(void);
}; };
@ -170,14 +175,18 @@ public:
// Routines to draw and hit-test the representation of the entity // Routines to draw and hit-test the representation of the entity
// on-screen. // on-screen.
struct { struct {
bool drawing; bool drawing;
Point2d mp; Point2d mp;
double dmin; double dmin;
} dogd; SEdgeList *edges;
} dogd; // state for drawing or getting distance (for hit testing)
void LineDrawOrGetDistance(Vector a, Vector b); void LineDrawOrGetDistance(Vector a, Vector b);
void LineDrawOrGetDistanceOrEdge(Vector a, Vector b);
void DrawOrGetDistance(int order); void DrawOrGetDistance(int order);
void Draw(int order); void Draw(int order);
double GetDistance(Point2d mp); double GetDistance(Point2d mp);
void GenerateEdges(SEdgeList *el);
char *DescriptionString(void); char *DescriptionString(void);
}; };
@ -253,9 +262,9 @@ public:
static void MenuConstrain(int id); static void MenuConstrain(int id);
struct { struct {
bool drawing; bool drawing;
Point2d mp; Point2d mp;
double dmin; double dmin;
} dogd; // state for drawing or getting distance (for hit testing) } dogd; // state for drawing or getting distance (for hit testing)
void LineDrawOrGetDistance(Vector a, Vector b); void LineDrawOrGetDistance(Vector a, Vector b);
void DrawOrGetDistance(Vector *labelPos); void DrawOrGetDistance(Vector *labelPos);

View File

@ -156,6 +156,8 @@ void SolveSpace::MenuFile(int id) {
case GraphicsWindow::MNU_NEW: case GraphicsWindow::MNU_NEW:
SS.NewFile(); SS.NewFile();
SS.GenerateAll(); SS.GenerateAll();
SS.GW.Init();
SS.TW.Init();
break; break;
case GraphicsWindow::MNU_OPEN: case GraphicsWindow::MNU_OPEN:

View File

@ -64,12 +64,14 @@ void MemFree(void *p);
// Utility functions that are provided in the platform-independent code. // Utility functions that are provided in the platform-independent code.
void glxVertex3v(Vector u); void glxVertex3v(Vector u);
void glxFillPolygon(SPolygon *p);
void glxWriteText(char *str); void glxWriteText(char *str);
void glxTranslatev(Vector u); void glxTranslatev(Vector u);
void glxOntoCsys(Vector u, Vector v); void glxOntoCsys(Vector u, Vector v);
void glxLockColorTo(double r, double g, double b); void glxLockColorTo(double r, double g, double b);
void glxUnlockColor(void); void glxUnlockColor(void);
void glxColor(double r, double g, double b); void glxColor3d(double r, double g, double b);
void glxColor4d(double r, double g, double b, double a);
#define arraylen(x) (sizeof((x))/sizeof((x)[0])) #define arraylen(x) (sizeof((x))/sizeof((x)[0]))

View File

@ -102,6 +102,13 @@ Vector Vector::MakeFrom(double x, double y, double z) {
return v; return v;
} }
bool Vector::Equals(Vector v) {
double tol = 0.1;
if(fabs(x - v.x) > tol) return false;
if(fabs(y - v.y) > tol) return false;
if(fabs(z - v.z) > tol) return false;
return true;
}
Vector Vector::Plus(Vector b) { Vector Vector::Plus(Vector b) {
Vector r; Vector r;