When clipping ears to triangulate a curved surface, clip the ear

that minimizes the chord tolerance.

[git-p4: depot-paths = "//depot/solvespace/": change = 1921]
This commit is contained in:
Jonathan Westhues 2009-02-27 06:05:08 -08:00
parent 2023667311
commit 77cace05ce
5 changed files with 50 additions and 13 deletions

View File

@ -61,7 +61,7 @@ public:
bool IsEar(int bp);
bool BridgeToContour(SContour *sc, SEdgeList *el, List<Vector> *vl);
void ClipEarInto(SMesh *m, int bp);
void UvTriangulateInto(SMesh *m);
void UvTriangulateInto(SMesh *m, SSurface *srf);
};
typedef struct {
@ -88,7 +88,7 @@ public:
bool IsEmpty(void);
Vector AnyPoint(void);
void OffsetInto(SPolygon *dest, double r);
void UvTriangulateInto(SMesh *m);
void UvTriangulateInto(SMesh *m, SSurface *srf);
};
class STriangle {

View File

@ -141,6 +141,7 @@ void vl(void); // debug function to validate heaps
//================
class SSurface;
#include "dsc.h"
#include "polygon.h"
#include "srf/surface.h"

View File

@ -731,7 +731,9 @@ void SSurface::TriangulateInto(SShell *shell, SMesh *sm) {
ZERO(&poly);
if(el.AssemblePolygon(&poly, NULL, true)) {
int i, start = sm->l.n;
poly.UvTriangulateInto(sm);
// Curved surfaces are triangulated in such a way as to minimize
// deviation between edges and surface; but doesn't matter for planes.
poly.UvTriangulateInto(sm, (degm == 1 && degn == 1) ? NULL : this);
STriMeta meta = { face, color };
for(i = start; i < sm->l.n; i++) {

View File

@ -211,6 +211,7 @@ public:
void TriangulateInto(SShell *shell, SMesh *sm);
void MakeEdgesInto(SShell *shell, SEdgeList *sel, bool asUv);
void MakeClassifyingBsp(SShell *shell);
double ChordToleranceForEdge(Vector a, Vector b);
void Reverse(void);
void Clear(void);

View File

@ -1,6 +1,6 @@
#include "../solvespace.h"
void SPolygon::UvTriangulateInto(SMesh *m) {
void SPolygon::UvTriangulateInto(SMesh *m, SSurface *srf) {
if(l.n <= 0) return;
SDWORD in = GetMilliseconds();
@ -80,7 +80,7 @@ void SPolygon::UvTriangulateInto(SMesh *m) {
}
// dbp("finished merging holes: %d ms", GetMilliseconds() - in);
merged.UvTriangulateInto(m);
merged.UvTriangulateInto(m, srf);
// dbp("finished ear clippping: %d ms", GetMilliseconds() - in);
merged.l.Clear();
el.Clear();
@ -250,7 +250,7 @@ void SContour::ClipEarInto(SMesh *m, int bp) {
l.RemoveTagged();
}
void SContour::UvTriangulateInto(SMesh *m) {
void SContour::UvTriangulateInto(SMesh *m, SSurface *srf) {
int i;
// Clean the original contour by removing any zero-length edges.
@ -276,24 +276,57 @@ void SContour::UvTriangulateInto(SMesh *m) {
}
}
// And find a candidate ear; alternate the starting position so
// we generate strip-like triangulations instead of fan-like
int ear = -1;
int bestEar = -1;
double bestChordTol = VERY_POSITIVE;
// Alternate the starting position so we generate strip-like
// triangulations instead of fan-like
toggle = !toggle;
int offset = toggle ? -1 : 0;
for(i = 0; i < l.n; i++) {
ear = WRAP(i+offset, l.n);
int ear = WRAP(i+offset, l.n);
if(l.elem[ear].ear == SPoint::EAR) {
break;
if(!srf) {
bestEar = ear;
break;
}
// If we are triangulating a curved surface, then try to
// clip ears that have a small chord tolerance from the
// surface.
Vector prev = l.elem[WRAP((i+offset-1), l.n)].p,
next = l.elem[WRAP((i+offset+1), l.n)].p;
double tol = srf->ChordToleranceForEdge(prev, next);
if(tol < bestChordTol - LENGTH_EPS) {
bestEar = ear;
bestChordTol = tol;
}
if(bestChordTol < 0.1*(SS.chordTol / SS.GW.scale)) {
break;
}
}
}
if(ear < 0) {
if(bestEar < 0) {
dbp("couldn't find an ear! fail");
return;
}
ClipEarInto(m, ear);
ClipEarInto(m, bestEar);
}
ClipEarInto(m, 0); // add the last triangle
}
double SSurface::ChordToleranceForEdge(Vector a, Vector b) {
Vector as = PointAt(a.x, a.y), bs = PointAt(b.x, b.y);
double worst = VERY_NEGATIVE;
int i;
for(i = 1; i <= 3; i++) {
Vector p = a. Plus((b. Minus(a )).ScaledBy(i/4.0)),
ps = as.Plus((bs.Minus(as)).ScaledBy(i/4.0));
Vector pps = PointAt(p.x, p.y);
worst = max(worst, (pps.Minus(ps)).MagSquared());
}
return sqrt(worst);
}