Fix triangulation issues when a polygon has more than two edges at

a vertex.

[git-p4: depot-paths = "//depot/solvespace/": change = 1916]
solver
Jonathan Westhues 2009-02-18 03:15:33 -08:00
parent 577cdf2255
commit 9ade574d36
3 changed files with 38 additions and 9 deletions

View File

@ -386,8 +386,11 @@ void SPolygon::FixContourDirections(void) {
int i, j; int i, j;
for(i = 0; i < l.n; i++) { for(i = 0; i < l.n; i++) {
SContour *sc = &(l.elem[i]); SContour *sc = &(l.elem[i]);
if(sc->l.n < 1) continue; if(sc->l.n < 2) continue;
Vector pt = (sc->l.elem[0]).p; // The contours may not intersect, but they may share vertices; so
// testing a vertex for point-in-polygon may fail, but the midpoint
// of an edge is okay.
Vector pt = (((sc->l.elem[0]).p).Plus(sc->l.elem[1].p)).ScaledBy(0.5);
sc->timesEnclosed = 0; sc->timesEnclosed = 0;
bool outer = true; bool outer = true;

View File

@ -426,7 +426,7 @@ SSurface SSurface::MakeCopyTrimAgainst(SShell *agnst, SShell *parent,
} }
final.l.RemoveTagged(); final.l.RemoveTagged();
// if(I == 1) DEBUGEDGELIST(&final, &ret); // if(I == 10) DEBUGEDGELIST(&final, &ret);
// Use our reassembled edges to trim the new surface. // Use our reassembled edges to trim the new surface.
ret.TrimFromEdgeList(&final); ret.TrimFromEdgeList(&final);
@ -485,13 +485,13 @@ void SShell::MakeFromBoolean(SShell *a, SShell *b, int type) {
a->MakeIntersectionCurvesAgainst(b, this); a->MakeIntersectionCurvesAgainst(b, this);
I = 100; I = 100;
if(b->surface.n == 0 || a->surface.n == 0) { if(b->surface.n == 0 || a->surface.n == 0 || a->surface.n == 6) {
// Then trim and copy the surfaces // Then trim and copy the surfaces
a->CopySurfacesTrimAgainst(b, this, type, true); a->CopySurfacesTrimAgainst(b, this, type, true);
b->CopySurfacesTrimAgainst(a, this, type, false); b->CopySurfacesTrimAgainst(a, this, type, false);
} else { } else {
a->CopySurfacesTrimAgainst(b, this, type, true);
I = 0; I = 0;
a->CopySurfacesTrimAgainst(b, this, type, true);
b->CopySurfacesTrimAgainst(a, this, type, false); b->CopySurfacesTrimAgainst(a, this, type, false);
} }

View File

@ -42,9 +42,14 @@ void SPolygon::UvTriangulateInto(SMesh *m) {
SContour *sc; SContour *sc;
for(sc = l.First(); sc; sc = l.NextAfter(sc)) { for(sc = l.First(); sc; sc = l.NextAfter(sc)) {
if(sc->timesEnclosed != 1) continue; if(sc->timesEnclosed != 1) continue;
if(sc->l.n < 1) continue; if(sc->l.n < 2) continue;
if(top->ContainsPointProjdToNormal(normal, sc->l.elem[0].p)) { // Test the midpoint of an edge. Our polygon may not be self-
// intersecting, but two countours may share a vertex; so a
// vertex could be on the edge of another polygon, in which
// case ContainsPointProjdToNormal returns indeterminate.
Vector tp = ((sc->l.elem[0].p).Plus(sc->l.elem[1].p)).ScaledBy(0.5);
if(top->ContainsPointProjdToNormal(normal, tp)) {
sc->tag = 2; sc->tag = 2;
sc->MakeEdgesInto(&el); sc->MakeEdgesInto(&el);
sc->FindPointWithMinX(); sc->FindPointWithMinX();
@ -180,6 +185,12 @@ bool SContour::IsEar(int bp) {
tr.b = l.elem[bp].p; tr.b = l.elem[bp].p;
tr.c = l.elem[cp].p; tr.c = l.elem[cp].p;
if((tr.a).Equals(tr.c)) {
// This is two coincident and anti-parallel edges. Zero-area, so
// won't generate a real triangle, but we certainly can clip it.
return true;
}
Vector n = Vector::From(0, 0, -1); Vector n = Vector::From(0, 0, -1);
if((tr.Normal()).Dot(n) < LENGTH_EPS) { if((tr.Normal()).Dot(n) < LENGTH_EPS) {
// This vertex is reflex, or between two collinear edges; either way, // This vertex is reflex, or between two collinear edges; either way,
@ -222,7 +233,12 @@ void SContour::ClipEarInto(SMesh *m, int bp) {
tr.a = l.elem[ap].p; tr.a = l.elem[ap].p;
tr.b = l.elem[bp].p; tr.b = l.elem[bp].p;
tr.c = l.elem[cp].p; tr.c = l.elem[cp].p;
if(tr.Normal().MagSquared() < LENGTH_EPS*LENGTH_EPS) {
// A vertex with more than two edges will cause us to generate
// zero-area triangles, which must be culled.
} else {
m->AddTriangle(&tr); m->AddTriangle(&tr);
}
// By deleting the point at bp, we may change the ear-ness of the points // By deleting the point at bp, we may change the ear-ness of the points
// on either side. // on either side.
@ -236,7 +252,17 @@ void SContour::ClipEarInto(SMesh *m, int bp) {
void SContour::UvTriangulateInto(SMesh *m) { void SContour::UvTriangulateInto(SMesh *m) {
int i; int i;
// First, calculate the ear-ness of all the points
// Clean the original contour by removing any zero-length edges.
l.ClearTags();
for(i = 1; i < l.n; i++) {
if((l.elem[i].p).Equals(l.elem[i-1].p)) {
l.elem[i].tag = 1;
}
}
l.RemoveTagged();
// Now calculate the ear-ness of each vertex
for(i = 0; i < l.n; i++) { for(i = 0; i < l.n; i++) {
(l.elem[i]).ear = IsEar(i) ? SPoint::EAR : SPoint::NOT_EAR; (l.elem[i]).ear = IsEar(i) ? SPoint::EAR : SPoint::NOT_EAR;
} }