Skip to content

Commit

Permalink
Use a separate value of chord tolerance for exporting.
Browse files Browse the repository at this point in the history
Before this commit, a single chord tolerance was used for both
displaying and exporting geometry. Moreover, this chord tolerance
was specified in screen pixels, and as such depended on zoom level.
This was inconvenient: exporting geometry with a required level of
precision required awkward manipulations of viewport. Moreover,
since some operations, e.g. mesh watertightness checking, were done
on triangle meshes which are generated differently depending on
the zoom level, these operations could report wildly different
and quite confusing results depending on zoom level.

The chord tolerance for display and export pursue completely distinct
goals: display chord tolerance should be set high enough to achieve
both fast regeneration and legible rendering, whereas export chord
tolerance should be set to match the dimension tolerance of
the fabrication process.

This commit introduces two distinct chord tolerances: a display
and an export one. Both chord tolerances are absolute and expressed
in millimeters; this is inappropriate for display purposes but
will be fixed in the next commits.

After exporting, the geometry is redrawn with the chord tolerance
configured for the export and an overlay message is displayed;
pressing Esc clears the message and returns the display back to
normal.
  • Loading branch information
Evil-Spirit authored and whitequark committed Feb 13, 2016
1 parent 139dd80 commit 89eb208
Show file tree
Hide file tree
Showing 11 changed files with 123 additions and 34 deletions.
42 changes: 37 additions & 5 deletions src/confscreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,27 @@ void TextWindow::ScreenChangeColor(int link, uint32_t v) {
}

void TextWindow::ScreenChangeChordTolerance(int link, uint32_t v) {
SS.TW.ShowEditControl(3, ssprintf("%.2f", SS.chordTol));
SS.TW.ShowEditControl(3, ssprintf("%lg", SS.chordTol));
SS.TW.edit.meaning = EDIT_CHORD_TOLERANCE;
SS.TW.edit.i = 0;
}

void TextWindow::ScreenChangeMaxSegments(int link, uint32_t v) {
SS.TW.ShowEditControl(3, ssprintf("%d", SS.maxSegments));
SS.TW.edit.meaning = EDIT_MAX_SEGMENTS;
SS.TW.edit.i = 0;
}

void TextWindow::ScreenChangeExportChordTolerance(int link, uint32_t v) {
SS.TW.ShowEditControl(3, ssprintf("%lg", SS.exportChordTol));
SS.TW.edit.meaning = EDIT_CHORD_TOLERANCE;
SS.TW.edit.i = 1;
}

void TextWindow::ScreenChangeExportMaxSegments(int link, uint32_t v) {
SS.TW.ShowEditControl(3, ssprintf("%d", SS.exportMaxSegments));
SS.TW.edit.meaning = EDIT_MAX_SEGMENTS;
SS.TW.edit.i = 1;
}

void TextWindow::ScreenChangeCameraTangent(int link, uint32_t v) {
Expand Down Expand Up @@ -182,6 +196,16 @@ void TextWindow::ShowConfiguration(void) {
SS.maxSegments,
&ScreenChangeMaxSegments);

Printf(false, "");
Printf(false, "%Ft export chord tolerance (in mm)%E");
Printf(false, "%Ba %@ %Fl%Ll%f%D[change]%E",
SS.exportChordTol,
&ScreenChangeExportChordTolerance, 0);
Printf(false, "%Ft export max piecewise linear segments%E");
Printf(false, "%Ba %d %Fl%Ll%f[change]%E",
SS.exportMaxSegments,
&ScreenChangeExportMaxSegments);

Printf(false, "");
Printf(false, "%Ft perspective factor (0 for parallel)%E");
Printf(false, "%Ba %# %Fl%Ll%f%D[change]%E",
Expand Down Expand Up @@ -312,13 +336,21 @@ bool TextWindow::EditControlDoneForConfiguration(const char *s) {
break;
}
case EDIT_CHORD_TOLERANCE: {
SS.chordTol = min(10.0, max(0.1, atof(s)));
SS.GenerateAll(SolveSpaceUI::GENERATE_ALL);
if(edit.i == 0) {
SS.chordTol = max(0.0, atof(s));
SS.GenerateAll(SolveSpaceUI::GENERATE_ALL);
} else {
SS.exportChordTol = max(0.0, atof(s));
}
break;
}
case EDIT_MAX_SEGMENTS: {
SS.maxSegments = min(1000, max(7, atoi(s)));
SS.GenerateAll(SolveSpaceUI::GENERATE_ALL);
if(edit.i == 0) {
SS.maxSegments = min(1000, max(7, atoi(s)));
SS.GenerateAll(SolveSpaceUI::GENERATE_ALL);
} else {
SS.exportMaxSegments = min(1000, max(7, atoi(s)));
}
break;
}
case EDIT_CAMERA_TANGENT: {
Expand Down
45 changes: 28 additions & 17 deletions src/draw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -796,28 +796,39 @@ nogrid:;

// A note to indicate the origin in the just-exported file.
if(SS.justExportedInfo.draw) {
ssglColorRGB(Style::Color(Style::DATUM));
Vector p = SS.justExportedInfo.pt,
u = SS.justExportedInfo.u,
v = SS.justExportedInfo.v;
Vector p, u, v;
if(SS.justExportedInfo.showOrigin) {
p = SS.justExportedInfo.pt,
u = SS.justExportedInfo.u,
v = SS.justExportedInfo.v;
} else {
p = SS.GW.offset.ScaledBy(-1);
u = SS.GW.projRight;
v = SS.GW.projUp;
}

ssglLineWidth(1.5);
glBegin(GL_LINES);
ssglVertex3v(p.Plus(u.WithMagnitude(-15/scale)));
ssglVertex3v(p.Plus(u.WithMagnitude(30/scale)));
ssglVertex3v(p.Plus(v.WithMagnitude(-15/scale)));
ssglVertex3v(p.Plus(v.WithMagnitude(30/scale)));
glEnd();
ssglColorRGB(Style::Color(Style::DATUM));

ssglWriteText("(x, y) = (0, 0) for file just exported",
ssglWriteText("previewing exported geometry; press Esc to return",
DEFAULT_TEXT_HEIGHT,
p.Plus(u.ScaledBy(10/scale)).Plus(v.ScaledBy(10/scale)),
u, v, NULL, NULL);
ssglWriteText("press Esc to clear this message",
DEFAULT_TEXT_HEIGHT,
p.Plus(u.ScaledBy(40/scale)).Plus(
v.ScaledBy(-(DEFAULT_TEXT_HEIGHT)/scale)),
u, v, NULL, NULL);

if(SS.justExportedInfo.showOrigin) {
ssglLineWidth(1.5);
glBegin(GL_LINES);
ssglVertex3v(p.Plus(u.WithMagnitude(-15/scale)));
ssglVertex3v(p.Plus(u.WithMagnitude(30/scale)));
ssglVertex3v(p.Plus(v.WithMagnitude(-15/scale)));
ssglVertex3v(p.Plus(v.WithMagnitude(30/scale)));
glEnd();

ssglWriteText("(x, y) = (0, 0) for file just exported",
DEFAULT_TEXT_HEIGHT,
p.Plus(u.ScaledBy(40/scale)).Plus(
v.ScaledBy(-(DEFAULT_TEXT_HEIGHT)/scale)),
u, v, NULL, NULL);
}
}

// And finally the toolbar.
Expand Down
27 changes: 22 additions & 5 deletions src/export.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ void SolveSpaceUI::ExportViewOrWireframeTo(const std::string &filename, bool wir
SEdgeList edges = {};
SBezierList beziers = {};

SS.exportMode = true;
GenerateAll(GENERATE_ALL);

SMesh *sm = NULL;
if(SS.GW.showShaded) {
Group *g = SK.GetGroup(SS.GW.activeGroup);
Expand Down Expand Up @@ -178,12 +181,16 @@ void SolveSpaceUI::ExportViewOrWireframeTo(const std::string &filename, bool wir
// These file formats don't have a canvas size, so they just
// get exported in the raw coordinate system. So indicate what
// that was on-screen.
SS.justExportedInfo.draw = true;
SS.justExportedInfo.showOrigin = true;
SS.justExportedInfo.pt = origin;
SS.justExportedInfo.u = u;
SS.justExportedInfo.v = v;
InvalidateGraphics();
} else {
SS.justExportedInfo.showOrigin = false;
}

SS.justExportedInfo.draw = true;
InvalidateGraphics();
}

edges.Clear();
Expand Down Expand Up @@ -365,7 +372,7 @@ void SolveSpaceUI::ExportLinesAndMesh(SEdgeList *sel, SBezierList *sbl, SMesh *s
SEdge notClosedAt;
sbl->l.ClearTags();
sblss.FindOuterFacesFrom(sbl, &spxyz, &srf,
SS.ChordTolMm()*s,
SS.ExportChordTolMm(),
&allClosed, &notClosedAt,
NULL, NULL,
&leftovers);
Expand Down Expand Up @@ -509,7 +516,7 @@ void VectorFileWriter::Output(SBezierLoopSetSet *sblss, SMesh *sm) {

void VectorFileWriter::BezierAsPwl(SBezier *sb) {
List<Vector> lv = {};
sb->MakePwlInto(&lv, SS.ChordTolMm() / SS.exportScale);
sb->MakePwlInto(&lv, SS.ExportChordTolMm());
int i;
for(i = 1; i < lv.n; i++) {
SBezier sb = SBezier::From(lv.elem[i-1], lv.elem[i]);
Expand All @@ -528,7 +535,7 @@ void VectorFileWriter::BezierAsNonrationalCubic(SBezier *sb, int depth) {
sb->Finish().Minus(t1.ScaledBy(1.0/3)),
sb->Finish());

double tol = SS.ChordTolMm() / SS.exportScale;
double tol = SS.ExportChordTolMm();
// Arbitrary choice, but make it a little finer than pwl tolerance since
// it should be easier to achieve that with the smooth curves.
tol /= 2;
Expand Down Expand Up @@ -559,6 +566,12 @@ void VectorFileWriter::BezierAsNonrationalCubic(SBezier *sb, int depth) {
// Export a triangle mesh, in the requested format.
//-----------------------------------------------------------------------------
void SolveSpaceUI::ExportMeshTo(const std::string &filename) {
SS.exportMode = true;
GenerateAll(GENERATE_ALL);

Group *g = SK.GetGroup(SS.GW.activeGroup);
g->GenerateDisplayItems();

SMesh *m = &(SK.GetGroup(SS.GW.activeGroup)->displayMesh);
if(m->IsEmpty()) {
Error("Active group mesh is empty; nothing to export.");
Expand All @@ -585,6 +598,10 @@ void SolveSpaceUI::ExportMeshTo(const std::string &filename) {
}

fclose(f);

SS.justExportedInfo.showOrigin = false;
SS.justExportedInfo.draw = true;
InvalidateGraphics();
}

//-----------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion src/exportstep.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ void StepFileWriter::ExportSurface(SSurface *ss, SBezierList *sbl) {
// tolerance are required, because they are used to calculate the
// contour directions and determine inner vs. outer contours.
sblss.FindOuterFacesFrom(sbl, &spxyz, ss,
SS.ChordTolMm() / SS.exportScale,
SS.ExportChordTolMm(),
&allClosed, &notClosedAt,
NULL, NULL,
NULL);
Expand Down
4 changes: 4 additions & 0 deletions src/graphicswin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,10 @@ void GraphicsWindow::MenuEdit(int id) {
for(p = SK.param.First(); p; p = SK.param.NextAfter(p)) {
p->free = false;
}
if(SS.exportMode) {
SS.exportMode = false;
SS.GenerateAll(SolveSpaceUI::GENERATE_ALL);
}
break;

case MNU_SELECT_ALL: {
Expand Down
20 changes: 19 additions & 1 deletion src/solvespace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,16 @@ void SolveSpaceUI::Init() {
lightDir[1].x = CnfThawFloat( 1.0f, "LightDir_1_Right" );
lightDir[1].y = CnfThawFloat( 0.0f, "LightDir_1_Up" );
lightDir[1].z = CnfThawFloat( 0.0f, "LightDir_1_Forward" );

exportMode = false;
// Chord tolerance
chordTol = CnfThawFloat(2.0f, "ChordTolerance");
// Max pwl segments to generate
maxSegments = CnfThawInt(10, "MaxSegments");
// Chord tolerance
exportChordTol = CnfThawFloat(0.1f, "ExportChordTolerance");
// Max pwl segments to generate
exportMaxSegments = CnfThawInt(64, "ExportMaxSegments");
// View units
viewUnits = (Unit)CnfThawInt((uint32_t)UNIT_MM, "ViewUnits");
// Number of digits after the decimal point
Expand Down Expand Up @@ -157,6 +163,10 @@ void SolveSpaceUI::Exit(void) {
CnfFreezeFloat((float)chordTol, "ChordTolerance");
// Max pwl segments to generate
CnfFreezeInt((uint32_t)maxSegments, "MaxSegments");
// Export Chord tolerance
CnfFreezeFloat((float)exportChordTol, "ExportChordTolerance");
// Export Max pwl segments to generate
CnfFreezeInt((uint32_t)exportMaxSegments, "ExportMaxSegments");
// View units
CnfFreezeInt((uint32_t)viewUnits, "ViewUnits");
// Number of digits after the decimal point
Expand Down Expand Up @@ -259,7 +269,15 @@ double SolveSpaceUI::StringToMm(const std::string &str) {
return std::stod(str) * MmPerUnit();
}
double SolveSpaceUI::ChordTolMm(void) {
return SS.chordTol / SS.GW.scale;
if(exportMode) return ExportChordTolMm();
return chordTol / GW.scale;
}
double SolveSpaceUI::ExportChordTolMm(void) {
return exportChordTol / exportScale;
}
int SolveSpaceUI::GetMaxSegments(void) {
if(exportMode) return exportMaxSegments;
return maxSegments;
}
int SolveSpaceUI::UnitDigitsAfterDecimal(void) {
return (viewUnits == UNIT_INCHES) ? afterDecimalInch : afterDecimalMm;
Expand Down
7 changes: 6 additions & 1 deletion src/solvespace.h
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,8 @@ class SolveSpaceUI {
double ambientIntensity;
double chordTol;
int maxSegments;
double exportChordTol;
int exportMaxSegments;
double cameraTangent;
float gridSpacing;
float exportScale;
Expand All @@ -764,6 +766,7 @@ class SolveSpaceUI {
bool exportShadedTriangles;
bool exportPwlCurves;
bool exportCanvasSizeAuto;
bool exportMode;
struct {
float left;
float right;
Expand Down Expand Up @@ -800,6 +803,8 @@ class SolveSpaceUI {
int UnitDigitsAfterDecimal(void);
void SetUnitDigitsAfterDecimal(int v);
double ChordTolMm(void);
double ExportChordTolMm(void);
int GetMaxSegments(void);
bool usePerspectiveProj;
double CameraTangent(void);

Expand Down Expand Up @@ -892,7 +897,7 @@ class SolveSpaceUI {
Vector origin;
} bgImage;
struct {
bool draw;
bool draw, showOrigin;
Vector pt, u, v;
} justExportedInfo;

Expand Down
4 changes: 2 additions & 2 deletions src/srf/ratpoly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ void SBezier::MakePwlWorker(List<Vector> *l, double ta, double tb, double chordT
Vector pm = PointAt((ta + tb) / 2.0);
double d = pm.DistanceToLine(pa, pb.Minus(pa));

double step = 1.0/SS.maxSegments;
double step = 1.0/SS.GetMaxSegments();
if((tb - ta) < step || d < chordTol) {
// A previous call has already added the beginning of our interval.
l->Add(&pb);
Expand Down Expand Up @@ -311,7 +311,7 @@ void SBezier::MakePwlInitialWorker(List<Vector> *l, double ta, double tb, double
pm3.DistanceToLine(pa, dir)
});

double step = 1.0/SS.maxSegments;
double step = 1.0/SS.GetMaxSegments();
if((tb - ta) < step || d < chordTol) {
// A previous call has already added the beginning of our interval.
l->Add(&pb);
Expand Down
2 changes: 1 addition & 1 deletion src/srf/surfinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ void SSurface::IntersectAgainst(SSurface *b, SShell *agnstA, SShell *agnstB,

// Our chord tolerance is whatever the user specified
double maxtol = SS.ChordTolMm();
int maxsteps = max(300, SS.maxSegments*3);
int maxsteps = max(300, SS.GetMaxSegments()*3);

// The curve starts at our starting point.
SCurvePt padd = {};
Expand Down
2 changes: 1 addition & 1 deletion src/srf/triangulate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ void SSurface::MakeTriangulationGridInto(List<double> *l, double vs, double vf,
worst = max(worst, pm2.DistanceToLine(ps, pf.Minus(ps)));
}

double step = 1.0/SS.maxSegments;
double step = 1.0/SS.GetMaxSegments();
if((vf - vs) < step || worst < SS.ChordTolMm()) {
l->Add(&vf);
} else {
Expand Down
2 changes: 2 additions & 0 deletions src/ui.h
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,8 @@ class TextWindow {
static void ScreenChangeColor(int link, uint32_t v);
static void ScreenChangeChordTolerance(int link, uint32_t v);
static void ScreenChangeMaxSegments(int link, uint32_t v);
static void ScreenChangeExportChordTolerance(int link, uint32_t v);
static void ScreenChangeExportMaxSegments(int link, uint32_t v);
static void ScreenChangeCameraTangent(int link, uint32_t v);
static void ScreenChangeGridSpacing(int link, uint32_t v);
static void ScreenChangeDigitsAfterDecimal(int link, uint32_t v);
Expand Down

0 comments on commit 89eb208

Please sign in to comment.