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:
parent
2023667311
commit
77cace05ce
@ -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 {
|
||||
|
@ -141,6 +141,7 @@ void vl(void); // debug function to validate heaps
|
||||
//================
|
||||
|
||||
|
||||
class SSurface;
|
||||
#include "dsc.h"
|
||||
#include "polygon.h"
|
||||
#include "srf/surface.h"
|
||||
|
@ -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++) {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user