Rip out the boundary rep csg stuff. I'll redo that with a triangle
mesh approach. [git-p4: depot-paths = "//depot/solvespace/": change = 1732]solver
parent
c4e1270e25
commit
e80328279e
|
@ -1183,32 +1183,7 @@ void GraphicsWindow::Paint(int w, int h) {
|
|||
|
||||
if(SS.group.n >= 5) {
|
||||
if(1) {
|
||||
SPolyhedron p; ZERO(&p);
|
||||
|
||||
(SS.group.elem[2].polyh).Boolean(&p, 0,
|
||||
&(SS.group.elem[4].polyh));
|
||||
|
||||
glEnable(GL_LIGHTING);
|
||||
GLfloat vec[] = { 0.3f, 0.3f, 0.3f, 1.0 };
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, vec);
|
||||
GLfloat vec2[] = { 1.0f, 0.3f, 0.3f, 1.0 };
|
||||
glMaterialfv(GL_BACK, GL_AMBIENT_AND_DIFFUSE, vec2);
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
for(i = 0; i < p.l.n; i++) {
|
||||
glxFillPolygon(&(p.l.elem[i]));
|
||||
}
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
p.Clear();
|
||||
} else {
|
||||
SPolygon p; ZERO(&p);
|
||||
|
||||
(SS.group.elem[1].polyg).Boolean(&p, SEdgeList::INTERSECT,
|
||||
&(SS.group.elem[2].polyg));
|
||||
glxDebugPolygon(&p);
|
||||
p.Clear();
|
||||
//XXX
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
283
polygon.cpp
283
polygon.cpp
|
@ -1,17 +1,5 @@
|
|||
#include "solvespace.h"
|
||||
|
||||
static int ByDouble(const void *av, const void *bv) {
|
||||
const double *a = (const double *)av;
|
||||
const double *b = (const double *)bv;
|
||||
if(*a == *b) {
|
||||
return 0;
|
||||
} else if(*a > *b) {
|
||||
return 1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
bool SEdgeList::AssemblePolygon(SPolygon *dest, SEdge *errorAt) {
|
||||
dest->Clear();
|
||||
|
||||
|
@ -64,109 +52,6 @@ bool SEdgeList::AssemblePolygon(SPolygon *dest, SEdge *errorAt) {
|
|||
}
|
||||
}
|
||||
|
||||
void SEdgeList::CopyBreaking(SEdgeList *dest) {
|
||||
int i, j, k;
|
||||
|
||||
for(i = 0; i < l.n; i++) {
|
||||
SEdge *ei = &(l.elem[i]);
|
||||
Vector p0i = ei->a;
|
||||
Vector dpi = (ei->b).Minus(ei->a);
|
||||
|
||||
double inter[100];
|
||||
int inters = 0;
|
||||
for(j = 0; j < l.n; j++) {
|
||||
if(i == j) continue;
|
||||
SEdge *ej = &(l.elem[j]);
|
||||
Vector p0j = ej->a;
|
||||
Vector dpj = (ej->b).Minus(ej->a);
|
||||
|
||||
// Find the intersection, if any
|
||||
Vector dn = dpi.Cross(dpj);
|
||||
if(dn.Magnitude() < 0.001) continue; // parallel, non-intersecting
|
||||
Vector dni = dn.Cross(dpi);
|
||||
Vector dnj = dn.Cross(dpj);
|
||||
double tj = ((p0i.Minus(p0j)).Dot(dni))/(dpj.Dot(dni));
|
||||
double ti = -((p0i.Minus(p0j)).Dot(dnj))/(dpi.Dot(dnj));
|
||||
// could also test for skew, but assume it's all in plane so not
|
||||
|
||||
if(ti <= 0 || ti >= 1) continue;
|
||||
if(tj < -0.001 || tj > 1.001) continue;
|
||||
|
||||
inter[inters++] = ti;
|
||||
}
|
||||
inter[inters++] = 0;
|
||||
inter[inters++] = 1;
|
||||
qsort(inter, inters, sizeof(inter[0]), ByDouble);
|
||||
|
||||
for(k = 1; k < inters; k++) {
|
||||
SEdge ne;
|
||||
ne.tag = 0;
|
||||
ne.a = p0i.Plus(dpi.ScaledBy(inter[k-1]));
|
||||
ne.b = p0i.Plus(dpi.ScaledBy(inter[k]));
|
||||
dest->l.Add(&ne);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SEdgeList::CullDuplicates(void) {
|
||||
int i, j;
|
||||
for(i = 0; i < l.n; i++) {
|
||||
SEdge *se = &(l.elem[i]);
|
||||
if(se->tag) continue;
|
||||
|
||||
if(((se->a).Minus(se->b)).Magnitude() < 0.01) {
|
||||
se->tag = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
for(j = i+1; j < l.n; j++) {
|
||||
SEdge *st = &(l.elem[j]);
|
||||
if(st->tag) continue;
|
||||
|
||||
if(((se->a).Equals(st->a) && (se->b).Equals(st->b)) ||
|
||||
((se->a).Equals(st->b) && (se->b).Equals(st->a)))
|
||||
{
|
||||
// This is an exact duplicate, so mark it as unused now.
|
||||
st->tag = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SEdgeList::BooleanOp(int op, bool inA, bool inB) {
|
||||
if(op == UNION) {
|
||||
return inA || inB;
|
||||
} else if(op == DIFF) {
|
||||
return inA && (!inB);
|
||||
} else if(op == INTERSECT) {
|
||||
return inA && inB;
|
||||
} else oops();
|
||||
}
|
||||
|
||||
void SEdgeList::CullForBoolean(int op, SPolygon *a, SPolygon *b) {
|
||||
int i;
|
||||
for(i = 0; i < l.n; i++) {
|
||||
SEdge *se = &(l.elem[i]);
|
||||
if(se->tag) continue;
|
||||
|
||||
Vector tp = ((se->a).Plus(se->b)).ScaledBy(0.5);
|
||||
Vector nudge = ((se->a).Minus(se->b)).Cross(a->normal);
|
||||
nudge = nudge.WithMagnitude(.01);
|
||||
Vector tp1 = tp.Plus(nudge);
|
||||
Vector tp2 = tp.Minus(nudge);
|
||||
|
||||
bool inf1 = BooleanOp(op, a->ContainsPoint(tp1), b->ContainsPoint(tp1));
|
||||
bool inf2 = BooleanOp(op, a->ContainsPoint(tp2), b->ContainsPoint(tp2));
|
||||
|
||||
if((inf1 && inf2) || (!inf1 && !inf2)) {
|
||||
// The "in polygon" state doesn't change as you cross the edge;
|
||||
// so it doesn't lie on the output polygon.
|
||||
se->tag = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SPolygon::Clear(void) {
|
||||
int i;
|
||||
for(i = 0; i < l.n; i++) {
|
||||
|
@ -216,80 +101,6 @@ bool SPolygon::ContainsPoint(Vector p) {
|
|||
return inside;
|
||||
}
|
||||
|
||||
void SPolygon::IntersectAgainstPlane(SEdgeList *dest, Vector p0, Vector n) {
|
||||
if(l.n == 0 || (l.elem[0].l.n == 0)) return;
|
||||
double od = normal.Dot(l.elem[0].l.elem[0].p);
|
||||
double d = n.Dot(p0);
|
||||
|
||||
Vector u = (normal.Cross(n));
|
||||
if(u.Magnitude() < 0.001) {
|
||||
if(n.Dot(normal) < 0) od = -od;
|
||||
if(fabs(od - d) < 0.001) {
|
||||
// The planes are coincident; so the intersection is a copy of
|
||||
// this polygon.
|
||||
MakeEdgesInto(dest);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
u = u.WithMagnitude(1);
|
||||
Vector v = normal.Cross(u);
|
||||
|
||||
Vector lp = Vector::AtIntersectionOfPlanes(n, d, normal, od);
|
||||
double vp = v.Dot(lp);
|
||||
|
||||
double inter[100];
|
||||
int inters = 0;
|
||||
int i;
|
||||
for(i = 0; i < l.n; i++) {
|
||||
SContour *sc = &(l.elem[i]);
|
||||
// The 0.01 is because I mishandle the case where the intersection
|
||||
// plane goes through a vertex
|
||||
sc->IntersectAgainstPlane(inter, &inters, u, v, vp);
|
||||
}
|
||||
qsort(inter, inters, sizeof(inter[0]), ByDouble);
|
||||
for(i = 0; i < inters; i += 2) {
|
||||
SEdge se;
|
||||
se.tag = 0;
|
||||
se.a = lp.Plus(u.ScaledBy(inter[i]));
|
||||
se.b = lp.Plus(u.ScaledBy(inter[i+1]));
|
||||
dest->l.Add(&se);
|
||||
}
|
||||
}
|
||||
|
||||
void SPolygon::CopyBreaking(SPolyhedron *dest, SPolyhedron *against, int how) {
|
||||
if(l.n == 0 || (l.elem[0].l.n == 0)) return;
|
||||
Vector p0 = l.elem[0].l.elem[0].p;
|
||||
|
||||
SEdgeList el; ZERO(&el);
|
||||
int i;
|
||||
for(i = 0; i < against->l.n; i++) {
|
||||
SPolygon *pb = &(against->l.elem[i]);
|
||||
pb->IntersectAgainstPlane(&el, p0, normal);
|
||||
}
|
||||
el.CullDuplicates();
|
||||
|
||||
SPolygon inter; ZERO(&inter);
|
||||
bool worked = el.AssemblePolygon(&inter, NULL);
|
||||
inter.normal = normal;
|
||||
|
||||
SPolygon res; ZERO(&res);
|
||||
if(how == 0) {
|
||||
this->Boolean(&res, SEdgeList::DIFF, &inter);
|
||||
res.normal = normal;
|
||||
} else if(how == 1) {
|
||||
this->Boolean(&res, SEdgeList::INTERSECT, &inter);
|
||||
res.normal = normal.ScaledBy(-1);
|
||||
} else oops();
|
||||
|
||||
if(res.l.n > 0) {
|
||||
dest->l.Add(&res);
|
||||
}
|
||||
|
||||
el.l.Clear();
|
||||
inter.Clear();
|
||||
}
|
||||
|
||||
void SPolygon::FixContourDirections(void) {
|
||||
// Outside curve looks counterclockwise, projected against our normal.
|
||||
int i, j;
|
||||
|
@ -314,32 +125,6 @@ void SPolygon::FixContourDirections(void) {
|
|||
}
|
||||
}
|
||||
|
||||
bool SPolygon::Boolean(SPolygon *dest, int op, SPolygon *b) {
|
||||
SEdgeList el;
|
||||
ZERO(&el);
|
||||
this->MakeEdgesInto(&el);
|
||||
b->MakeEdgesInto(&el);
|
||||
|
||||
SEdgeList br;
|
||||
ZERO(&br);
|
||||
el.CopyBreaking(&br);
|
||||
|
||||
br.CullDuplicates();
|
||||
br.CullForBoolean(op, this, b);
|
||||
|
||||
SEdge e;
|
||||
bool ret = br.AssemblePolygon(dest, &e);
|
||||
if(!ret) {
|
||||
br.l.ClearTags();
|
||||
br.CullDuplicates();
|
||||
br.CullForBoolean(op, this, b);
|
||||
}
|
||||
|
||||
br.l.Clear();
|
||||
el.l.Clear();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void SContour::MakeEdgesInto(SEdgeList *el) {
|
||||
int i;
|
||||
for(i = 0; i < (l.n-1); i++) {
|
||||
|
@ -413,37 +198,6 @@ bool SContour::ContainsPointProjdToNormal(Vector n, Vector p) {
|
|||
return inside;
|
||||
}
|
||||
|
||||
|
||||
void SContour::IntersectAgainstPlane(double *inter, int *inters,
|
||||
Vector u, Vector v, double vp)
|
||||
{
|
||||
for(int i = 0; i < (l.n - 1); i++) {
|
||||
double ua = (l.elem[i ].p).Dot(u);
|
||||
double va = (l.elem[i ].p).Dot(v);
|
||||
double ub = (l.elem[(i+1)%(l.n-1)].p).Dot(u);
|
||||
double vb = (l.elem[(i+1)%(l.n-1)].p).Dot(v);
|
||||
|
||||
double u0, v0, du, dv;
|
||||
|
||||
if(va < vb) {
|
||||
u0 = ua; v0 = va;
|
||||
du = (ub - ua); dv = (vb - va);
|
||||
} else {
|
||||
u0 = ub; v0 = vb;
|
||||
du = (ua - ub); dv = (va - vb);
|
||||
}
|
||||
|
||||
if(dv == 0) continue;
|
||||
|
||||
double t = (vp - v0)/dv;
|
||||
if(t >= 0 && t < 1) {
|
||||
double ui = u0 + t*du;
|
||||
// Our line v = vp intersects the edge; record the u value
|
||||
inter[(*inters)++] = ui;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SContour::Reverse(void) {
|
||||
int i;
|
||||
for(i = 0; i < (l.n / 2); i++) {
|
||||
|
@ -454,40 +208,3 @@ void SContour::Reverse(void) {
|
|||
}
|
||||
}
|
||||
|
||||
void SPolyhedron::AddFace(SPolygon *p) {
|
||||
l.Add(p);
|
||||
}
|
||||
|
||||
void SPolyhedron::Clear(void) {
|
||||
int i;
|
||||
for(i = 0; i < l.n; i++) {
|
||||
(l.elem[i]).Clear();
|
||||
}
|
||||
l.Clear();
|
||||
}
|
||||
|
||||
void SPolyhedron::IntersectAgainstPlane(SEdgeList *d, Vector p0, Vector n) {
|
||||
int i;
|
||||
for(i = 0; i < l.n; i++) {
|
||||
SPolygon *sp = &(l.elem[i]);
|
||||
sp->IntersectAgainstPlane(d, p0, n);
|
||||
}
|
||||
}
|
||||
|
||||
bool SPolyhedron::Boolean(SPolyhedron *dest, int op, SPolyhedron *b) {
|
||||
int i;
|
||||
dbp(">>>");
|
||||
|
||||
for(i = 0; i < l.n; i++) {
|
||||
SPolygon *sp = &(l.elem[i]);
|
||||
sp->CopyBreaking(dest, b, 0);
|
||||
}
|
||||
|
||||
for(i = 0; i < b->l.n; i++) {
|
||||
SPolygon *sp = &(b->l.elem[i]);
|
||||
sp->CopyBreaking(dest, this, 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
37
polygon.h
37
polygon.h
|
@ -3,7 +3,6 @@
|
|||
#define __POLYGON_H
|
||||
|
||||
class SPolygon;
|
||||
class SPolyhedron;
|
||||
|
||||
template <class T>
|
||||
class SList {
|
||||
|
@ -83,22 +82,36 @@ public:
|
|||
void MakeEdgesInto(SEdgeList *el);
|
||||
void FixContourDirections(void);
|
||||
void Clear(void);
|
||||
|
||||
bool Boolean(SPolygon *dest, int op, SPolygon *b);
|
||||
|
||||
void CopyBreaking(SPolyhedron *dest, SPolyhedron *against, int how);
|
||||
void IntersectAgainstPlane(SEdgeList *dest, Vector p0, Vector n);
|
||||
};
|
||||
|
||||
class SPolyhedron {
|
||||
class STriangle {
|
||||
public:
|
||||
SList<SPolygon> l;
|
||||
Vector a, b, c;
|
||||
};
|
||||
|
||||
void AddFace(SPolygon *p);
|
||||
void Clear(void);
|
||||
class SBsp2 {
|
||||
SEdge edge;
|
||||
};
|
||||
|
||||
void IntersectAgainstPlane(SEdgeList *dest, Vector p0, Vector n);
|
||||
bool Boolean(SPolyhedron *dest, int op, SPolyhedron *b);
|
||||
class SBsp1d {
|
||||
SEdge edge;
|
||||
};
|
||||
|
||||
class SBsp3 {
|
||||
public:
|
||||
STriangle tri;
|
||||
SBsp3 *pos;
|
||||
SBsp3 *neg;
|
||||
|
||||
SBsp3 *more;
|
||||
|
||||
SBsp2 *edges;
|
||||
};
|
||||
|
||||
|
||||
class SMesh {
|
||||
public:
|
||||
SList<STriangle> l;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
40
sketch.cpp
40
sketch.cpp
|
@ -383,8 +383,7 @@ void Group::CopyEntity(hEntity in, int a, hParam dx, hParam dy, hParam dz,
|
|||
|
||||
void Group::MakePolygons(void) {
|
||||
int i;
|
||||
polyh.Clear();
|
||||
polyg.Clear();
|
||||
poly.Clear();
|
||||
|
||||
SEdgeList edges;
|
||||
ZERO(&edges);
|
||||
|
@ -398,13 +397,13 @@ void Group::MakePolygons(void) {
|
|||
e->GenerateEdges(&edges);
|
||||
}
|
||||
SEdge error;
|
||||
if(edges.AssemblePolygon(&polyg, &error)) {
|
||||
if(edges.AssemblePolygon(&poly, &error)) {
|
||||
polyError.yes = false;
|
||||
polyg.normal = polyg.ComputeNormal();
|
||||
poly.normal = poly.ComputeNormal();
|
||||
} else {
|
||||
polyError.yes = true;
|
||||
polyError.notClosedAt = error;
|
||||
polyg.Clear();
|
||||
poly.Clear();
|
||||
}
|
||||
} else if(type == EXTRUDE) {
|
||||
Vector translate;
|
||||
|
@ -422,7 +421,7 @@ void Group::MakePolygons(void) {
|
|||
edges.l.Clear();
|
||||
Group *src = SS.GetGroup(opA);
|
||||
|
||||
(src->polyg).MakeEdgesInto(&edges);
|
||||
(src->poly).MakeEdgesInto(&edges);
|
||||
for(i = 0; i < edges.l.n; i++) {
|
||||
SEdge *edge = &(edges.l.elem[i]);
|
||||
edge->a = (edge->a).Plus(t0);
|
||||
|
@ -439,7 +438,6 @@ void Group::MakePolygons(void) {
|
|||
}
|
||||
np.normal = n;
|
||||
np.FixContourDirections();
|
||||
polyh.AddFace(&np);
|
||||
|
||||
// Regenerate the edges, with the contour directions fixed up.
|
||||
edges.l.Clear();
|
||||
|
@ -457,7 +455,6 @@ void Group::MakePolygons(void) {
|
|||
np.AddPoint((edge->a).Plus(dt));
|
||||
np.AddPoint(edge->a);
|
||||
np.normal = ((edge->a).Minus(edge->b).Cross(n)).WithMagnitude(1);
|
||||
polyh.AddFace(&np);
|
||||
|
||||
edge->a = (edge->a).Plus(dt);
|
||||
edge->b = (edge->b).Plus(dt);
|
||||
|
@ -467,7 +464,6 @@ void Group::MakePolygons(void) {
|
|||
memset(&np, 0, sizeof(np));
|
||||
if(!edges.AssemblePolygon(&np, NULL)) oops();
|
||||
np.normal = n.ScaledBy(-1);
|
||||
polyh.AddFace(&np);
|
||||
}
|
||||
edges.l.Clear();
|
||||
}
|
||||
|
@ -492,27 +488,11 @@ void Group::Draw(void) {
|
|||
} else {
|
||||
int i;
|
||||
glEnable(GL_LIGHTING);
|
||||
GLfloat vec[] = { 0.3f, 0.3f, 0.3f, 1.0 };
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, vec);
|
||||
GLfloat vec2[] = { 1.0f, 0.3f, 0.3f, 1.0 };
|
||||
glMaterialfv(GL_BACK, GL_AMBIENT_AND_DIFFUSE, vec2);
|
||||
for(i = 0; i < polyh.l.n; i++) {
|
||||
glxFillPolygon(&(polyh.l.elem[i]));
|
||||
#if 0
|
||||
// Debug stuff to show normals to the faces on-screen
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glxMarkPolygonNormal(&(polyh.l.elem[i]));
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
#endif
|
||||
}
|
||||
|
||||
GLfloat vec3[] = { 0.3f, 1.0f, 0.3f, 0.5 };
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, vec3);
|
||||
GLfloat vec4[] = { 1.0f, 0.3f, 0.3f, 0.5 };
|
||||
glMaterialfv(GL_BACK, GL_AMBIENT_AND_DIFFUSE, vec4);
|
||||
glxFillPolygon(&polyg);
|
||||
GLfloat mpf[] = { 0.3f, 1.0f, 0.3f, 0.5 };
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mpf);
|
||||
GLfloat mpb[] = { 1.0f, 0.3f, 0.3f, 0.5 };
|
||||
glMaterialfv(GL_BACK, GL_AMBIENT_AND_DIFFUSE, mpb);
|
||||
glxFillPolygon(&poly);
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue