From 47288e9a4c9339ff53db88b3f7819895eeec140c Mon Sep 17 00:00:00 2001 From: whitequark Date: Tue, 11 Oct 2016 10:38:21 +0000 Subject: [PATCH] Stitch outlines before display to preserve phase of stippling. Before this commit, the outlines are generated in an arbitrary order from the kd-tree. This worked just fine for continuous lines, but for stippling, especially on curves, this meant that most of the piecewise linear edges would have the stippling phase restart from zero, leading to a very poor appearance. --- src/groupmesh.cpp | 10 +++++++-- src/polygon.h | 5 +++++ src/polyline.cpp | 55 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 2 deletions(-) diff --git a/src/groupmesh.cpp b/src/groupmesh.cpp index afd76bb..dac5869 100644 --- a/src/groupmesh.cpp +++ b/src/groupmesh.cpp @@ -401,12 +401,18 @@ void Group::GenerateDisplayItems() { displayOutlines.Clear(); if(SS.GW.showEdges || SS.GW.showOutlines) { + SOutlineList rawOutlines = {}; if(runningMesh.l.n > 0) { // Triangle mesh only; no shell or emphasized edges. - runningMesh.MakeOutlinesInto(&displayOutlines, EdgeKind::EMPHASIZED); + runningMesh.MakeOutlinesInto(&rawOutlines, EdgeKind::EMPHASIZED); } else { - displayMesh.MakeOutlinesInto(&displayOutlines, EdgeKind::SHARP); + displayMesh.MakeOutlinesInto(&rawOutlines, EdgeKind::SHARP); } + + PolylineBuilder builder; + builder.MakeFromOutlines(rawOutlines); + builder.GenerateOutlines(&displayOutlines); + rawOutlines.Clear(); } } diff --git a/src/polygon.h b/src/polygon.h index 2ef818c..8136860 100644 --- a/src/polygon.h +++ b/src/polygon.h @@ -396,6 +396,11 @@ public: std::function nextFunc, std::function aloneFunc, std::function endFunc = [](){}); + + void MakeFromEdges(const SEdgeList &sel); + void MakeFromOutlines(const SOutlineList &sol); + void GenerateEdges(SEdgeList *sel); + void GenerateOutlines(SOutlineList *sol); }; #endif diff --git a/src/polyline.cpp b/src/polyline.cpp index f7dcace..bddf1ab 100644 --- a/src/polyline.cpp +++ b/src/polyline.cpp @@ -187,3 +187,58 @@ void PolylineBuilder::Generate( aloneFunc(e); } } + +void PolylineBuilder::MakeFromEdges(const SEdgeList &sel) { + for(const SEdge &se : sel.l) { + AddEdge(se.a, se.b, (uint32_t)se.auxA, reinterpret_cast(&se)); + } +} + +void PolylineBuilder::MakeFromOutlines(const SOutlineList &ol) { + for(const SOutline &so : ol.l) { + // Use outline tag as kind, so that emphasized and contour outlines + // would not be composed together. + AddEdge(so.a, so.b, (uint32_t)so.tag, reinterpret_cast(&so)); + } +} + +void PolylineBuilder::GenerateEdges(SEdgeList *sel) { + Vector prev; + auto startFunc = [&](Vertex *start, Vertex *next, Edge *e) { + sel->AddEdge(start->pos, next->pos, e->kind); + prev = next->pos; + }; + + auto nextFunc = [&](Vertex *next, Edge *e) { + sel->AddEdge(prev, next->pos, e->kind); + prev = next->pos; + }; + + auto aloneFunc = [&](Edge *e) { + sel->AddEdge(e->a->pos, e->b->pos, e->kind); + }; + + Generate(startFunc, nextFunc, aloneFunc); +} + +void PolylineBuilder::GenerateOutlines(SOutlineList *sol) { + Vector prev; + auto startFunc = [&](Vertex *start, Vertex *next, Edge *e) { + SOutline *so = e->outline; + sol->AddEdge(start->pos, next->pos, so->nl, so->nr, so->tag); + prev = next->pos; + }; + + auto nextFunc = [&](Vertex *next, Edge *e) { + SOutline *so = e->outline; + sol->AddEdge(prev, next->pos, so->nl, so->nr, so->tag); + prev = next->pos; + }; + + auto aloneFunc = [&](Edge *e) { + SOutline *so = e->outline; + sol->AddEdge(so->a, so->b, so->nl, so->nr, so->tag); + }; + + Generate(startFunc, nextFunc, aloneFunc); +}