Use relative chord tolerance instead of absolute.

Commit 89eb208 has improved the overall situation with chord
tolerance, but it changed the display chord tolerance to use
an absolute value in millimeters as a stopgap measure.

This commit changes the display chord tolerance to be specified
in percents of entity bounding box instead of millimeters.
As a result, the linearized curves are both zoom level and sketch
scale independent.

In order to compute the bounding box, all entities are generated
twice. However, this shouldn't result in a noticeable slowdown,
since the bounding box calculation does not need the expensive
triangle mesh generation and the solver will converge immediately
on the second run.

Since the meaning of the preference has changed, a new name is
used (ChordTolerancePct instead of ChordTolerance), so that it
would be reset to the default value after updating SolveSpace.

The default value, 0.5%, was selected using trial and error by
judging whether cylinders of moderate dimensions were looking
aesthetically pleasing enough.

After this change, the only real function of the spacebar
shortcut is to reload imported groups, since manual regeneration
should not change anything anymore unless there is a bug.
pull/4/head
EvilSpirit 2016-01-29 16:33:56 +06:00 committed by whitequark
parent fc68804f65
commit 34a5d87011
4 changed files with 27 additions and 13 deletions

View File

@ -186,10 +186,10 @@ void TextWindow::ShowConfiguration(void) {
}
Printf(false, "");
Printf(false, "%Ft chord tolerance (in screen pixels)%E");
Printf(false, "%Ba %@ %Fl%Ll%f%D[change]%E; now %d triangles",
Printf(false, "%Ft chord tolerance (in percents)%E");
Printf(false, "%Ba %@ %% %Fl%Ll%f%D[change]%E; %@ mm, %d triangles",
SS.chordTol,
&ScreenChangeChordTolerance, 0,
&ScreenChangeChordTolerance, 0, SS.chordTolCalculated,
SK.GetGroup(SS.GW.activeGroup)->displayMesh.l.n);
Printf(false, "%Ft max piecewise linear segments%E");
Printf(false, "%Ba %d %Fl%Ll%f[change]%E",

View File

@ -174,7 +174,7 @@ void SolveSpaceUI::GenerateAll(GenerateType type, bool andFindFree) {
}
}
void SolveSpaceUI::GenerateAll(int first, int last, bool andFindFree) {
void SolveSpaceUI::GenerateAll(int first, int last, bool andFindFree, bool genForBBox) {
int i, j;
// generate until active group
@ -183,6 +183,16 @@ void SolveSpaceUI::GenerateAll(int first, int last, bool andFindFree) {
if(last == -1) last = INT_MAX;
}
// If we're generating entities for display, first we need to find
// the bounding box to turn relative chord tolerance to absolute.
if(!SS.exportMode && !genForBBox) {
GenerateAll(first, last, false, true);
BBox box = SK.CalculateEntityBBox(false);
Vector size = box.maxp.Minus(box.minp);
double maxSize = std::max({ size.x, size.y, size.z });
chordTolCalculated = maxSize * chordTol / 100.0;
}
// Remove any requests or constraints that refer to a nonexistent
// group; can check those immediately, since we know what the list
// of groups should be.
@ -275,10 +285,13 @@ void SolveSpaceUI::GenerateAll(int first, int last, bool andFindFree) {
if(i >= first && i <= last) {
// The group falls inside the range, so really solve it,
// and then regenerate the mesh based on the solved stuff.
SolveGroup(g->h, andFindFree);
g->GenerateLoops();
g->GenerateShellAndMesh();
g->clean = true;
if(genForBBox) {
SolveGroup(g->h, andFindFree);
} else {
g->GenerateLoops();
g->GenerateShellAndMesh();
g->clean = true;
}
} else {
// The group falls outside the range, so just assume that
// it's good wherever we left it. The mesh is unchanged,
@ -364,7 +377,7 @@ pruned:
SK.param.Clear();
prev.MoveSelfInto(&(SK.param));
// Try again
GenerateAll(first, last);
GenerateAll(first, last, andFindFree, genForBBox);
}
void SolveSpaceUI::ForceReferences(void) {

View File

@ -39,7 +39,7 @@ void SolveSpaceUI::Init() {
exportMode = false;
// Chord tolerance
chordTol = CnfThawFloat(2.0f, "ChordTolerance");
chordTol = CnfThawFloat(0.5f, "ChordTolerancePct");
// Max pwl segments to generate
maxSegments = CnfThawInt(10, "MaxSegments");
// Chord tolerance
@ -160,7 +160,7 @@ void SolveSpaceUI::Exit(void) {
CnfFreezeFloat((float)lightDir[1].y, "LightDir_1_Up");
CnfFreezeFloat((float)lightDir[1].z, "LightDir_1_Forward");
// Chord tolerance
CnfFreezeFloat((float)chordTol, "ChordTolerance");
CnfFreezeFloat((float)chordTol, "ChordTolerancePct");
// Max pwl segments to generate
CnfFreezeInt((uint32_t)maxSegments, "MaxSegments");
// Export Chord tolerance
@ -270,7 +270,7 @@ double SolveSpaceUI::StringToMm(const std::string &str) {
}
double SolveSpaceUI::ChordTolMm(void) {
if(exportMode) return ExportChordTolMm();
return chordTol / GW.scale;
return chordTolCalculated;
}
double SolveSpaceUI::ExportChordTolMm(void) {
return exportChordTol / exportScale;

View File

@ -753,6 +753,7 @@ public:
double lightIntensity[2];
double ambientIntensity;
double chordTol;
double chordTolCalculated;
int maxSegments;
double exportChordTol;
int exportMaxSegments;
@ -941,7 +942,7 @@ public:
void GenerateAll(GenerateType type, bool andFindFree = false);
void GenerateAll(void);
void GenerateAll(int first, int last, bool andFindFree=false);
void GenerateAll(int first, int last, bool andFindFree = false, bool genForBBox = false);
void SolveGroup(hGroup hg, bool andFindFree);
void MarkDraggedParams(void);
void ForceReferences(void);