diff --git a/export.cpp b/export.cpp index f0da055..15acf88 100644 --- a/export.cpp +++ b/export.cpp @@ -237,6 +237,8 @@ void SolveSpace::ExportLinesAndMesh(SEdgeList *sel, SMesh *sm, // Split the original edge against the mesh out.AddEdge(se->a, se->b); root->OcclusionTestLine(*se, &out, cnt); + // the occlusion test splits unnecessarily; so fix those + out.MergeCollinearSegments(se->a, se->b); cnt++; // And add the results to our output SEdge *sen; diff --git a/polygon.cpp b/polygon.cpp index c74b783..7e3e031 100644 --- a/polygon.cpp +++ b/polygon.cpp @@ -247,6 +247,41 @@ void SEdgeList::CullExtraneousEdges(void) { l.RemoveTagged(); } +//----------------------------------------------------------------------------- +// We have an edge list that contains only collinear edges, maybe with more +// splits than necessary. Merge any collinear segments that join. +//----------------------------------------------------------------------------- +static Vector LineStart, LineDirection; +static int ByTAlongLine(const void *av, const void *bv) +{ + SEdge *a = (SEdge *)av, + *b = (SEdge *)bv; + + double ta = (a->a.Minus(LineStart)).DivPivoting(LineDirection), + tb = (b->a.Minus(LineStart)).DivPivoting(LineDirection); + + return (ta > tb) ? 1 : -1; +} +void SEdgeList::MergeCollinearSegments(Vector a, Vector b) { + LineStart = a; + LineDirection = b.Minus(a); + qsort(l.elem, l.n, sizeof(l.elem[0]), ByTAlongLine); + + l.ClearTags(); + int i; + for(i = 1; i < l.n; i++) { + SEdge *prev = &(l.elem[i-1]), + *now = &(l.elem[i]); + + if((prev->b).Equals(now->a)) { + // The previous segment joins up to us; so merge it into us. + prev->tag = 1; + now->a = prev->a; + } + } + l.RemoveTagged(); +} + void SContour::AddPoint(Vector p) { SPoint sp; sp.tag = 0; diff --git a/polygon.h b/polygon.h index 47c59ee..caccb91 100644 --- a/polygon.h +++ b/polygon.h @@ -27,6 +27,7 @@ public: SEdge *errorAt, bool keepDir); int AnyEdgeCrossings(Vector a, Vector b, Vector *pi=NULL); void CullExtraneousEdges(void); + void MergeCollinearSegments(Vector a, Vector b); }; class SPoint {