From 66c93aab73d84f42956274c79909a01cdaeb3b6e Mon Sep 17 00:00:00 2001 From: Jonathan Westhues Date: Fri, 3 Jul 2009 12:55:57 -0800 Subject: [PATCH] Add a mechanism to record the lines drawn when we display a constraint, so that we can export that too. This includes the lines for the vector font. A little ugly; it needs some kind of line style (color or width) to distinguish those lines from the real geometry in the exported file. [git-p4: depot-paths = "//depot/solvespace/": change = 2007] --- drawconstraint.cpp | 65 ++++++++++++++++++++++++------------------- drawentity.cpp | 6 +--- export.cpp | 9 +++++- glhelper.cpp | 69 +++++++++++++++++++++++++--------------------- groupmesh.cpp | 23 ++++++---------- sketch.h | 2 ++ solvespace.h | 12 +++++--- 7 files changed, 102 insertions(+), 84 deletions(-) diff --git a/drawconstraint.cpp b/drawconstraint.cpp index 37e1d99..9aac25c 100644 --- a/drawconstraint.cpp +++ b/drawconstraint.cpp @@ -19,10 +19,14 @@ bool Constraint::HasLabel(void) { void Constraint::LineDrawOrGetDistance(Vector a, Vector b) { if(dogd.drawing) { - glBegin(GL_LINE_STRIP); - glxVertex3v(a); - glxVertex3v(b); - glEnd(); + if(dogd.sel) { + dogd.sel->AddEdge(a, b); + } else { + glBegin(GL_LINE_STRIP); + glxVertex3v(a); + glxVertex3v(b); + glEnd(); + } } else { Point2d ap = SS.GW.ProjectPoint(a); Point2d bp = SS.GW.ProjectPoint(b); @@ -33,6 +37,12 @@ void Constraint::LineDrawOrGetDistance(Vector a, Vector b) { dogd.refp = (a.Plus(b)).ScaledBy(0.5); } +static void LineCallback(void *fndata, Vector a, Vector b) +{ + Constraint *c = (Constraint *)fndata; + c->LineDrawOrGetDistance(a, b); +} + double Constraint::EllipticalInterpolation(double rx, double ry, double theta) { double ex = rx*cos(theta); double ey = ry*sin(theta); @@ -70,11 +80,7 @@ void Constraint::DoLabel(Vector ref, Vector *labelPos, Vector gr, Vector gu) { } if(dogd.drawing) { - glPushMatrix(); - glxTranslatev(ref); - glxOntoWorkplane(gr, gu); - glxWriteTextRefCenter(s); - glPopMatrix(); + glxWriteTextRefCenter(s, ref, gr, gu, LineCallback, this); } else { double l = swidth/2 - sheight/2; l = max(l, 5/SS.GW.scale); @@ -183,12 +189,10 @@ void Constraint::DoArcForAngle(Vector a0, Vector da, Vector b0, Vector db, // The lines are skew; no wonderful way to illustrate that. *ref = a0.Plus(b0); *ref = (*ref).ScaledBy(0.5).Plus(disp.offset); - glPushMatrix(); - gu = gu.WithMagnitude(1); - glxTranslatev((*ref).Plus(gu.ScaledBy(-1.5*glxStrHeight()))); - glxOntoWorkplane(gr, gu); - glxWriteTextRefCenter("angle between skew lines"); - glPopMatrix(); + gu = gu.WithMagnitude(1); + Vector trans = (*ref).Plus(gu.ScaledBy(-1.5*glxStrHeight())); + glxWriteTextRefCenter("angle between skew lines", + trans, gr, gu, LineCallback, this); } } @@ -500,11 +504,7 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) { } if(dogd.drawing) { - glPushMatrix(); - glxTranslatev(textAt); - glxOntoWorkplane(u, v); - glxWriteTextRefCenter("T"); - glPopMatrix(); + glxWriteTextRefCenter("T", textAt, u, v, LineCallback, this); } else { dogd.refp = textAt; Point2d ref = SS.GW.ProjectPoint(dogd.refp); @@ -682,14 +682,12 @@ s: if(type == AT_MIDPOINT) offset = offset.ScaledBy(-1); if(dogd.drawing) { - glPushMatrix(); - glxTranslatev(m.Plus(offset)); - glxOntoWorkplane(r, u); - glxWriteTextRefCenter( - (type == HORIZONTAL) ? "H" : ( - (type == VERTICAL) ? "V" : ( - (type == AT_MIDPOINT) ? "M" : NULL))); - glPopMatrix(); + char *s = (type == HORIZONTAL) ? "H" : ( + (type == VERTICAL) ? "V" : ( + (type == AT_MIDPOINT) ? "M" : NULL)); + + glxWriteTextRefCenter(s, m.Plus(offset), r, u, + LineCallback, this); } else { dogd.refp = m.Plus(offset); Point2d ref = SS.GW.ProjectPoint(dogd.refp); @@ -742,12 +740,14 @@ s: void Constraint::Draw(void) { dogd.drawing = true; + dogd.sel = NULL; glLineWidth(1); DrawOrGetDistance(NULL); } double Constraint::GetDistance(Point2d mp) { dogd.drawing = false; + dogd.sel = NULL; dogd.mp = mp; dogd.dmin = 1e12; @@ -758,6 +758,7 @@ double Constraint::GetDistance(Point2d mp) { Vector Constraint::GetLabelPos(void) { dogd.drawing = false; + dogd.sel = NULL; dogd.mp.x = 0; dogd.mp.y = 0; dogd.dmin = 1e12; @@ -768,6 +769,7 @@ Vector Constraint::GetLabelPos(void) { Vector Constraint::GetReferencePos(void) { dogd.drawing = false; + dogd.sel = NULL; dogd.refp = SS.GW.offset.ScaledBy(-1); DrawOrGetDistance(NULL); @@ -775,3 +777,10 @@ Vector Constraint::GetReferencePos(void) { return dogd.refp; } +void Constraint::GetEdges(SEdgeList *sel) { + dogd.drawing = true; + dogd.sel = sel; + DrawOrGetDistance(NULL); + dogd.sel = NULL; +} + diff --git a/drawentity.cpp b/drawentity.cpp index 9a4af1d..ecf4b88 100644 --- a/drawentity.cpp +++ b/drawentity.cpp @@ -440,11 +440,7 @@ void Entity::DrawOrGetDistance(void) { char *str = DescriptionString()+5; if(dogd.drawing) { - glPushMatrix(); - glxTranslatev(mm2); - glxOntoWorkplane(u, v); - glxWriteText(str); - glPopMatrix(); + glxWriteText(str, mm2, u, v, NULL, NULL); } else { Vector pos = mm2.Plus(u.ScaledBy(glxStrWidth(str)/2)).Plus( v.ScaledBy(glxStrHeight()/2)); diff --git a/export.cpp b/export.cpp index 21d461b..3713a51 100644 --- a/export.cpp +++ b/export.cpp @@ -135,6 +135,13 @@ void SolveSpace::ExportViewTo(char *filename) { } } + if(SS.GW.showConstraints) { + Constraint *c; + for(c = SK.constraint.First(); c; c = SK.constraint.NextAfter(c)) { + c->GetEdges(&edges); + } + } + Vector u = SS.GW.projRight, v = SS.GW.projUp, n = u.Cross(v), @@ -856,7 +863,7 @@ void PdfFileWriter::Bezier(SBezier *sb) { //----------------------------------------------------------------------------- const char *SvgFileWriter::SVG_STYLE = - "stroke-width='1' stroke='black' style='fill: none;'"; + "stroke-width='0.1' stroke='black' style='fill: none;'"; void SvgFileWriter::StartFile(void) { fprintf(f, diff --git a/glhelper.cpp b/glhelper.cpp index 6968e66..22760e9 100644 --- a/glhelper.cpp +++ b/glhelper.cpp @@ -22,21 +22,41 @@ double glxStrHeight(void) { // The characters have height ~21, as they appear in the table. return 21.0*FONT_SCALE/SS.GW.scale; } -void glxWriteTextRefCenter(char *str) +void glxWriteTextRefCenter(char *str, Vector t, Vector u, Vector v, + glxLineFn *fn, void *fndata) { + u = u.WithMagnitude(1); + v = v.WithMagnitude(1); + double scale = FONT_SCALE/SS.GW.scale; double fh = glxStrHeight(); double fw = glxStrWidth(str); - glPushMatrix(); - glTranslated(-fw/2, -fh/2, 0); - // Undo the (+5, +5) offset that glxWriteText applies. - glTranslated(-5*scale, -5*scale, 0); - glxWriteText(str); - glPopMatrix(); + + t = t.Plus(u.ScaledBy(-fw/2)); + t = t.Plus(v.ScaledBy(-fh/2)); + + // Undo the (+5, +5) offset that glxWriteText applies. + t = t.Plus(u.ScaledBy(-5*scale)); + t = t.Plus(v.ScaledBy(-5*scale)); + + glxWriteText(str, t, u, v, fn, fndata); } -void glxWriteText(char *str) +static void LineDrawCallback(void *fndata, Vector a, Vector b) { + glBegin(GL_LINES); + glxVertex3v(a); + glxVertex3v(b); + glEnd(); +} + +void glxWriteText(char *str, Vector t, Vector u, Vector v, + glxLineFn *fn, void *fndata) +{ + if(!fn) fn = LineDrawCallback; + u = u.WithMagnitude(1); + v = v.WithMagnitude(1); + double scale = FONT_SCALE/SS.GW.scale; int xo = 5; int yo = 5; @@ -47,20 +67,24 @@ void glxWriteText(char *str) c -= 32; - glBegin(GL_LINE_STRIP); int j; + Vector prevp = Vector::From(VERY_POSITIVE, 0, 0); for(j = 0; j < Font[c].points; j++) { int x = Font[c].coord[j*2]; int y = Font[c].coord[j*2+1]; if(x == PEN_UP && y == PEN_UP) { - glEnd(); - glBegin(GL_LINE_STRIP); + prevp.x = VERY_POSITIVE; } else { - glVertex3d((xo + x)*scale, (yo + y)*scale, 0); + Vector p = t; + p = p.Plus(u.ScaledBy((xo + x)*scale)); + p = p.Plus(v.ScaledBy((yo + y)*scale)); + if(prevp.x != VERY_POSITIVE) { + fn(fndata, prevp, p); + } + prevp = p; } } - glEnd(); xo += Font[c].width; } @@ -71,25 +95,6 @@ void glxVertex3v(Vector u) glVertex3f((GLfloat)u.x, (GLfloat)u.y, (GLfloat)u.z); } -void glxTranslatev(Vector u) -{ - glTranslated((GLdouble)u.x, (GLdouble)u.y, (GLdouble)u.z); -} - -void glxOntoWorkplane(Vector u, Vector v) -{ - u = u.WithMagnitude(1); - v = v.WithMagnitude(1); - - double mat[16]; - Vector n = u.Cross(v); - MakeMatrix(mat, u.x, v.x, n.x, 0, - u.y, v.y, n.y, 0, - u.z, v.z, n.z, 0, - 0, 0, 0, 1); - glMultMatrixd(mat); -} - void glxLockColorTo(double r, double g, double b) { ColorLocked = false; diff --git a/groupmesh.cpp b/groupmesh.cpp index 599c6ed..de717aa 100644 --- a/groupmesh.cpp +++ b/groupmesh.cpp @@ -453,11 +453,9 @@ void Group::Draw(void) { glEnd(); glLineWidth(1); glxColor3d(1, 0, 0); - glPushMatrix(); - glxTranslatev(polyError.notClosedAt.b); - glxOntoWorkplane(SS.GW.projRight, SS.GW.projUp); - glxWriteText("not closed contour!"); - glPopMatrix(); + glxWriteText("not closed contour!", + polyError.notClosedAt.b, SS.GW.projRight, SS.GW.projUp, + NULL, NULL); glEnable(GL_DEPTH_TEST); } } else if(polyError.how == POLY_NOT_COPLANAR || @@ -467,15 +465,12 @@ void Group::Draw(void) { if(type == DRAWING_WORKPLANE) { glDisable(GL_DEPTH_TEST); glxColor3d(1, 0, 0); - glPushMatrix(); - glxTranslatev(polyError.errorPointAt); - glxOntoWorkplane(SS.GW.projRight, SS.GW.projUp); - if(polyError.how == POLY_NOT_COPLANAR) { - glxWriteText("points not all coplanar!"); - } else { - glxWriteText("contour is self-intersecting!"); - } - glPopMatrix(); + char *msg = (polyError.how == POLY_NOT_COPLANAR) ? + "points not all coplanar!" : + "contour is self-intersecting!"; + glxWriteText(msg, + polyError.errorPointAt, SS.GW.projRight, SS.GW.projUp, + NULL, NULL); glEnable(GL_DEPTH_TEST); } } else { diff --git a/sketch.h b/sketch.h index cfea758..e47ba78 100644 --- a/sketch.h +++ b/sketch.h @@ -531,12 +531,14 @@ public: Point2d mp; double dmin; Vector refp; + SEdgeList *sel; } dogd; double GetDistance(Point2d mp); Vector GetLabelPos(void); Vector GetReferencePos(void); void Draw(void); + void GetEdges(SEdgeList *sel); void LineDrawOrGetDistance(Vector a, Vector b); void DrawOrGetDistance(Vector *labelPos); diff --git a/solvespace.h b/solvespace.h index 5aebc68..18dcc7f 100644 --- a/solvespace.h +++ b/solvespace.h @@ -184,12 +184,13 @@ void glxDebugPolygon(SPolygon *p); void glxDrawEdges(SEdgeList *l, bool endpointsToo); void glxDebugMesh(SMesh *m); void glxMarkPolygonNormal(SPolygon *p); -void glxWriteText(char *str); -void glxWriteTextRefCenter(char *str); +typedef void glxLineFn(void *data, Vector a, Vector b); +void glxWriteText(char *str, Vector t, Vector u, Vector v, + glxLineFn *fn, void *fndata); +void glxWriteTextRefCenter(char *str, Vector t, Vector u, Vector v, + glxLineFn *fn, void *fndata); double glxStrWidth(char *str); double glxStrHeight(void); -void glxTranslatev(Vector u); -void glxOntoWorkplane(Vector u, Vector v); void glxLockColorTo(double r, double g, double b); void glxUnlockColor(void); void glxColor3d(double r, double g, double b); @@ -383,6 +384,9 @@ class VectorFileWriter { public: FILE *f; Vector ptMin, ptMax; + + double width; + double r, g, b; static double MmToPts(double mm); static bool StringEndsIn(char *str, char *ending);