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
parent
1331457928
commit
a7cec38656
1
Makefile
1
Makefile
|
@ -21,6 +21,7 @@ SSOBJS = $(OBJDIR)\solvespace.obj \
|
|||
$(OBJDIR)\drawconstraint.obj \
|
||||
$(OBJDIR)\file.obj \
|
||||
$(OBJDIR)\system.obj \
|
||||
$(OBJDIR)\polygon.obj \
|
||||
|
||||
|
||||
LIBS = user32.lib gdi32.lib comctl32.lib advapi32.lib opengl32.lib glu32.lib
|
||||
|
|
|
@ -33,7 +33,7 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) {
|
|||
Vector gu = SS.GW.projUp;
|
||||
Vector gn = gr.Cross(gu);
|
||||
|
||||
glxColor(1, 0.2, 1);
|
||||
glxColor3d(1, 0.2, 1);
|
||||
switch(type) {
|
||||
case PT_PT_DISTANCE: {
|
||||
Vector ap = SS.GetEntity(ptA)->PointGetCoords();
|
||||
|
@ -86,7 +86,7 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) {
|
|||
for(int i = 0; i < 2; i++) {
|
||||
Vector p = SS.GetEntity(i == 0 ? ptA : ptB)->
|
||||
PointGetCoords();
|
||||
glxColor(0.4, 0, 0.4);
|
||||
glxColor3d(0.4, 0, 0.4);
|
||||
glBegin(GL_QUADS);
|
||||
glxVertex3v(p.Plus (r).Plus (d));
|
||||
glxVertex3v(p.Plus (r).Minus(d));
|
||||
|
|
1
dsc.h
1
dsc.h
|
@ -33,6 +33,7 @@ public:
|
|||
|
||||
static Vector MakeFrom(double x, double y, double z);
|
||||
|
||||
bool Equals(Vector v);
|
||||
Vector Plus(Vector b);
|
||||
Vector Minus(Vector b);
|
||||
Vector Negated(void);
|
||||
|
|
26
entity.cpp
26
entity.cpp
|
@ -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) {
|
||||
dogd.drawing = true;
|
||||
dogd.edges = NULL;
|
||||
DrawOrGetDistance(order);
|
||||
}
|
||||
|
||||
void Entity::GenerateEdges(SEdgeList *el) {
|
||||
dogd.drawing = false;
|
||||
dogd.edges = el;
|
||||
DrawOrGetDistance(-1);
|
||||
dogd.edges = NULL;
|
||||
}
|
||||
|
||||
double Entity::GetDistance(Point2d mp) {
|
||||
dogd.drawing = false;
|
||||
dogd.edges = NULL;
|
||||
dogd.mp = mp;
|
||||
dogd.dmin = 1e12;
|
||||
|
||||
|
@ -227,7 +245,7 @@ double Entity::GetDistance(Point2d mp) {
|
|||
}
|
||||
|
||||
void Entity::DrawOrGetDistance(int order) {
|
||||
glxColor(1, 1, 1);
|
||||
glxColor3d(1, 1, 1);
|
||||
|
||||
switch(type) {
|
||||
case POINT_IN_3D:
|
||||
|
@ -245,7 +263,7 @@ void Entity::DrawOrGetDistance(int order) {
|
|||
Vector r = SS.GW.projRight.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);
|
||||
glxVertex3v(v.Plus (r).Plus (d));
|
||||
glxVertex3v(v.Plus (r).Minus(d));
|
||||
|
@ -279,7 +297,7 @@ void Entity::DrawOrGetDistance(int order) {
|
|||
Vector mm = p.Minus(us).Minus(vs);
|
||||
Vector mp = p.Minus(us).Plus (vs);
|
||||
|
||||
glxColor(0, 0.4, 0.4);
|
||||
glxColor3d(0, 0.4, 0.4);
|
||||
LineDrawOrGetDistance(pp, pm);
|
||||
LineDrawOrGetDistance(pm, mm);
|
||||
LineDrawOrGetDistance(mm, mp);
|
||||
|
@ -299,7 +317,7 @@ void Entity::DrawOrGetDistance(int order) {
|
|||
if(order >= 0 && order != 1) break;
|
||||
Vector a = SS.GetEntity(assoc[0])->PointGetCoords();
|
||||
Vector b = SS.GetEntity(assoc[1])->PointGetCoords();
|
||||
LineDrawOrGetDistance(a, b);
|
||||
LineDrawOrGetDistanceOrEdge(a, b);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
46
glhelper.cpp
46
glhelper.cpp
|
@ -60,7 +60,7 @@ void glxOntoCsys(Vector u, Vector v)
|
|||
void glxLockColorTo(double r, double g, double b)
|
||||
{
|
||||
ColorLocked = false;
|
||||
glxColor(r, g, b);
|
||||
glxColor3d(r, g, b);
|
||||
ColorLocked = true;
|
||||
}
|
||||
|
||||
|
@ -69,9 +69,45 @@ void glxUnlockColor(void)
|
|||
ColorLocked = false;
|
||||
}
|
||||
|
||||
void glxColor(double r, double g, double b)
|
||||
void glxColor3d(double r, double g, double b)
|
||||
{
|
||||
if(!ColorLocked) {
|
||||
glColor3f((GLfloat)r, (GLfloat)g, (GLfloat)b);
|
||||
}
|
||||
if(!ColorLocked) glColor3d(r, g, 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -280,7 +280,21 @@ void GraphicsWindow::MenuEdit(int id) {
|
|||
if(s->entity.v) {
|
||||
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) {
|
||||
SS.constraint.Tag(s->constraint, 1);
|
||||
}
|
||||
|
@ -561,19 +575,22 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
|
|||
hRequest hr;
|
||||
switch(pendingOperation) {
|
||||
case MNU_DATUM_POINT:
|
||||
ClearSelection(); hover.Clear();
|
||||
|
||||
hr = AddRequest(Request::DATUM_POINT);
|
||||
SS.GetEntity(hr.entity(0))->PointForceTo(v);
|
||||
|
||||
ClearSelection(); hover.Clear();
|
||||
|
||||
pendingOperation = 0;
|
||||
break;
|
||||
|
||||
case MNU_LINE_SEGMENT:
|
||||
ClearSelection(); hover.Clear();
|
||||
|
||||
hr = AddRequest(Request::LINE_SEGMENT);
|
||||
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;
|
||||
pendingPoint = hr.entity(2);
|
||||
|
@ -776,6 +793,11 @@ void GraphicsWindow::Paint(int w, int h) {
|
|||
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.
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glxLockColorTo(1, 1, 0);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
37
polygon.h
37
polygon.h
|
@ -2,16 +2,40 @@
|
|||
#ifndef __POLYGON_H
|
||||
#define __POLYGON_H
|
||||
|
||||
class SPolygon;
|
||||
|
||||
template <class T>
|
||||
class SList {
|
||||
public:
|
||||
T *elem;
|
||||
int n;
|
||||
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 {
|
||||
public:
|
||||
int tag;
|
||||
Vector a, b;
|
||||
};
|
||||
|
||||
|
@ -19,16 +43,27 @@ class SEdgeList {
|
|||
public:
|
||||
SList<SEdge> l;
|
||||
|
||||
bool AssemblePolygon(SPolygon *dest, SEdge *errorAt);
|
||||
};
|
||||
|
||||
class SPoint {
|
||||
public:
|
||||
int tag;
|
||||
Vector p;
|
||||
};
|
||||
|
||||
class SContour {
|
||||
public:
|
||||
SList<Vector> l;
|
||||
SList<SPoint> l;
|
||||
};
|
||||
|
||||
class SPolygon {
|
||||
public:
|
||||
SList<SContour> l;
|
||||
|
||||
void AddEmptyContour(void);
|
||||
void AddPoint(Vector p);
|
||||
void Clear(void);
|
||||
};
|
||||
|
||||
class SPolyhedron {
|
||||
|
|
28
sketch.cpp
28
sketch.cpp
|
@ -17,6 +17,34 @@ char *Group::DescriptionString(void) {
|
|||
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) {
|
||||
Param pa;
|
||||
memset(&pa, 0, sizeof(pa));
|
||||
|
|
23
sketch.h
23
sketch.h
|
@ -65,10 +65,15 @@ public:
|
|||
|
||||
bool visible;
|
||||
|
||||
SEdgeList edges;
|
||||
SPolygon poly;
|
||||
|
||||
NameStr name;
|
||||
|
||||
char *DescriptionString(void);
|
||||
|
||||
void Draw(void);
|
||||
|
||||
SPolygon GetPolygon(void);
|
||||
};
|
||||
|
||||
|
@ -170,14 +175,18 @@ public:
|
|||
// Routines to draw and hit-test the representation of the entity
|
||||
// on-screen.
|
||||
struct {
|
||||
bool drawing;
|
||||
Point2d mp;
|
||||
double dmin;
|
||||
} dogd;
|
||||
bool drawing;
|
||||
Point2d mp;
|
||||
double dmin;
|
||||
SEdgeList *edges;
|
||||
} dogd; // state for drawing or getting distance (for hit testing)
|
||||
void LineDrawOrGetDistance(Vector a, Vector b);
|
||||
void LineDrawOrGetDistanceOrEdge(Vector a, Vector b);
|
||||
void DrawOrGetDistance(int order);
|
||||
|
||||
void Draw(int order);
|
||||
double GetDistance(Point2d mp);
|
||||
void GenerateEdges(SEdgeList *el);
|
||||
|
||||
char *DescriptionString(void);
|
||||
};
|
||||
|
@ -253,9 +262,9 @@ public:
|
|||
static void MenuConstrain(int id);
|
||||
|
||||
struct {
|
||||
bool drawing;
|
||||
Point2d mp;
|
||||
double dmin;
|
||||
bool drawing;
|
||||
Point2d mp;
|
||||
double dmin;
|
||||
} dogd; // state for drawing or getting distance (for hit testing)
|
||||
void LineDrawOrGetDistance(Vector a, Vector b);
|
||||
void DrawOrGetDistance(Vector *labelPos);
|
||||
|
|
|
@ -156,6 +156,8 @@ void SolveSpace::MenuFile(int id) {
|
|||
case GraphicsWindow::MNU_NEW:
|
||||
SS.NewFile();
|
||||
SS.GenerateAll();
|
||||
SS.GW.Init();
|
||||
SS.TW.Init();
|
||||
break;
|
||||
|
||||
case GraphicsWindow::MNU_OPEN:
|
||||
|
|
|
@ -64,12 +64,14 @@ void MemFree(void *p);
|
|||
|
||||
// Utility functions that are provided in the platform-independent code.
|
||||
void glxVertex3v(Vector u);
|
||||
void glxFillPolygon(SPolygon *p);
|
||||
void glxWriteText(char *str);
|
||||
void glxTranslatev(Vector u);
|
||||
void glxOntoCsys(Vector u, Vector v);
|
||||
void glxLockColorTo(double r, double g, double b);
|
||||
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]))
|
||||
|
|
7
util.cpp
7
util.cpp
|
@ -102,6 +102,13 @@ Vector Vector::MakeFrom(double x, double y, double z) {
|
|||
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 r;
|
||||
|
|
Loading…
Reference in New Issue