2008-04-25 07:04:09 +00:00
|
|
|
#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);
|
|
|
|
}
|
|
|
|
|
2008-05-02 10:54:22 +00:00
|
|
|
void SPolygon::MakeEdgesInto(SEdgeList *el) {
|
|
|
|
int i;
|
|
|
|
for(i = 0; i < l.n; i++) {
|
|
|
|
(l.elem[i]).MakeEdgesInto(el);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Vector SPolygon::Normal(void) {
|
|
|
|
if(l.n < 1) return Vector::MakeFrom(0, 0, 0);
|
|
|
|
return (l.elem[0]).Normal();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SContour::MakeEdgesInto(SEdgeList *el) {
|
|
|
|
int i;
|
|
|
|
for(i = 0; i < (l.n-1); i++) {
|
|
|
|
SEdge e;
|
|
|
|
e.a = l.elem[i].p;
|
|
|
|
e.b = l.elem[i+1].p;
|
|
|
|
el->l.Add(&e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Vector SContour::Normal(void) {
|
|
|
|
if(l.n < 3) return Vector::MakeFrom(0, 0, 0);
|
|
|
|
|
|
|
|
Vector u = (l.elem[0].p).Minus(l.elem[1].p);
|
|
|
|
|
|
|
|
Vector v;
|
|
|
|
double dot = 2;
|
|
|
|
// Find the edge in the contour that's closest to perpendicular to the
|
|
|
|
// first edge, since that will give best numerical stability.
|
|
|
|
for(int i = 1; i < (l.n-1); i++) {
|
|
|
|
Vector vt = (l.elem[i].p).Minus(l.elem[i+1].p);
|
|
|
|
double dott = fabs(vt.Dot(u)/(u.Magnitude()*vt.Magnitude()));
|
|
|
|
if(dott < dot) {
|
|
|
|
dot = dott;
|
|
|
|
v = vt;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (u.Cross(v)).WithMagnitude(1);
|
|
|
|
}
|
|
|
|
|