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.
This commit is contained in:
parent
16ea824456
commit
7c60be8203
120
src/export.cpp
120
src/export.cpp
|
@ -362,6 +362,126 @@ void SolveSpaceUI::ExportLinesAndMesh(SEdgeList *sel, SBezierList *sbl, SMesh *s
|
||||||
sel = &hlrd;
|
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
|
// 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 together, and also project everything into the xy plane, since not
|
||||||
// all export targets ignore the z component of the points.
|
// all export targets ignore the z component of the points.
|
||||||
|
|
|
@ -796,6 +796,7 @@ public:
|
||||||
bool exportable;
|
bool exportable;
|
||||||
int stippleType;
|
int stippleType;
|
||||||
double stippleScale;
|
double stippleScale;
|
||||||
|
int zIndex;
|
||||||
|
|
||||||
// The default styles, for entities that don't have a style assigned yet,
|
// The default styles, for entities that don't have a style assigned yet,
|
||||||
// and for datums and such.
|
// and for datums and such.
|
||||||
|
@ -804,6 +805,7 @@ public:
|
||||||
const char *cnfPrefix;
|
const char *cnfPrefix;
|
||||||
RgbaColor color;
|
RgbaColor color;
|
||||||
double width;
|
double width;
|
||||||
|
int zIndex;
|
||||||
} Default;
|
} Default;
|
||||||
static const Default Defaults[];
|
static const Default Defaults[];
|
||||||
|
|
||||||
|
|
|
@ -11,20 +11,20 @@
|
||||||
#define DEFAULT_TEXT_HEIGHT 11.5
|
#define DEFAULT_TEXT_HEIGHT 11.5
|
||||||
|
|
||||||
const Style::Default Style::Defaults[] = {
|
const Style::Default Style::Defaults[] = {
|
||||||
{ { ACTIVE_GRP }, "ActiveGrp", RGBf(1.0, 1.0, 1.0), 1.5, },
|
{ { ACTIVE_GRP }, "ActiveGrp", RGBf(1.0, 1.0, 1.0), 1.5, 4 },
|
||||||
{ { CONSTRUCTION }, "Construction", RGBf(0.1, 0.7, 0.1), 1.5, },
|
{ { CONSTRUCTION }, "Construction", RGBf(0.1, 0.7, 0.1), 1.5, 0 },
|
||||||
{ { INACTIVE_GRP }, "InactiveGrp", RGBf(0.5, 0.3, 0.0), 1.5, },
|
{ { INACTIVE_GRP }, "InactiveGrp", RGBf(0.5, 0.3, 0.0), 1.5, 3 },
|
||||||
{ { DATUM }, "Datum", RGBf(0.0, 0.8, 0.0), 1.5, },
|
{ { DATUM }, "Datum", RGBf(0.0, 0.8, 0.0), 1.5, 0 },
|
||||||
{ { SOLID_EDGE }, "SolidEdge", RGBf(0.8, 0.8, 0.8), 1.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, },
|
{ { CONSTRAINT }, "Constraint", RGBf(1.0, 0.1, 1.0), 1.0, 0 },
|
||||||
{ { SELECTED }, "Selected", RGBf(1.0, 0.0, 0.0), 1.5, },
|
{ { SELECTED }, "Selected", RGBf(1.0, 0.0, 0.0), 1.5, 0 },
|
||||||
{ { HOVERED }, "Hovered", RGBf(1.0, 1.0, 0.0), 1.5, },
|
{ { HOVERED }, "Hovered", RGBf(1.0, 1.0, 0.0), 1.5, 0 },
|
||||||
{ { CONTOUR_FILL }, "ContourFill", RGBf(0.0, 0.1, 0.1), 1.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, },
|
{ { NORMALS }, "Normals", RGBf(0.0, 0.4, 0.4), 1.0, 0 },
|
||||||
{ { ANALYZE }, "Analyze", RGBf(0.0, 1.0, 1.0), 1.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, },
|
{ { 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, },
|
{ { 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 }, NULL, RGBf(0.0, 0.0, 0.0), 0.0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string Style::CnfColor(const std::string &prefix) {
|
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->fillColor = RGBf(0.3, 0.3, 0.3);
|
||||||
s->stippleType = Style::STIPPLE_CONTINUOUS;
|
s->stippleType = Style::STIPPLE_CONTINUOUS;
|
||||||
s->stippleScale = 15.0;
|
s->stippleScale = 15.0;
|
||||||
|
s->zIndex = d->zIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Style::LoadFactoryDefaults(void) {
|
void Style::LoadFactoryDefaults(void) {
|
||||||
|
@ -117,6 +118,7 @@ void Style::LoadFactoryDefaults(void) {
|
||||||
s->stippleType = Style::STIPPLE_CONTINUOUS;
|
s->stippleType = Style::STIPPLE_CONTINUOUS;
|
||||||
s->stippleScale = 15.0;
|
s->stippleScale = 15.0;
|
||||||
s->name = CnfPrefixToName(d->cnfPrefix);
|
s->name = CnfPrefixToName(d->cnfPrefix);
|
||||||
|
s->zIndex = d->zIndex;
|
||||||
}
|
}
|
||||||
SS.backgroundColor = RGBi(0, 0, 0);
|
SS.backgroundColor = RGBi(0, 0, 0);
|
||||||
if(SS.bgImage.fromFile) MemFree(SS.bgImage.fromFile);
|
if(SS.bgImage.fromFile) MemFree(SS.bgImage.fromFile);
|
||||||
|
@ -781,7 +783,6 @@ void TextWindow::ShowStyleInfo(void) {
|
||||||
s->h.v, &ScreenChangeStyleName,
|
s->h.v, &ScreenChangeStyleName,
|
||||||
s->h.v, &ScreenDeleteStyle);
|
s->h.v, &ScreenDeleteStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
Printf(true, "%Ft line stroke style%E");
|
Printf(true, "%Ft line stroke style%E");
|
||||||
Printf(false, "%Ba %Ftcolor %E%Bz %Ba (%@, %@, %@) %D%f%Ls%Fl[change]%E",
|
Printf(false, "%Ba %Ftcolor %E%Bz %Ba (%@, %@, %@) %D%f%Ls%Fl[change]%E",
|
||||||
&s->color,
|
&s->color,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user