Now actually export the line styles, for PDF, EPS, and SVG file
formats, with the proper color and width. This may need a bit of cleanup for stuff like the hidden line removal, which currently loses the style. Also fix a bug in the test for arcs of a circle. A second-order Bezier with collinear control points really is an arc, but it's an arc with infinite radius so stuff tends to blow up. So return false for that one. [git-p4: depot-paths = "//depot/solvespace/": change = 2030]
This commit is contained in:
parent
517c5edbfa
commit
9b8f32dad7
@ -20,7 +20,7 @@ bool Constraint::HasLabel(void) {
|
|||||||
void Constraint::LineDrawOrGetDistance(Vector a, Vector b) {
|
void Constraint::LineDrawOrGetDistance(Vector a, Vector b) {
|
||||||
if(dogd.drawing) {
|
if(dogd.drawing) {
|
||||||
if(dogd.sel) {
|
if(dogd.sel) {
|
||||||
dogd.sel->AddEdge(a, b);
|
dogd.sel->AddEdge(a, b, Style::CONSTRAINT);
|
||||||
} else {
|
} else {
|
||||||
glBegin(GL_LINE_STRIP);
|
glBegin(GL_LINE_STRIP);
|
||||||
glxVertex3v(a);
|
glxVertex3v(a);
|
||||||
|
@ -179,7 +179,7 @@ void Entity::GenerateEdges(SEdgeList *el, bool includingConstruction) {
|
|||||||
ZERO(&lv);
|
ZERO(&lv);
|
||||||
sb->MakePwlInto(&lv);
|
sb->MakePwlInto(&lv);
|
||||||
for(j = 1; j < lv.n; j++) {
|
for(j = 1; j < lv.n; j++) {
|
||||||
el->AddEdge(lv.elem[j-1], lv.elem[j]);
|
el->AddEdge(lv.elem[j-1], lv.elem[j], style.v);
|
||||||
}
|
}
|
||||||
lv.Clear();
|
lv.Clear();
|
||||||
}
|
}
|
||||||
@ -230,6 +230,11 @@ bool Entity::IsVisible(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(style.v) {
|
||||||
|
Style *s = Style::Get(style);
|
||||||
|
if(!s->visible) return false;
|
||||||
|
}
|
||||||
|
|
||||||
if(forceHidden) return false;
|
if(forceHidden) return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -259,9 +264,11 @@ bool Entity::PointIsFromReferences(void) {
|
|||||||
return h.request().IsFromReferences();
|
return h.request().IsFromReferences();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entity::GenerateBezierCurves(SBezierList *sbl) {
|
void Entity::GenerateBezierCurves(SBezierList *sbl) {
|
||||||
SBezier sb;
|
SBezier sb;
|
||||||
|
|
||||||
|
int i = sbl->l.n;
|
||||||
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case LINE_SEGMENT: {
|
case LINE_SEGMENT: {
|
||||||
Vector a = SK.GetEntity(point[0])->PointGetNum();
|
Vector a = SK.GetEntity(point[0])->PointGetNum();
|
||||||
@ -357,6 +364,11 @@ void Entity::GenerateBezierCurves(SBezierList *sbl) {
|
|||||||
// Not a problem, points and normals and such don't generate curves
|
// Not a problem, points and normals and such don't generate curves
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Record our style for all of the Beziers that we just created.
|
||||||
|
for(; i < sbl->l.n; i++) {
|
||||||
|
sbl->l.elem[i].auxA = style.v;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entity::DrawOrGetDistance(void) {
|
void Entity::DrawOrGetDistance(void) {
|
||||||
|
40
export.cpp
40
export.cpp
@ -82,6 +82,16 @@ void SolveSpace::ExportSectionTo(char *filename) {
|
|||||||
&el,
|
&el,
|
||||||
(SS.exportPwlCurves || fabs(SS.exportOffset) > LENGTH_EPS) ? NULL : &bl);
|
(SS.exportPwlCurves || fabs(SS.exportOffset) > LENGTH_EPS) ? NULL : &bl);
|
||||||
|
|
||||||
|
// All of these are solid model edges, so use the appropriate style.
|
||||||
|
SEdge *se;
|
||||||
|
for(se = el.l.First(); se; se = el.l.NextAfter(se)) {
|
||||||
|
se->auxA = Style::SOLID_EDGE;
|
||||||
|
}
|
||||||
|
SBezier *sb;
|
||||||
|
for(sb = bl.l.First(); sb; sb = bl.l.NextAfter(sb)) {
|
||||||
|
sb->auxA = Style::SOLID_EDGE;
|
||||||
|
}
|
||||||
|
|
||||||
el.CullExtraneousEdges();
|
el.CullExtraneousEdges();
|
||||||
bl.CullIdenticalBeziers();
|
bl.CullIdenticalBeziers();
|
||||||
|
|
||||||
@ -137,7 +147,7 @@ void SolveSpace::ExportViewTo(char *filename) {
|
|||||||
SEdgeList *selr = &(g->displayEdges);
|
SEdgeList *selr = &(g->displayEdges);
|
||||||
SEdge *se;
|
SEdge *se;
|
||||||
for(se = selr->l.First(); se; se = selr->l.NextAfter(se)) {
|
for(se = selr->l.First(); se; se = selr->l.NextAfter(se)) {
|
||||||
edges.AddEdge(se->a, se->b);
|
edges.AddEdge(se->a, se->b, Style::SOLID_EDGE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,30 +416,40 @@ void VectorFileWriter::Output(SEdgeList *sel, SBezierList *sbl, SMesh *sm) {
|
|||||||
}
|
}
|
||||||
if(sel) {
|
if(sel) {
|
||||||
for(e = sel->l.First(); e; e = sel->l.NextAfter(e)) {
|
for(e = sel->l.First(); e; e = sel->l.NextAfter(e)) {
|
||||||
LineSegment(e->a.x, e->a.y, e->b.x, e->b.y);
|
if(!Style::Exportable(e->auxA)) continue;
|
||||||
|
|
||||||
|
DWORD rgb = Style::Color (e->auxA, true);
|
||||||
|
double w = Style::WidthMm(e->auxA);
|
||||||
|
LineSegment(rgb, w, e->a.x, e->a.y, e->b.x, e->b.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(sbl) {
|
if(sbl) {
|
||||||
for(b = sbl->l.First(); b; b = sbl->l.NextAfter(b)) {
|
for(b = sbl->l.First(); b; b = sbl->l.NextAfter(b)) {
|
||||||
Bezier(b);
|
if(!Style::Exportable(b->auxA)) continue;
|
||||||
|
|
||||||
|
DWORD rgb = Style::Color (b->auxA, true);
|
||||||
|
double w = Style::WidthMm(b->auxA);
|
||||||
|
Bezier(rgb, w, b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FinishAndCloseFile();
|
FinishAndCloseFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VectorFileWriter::BezierAsPwl(SBezier *sb) {
|
void VectorFileWriter::BezierAsPwl(DWORD rgb, double width, SBezier *sb) {
|
||||||
List<Vector> lv;
|
List<Vector> lv;
|
||||||
ZERO(&lv);
|
ZERO(&lv);
|
||||||
sb->MakePwlInto(&lv);
|
sb->MakePwlInto(&lv);
|
||||||
int i;
|
int i;
|
||||||
for(i = 1; i < lv.n; i++) {
|
for(i = 1; i < lv.n; i++) {
|
||||||
LineSegment(lv.elem[i-1].x, lv.elem[i-1].y,
|
LineSegment(rgb, width, lv.elem[i-1].x, lv.elem[i-1].y,
|
||||||
lv.elem[i ].x, lv.elem[i ].y);
|
lv.elem[i ].x, lv.elem[i ].y);
|
||||||
}
|
}
|
||||||
lv.Clear();
|
lv.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VectorFileWriter::BezierAsNonrationalCubic(SBezier *sb, int depth) {
|
void VectorFileWriter::BezierAsNonrationalCubic(DWORD rgb, double width,
|
||||||
|
SBezier *sb, int depth)
|
||||||
|
{
|
||||||
Vector t0 = sb->TangentAt(0), t1 = sb->TangentAt(1);
|
Vector t0 = sb->TangentAt(0), t1 = sb->TangentAt(1);
|
||||||
// The curve is correct, and the first derivatives are correct, at the
|
// The curve is correct, and the first derivatives are correct, at the
|
||||||
// endpoints.
|
// endpoints.
|
||||||
@ -457,12 +477,12 @@ void VectorFileWriter::BezierAsNonrationalCubic(SBezier *sb, int depth) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(closeEnough || depth > 3) {
|
if(closeEnough || depth > 3) {
|
||||||
Bezier(&bnr);
|
Bezier(rgb, width, &bnr);
|
||||||
} else {
|
} else {
|
||||||
SBezier bef, aft;
|
SBezier bef, aft;
|
||||||
sb->SplitAt(0.5, &bef, &aft);
|
sb->SplitAt(0.5, &bef, &aft);
|
||||||
BezierAsNonrationalCubic(&bef, depth+1);
|
BezierAsNonrationalCubic(rgb, width, &bef, depth+1);
|
||||||
BezierAsNonrationalCubic(&aft, depth+1);
|
BezierAsNonrationalCubic(rgb, width, &aft, depth+1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
118
exportvector.cpp
118
exportvector.cpp
@ -62,7 +62,9 @@ void DxfFileWriter::StartFile(void) {
|
|||||||
"ENTITIES\r\n");
|
"ENTITIES\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void DxfFileWriter::LineSegment(double x0, double y0, double x1, double y1) {
|
void DxfFileWriter::LineSegment(DWORD rgb, double w,
|
||||||
|
double x0, double y0, double x1, double y1)
|
||||||
|
{
|
||||||
fprintf(f,
|
fprintf(f,
|
||||||
" 0\r\n"
|
" 0\r\n"
|
||||||
"LINE\r\n"
|
"LINE\r\n"
|
||||||
@ -88,7 +90,7 @@ void DxfFileWriter::LineSegment(double x0, double y0, double x1, double y1) {
|
|||||||
void DxfFileWriter::Triangle(STriangle *tr) {
|
void DxfFileWriter::Triangle(STriangle *tr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DxfFileWriter::Bezier(SBezier *sb) {
|
void DxfFileWriter::Bezier(DWORD rgb, double w, SBezier *sb) {
|
||||||
Vector c, n = Vector::From(0, 0, 1);
|
Vector c, n = Vector::From(0, 0, 1);
|
||||||
double r;
|
double r;
|
||||||
if(sb->IsCircle(n, &c, &r)) {
|
if(sb->IsCircle(n, &c, &r)) {
|
||||||
@ -121,7 +123,7 @@ void DxfFileWriter::Bezier(SBezier *sb) {
|
|||||||
r,
|
r,
|
||||||
theta0*180/PI, theta1*180/PI);
|
theta0*180/PI, theta1*180/PI);
|
||||||
} else {
|
} else {
|
||||||
BezierAsPwl(sb);
|
BezierAsPwl(rgb, w, sb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,6 +139,17 @@ void DxfFileWriter::FinishAndCloseFile(void) {
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Routines for EPS output
|
// Routines for EPS output
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
char *EpsFileWriter::StyleString(DWORD rgb, double w) {
|
||||||
|
static char ret[300];
|
||||||
|
sprintf(ret, " %.3f setlinewidth\r\n"
|
||||||
|
" %.3f %.3f %.3f setrgbcolor\r\n"
|
||||||
|
" 1 setlinejoin\r\n" // rounded
|
||||||
|
" 1 setlinecap\r\n", // rounded
|
||||||
|
MmToPts(w),
|
||||||
|
REDf(rgb), GREENf(rgb), BLUEf(rgb));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void EpsFileWriter::StartFile(void) {
|
void EpsFileWriter::StartFile(void) {
|
||||||
fprintf(f,
|
fprintf(f,
|
||||||
"%%!PS-Adobe-2.0\r\n"
|
"%%!PS-Adobe-2.0\r\n"
|
||||||
@ -156,16 +169,18 @@ void EpsFileWriter::StartFile(void) {
|
|||||||
MmToPts(ptMax.y - ptMin.y));
|
MmToPts(ptMax.y - ptMin.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
void EpsFileWriter::LineSegment(double x0, double y0, double x1, double y1) {
|
void EpsFileWriter::LineSegment(DWORD rgb, double w,
|
||||||
|
double x0, double y0, double x1, double y1)
|
||||||
|
{
|
||||||
fprintf(f,
|
fprintf(f,
|
||||||
"newpath\r\n"
|
"newpath\r\n"
|
||||||
" %.3f %.3f moveto\r\n"
|
" %.3f %.3f moveto\r\n"
|
||||||
" %.3f %.3f lineto\r\n"
|
" %.3f %.3f lineto\r\n"
|
||||||
" 1 setlinewidth\r\n"
|
"%s"
|
||||||
" 0 setgray\r\n"
|
|
||||||
"stroke\r\n",
|
"stroke\r\n",
|
||||||
MmToPts(x0 - ptMin.x), MmToPts(y0 - ptMin.y),
|
MmToPts(x0 - ptMin.x), MmToPts(y0 - ptMin.y),
|
||||||
MmToPts(x1 - ptMin.x), MmToPts(y1 - ptMin.y));
|
MmToPts(x1 - ptMin.x), MmToPts(y1 - ptMin.y),
|
||||||
|
StyleString(rgb, w));
|
||||||
}
|
}
|
||||||
|
|
||||||
void EpsFileWriter::Triangle(STriangle *tr) {
|
void EpsFileWriter::Triangle(STriangle *tr) {
|
||||||
@ -200,7 +215,7 @@ void EpsFileWriter::Triangle(STriangle *tr) {
|
|||||||
MmToPts(tr->c.x - ptMin.x), MmToPts(tr->c.y - ptMin.y));
|
MmToPts(tr->c.x - ptMin.x), MmToPts(tr->c.y - ptMin.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
void EpsFileWriter::Bezier(SBezier *sb) {
|
void EpsFileWriter::Bezier(DWORD rgb, double w, SBezier *sb) {
|
||||||
Vector c, n = Vector::From(0, 0, 1);
|
Vector c, n = Vector::From(0, 0, 1);
|
||||||
double r;
|
double r;
|
||||||
if(sb->IsCircle(n, &c, &r)) {
|
if(sb->IsCircle(n, &c, &r)) {
|
||||||
@ -216,27 +231,27 @@ void EpsFileWriter::Bezier(SBezier *sb) {
|
|||||||
"newpath\r\n"
|
"newpath\r\n"
|
||||||
" %.3f %.3f moveto\r\n"
|
" %.3f %.3f moveto\r\n"
|
||||||
" %.3f %.3f %.3f %.3f %.3f arc\r\n"
|
" %.3f %.3f %.3f %.3f %.3f arc\r\n"
|
||||||
" 1 setlinewidth\r\n"
|
"%s"
|
||||||
" 0 setgray\r\n"
|
|
||||||
"stroke\r\n",
|
"stroke\r\n",
|
||||||
MmToPts(p0.x - ptMin.x), MmToPts(p0.y - ptMin.y),
|
MmToPts(p0.x - ptMin.x), MmToPts(p0.y - ptMin.y),
|
||||||
MmToPts(c.x - ptMin.x), MmToPts(c.y - ptMin.y),
|
MmToPts(c.x - ptMin.x), MmToPts(c.y - ptMin.y),
|
||||||
MmToPts(r),
|
MmToPts(r),
|
||||||
theta0*180/PI, theta1*180/PI);
|
theta0*180/PI, theta1*180/PI,
|
||||||
|
StyleString(rgb, w));
|
||||||
} else if(sb->deg == 3 && !sb->IsRational()) {
|
} else if(sb->deg == 3 && !sb->IsRational()) {
|
||||||
fprintf(f,
|
fprintf(f,
|
||||||
"newpath\r\n"
|
"newpath\r\n"
|
||||||
" %.3f %.3f moveto\r\n"
|
" %.3f %.3f moveto\r\n"
|
||||||
" %.3f %.3f %.3f %.3f %.3f %.3f curveto\r\n"
|
" %.3f %.3f %.3f %.3f %.3f %.3f curveto\r\n"
|
||||||
" 1 setlinewidth\r\n"
|
"%s"
|
||||||
" 0 setgray\r\n"
|
|
||||||
"stroke\r\n",
|
"stroke\r\n",
|
||||||
MmToPts(sb->ctrl[0].x - ptMin.x), MmToPts(sb->ctrl[0].y - ptMin.y),
|
MmToPts(sb->ctrl[0].x - ptMin.x), MmToPts(sb->ctrl[0].y - ptMin.y),
|
||||||
MmToPts(sb->ctrl[1].x - ptMin.x), MmToPts(sb->ctrl[1].y - ptMin.y),
|
MmToPts(sb->ctrl[1].x - ptMin.x), MmToPts(sb->ctrl[1].y - ptMin.y),
|
||||||
MmToPts(sb->ctrl[2].x - ptMin.x), MmToPts(sb->ctrl[2].y - ptMin.y),
|
MmToPts(sb->ctrl[2].x - ptMin.x), MmToPts(sb->ctrl[2].y - ptMin.y),
|
||||||
MmToPts(sb->ctrl[3].x - ptMin.x), MmToPts(sb->ctrl[3].y - ptMin.y));
|
MmToPts(sb->ctrl[3].x - ptMin.x), MmToPts(sb->ctrl[3].y - ptMin.y),
|
||||||
|
StyleString(rgb, w));
|
||||||
} else {
|
} else {
|
||||||
BezierAsNonrationalCubic(sb);
|
BezierAsNonrationalCubic(rgb, w, sb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,6 +267,16 @@ void EpsFileWriter::FinishAndCloseFile(void) {
|
|||||||
// Routines for PDF output, some extra complexity because we have to generate
|
// Routines for PDF output, some extra complexity because we have to generate
|
||||||
// a correct xref table.
|
// a correct xref table.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
char *PdfFileWriter::StyleString(DWORD rgb, double w) {
|
||||||
|
static char ret[300];
|
||||||
|
sprintf(ret, "1 J 1 j " // round endcaps and joins
|
||||||
|
"%.3f w "
|
||||||
|
"%.3f %.3f %.3f RG\r\n",
|
||||||
|
MmToPts(w),
|
||||||
|
REDf(rgb), GREENf(rgb), BLUEf(rgb));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void PdfFileWriter::StartFile(void) {
|
void PdfFileWriter::StartFile(void) {
|
||||||
fprintf(f,
|
fprintf(f,
|
||||||
"%%PDF-1.1\r\n"
|
"%%PDF-1.1\r\n"
|
||||||
@ -371,12 +396,15 @@ void PdfFileWriter::FinishAndCloseFile(void) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PdfFileWriter::LineSegment(double x0, double y0, double x1, double y1) {
|
void PdfFileWriter::LineSegment(DWORD rgb, double w,
|
||||||
|
double x0, double y0, double x1, double y1)
|
||||||
|
{
|
||||||
fprintf(f,
|
fprintf(f,
|
||||||
"1 w 0 0 0 RG\r\n"
|
"%s"
|
||||||
"%.3f %.3f m\r\n"
|
"%.3f %.3f m\r\n"
|
||||||
"%.3f %.3f l\r\n"
|
"%.3f %.3f l\r\n"
|
||||||
"S\r\n",
|
"S\r\n",
|
||||||
|
StyleString(rgb, w),
|
||||||
MmToPts(x0 - ptMin.x), MmToPts(y0 - ptMin.y),
|
MmToPts(x0 - ptMin.x), MmToPts(y0 - ptMin.y),
|
||||||
MmToPts(x1 - ptMin.x), MmToPts(y1 - ptMin.y));
|
MmToPts(x1 - ptMin.x), MmToPts(y1 - ptMin.y));
|
||||||
}
|
}
|
||||||
@ -400,29 +428,34 @@ void PdfFileWriter::Triangle(STriangle *tr) {
|
|||||||
MmToPts(tr->c.x - ptMin.x), MmToPts(tr->c.y - ptMin.y));
|
MmToPts(tr->c.x - ptMin.x), MmToPts(tr->c.y - ptMin.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PdfFileWriter::Bezier(SBezier *sb) {
|
void PdfFileWriter::Bezier(DWORD rgb, double w, SBezier *sb) {
|
||||||
if(sb->deg == 3 && !sb->IsRational()) {
|
if(sb->deg == 3 && !sb->IsRational()) {
|
||||||
fprintf(f,
|
fprintf(f,
|
||||||
"1 w 0 0 0 RG\r\n"
|
"%s"
|
||||||
"%.3f %.3f m\r\n"
|
"%.3f %.3f m\r\n"
|
||||||
"%.3f %.3f %.3f %.3f %.3f %.3f c\r\n"
|
"%.3f %.3f %.3f %.3f %.3f %.3f c\r\n"
|
||||||
"S\r\n",
|
"S\r\n",
|
||||||
|
StyleString(rgb, w),
|
||||||
MmToPts(sb->ctrl[0].x - ptMin.x), MmToPts(sb->ctrl[0].y - ptMin.y),
|
MmToPts(sb->ctrl[0].x - ptMin.x), MmToPts(sb->ctrl[0].y - ptMin.y),
|
||||||
MmToPts(sb->ctrl[1].x - ptMin.x), MmToPts(sb->ctrl[1].y - ptMin.y),
|
MmToPts(sb->ctrl[1].x - ptMin.x), MmToPts(sb->ctrl[1].y - ptMin.y),
|
||||||
MmToPts(sb->ctrl[2].x - ptMin.x), MmToPts(sb->ctrl[2].y - ptMin.y),
|
MmToPts(sb->ctrl[2].x - ptMin.x), MmToPts(sb->ctrl[2].y - ptMin.y),
|
||||||
MmToPts(sb->ctrl[3].x - ptMin.x), MmToPts(sb->ctrl[3].y - ptMin.y));
|
MmToPts(sb->ctrl[3].x - ptMin.x), MmToPts(sb->ctrl[3].y - ptMin.y));
|
||||||
} else {
|
} else {
|
||||||
BezierAsNonrationalCubic(sb);
|
BezierAsNonrationalCubic(rgb, w, sb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Routines for SVG output
|
// Routines for SVG output
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
char *SvgFileWriter::StyleString(DWORD rgb, double w) {
|
||||||
const char *SvgFileWriter::SVG_STYLE =
|
static char ret[200];
|
||||||
"stroke-width='0.1' stroke='black' style='fill: none;'";
|
sprintf(ret, "stroke-width='%.3f' stroke='#%02x%02x%02x' "
|
||||||
|
"style='fill: none;' "
|
||||||
|
"stroke-linecap='round' stroke-linejoin='round' ",
|
||||||
|
w, RED(rgb), GREEN(rgb), BLUE(rgb));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void SvgFileWriter::StartFile(void) {
|
void SvgFileWriter::StartFile(void) {
|
||||||
fprintf(f,
|
fprintf(f,
|
||||||
@ -440,13 +473,15 @@ void SvgFileWriter::StartFile(void) {
|
|||||||
// A little bit of extra space for the stroke width.
|
// A little bit of extra space for the stroke width.
|
||||||
}
|
}
|
||||||
|
|
||||||
void SvgFileWriter::LineSegment(double x0, double y0, double x1, double y1) {
|
void SvgFileWriter::LineSegment(DWORD rgb, double w,
|
||||||
|
double x0, double y0, double x1, double y1)
|
||||||
|
{
|
||||||
// SVG uses a coordinate system with the origin at top left, +y down
|
// SVG uses a coordinate system with the origin at top left, +y down
|
||||||
fprintf(f,
|
fprintf(f,
|
||||||
"<polyline points='%.3f,%.3f %.3f,%.3f' %s />\r\n",
|
"<polyline points='%.3f,%.3f %.3f,%.3f' %s />\r\n",
|
||||||
(x0 - ptMin.x), (ptMax.y - y0),
|
(x0 - ptMin.x), (ptMax.y - y0),
|
||||||
(x1 - ptMin.x), (ptMax.y - y1),
|
(x1 - ptMin.x), (ptMax.y - y1),
|
||||||
SVG_STYLE);
|
StyleString(rgb, w));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SvgFileWriter::Triangle(STriangle *tr) {
|
void SvgFileWriter::Triangle(STriangle *tr) {
|
||||||
@ -466,7 +501,7 @@ void SvgFileWriter::Triangle(STriangle *tr) {
|
|||||||
RED(tr->meta.color), GREEN(tr->meta.color), BLUE(tr->meta.color));
|
RED(tr->meta.color), GREEN(tr->meta.color), BLUE(tr->meta.color));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SvgFileWriter::Bezier(SBezier *sb) {
|
void SvgFileWriter::Bezier(DWORD rgb, double w, SBezier *sb) {
|
||||||
Vector c, n = Vector::From(0, 0, 1);
|
Vector c, n = Vector::From(0, 0, 1);
|
||||||
double r;
|
double r;
|
||||||
if(sb->IsCircle(n, &c, &r)) {
|
if(sb->IsCircle(n, &c, &r)) {
|
||||||
@ -487,11 +522,11 @@ void SvgFileWriter::Bezier(SBezier *sb) {
|
|||||||
p0.x - ptMin.x, ptMax.y - p0.y,
|
p0.x - ptMin.x, ptMax.y - p0.y,
|
||||||
r, r,
|
r, r,
|
||||||
p1.x - ptMin.x, ptMax.y - p1.y,
|
p1.x - ptMin.x, ptMax.y - p1.y,
|
||||||
SVG_STYLE);
|
StyleString(rgb, w));
|
||||||
} else if(!sb->IsRational()) {
|
} else if(!sb->IsRational()) {
|
||||||
if(sb->deg == 1) {
|
if(sb->deg == 1) {
|
||||||
LineSegment(sb->ctrl[0].x, sb->ctrl[0].y,
|
LineSegment(rgb, w, sb->ctrl[0].x, sb->ctrl[0].y,
|
||||||
sb->ctrl[1].x, sb->ctrl[1].y);
|
sb->ctrl[1].x, sb->ctrl[1].y);
|
||||||
} else if(sb->deg == 2) {
|
} else if(sb->deg == 2) {
|
||||||
fprintf(f,
|
fprintf(f,
|
||||||
"<path d='M%.3f,%.3f "
|
"<path d='M%.3f,%.3f "
|
||||||
@ -499,7 +534,7 @@ void SvgFileWriter::Bezier(SBezier *sb) {
|
|||||||
sb->ctrl[0].x - ptMin.x, ptMax.y - sb->ctrl[0].y,
|
sb->ctrl[0].x - ptMin.x, ptMax.y - sb->ctrl[0].y,
|
||||||
sb->ctrl[1].x - ptMin.x, ptMax.y - sb->ctrl[1].y,
|
sb->ctrl[1].x - ptMin.x, ptMax.y - sb->ctrl[1].y,
|
||||||
sb->ctrl[2].x - ptMin.x, ptMax.y - sb->ctrl[2].y,
|
sb->ctrl[2].x - ptMin.x, ptMax.y - sb->ctrl[2].y,
|
||||||
SVG_STYLE);
|
StyleString(rgb, w));
|
||||||
} else if(sb->deg == 3) {
|
} else if(sb->deg == 3) {
|
||||||
fprintf(f,
|
fprintf(f,
|
||||||
"<path d='M%.3f,%.3f "
|
"<path d='M%.3f,%.3f "
|
||||||
@ -508,11 +543,10 @@ void SvgFileWriter::Bezier(SBezier *sb) {
|
|||||||
sb->ctrl[1].x - ptMin.x, ptMax.y - sb->ctrl[1].y,
|
sb->ctrl[1].x - ptMin.x, ptMax.y - sb->ctrl[1].y,
|
||||||
sb->ctrl[2].x - ptMin.x, ptMax.y - sb->ctrl[2].y,
|
sb->ctrl[2].x - ptMin.x, ptMax.y - sb->ctrl[2].y,
|
||||||
sb->ctrl[3].x - ptMin.x, ptMax.y - sb->ctrl[3].y,
|
sb->ctrl[3].x - ptMin.x, ptMax.y - sb->ctrl[3].y,
|
||||||
SVG_STYLE);
|
StyleString(rgb, w));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
BezierAsNonrationalCubic(sb);
|
BezierAsNonrationalCubic(rgb, w, sb);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -533,7 +567,9 @@ void HpglFileWriter::StartFile(void) {
|
|||||||
fprintf(f, "SP1;\r\n");
|
fprintf(f, "SP1;\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void HpglFileWriter::LineSegment(double x0, double y0, double x1, double y1) {
|
void HpglFileWriter::LineSegment(DWORD rgb, double w,
|
||||||
|
double x0, double y0, double x1, double y1)
|
||||||
|
{
|
||||||
fprintf(f, "PU%d,%d;\r\n", (int)MmToHpglUnits(x0), (int)MmToHpglUnits(y0));
|
fprintf(f, "PU%d,%d;\r\n", (int)MmToHpglUnits(x0), (int)MmToHpglUnits(y0));
|
||||||
fprintf(f, "PD%d,%d;\r\n", (int)MmToHpglUnits(x1), (int)MmToHpglUnits(y1));
|
fprintf(f, "PD%d,%d;\r\n", (int)MmToHpglUnits(x1), (int)MmToHpglUnits(y1));
|
||||||
}
|
}
|
||||||
@ -541,8 +577,8 @@ void HpglFileWriter::LineSegment(double x0, double y0, double x1, double y1) {
|
|||||||
void HpglFileWriter::Triangle(STriangle *tr) {
|
void HpglFileWriter::Triangle(STriangle *tr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HpglFileWriter::Bezier(SBezier *sb) {
|
void HpglFileWriter::Bezier(DWORD rgb, double w, SBezier *sb) {
|
||||||
BezierAsPwl(sb);
|
BezierAsPwl(rgb, w, sb);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HpglFileWriter::FinishAndCloseFile(void) {
|
void HpglFileWriter::FinishAndCloseFile(void) {
|
||||||
@ -562,13 +598,15 @@ void Step2dFileWriter::StartFile(void) {
|
|||||||
void Step2dFileWriter::Triangle(STriangle *tr) {
|
void Step2dFileWriter::Triangle(STriangle *tr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Step2dFileWriter::LineSegment(double x0, double y0, double x1, double y1) {
|
void Step2dFileWriter::LineSegment(DWORD rgb, double w,
|
||||||
|
double x0, double y0, double x1, double y1)
|
||||||
|
{
|
||||||
SBezier sb = SBezier::From(Vector::From(x0, y0, 0),
|
SBezier sb = SBezier::From(Vector::From(x0, y0, 0),
|
||||||
Vector::From(x1, y1, 0));
|
Vector::From(x1, y1, 0));
|
||||||
Bezier(&sb);
|
Bezier(rgb, w, &sb);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Step2dFileWriter::Bezier(SBezier *sb) {
|
void Step2dFileWriter::Bezier(DWORD rgb, double w, SBezier *sb) {
|
||||||
int c = sfw.ExportCurve(sb);
|
int c = sfw.ExportCurve(sb);
|
||||||
sfw.curves.Add(&c);
|
sfw.curves.Add(&c);
|
||||||
}
|
}
|
||||||
|
@ -579,6 +579,8 @@ void Group::MakeExtrusionLines(IdList<Entity,hEntity> *el, hEntity in) {
|
|||||||
en.point[0] = Remap(ep->h, REMAP_TOP);
|
en.point[0] = Remap(ep->h, REMAP_TOP);
|
||||||
en.point[1] = Remap(ep->h, REMAP_BOTTOM);
|
en.point[1] = Remap(ep->h, REMAP_BOTTOM);
|
||||||
en.group = h;
|
en.group = h;
|
||||||
|
en.construction = ep->construction;
|
||||||
|
en.style = ep->style;
|
||||||
en.h = Remap(ep->h, REMAP_PT_TO_LINE);
|
en.h = Remap(ep->h, REMAP_PT_TO_LINE);
|
||||||
en.type = Entity::LINE_SEGMENT;
|
en.type = Entity::LINE_SEGMENT;
|
||||||
el->Add(&en);
|
el->Add(&en);
|
||||||
@ -596,6 +598,8 @@ void Group::MakeExtrusionLines(IdList<Entity,hEntity> *el, hEntity in) {
|
|||||||
en.numNormal = Quaternion::From(0, ab.x, ab.y, ab.z);
|
en.numNormal = Quaternion::From(0, ab.x, ab.y, ab.z);
|
||||||
|
|
||||||
en.group = h;
|
en.group = h;
|
||||||
|
en.construction = ep->construction;
|
||||||
|
en.style = ep->style;
|
||||||
en.h = Remap(ep->h, REMAP_LINE_TO_FACE);
|
en.h = Remap(ep->h, REMAP_LINE_TO_FACE);
|
||||||
en.type = Entity::FACE_XPROD;
|
en.type = Entity::FACE_XPROD;
|
||||||
el->Add(&en);
|
el->Add(&en);
|
||||||
@ -636,6 +640,7 @@ void Group::CopyEntity(IdList<Entity,hEntity> *el,
|
|||||||
en.timesApplied = timesApplied;
|
en.timesApplied = timesApplied;
|
||||||
en.group = h;
|
en.group = h;
|
||||||
en.construction = ep->construction;
|
en.construction = ep->construction;
|
||||||
|
en.style = ep->style;
|
||||||
|
|
||||||
switch(ep->type) {
|
switch(ep->type) {
|
||||||
case Entity::WORKPLANE:
|
case Entity::WORKPLANE:
|
||||||
|
@ -353,12 +353,8 @@ void SContour::AddPoint(Vector p) {
|
|||||||
|
|
||||||
void SContour::MakeEdgesInto(SEdgeList *el) {
|
void SContour::MakeEdgesInto(SEdgeList *el) {
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i < (l.n-1); i++) {
|
for(i = 0; i < (l.n - 1); i++) {
|
||||||
SEdge e;
|
el->AddEdge(l.elem[i].p, l.elem[i+1].p);
|
||||||
e.tag = 0;
|
|
||||||
e.a = l.elem[i].p;
|
|
||||||
e.b = l.elem[i+1].p;
|
|
||||||
el->l.Add(&e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
sketch.h
2
sketch.h
@ -659,6 +659,8 @@ public:
|
|||||||
static float Width(hStyle hs);
|
static float Width(hStyle hs);
|
||||||
static DWORD Color(int hs, bool forExport=false);
|
static DWORD Color(int hs, bool forExport=false);
|
||||||
static float Width(int hs);
|
static float Width(int hs);
|
||||||
|
static double WidthMm(int hs);
|
||||||
|
static bool Exportable(int hs);
|
||||||
static hStyle ForEntity(hEntity he);
|
static hStyle ForEntity(hEntity he);
|
||||||
|
|
||||||
char *DescriptionString(void);
|
char *DescriptionString(void);
|
||||||
|
@ -68,6 +68,8 @@ void SolveSpace::Init(char *cmdLine) {
|
|||||||
exportScale = CnfThawFloat(1.0f, "ExportScale");
|
exportScale = CnfThawFloat(1.0f, "ExportScale");
|
||||||
// Export offset (cutter radius comp)
|
// Export offset (cutter radius comp)
|
||||||
exportOffset = CnfThawFloat(0.0f, "ExportOffset");
|
exportOffset = CnfThawFloat(0.0f, "ExportOffset");
|
||||||
|
// Rewrite exported colors close to white into black (assuming white bg)
|
||||||
|
fixExportColors = CnfThawDWORD(1, "FixExportColors");
|
||||||
// Draw back faces of triangles (when mesh is leaky/self-intersecting)
|
// Draw back faces of triangles (when mesh is leaky/self-intersecting)
|
||||||
drawBackFaces = CnfThawDWORD(1, "DrawBackFaces");
|
drawBackFaces = CnfThawDWORD(1, "DrawBackFaces");
|
||||||
// Export shaded triangles in a 2d view
|
// Export shaded triangles in a 2d view
|
||||||
@ -152,6 +154,8 @@ void SolveSpace::Exit(void) {
|
|||||||
CnfFreezeFloat(exportScale, "ExportScale");
|
CnfFreezeFloat(exportScale, "ExportScale");
|
||||||
// Export offset (cutter radius comp)
|
// Export offset (cutter radius comp)
|
||||||
CnfFreezeFloat(exportOffset, "ExportOffset");
|
CnfFreezeFloat(exportOffset, "ExportOffset");
|
||||||
|
// Rewrite exported colors close to white into black (assuming white bg)
|
||||||
|
CnfFreezeDWORD(fixExportColors, "FixExportColors");
|
||||||
// Draw back faces of triangles (when mesh is leaky/self-intersecting)
|
// Draw back faces of triangles (when mesh is leaky/self-intersecting)
|
||||||
CnfFreezeDWORD(drawBackFaces, "DrawBackFaces");
|
CnfFreezeDWORD(drawBackFaces, "DrawBackFaces");
|
||||||
// Export shaded triangles in a 2d view
|
// Export shaded triangles in a 2d view
|
||||||
|
46
solvespace.h
46
solvespace.h
@ -395,28 +395,34 @@ public:
|
|||||||
static VectorFileWriter *ForFile(char *file);
|
static VectorFileWriter *ForFile(char *file);
|
||||||
|
|
||||||
void Output(SEdgeList *sel, SBezierList *sbl, SMesh *sm);
|
void Output(SEdgeList *sel, SBezierList *sbl, SMesh *sm);
|
||||||
void BezierAsPwl(SBezier *sb);
|
|
||||||
void BezierAsNonrationalCubic(SBezier *sb, int depth=0);
|
|
||||||
|
|
||||||
virtual void Bezier(SBezier *sb) = 0;
|
void BezierAsPwl(DWORD rgb, double width, SBezier *sb);
|
||||||
virtual void LineSegment(double x0, double y0, double x1, double y1) = 0;
|
void BezierAsNonrationalCubic(DWORD rgb, double width,
|
||||||
|
SBezier *sb, int depth=0);
|
||||||
|
|
||||||
|
virtual void Bezier(DWORD rgb, double width, SBezier *sb) = 0;
|
||||||
|
virtual void LineSegment(DWORD rgb, double width,
|
||||||
|
double x0, double y0, double x1, double y1) = 0;
|
||||||
virtual void Triangle(STriangle *tr) = 0;
|
virtual void Triangle(STriangle *tr) = 0;
|
||||||
virtual void StartFile(void) = 0;
|
virtual void StartFile(void) = 0;
|
||||||
virtual void FinishAndCloseFile(void) = 0;
|
virtual void FinishAndCloseFile(void) = 0;
|
||||||
};
|
};
|
||||||
class DxfFileWriter : public VectorFileWriter {
|
class DxfFileWriter : public VectorFileWriter {
|
||||||
public:
|
public:
|
||||||
void LineSegment(double x0, double y0, double x1, double y1);
|
void LineSegment(DWORD rgb, double width,
|
||||||
|
double x0, double y0, double x1, double y1);
|
||||||
void Triangle(STriangle *tr);
|
void Triangle(STriangle *tr);
|
||||||
void Bezier(SBezier *sb);
|
void Bezier(DWORD rgb, double width, SBezier *sb);
|
||||||
void StartFile(void);
|
void StartFile(void);
|
||||||
void FinishAndCloseFile(void);
|
void FinishAndCloseFile(void);
|
||||||
};
|
};
|
||||||
class EpsFileWriter : public VectorFileWriter {
|
class EpsFileWriter : public VectorFileWriter {
|
||||||
public:
|
public:
|
||||||
void LineSegment(double x0, double y0, double x1, double y1);
|
static char *StyleString(DWORD rgb, double width);
|
||||||
|
void LineSegment(DWORD rgb, double width,
|
||||||
|
double x0, double y0, double x1, double y1);
|
||||||
void Triangle(STriangle *tr);
|
void Triangle(STriangle *tr);
|
||||||
void Bezier(SBezier *sb);
|
void Bezier(DWORD rgb, double width, SBezier *sb);
|
||||||
void StartFile(void);
|
void StartFile(void);
|
||||||
void FinishAndCloseFile(void);
|
void FinishAndCloseFile(void);
|
||||||
};
|
};
|
||||||
@ -425,35 +431,40 @@ public:
|
|||||||
DWORD xref[10];
|
DWORD xref[10];
|
||||||
DWORD bodyStart;
|
DWORD bodyStart;
|
||||||
|
|
||||||
void LineSegment(double x0, double y0, double x1, double y1);
|
static char *StyleString(DWORD rgb, double width);
|
||||||
|
void LineSegment(DWORD rgb, double width,
|
||||||
|
double x0, double y0, double x1, double y1);
|
||||||
void Triangle(STriangle *tr);
|
void Triangle(STriangle *tr);
|
||||||
void Bezier(SBezier *sb);
|
void Bezier(DWORD rgb, double width, SBezier *sb);
|
||||||
void StartFile(void);
|
void StartFile(void);
|
||||||
void FinishAndCloseFile(void);
|
void FinishAndCloseFile(void);
|
||||||
};
|
};
|
||||||
class SvgFileWriter : public VectorFileWriter {
|
class SvgFileWriter : public VectorFileWriter {
|
||||||
public:
|
public:
|
||||||
static const char *SVG_STYLE;
|
static char *StyleString(DWORD rgb, double width);
|
||||||
void LineSegment(double x0, double y0, double x1, double y1);
|
void LineSegment(DWORD rgb, double width,
|
||||||
|
double x0, double y0, double x1, double y1);
|
||||||
void Triangle(STriangle *tr);
|
void Triangle(STriangle *tr);
|
||||||
void Bezier(SBezier *sb);
|
void Bezier(DWORD rgb, double width, SBezier *sb);
|
||||||
void StartFile(void);
|
void StartFile(void);
|
||||||
void FinishAndCloseFile(void);
|
void FinishAndCloseFile(void);
|
||||||
};
|
};
|
||||||
class HpglFileWriter : public VectorFileWriter {
|
class HpglFileWriter : public VectorFileWriter {
|
||||||
public:
|
public:
|
||||||
static double MmToHpglUnits(double mm);
|
static double MmToHpglUnits(double mm);
|
||||||
void LineSegment(double x0, double y0, double x1, double y1);
|
void LineSegment(DWORD rgb, double width,
|
||||||
|
double x0, double y0, double x1, double y1);
|
||||||
void Triangle(STriangle *tr);
|
void Triangle(STriangle *tr);
|
||||||
void Bezier(SBezier *sb);
|
void Bezier(DWORD rgb, double width, SBezier *sb);
|
||||||
void StartFile(void);
|
void StartFile(void);
|
||||||
void FinishAndCloseFile(void);
|
void FinishAndCloseFile(void);
|
||||||
};
|
};
|
||||||
class Step2dFileWriter : public VectorFileWriter {
|
class Step2dFileWriter : public VectorFileWriter {
|
||||||
StepFileWriter sfw;
|
StepFileWriter sfw;
|
||||||
void LineSegment(double x0, double y0, double x1, double y1);
|
void LineSegment(DWORD rgb, double width,
|
||||||
|
double x0, double y0, double x1, double y1);
|
||||||
void Triangle(STriangle *tr);
|
void Triangle(STriangle *tr);
|
||||||
void Bezier(SBezier *sb);
|
void Bezier(DWORD rgb, double width, SBezier *sb);
|
||||||
void StartFile(void);
|
void StartFile(void);
|
||||||
void FinishAndCloseFile(void);
|
void FinishAndCloseFile(void);
|
||||||
};
|
};
|
||||||
@ -530,6 +541,7 @@ public:
|
|||||||
double cameraTangent;
|
double cameraTangent;
|
||||||
float exportScale;
|
float exportScale;
|
||||||
float exportOffset;
|
float exportOffset;
|
||||||
|
int fixExportColors;
|
||||||
int drawBackFaces;
|
int drawBackFaces;
|
||||||
int showToolbar;
|
int showToolbar;
|
||||||
DWORD backgroundColor;
|
DWORD backgroundColor;
|
||||||
|
@ -104,6 +104,13 @@ SBezier SBezier::TransformedBy(Vector t, Quaternion q) {
|
|||||||
bool SBezier::IsCircle(Vector axis, Vector *center, double *r) {
|
bool SBezier::IsCircle(Vector axis, Vector *center, double *r) {
|
||||||
if(deg != 2) return false;
|
if(deg != 2) return false;
|
||||||
|
|
||||||
|
if(ctrl[1].DistanceToLine(ctrl[0], ctrl[2].Minus(ctrl[0])) < LENGTH_EPS) {
|
||||||
|
// This is almost a line segment. So it's a circle with very large
|
||||||
|
// radius, which is likely to make code that tries to handle circles
|
||||||
|
// blow up. So return false.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Vector t0 = (ctrl[0]).Minus(ctrl[1]),
|
Vector t0 = (ctrl[0]).Minus(ctrl[1]),
|
||||||
t2 = (ctrl[2]).Minus(ctrl[1]),
|
t2 = (ctrl[2]).Minus(ctrl[1]),
|
||||||
r0 = axis.Cross(t0),
|
r0 = axis.Cross(t0),
|
||||||
|
@ -62,6 +62,8 @@ public:
|
|||||||
class SBezier {
|
class SBezier {
|
||||||
public:
|
public:
|
||||||
int tag;
|
int tag;
|
||||||
|
int auxA, auxB;
|
||||||
|
|
||||||
int deg;
|
int deg;
|
||||||
Vector ctrl[4];
|
Vector ctrl[4];
|
||||||
double weight[4];
|
double weight[4];
|
||||||
|
66
style.cpp
66
style.cpp
@ -111,6 +111,8 @@ void Style::FreezeDefaultStyles(void) {
|
|||||||
// the style, according to our table of default styles.
|
// the style, according to our table of default styles.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
Style *Style::Get(hStyle h) {
|
Style *Style::Get(hStyle h) {
|
||||||
|
if(h.v == 0) h.v = ACTIVE_GRP;
|
||||||
|
|
||||||
Style *s = SK.style.FindByIdNoOops(h);
|
Style *s = SK.style.FindByIdNoOops(h);
|
||||||
if(s) {
|
if(s) {
|
||||||
// It exists, good.
|
// It exists, good.
|
||||||
@ -140,6 +142,19 @@ float Style::Width(int s) {
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
DWORD Style::Color(hStyle h, bool forExport) {
|
DWORD Style::Color(hStyle h, bool forExport) {
|
||||||
Style *s = Get(h);
|
Style *s = Get(h);
|
||||||
|
if(forExport) {
|
||||||
|
Vector rgb = Vector::From(REDf(s->color),
|
||||||
|
GREENf(s->color),
|
||||||
|
BLUEf(s->color));
|
||||||
|
rgb = rgb.Minus(Vector::From(1, 1, 1));
|
||||||
|
if(rgb.Magnitude() < 0.4 && SS.fixExportColors) {
|
||||||
|
// This is an almost-white color in a default style, which is
|
||||||
|
// good for the default on-screen view (black bg) but probably
|
||||||
|
// not desired in the exported files, which typically are shown
|
||||||
|
// against white backgrounds.
|
||||||
|
return RGB(0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
return s->color;
|
return s->color;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,6 +173,24 @@ float Style::Width(hStyle h) {
|
|||||||
return (float)r;
|
return (float)r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Return the width associated with our style in millimeters..
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
double Style::WidthMm(int hs) {
|
||||||
|
double widthpx = Width(hs);
|
||||||
|
return widthpx / SS.GW.scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Should lines and curves from this style appear in the output file? Only
|
||||||
|
// if it's both shown and exportable.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
bool Style::Exportable(int si) {
|
||||||
|
hStyle hs = { si };
|
||||||
|
Style *s = Get(hs);
|
||||||
|
return (s->exportable) && (s->visible);
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Return the appropriate style for our entity. If the entity has a style
|
// Return the appropriate style for our entity. If the entity has a style
|
||||||
// explicitly assigned, then it's that style. Otherwise it's the appropriate
|
// explicitly assigned, then it's that style. Otherwise it's the appropriate
|
||||||
@ -432,6 +465,39 @@ void TextWindow::ShowStyleInfo(void) {
|
|||||||
s->h.v, &ScreenChangeStyleYesNo,
|
s->h.v, &ScreenChangeStyleYesNo,
|
||||||
(!s->exportable ? "" : "no"),
|
(!s->exportable ? "" : "no"),
|
||||||
(!s->exportable ? "no" : ""));
|
(!s->exportable ? "no" : ""));
|
||||||
|
|
||||||
|
Printf(false, "");
|
||||||
|
Printf(false, "To assign lines or curves to this style,");
|
||||||
|
Printf(false, "select them on the drawing. Then commit");
|
||||||
|
Printf(false, "by clicking the link at the bottom of");
|
||||||
|
Printf(false, "this window.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextWindow::ScreenAssignSelectionToStyle(int link, DWORD v) {
|
||||||
|
bool showError = false;
|
||||||
|
SS.GW.GroupSelection();
|
||||||
|
|
||||||
|
SS.UndoRemember();
|
||||||
|
for(int i = 0; i < SS.GW.gs.entities; i++) {
|
||||||
|
hEntity he = SS.GW.gs.entity[i];
|
||||||
|
if(!he.isFromRequest()) {
|
||||||
|
showError = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
hRequest hr = he.request();
|
||||||
|
Request *r = SK.GetRequest(hr);
|
||||||
|
r->style.v = v;
|
||||||
|
SS.later.generateAll = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(showError) {
|
||||||
|
Error("Can't assign style to an entity that's derived from another "
|
||||||
|
"entity; try assigning a style to this entity's parent.");
|
||||||
|
}
|
||||||
|
|
||||||
|
SS.GW.ClearSelection();
|
||||||
|
InvalidateGraphics();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -636,6 +636,9 @@ void TextWindow::ScreenChangeExportOffset(int link, DWORD v) {
|
|||||||
ShowTextEditControl(57, 3, SS.MmToString(SS.exportOffset));
|
ShowTextEditControl(57, 3, SS.MmToString(SS.exportOffset));
|
||||||
SS.TW.edit.meaning = EDIT_EXPORT_OFFSET;
|
SS.TW.edit.meaning = EDIT_EXPORT_OFFSET;
|
||||||
}
|
}
|
||||||
|
void TextWindow::ScreenChangeFixExportColors(int link, DWORD v) {
|
||||||
|
SS.fixExportColors = !SS.fixExportColors;
|
||||||
|
}
|
||||||
void TextWindow::ScreenChangeBackFaces(int link, DWORD v) {
|
void TextWindow::ScreenChangeBackFaces(int link, DWORD v) {
|
||||||
SS.drawBackFaces = !SS.drawBackFaces;
|
SS.drawBackFaces = !SS.drawBackFaces;
|
||||||
InvalidateGraphics();
|
InvalidateGraphics();
|
||||||
@ -786,7 +789,14 @@ void TextWindow::ShowConfiguration(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Printf(false, "");
|
Printf(false, "");
|
||||||
Printf(false, "%Ft draw back faces: "
|
Printf(false, "%Ft fix white exported lines: "
|
||||||
|
"%Fh%f%Ll%s%E%Fs%s%E / %Fh%f%Ll%s%E%Fs%s%E",
|
||||||
|
&ScreenChangeFixExportColors,
|
||||||
|
( SS.fixExportColors ? "" : "yes"), ( SS.fixExportColors ? "yes" : ""),
|
||||||
|
&ScreenChangeFixExportColors,
|
||||||
|
(!SS.fixExportColors ? "" : "no"), (!SS.fixExportColors ? "no" : ""));
|
||||||
|
|
||||||
|
Printf(false, "%Ft draw triangle back faces: "
|
||||||
"%Fh%f%Ll%s%E%Fs%s%E / %Fh%f%Ll%s%E%Fs%s%E",
|
"%Fh%f%Ll%s%E%Fs%s%E / %Fh%f%Ll%s%E%Fs%s%E",
|
||||||
&ScreenChangeBackFaces,
|
&ScreenChangeBackFaces,
|
||||||
(SS.drawBackFaces ? "" : "yes"), (SS.drawBackFaces ? "yes" : ""),
|
(SS.drawBackFaces ? "" : "yes"), (SS.drawBackFaces ? "yes" : ""),
|
||||||
|
31
textwin.cpp
31
textwin.cpp
@ -414,6 +414,12 @@ void TextWindow::DescribeSelection(void) {
|
|||||||
Entity *w = SK.GetEntity(e->workplane);
|
Entity *w = SK.GetEntity(e->workplane);
|
||||||
Printf(false, "%FtIN WORKPLANE%E %s", w->DescriptionString());
|
Printf(false, "%FtIN WORKPLANE%E %s", w->DescriptionString());
|
||||||
}
|
}
|
||||||
|
if(e->style.v) {
|
||||||
|
Style *s = Style::Get(e->style);
|
||||||
|
Printf(false, "%FtIN STYLE%E %s", s->DescriptionString());
|
||||||
|
} else {
|
||||||
|
Printf(false, "%FtIN STYLE%E none");
|
||||||
|
}
|
||||||
} else if(gs.n == 2 && gs.points == 2) {
|
} else if(gs.n == 2 && gs.points == 2) {
|
||||||
Printf(false, "%FtTWO POINTS");
|
Printf(false, "%FtTWO POINTS");
|
||||||
Vector p0 = SK.GetEntity(gs.point[0])->PointGetNum();
|
Vector p0 = SK.GetEntity(gs.point[0])->PointGetNum();
|
||||||
@ -481,6 +487,31 @@ void TextWindow::DescribeSelection(void) {
|
|||||||
Printf(true, "%FtSELECTED:%E %d item%s", gs.n, gs.n == 1 ? "" : "s");
|
Printf(true, "%FtSELECTED:%E %d item%s", gs.n, gs.n == 1 ? "" : "s");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(shown.screen == SCREEN_STYLE_INFO &&
|
||||||
|
shown.style.v >= Style::FIRST_CUSTOM)
|
||||||
|
{
|
||||||
|
// If we are showing a screen for a particular style, then offer the
|
||||||
|
// option to assign our selected entities to that style.
|
||||||
|
Style *s = Style::Get(shown.style);
|
||||||
|
Printf(true, "%Fl%D%f%Ll(assign to style %s)%E",
|
||||||
|
shown.style.v,
|
||||||
|
&ScreenAssignSelectionToStyle,
|
||||||
|
s->DescriptionString());
|
||||||
|
}
|
||||||
|
// If any of the selected entities have an assigned style, then offer
|
||||||
|
// the option to remove that style.
|
||||||
|
for(i = 0; i < gs.entities; i++) {
|
||||||
|
Entity *e = SK.GetEntity(gs.entity[i]);
|
||||||
|
if(e->style.v != 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(i < gs.entities) {
|
||||||
|
Printf(true, "%Fl%D%f%Ll(remove assigned style)%E",
|
||||||
|
0,
|
||||||
|
&ScreenAssignSelectionToStyle);
|
||||||
|
}
|
||||||
|
|
||||||
Printf(true, "%Fl%f%Ll(unselect all)%E", &TextWindow::ScreenUnselectAll);
|
Printf(true, "%Fl%f%Ll(unselect all)%E", &TextWindow::ScreenUnselectAll);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
ui.h
2
ui.h
@ -159,10 +159,12 @@ public:
|
|||||||
static void ScreenChangeStyleYesNo(int link, DWORD v);
|
static void ScreenChangeStyleYesNo(int link, DWORD v);
|
||||||
static void ScreenCreateCustomStyle(int link, DWORD v);
|
static void ScreenCreateCustomStyle(int link, DWORD v);
|
||||||
static void ScreenLoadFactoryDefaultStyles(int link, DWORD v);
|
static void ScreenLoadFactoryDefaultStyles(int link, DWORD v);
|
||||||
|
static void ScreenAssignSelectionToStyle(int link, DWORD v);
|
||||||
|
|
||||||
static void ScreenShowConfiguration(int link, DWORD v);
|
static void ScreenShowConfiguration(int link, DWORD v);
|
||||||
static void ScreenGoToWebsite(int link, DWORD v);
|
static void ScreenGoToWebsite(int link, DWORD v);
|
||||||
|
|
||||||
|
static void ScreenChangeFixExportColors(int link, DWORD v);
|
||||||
static void ScreenChangeBackFaces(int link, DWORD v);
|
static void ScreenChangeBackFaces(int link, DWORD v);
|
||||||
static void ScreenChangePwlCurves(int link, DWORD v);
|
static void ScreenChangePwlCurves(int link, DWORD v);
|
||||||
static void ScreenChangeCanvasSizeAuto(int link, DWORD v);
|
static void ScreenChangeCanvasSizeAuto(int link, DWORD v);
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
|
|
||||||
grid
|
grid
|
||||||
line styles (color, thickness)
|
|
||||||
background color setting
|
|
||||||
better text
|
better text
|
||||||
|
right-click menu
|
||||||
faster triangulation
|
faster triangulation
|
||||||
interpolating splines
|
interpolating splines
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user