From 7c60be8203cda47a420d566003dc05f4ee7c6fb7 Mon Sep 17 00:00:00 2001 From: EvilSpirit Date: Sun, 13 Mar 2016 15:27:59 +0600 Subject: [PATCH] Remove overlapping line segments when exporting a 2d view. This adds a new style attribute, "Z-index", which is not currently displayed and cannot be modified. It may be exposed in the UI later. --- src/export.cpp | 120 +++++++++++++++++++++++++++++++++++++++++++++++++ src/sketch.h | 2 + src/style.cpp | 31 ++++++------- 3 files changed, 138 insertions(+), 15 deletions(-) diff --git a/src/export.cpp b/src/export.cpp index eb8a953..ea7d599 100644 --- a/src/export.cpp +++ b/src/export.cpp @@ -362,6 +362,126 @@ void SolveSpaceUI::ExportLinesAndMesh(SEdgeList *sel, SBezierList *sbl, SMesh *s sel = &hlrd; } + // Clean up: remove overlapping line segments and + // segments with zero-length projections. + sel->l.ClearTags(); + for(int i = 0; i < sel->l.n; ++i) { + SEdge *sei = &sel->l.elem[i]; + hStyle hsi = { (uint32_t)sei->auxA }; + Style *si = Style::Get(hsi); + if(sei->tag != 0) continue; + + // Remove segments with zero length projections. + Vector ai = sei->a; + ai.z = 0.0; + Vector bi = sei->b; + bi.z = 0.0; + Vector di = bi.Minus(ai); + if(fabs(di.x) < LENGTH_EPS && fabs(di.y) < LENGTH_EPS) { + sei->tag = 1; + continue; + } + + for(int j = i + 1; j < sel->l.n; ++j) { + SEdge *sej = &sel->l.elem[j]; + if(sej->tag != 0) continue; + + Vector *pAj = &sej->a; + Vector *pBj = &sej->b; + + // Remove segments with zero length projections. + Vector aj = sej->a; + aj.z = 0.0; + Vector bj = sej->b; + bj.z = 0.0; + Vector dj = bj.Minus(aj); + if(fabs(dj.x) < LENGTH_EPS && fabs(dj.y) < LENGTH_EPS) { + sej->tag = 1; + continue; + } + + // Skip non-collinear segments. + const double eps = 1e-6; + if(aj.DistanceToLine(ai, di) > eps) continue; + if(bj.DistanceToLine(ai, di) > eps) continue; + + double ta = aj.Minus(ai).Dot(di) / di.Dot(di); + double tb = bj.Minus(ai).Dot(di) / di.Dot(di); + if(ta > tb) { + std::swap(pAj, pBj); + std::swap(ta, tb); + } + + hStyle hsj = { (uint32_t)sej->auxA }; + Style *sj = Style::Get(hsj); + + bool canRemoveI = sej->auxA == sei->auxA || si->zIndex < sj->zIndex; + bool canRemoveJ = sej->auxA == sei->auxA || sj->zIndex < si->zIndex; + + if(canRemoveJ) { + // j-segment inside i-segment + if(ta > 0.0 - eps && tb < 1.0 + eps) { + sej->tag = 1; + continue; + } + + // cut segment + bool aInside = ta > 0.0 - eps && ta < 1.0 + eps; + if(tb > 1.0 - eps && aInside) { + *pAj = sei->b; + continue; + } + + // cut segment + bool bInside = tb > 0.0 - eps && tb < 1.0 + eps; + if(ta < 0.0 - eps && bInside) { + *pBj = sei->a; + continue; + } + + // split segment + if(ta < 0.0 - eps && tb > 1.0 + eps) { + sel->AddEdge(sei->b, *pBj, sej->auxA, sej->auxB); + *pBj = sei->a; + continue; + } + } + + if(canRemoveI) { + // j-segment inside i-segment + if(ta < 0.0 + eps && tb > 1.0 - eps) { + sei->tag = 1; + break; + } + + // cut segment + bool aInside = ta > 0.0 + eps && ta < 1.0 - eps; + if(tb > 1.0 - eps && aInside) { + sei->b = *pAj; + i--; + break; + } + + // cut segment + bool bInside = tb > 0.0 + eps && tb < 1.0 - eps; + if(ta < 0.0 + eps && bInside) { + sei->a = *pBj; + i--; + break; + } + + // split segment + if(ta > 0.0 + eps && tb < 1.0 - eps) { + sel->AddEdge(*pBj, sei->b, sei->auxA, sei->auxB); + sei->b = *pAj; + i--; + break; + } + } + } + } + sel->l.RemoveTagged(); + // We kept the line segments and Beziers separate until now; but put them // all together, and also project everything into the xy plane, since not // all export targets ignore the z component of the points. diff --git a/src/sketch.h b/src/sketch.h index 371bb38..e700c48 100644 --- a/src/sketch.h +++ b/src/sketch.h @@ -796,6 +796,7 @@ public: bool exportable; int stippleType; double stippleScale; + int zIndex; // The default styles, for entities that don't have a style assigned yet, // and for datums and such. @@ -804,6 +805,7 @@ public: const char *cnfPrefix; RgbaColor color; double width; + int zIndex; } Default; static const Default Defaults[]; diff --git a/src/style.cpp b/src/style.cpp index a86a017..f7d8622 100644 --- a/src/style.cpp +++ b/src/style.cpp @@ -11,20 +11,20 @@ #define DEFAULT_TEXT_HEIGHT 11.5 const Style::Default Style::Defaults[] = { - { { ACTIVE_GRP }, "ActiveGrp", RGBf(1.0, 1.0, 1.0), 1.5, }, - { { CONSTRUCTION }, "Construction", RGBf(0.1, 0.7, 0.1), 1.5, }, - { { INACTIVE_GRP }, "InactiveGrp", RGBf(0.5, 0.3, 0.0), 1.5, }, - { { DATUM }, "Datum", RGBf(0.0, 0.8, 0.0), 1.5, }, - { { SOLID_EDGE }, "SolidEdge", RGBf(0.8, 0.8, 0.8), 1.0, }, - { { CONSTRAINT }, "Constraint", RGBf(1.0, 0.1, 1.0), 1.0, }, - { { SELECTED }, "Selected", RGBf(1.0, 0.0, 0.0), 1.5, }, - { { HOVERED }, "Hovered", RGBf(1.0, 1.0, 0.0), 1.5, }, - { { CONTOUR_FILL }, "ContourFill", RGBf(0.0, 0.1, 0.1), 1.0, }, - { { NORMALS }, "Normals", RGBf(0.0, 0.4, 0.4), 1.0, }, - { { ANALYZE }, "Analyze", RGBf(0.0, 1.0, 1.0), 1.0, }, - { { DRAW_ERROR }, "DrawError", RGBf(1.0, 0.0, 0.0), 8.0, }, - { { DIM_SOLID }, "DimSolid", RGBf(0.1, 0.1, 0.1), 1.0, }, - { { 0 }, NULL, RGBf(0.0, 0.0, 0.0), 0.0 } + { { ACTIVE_GRP }, "ActiveGrp", RGBf(1.0, 1.0, 1.0), 1.5, 4 }, + { { CONSTRUCTION }, "Construction", RGBf(0.1, 0.7, 0.1), 1.5, 0 }, + { { INACTIVE_GRP }, "InactiveGrp", RGBf(0.5, 0.3, 0.0), 1.5, 3 }, + { { DATUM }, "Datum", RGBf(0.0, 0.8, 0.0), 1.5, 0 }, + { { SOLID_EDGE }, "SolidEdge", RGBf(0.8, 0.8, 0.8), 1.0, 2 }, + { { CONSTRAINT }, "Constraint", RGBf(1.0, 0.1, 1.0), 1.0, 0 }, + { { SELECTED }, "Selected", RGBf(1.0, 0.0, 0.0), 1.5, 0 }, + { { HOVERED }, "Hovered", RGBf(1.0, 1.0, 0.0), 1.5, 0 }, + { { CONTOUR_FILL }, "ContourFill", RGBf(0.0, 0.1, 0.1), 1.0, 0 }, + { { NORMALS }, "Normals", RGBf(0.0, 0.4, 0.4), 1.0, 0 }, + { { ANALYZE }, "Analyze", RGBf(0.0, 1.0, 1.0), 1.0, 0 }, + { { DRAW_ERROR }, "DrawError", RGBf(1.0, 0.0, 0.0), 8.0, 0 }, + { { DIM_SOLID }, "DimSolid", RGBf(0.1, 0.1, 0.1), 1.0, 0 }, + { { 0 }, NULL, RGBf(0.0, 0.0, 0.0), 0.0, 0 } }; std::string Style::CnfColor(const std::string &prefix) { @@ -96,6 +96,7 @@ void Style::FillDefaultStyle(Style *s, const Default *d) { s->fillColor = RGBf(0.3, 0.3, 0.3); s->stippleType = Style::STIPPLE_CONTINUOUS; s->stippleScale = 15.0; + s->zIndex = d->zIndex; } void Style::LoadFactoryDefaults(void) { @@ -117,6 +118,7 @@ void Style::LoadFactoryDefaults(void) { s->stippleType = Style::STIPPLE_CONTINUOUS; s->stippleScale = 15.0; s->name = CnfPrefixToName(d->cnfPrefix); + s->zIndex = d->zIndex; } SS.backgroundColor = RGBi(0, 0, 0); if(SS.bgImage.fromFile) MemFree(SS.bgImage.fromFile); @@ -781,7 +783,6 @@ void TextWindow::ShowStyleInfo(void) { s->h.v, &ScreenChangeStyleName, s->h.v, &ScreenDeleteStyle); } - Printf(true, "%Ft line stroke style%E"); Printf(false, "%Ba %Ftcolor %E%Bz %Ba (%@, %@, %@) %D%f%Ls%Fl[change]%E", &s->color,