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]
This commit is contained in:
Jonathan Westhues 2009-07-03 12:55:57 -08:00
parent a74f85e0d1
commit 66c93aab73
7 changed files with 102 additions and 84 deletions

View File

@ -19,10 +19,14 @@ bool Constraint::HasLabel(void) {
void Constraint::LineDrawOrGetDistance(Vector a, Vector b) { void Constraint::LineDrawOrGetDistance(Vector a, Vector b) {
if(dogd.drawing) { if(dogd.drawing) {
glBegin(GL_LINE_STRIP); if(dogd.sel) {
glxVertex3v(a); dogd.sel->AddEdge(a, b);
glxVertex3v(b); } else {
glEnd(); glBegin(GL_LINE_STRIP);
glxVertex3v(a);
glxVertex3v(b);
glEnd();
}
} else { } else {
Point2d ap = SS.GW.ProjectPoint(a); Point2d ap = SS.GW.ProjectPoint(a);
Point2d bp = SS.GW.ProjectPoint(b); 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); 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 Constraint::EllipticalInterpolation(double rx, double ry, double theta) {
double ex = rx*cos(theta); double ex = rx*cos(theta);
double ey = ry*sin(theta); double ey = ry*sin(theta);
@ -70,11 +80,7 @@ void Constraint::DoLabel(Vector ref, Vector *labelPos, Vector gr, Vector gu) {
} }
if(dogd.drawing) { if(dogd.drawing) {
glPushMatrix(); glxWriteTextRefCenter(s, ref, gr, gu, LineCallback, this);
glxTranslatev(ref);
glxOntoWorkplane(gr, gu);
glxWriteTextRefCenter(s);
glPopMatrix();
} else { } else {
double l = swidth/2 - sheight/2; double l = swidth/2 - sheight/2;
l = max(l, 5/SS.GW.scale); 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. // The lines are skew; no wonderful way to illustrate that.
*ref = a0.Plus(b0); *ref = a0.Plus(b0);
*ref = (*ref).ScaledBy(0.5).Plus(disp.offset); *ref = (*ref).ScaledBy(0.5).Plus(disp.offset);
glPushMatrix(); gu = gu.WithMagnitude(1);
gu = gu.WithMagnitude(1); Vector trans = (*ref).Plus(gu.ScaledBy(-1.5*glxStrHeight()));
glxTranslatev((*ref).Plus(gu.ScaledBy(-1.5*glxStrHeight()))); glxWriteTextRefCenter("angle between skew lines",
glxOntoWorkplane(gr, gu); trans, gr, gu, LineCallback, this);
glxWriteTextRefCenter("angle between skew lines");
glPopMatrix();
} }
} }
@ -500,11 +504,7 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) {
} }
if(dogd.drawing) { if(dogd.drawing) {
glPushMatrix(); glxWriteTextRefCenter("T", textAt, u, v, LineCallback, this);
glxTranslatev(textAt);
glxOntoWorkplane(u, v);
glxWriteTextRefCenter("T");
glPopMatrix();
} else { } else {
dogd.refp = textAt; dogd.refp = textAt;
Point2d ref = SS.GW.ProjectPoint(dogd.refp); Point2d ref = SS.GW.ProjectPoint(dogd.refp);
@ -682,14 +682,12 @@ s:
if(type == AT_MIDPOINT) offset = offset.ScaledBy(-1); if(type == AT_MIDPOINT) offset = offset.ScaledBy(-1);
if(dogd.drawing) { if(dogd.drawing) {
glPushMatrix(); char *s = (type == HORIZONTAL) ? "H" : (
glxTranslatev(m.Plus(offset)); (type == VERTICAL) ? "V" : (
glxOntoWorkplane(r, u); (type == AT_MIDPOINT) ? "M" : NULL));
glxWriteTextRefCenter(
(type == HORIZONTAL) ? "H" : ( glxWriteTextRefCenter(s, m.Plus(offset), r, u,
(type == VERTICAL) ? "V" : ( LineCallback, this);
(type == AT_MIDPOINT) ? "M" : NULL)));
glPopMatrix();
} else { } else {
dogd.refp = m.Plus(offset); dogd.refp = m.Plus(offset);
Point2d ref = SS.GW.ProjectPoint(dogd.refp); Point2d ref = SS.GW.ProjectPoint(dogd.refp);
@ -742,12 +740,14 @@ s:
void Constraint::Draw(void) { void Constraint::Draw(void) {
dogd.drawing = true; dogd.drawing = true;
dogd.sel = NULL;
glLineWidth(1); glLineWidth(1);
DrawOrGetDistance(NULL); DrawOrGetDistance(NULL);
} }
double Constraint::GetDistance(Point2d mp) { double Constraint::GetDistance(Point2d mp) {
dogd.drawing = false; dogd.drawing = false;
dogd.sel = NULL;
dogd.mp = mp; dogd.mp = mp;
dogd.dmin = 1e12; dogd.dmin = 1e12;
@ -758,6 +758,7 @@ double Constraint::GetDistance(Point2d mp) {
Vector Constraint::GetLabelPos(void) { Vector Constraint::GetLabelPos(void) {
dogd.drawing = false; dogd.drawing = false;
dogd.sel = NULL;
dogd.mp.x = 0; dogd.mp.y = 0; dogd.mp.x = 0; dogd.mp.y = 0;
dogd.dmin = 1e12; dogd.dmin = 1e12;
@ -768,6 +769,7 @@ Vector Constraint::GetLabelPos(void) {
Vector Constraint::GetReferencePos(void) { Vector Constraint::GetReferencePos(void) {
dogd.drawing = false; dogd.drawing = false;
dogd.sel = NULL;
dogd.refp = SS.GW.offset.ScaledBy(-1); dogd.refp = SS.GW.offset.ScaledBy(-1);
DrawOrGetDistance(NULL); DrawOrGetDistance(NULL);
@ -775,3 +777,10 @@ Vector Constraint::GetReferencePos(void) {
return dogd.refp; return dogd.refp;
} }
void Constraint::GetEdges(SEdgeList *sel) {
dogd.drawing = true;
dogd.sel = sel;
DrawOrGetDistance(NULL);
dogd.sel = NULL;
}

View File

@ -440,11 +440,7 @@ void Entity::DrawOrGetDistance(void) {
char *str = DescriptionString()+5; char *str = DescriptionString()+5;
if(dogd.drawing) { if(dogd.drawing) {
glPushMatrix(); glxWriteText(str, mm2, u, v, NULL, NULL);
glxTranslatev(mm2);
glxOntoWorkplane(u, v);
glxWriteText(str);
glPopMatrix();
} else { } else {
Vector pos = mm2.Plus(u.ScaledBy(glxStrWidth(str)/2)).Plus( Vector pos = mm2.Plus(u.ScaledBy(glxStrWidth(str)/2)).Plus(
v.ScaledBy(glxStrHeight()/2)); v.ScaledBy(glxStrHeight()/2));

View File

@ -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, Vector u = SS.GW.projRight,
v = SS.GW.projUp, v = SS.GW.projUp,
n = u.Cross(v), n = u.Cross(v),
@ -856,7 +863,7 @@ void PdfFileWriter::Bezier(SBezier *sb) {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
const char *SvgFileWriter::SVG_STYLE = 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) { void SvgFileWriter::StartFile(void) {
fprintf(f, fprintf(f,

View File

@ -22,21 +22,41 @@ double glxStrHeight(void) {
// The characters have height ~21, as they appear in the table. // The characters have height ~21, as they appear in the table.
return 21.0*FONT_SCALE/SS.GW.scale; 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 scale = FONT_SCALE/SS.GW.scale;
double fh = glxStrHeight(); double fh = glxStrHeight();
double fw = glxStrWidth(str); double fw = glxStrWidth(str);
glPushMatrix();
glTranslated(-fw/2, -fh/2, 0); t = t.Plus(u.ScaledBy(-fw/2));
// Undo the (+5, +5) offset that glxWriteText applies. t = t.Plus(v.ScaledBy(-fh/2));
glTranslated(-5*scale, -5*scale, 0);
glxWriteText(str); // Undo the (+5, +5) offset that glxWriteText applies.
glPopMatrix(); 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; double scale = FONT_SCALE/SS.GW.scale;
int xo = 5; int xo = 5;
int yo = 5; int yo = 5;
@ -47,20 +67,24 @@ void glxWriteText(char *str)
c -= 32; c -= 32;
glBegin(GL_LINE_STRIP);
int j; int j;
Vector prevp = Vector::From(VERY_POSITIVE, 0, 0);
for(j = 0; j < Font[c].points; j++) { for(j = 0; j < Font[c].points; j++) {
int x = Font[c].coord[j*2]; int x = Font[c].coord[j*2];
int y = Font[c].coord[j*2+1]; int y = Font[c].coord[j*2+1];
if(x == PEN_UP && y == PEN_UP) { if(x == PEN_UP && y == PEN_UP) {
glEnd(); prevp.x = VERY_POSITIVE;
glBegin(GL_LINE_STRIP);
} else { } 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; xo += Font[c].width;
} }
@ -71,25 +95,6 @@ void glxVertex3v(Vector u)
glVertex3f((GLfloat)u.x, (GLfloat)u.y, (GLfloat)u.z); 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) void glxLockColorTo(double r, double g, double b)
{ {
ColorLocked = false; ColorLocked = false;

View File

@ -453,11 +453,9 @@ void Group::Draw(void) {
glEnd(); glEnd();
glLineWidth(1); glLineWidth(1);
glxColor3d(1, 0, 0); glxColor3d(1, 0, 0);
glPushMatrix(); glxWriteText("not closed contour!",
glxTranslatev(polyError.notClosedAt.b); polyError.notClosedAt.b, SS.GW.projRight, SS.GW.projUp,
glxOntoWorkplane(SS.GW.projRight, SS.GW.projUp); NULL, NULL);
glxWriteText("not closed contour!");
glPopMatrix();
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
} }
} else if(polyError.how == POLY_NOT_COPLANAR || } else if(polyError.how == POLY_NOT_COPLANAR ||
@ -467,15 +465,12 @@ void Group::Draw(void) {
if(type == DRAWING_WORKPLANE) { if(type == DRAWING_WORKPLANE) {
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glxColor3d(1, 0, 0); glxColor3d(1, 0, 0);
glPushMatrix(); char *msg = (polyError.how == POLY_NOT_COPLANAR) ?
glxTranslatev(polyError.errorPointAt); "points not all coplanar!" :
glxOntoWorkplane(SS.GW.projRight, SS.GW.projUp); "contour is self-intersecting!";
if(polyError.how == POLY_NOT_COPLANAR) { glxWriteText(msg,
glxWriteText("points not all coplanar!"); polyError.errorPointAt, SS.GW.projRight, SS.GW.projUp,
} else { NULL, NULL);
glxWriteText("contour is self-intersecting!");
}
glPopMatrix();
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
} }
} else { } else {

View File

@ -531,12 +531,14 @@ public:
Point2d mp; Point2d mp;
double dmin; double dmin;
Vector refp; Vector refp;
SEdgeList *sel;
} dogd; } dogd;
double GetDistance(Point2d mp); double GetDistance(Point2d mp);
Vector GetLabelPos(void); Vector GetLabelPos(void);
Vector GetReferencePos(void); Vector GetReferencePos(void);
void Draw(void); void Draw(void);
void GetEdges(SEdgeList *sel);
void LineDrawOrGetDistance(Vector a, Vector b); void LineDrawOrGetDistance(Vector a, Vector b);
void DrawOrGetDistance(Vector *labelPos); void DrawOrGetDistance(Vector *labelPos);

View File

@ -184,12 +184,13 @@ void glxDebugPolygon(SPolygon *p);
void glxDrawEdges(SEdgeList *l, bool endpointsToo); void glxDrawEdges(SEdgeList *l, bool endpointsToo);
void glxDebugMesh(SMesh *m); void glxDebugMesh(SMesh *m);
void glxMarkPolygonNormal(SPolygon *p); void glxMarkPolygonNormal(SPolygon *p);
void glxWriteText(char *str); typedef void glxLineFn(void *data, Vector a, Vector b);
void glxWriteTextRefCenter(char *str); 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 glxStrWidth(char *str);
double glxStrHeight(void); double glxStrHeight(void);
void glxTranslatev(Vector u);
void glxOntoWorkplane(Vector u, Vector v);
void glxLockColorTo(double r, double g, double b); void glxLockColorTo(double r, double g, double b);
void glxUnlockColor(void); void glxUnlockColor(void);
void glxColor3d(double r, double g, double b); void glxColor3d(double r, double g, double b);
@ -384,6 +385,9 @@ public:
FILE *f; FILE *f;
Vector ptMin, ptMax; Vector ptMin, ptMax;
double width;
double r, g, b;
static double MmToPts(double mm); static double MmToPts(double mm);
static bool StringEndsIn(char *str, char *ending); static bool StringEndsIn(char *str, char *ending);