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 IsEar(int bp);
|
||||||
bool BridgeToContour(SContour *sc, SEdgeList *el, List<Vector> *vl);
|
bool BridgeToContour(SContour *sc, SEdgeList *el, List<Vector> *vl);
|
||||||
void ClipEarInto(SMesh *m, int bp);
|
void ClipEarInto(SMesh *m, int bp);
|
||||||
void UvTriangulateInto(SMesh *m);
|
void UvTriangulateInto(SMesh *m, SSurface *srf);
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -88,7 +88,7 @@ public:
|
|||||||
bool IsEmpty(void);
|
bool IsEmpty(void);
|
||||||
Vector AnyPoint(void);
|
Vector AnyPoint(void);
|
||||||
void OffsetInto(SPolygon *dest, double r);
|
void OffsetInto(SPolygon *dest, double r);
|
||||||
void UvTriangulateInto(SMesh *m);
|
void UvTriangulateInto(SMesh *m, SSurface *srf);
|
||||||
};
|
};
|
||||||
|
|
||||||
class STriangle {
|
class STriangle {
|
||||||
|
@ -141,6 +141,7 @@ void vl(void); // debug function to validate heaps
|
|||||||
//================
|
//================
|
||||||
|
|
||||||
|
|
||||||
|
class SSurface;
|
||||||
#include "dsc.h"
|
#include "dsc.h"
|
||||||
#include "polygon.h"
|
#include "polygon.h"
|
||||||
#include "srf/surface.h"
|
#include "srf/surface.h"
|
||||||
|
@ -731,7 +731,9 @@ void SSurface::TriangulateInto(SShell *shell, SMesh *sm) {
|
|||||||
ZERO(&poly);
|
ZERO(&poly);
|
||||||
if(el.AssemblePolygon(&poly, NULL, true)) {
|
if(el.AssemblePolygon(&poly, NULL, true)) {
|
||||||
int i, start = sm->l.n;
|
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 };
|
STriMeta meta = { face, color };
|
||||||
for(i = start; i < sm->l.n; i++) {
|
for(i = start; i < sm->l.n; i++) {
|
||||||
|
@ -211,6 +211,7 @@ public:
|
|||||||
void TriangulateInto(SShell *shell, SMesh *sm);
|
void TriangulateInto(SShell *shell, SMesh *sm);
|
||||||
void MakeEdgesInto(SShell *shell, SEdgeList *sel, bool asUv);
|
void MakeEdgesInto(SShell *shell, SEdgeList *sel, bool asUv);
|
||||||
void MakeClassifyingBsp(SShell *shell);
|
void MakeClassifyingBsp(SShell *shell);
|
||||||
|
double ChordToleranceForEdge(Vector a, Vector b);
|
||||||
|
|
||||||
void Reverse(void);
|
void Reverse(void);
|
||||||
void Clear(void);
|
void Clear(void);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "../solvespace.h"
|
#include "../solvespace.h"
|
||||||
|
|
||||||
void SPolygon::UvTriangulateInto(SMesh *m) {
|
void SPolygon::UvTriangulateInto(SMesh *m, SSurface *srf) {
|
||||||
if(l.n <= 0) return;
|
if(l.n <= 0) return;
|
||||||
|
|
||||||
SDWORD in = GetMilliseconds();
|
SDWORD in = GetMilliseconds();
|
||||||
@ -80,7 +80,7 @@ void SPolygon::UvTriangulateInto(SMesh *m) {
|
|||||||
}
|
}
|
||||||
// dbp("finished merging holes: %d ms", GetMilliseconds() - in);
|
// dbp("finished merging holes: %d ms", GetMilliseconds() - in);
|
||||||
|
|
||||||
merged.UvTriangulateInto(m);
|
merged.UvTriangulateInto(m, srf);
|
||||||
// dbp("finished ear clippping: %d ms", GetMilliseconds() - in);
|
// dbp("finished ear clippping: %d ms", GetMilliseconds() - in);
|
||||||
merged.l.Clear();
|
merged.l.Clear();
|
||||||
el.Clear();
|
el.Clear();
|
||||||
@ -250,7 +250,7 @@ void SContour::ClipEarInto(SMesh *m, int bp) {
|
|||||||
l.RemoveTagged();
|
l.RemoveTagged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SContour::UvTriangulateInto(SMesh *m) {
|
void SContour::UvTriangulateInto(SMesh *m, SSurface *srf) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
// Clean the original contour by removing any zero-length edges.
|
// 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
|
int bestEar = -1;
|
||||||
// we generate strip-like triangulations instead of fan-like
|
double bestChordTol = VERY_POSITIVE;
|
||||||
int ear = -1;
|
// Alternate the starting position so we generate strip-like
|
||||||
|
// triangulations instead of fan-like
|
||||||
toggle = !toggle;
|
toggle = !toggle;
|
||||||
int offset = toggle ? -1 : 0;
|
int offset = toggle ? -1 : 0;
|
||||||
for(i = 0; i < l.n; i++) {
|
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) {
|
if(l.elem[ear].ear == SPoint::EAR) {
|
||||||
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(ear < 0) {
|
}
|
||||||
|
if(bestEar < 0) {
|
||||||
dbp("couldn't find an ear! fail");
|
dbp("couldn't find an ear! fail");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ClipEarInto(m, ear);
|
ClipEarInto(m, bestEar);
|
||||||
}
|
}
|
||||||
|
|
||||||
ClipEarInto(m, 0); // add the last triangle
|
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