diff --git a/src/confscreen.cpp b/src/confscreen.cpp index df5a95d20..12b543756 100644 --- a/src/confscreen.cpp +++ b/src/confscreen.cpp @@ -60,10 +60,15 @@ void TextWindow::ScreenChangeGridSpacing(int link, uint32_t v) { } void TextWindow::ScreenChangeDigitsAfterDecimal(int link, uint32_t v) { - SS.TW.ShowEditControl(3, ssprintf("%d", SS.UnitDigitsAfterDecimal())); + SS.TW.ShowEditControl(14, ssprintf("%d", SS.UnitDigitsAfterDecimal())); SS.TW.edit.meaning = Edit::DIGITS_AFTER_DECIMAL; } +void TextWindow::ScreenChangeDigitsAfterDecimalDegree(int link, uint32_t v) { + SS.TW.ShowEditControl(14, ssprintf("%d", SS.afterDecimalDegree)); + SS.TW.edit.meaning = Edit::DIGITS_AFTER_DECIMAL_DEGREE; +} + void TextWindow::ScreenChangeExportScale(int link, uint32_t v) { SS.TW.ShowEditControl(5, ssprintf("%.3f", (double)SS.exportScale)); SS.TW.edit.meaning = Edit::EXPORT_SCALE; @@ -235,10 +240,14 @@ void TextWindow::ShowConfiguration() { SS.MmToString(SS.gridSpacing).c_str(), &ScreenChangeGridSpacing, 0); Printf(false, "%Ft digits after decimal point to show%E"); - Printf(false, "%Ba %d %Fl%Ll%f%D[change]%E (e.g. '%s')", + Printf(false, "%Ba%Ft distances: %Fd%d %Fl%Ll%f%D[change]%E (e.g. '%s')", SS.UnitDigitsAfterDecimal(), &ScreenChangeDigitsAfterDecimal, 0, SS.MmToString(SS.StringToMm("1.23456789")).c_str()); + Printf(false, "%Ba%Ft angles: %Fd%d %Fl%Ll%f%D[change]%E (e.g. '%s')", + SS.afterDecimalDegree, + &ScreenChangeDigitsAfterDecimalDegree, 0, + SS.DegreeToString(1.23456789).c_str()); Printf(false, ""); Printf(false, "%Ft export scale factor (1:1=mm, 1:25.4=inch)"); @@ -400,13 +409,23 @@ bool TextWindow::EditControlDoneForConfiguration(const std::string &s) { case Edit::DIGITS_AFTER_DECIMAL: { int v = atoi(s.c_str()); if(v < 0 || v > 8) { - Error(_("Specify between 0 and 8 digits after the decimal.")); + Error(_("Specify between 0 and %d digits after the decimal."), 8); } else { SS.SetUnitDigitsAfterDecimal(v); SS.GW.Invalidate(); } break; } + case Edit::DIGITS_AFTER_DECIMAL_DEGREE: { + int v = atoi(s.c_str()); + if(v < 0 || v > 4) { + Error(_("Specify between 0 and %d digits after the decimal."), 4); + } else { + SS.afterDecimalDegree = v; + SS.GW.Invalidate(); + } + break; + } case Edit::EXPORT_SCALE: { Expr *e = Expr::From(s, /*popUpError=*/true); if(e) { diff --git a/src/drawconstraint.cpp b/src/drawconstraint.cpp index 5c5836245..02aa6ab20 100644 --- a/src/drawconstraint.cpp +++ b/src/drawconstraint.cpp @@ -11,11 +11,7 @@ std::string Constraint::Label() const { std::string result; if(type == Type::ANGLE) { - if(valA == floor(valA)) { - result = ssprintf("%.0f°", valA); - } else { - result = ssprintf("%.2f°", valA); - } + result = SS.DegreeToString(valA) + "°"; } else if(type == Type::LENGTH_RATIO) { result = ssprintf("%.3f:1", valA); } else if(type == Type::COMMENT) { diff --git a/src/mouse.cpp b/src/mouse.cpp index 685eaeb3f..4e1c3fcd4 100644 --- a/src/mouse.cpp +++ b/src/mouse.cpp @@ -1361,36 +1361,30 @@ void GraphicsWindow::MouseLeftDoubleClick(double mx, double my) { editPlaceholder = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; break; - case Constraint::Type::ANGLE: - case Constraint::Type::LENGTH_RATIO: - editValue = ssprintf("%.3f", c->valA); - editPlaceholder = "0.000"; - break; - default: { - double v = fabs(c->valA); + double value = fabs(c->valA); // If displayed as radius, also edit as radius. if(c->type == Constraint::Type::DIAMETER && c->other) - v /= 2; - - std::string def = SS.MmToString(v); - double eps = 1e-12; - if(fabs(SS.StringToMm(def) - v) < eps) { - // Show value with default number of digits after decimal, - // which is at least enough to represent it exactly. - editValue = def; + value /= 2; + + // Try showing value with default number of digits after decimal first. + if(c->type == Constraint::Type::LENGTH_RATIO) { + editValue = ssprintf("%.3f", value); + } else if(c->type == Constraint::Type::ANGLE) { + editValue = SS.DegreeToString(value); } else { - // Show value with as many digits after decimal as - // required to represent it exactly, up to 10. - v /= SS.MmPerUnit(); - int i; - for(i = 0; i <= 10; i++) { - editValue = ssprintf("%.*f", i, v); - if(fabs(std::stod(editValue) - v) < eps) break; - } + editValue = SS.MmToString(value); + value /= SS.MmPerUnit(); + } + // If that's not enough to represent it exactly, show the value with as many + // digits after decimal as required, up to 10. + int digits = 0; + while(fabs(std::stod(editValue) - value) > 1e-10) { + editValue = ssprintf("%.*f", digits, value); + digits++; } - editPlaceholder = "0.00000"; + editPlaceholder = "10.000000"; break; } } diff --git a/src/solvespace.cpp b/src/solvespace.cpp index 409c7eda4..944ac431d 100644 --- a/src/solvespace.cpp +++ b/src/solvespace.cpp @@ -56,6 +56,7 @@ void SolveSpaceUI::Init() { // Number of digits after the decimal point afterDecimalMm = settings->ThawInt("AfterDecimalMm", 2); afterDecimalInch = settings->ThawInt("AfterDecimalInch", 3); + afterDecimalDegree = settings->ThawInt("AfterDecimalDegree", 2); // Camera tangent (determines perspective) cameraTangent = settings->ThawFloat("CameraTangent", 0.3f/1e3); // Grid spacing @@ -229,6 +230,7 @@ void SolveSpaceUI::Exit() { // Number of digits after the decimal point settings->FreezeInt("AfterDecimalMm", (uint32_t)afterDecimalMm); settings->FreezeInt("AfterDecimalInch", (uint32_t)afterDecimalInch); + settings->FreezeInt("AfterDecimalDegree", (uint32_t)afterDecimalDegree); // Camera tangent (determines perspective) settings->FreezeFloat("CameraTangent", (float)cameraTangent); // Grid spacing @@ -320,6 +322,13 @@ std::string SolveSpaceUI::MmToString(double v) { } return ""; } +std::string SolveSpaceUI::DegreeToString(double v) { + if(fabs(v - floor(v)) > 1e-10) { + return ssprintf("%.*f", afterDecimalDegree, v); + } else { + return ssprintf("%.0f", v); + } +} double SolveSpaceUI::ExprToMm(Expr *e) { return (e->Eval()) * MmPerUnit(); } diff --git a/src/solvespace.h b/src/solvespace.h index 46d2104c2..f6be2509d 100644 --- a/src/solvespace.h +++ b/src/solvespace.h @@ -621,9 +621,11 @@ class SolveSpaceUI { Unit viewUnits; int afterDecimalMm; int afterDecimalInch; + int afterDecimalDegree; int autosaveInterval; // in minutes std::string MmToString(double v); + std::string DegreeToString(double v); double ExprToMm(Expr *e); double StringToMm(const std::string &s); const char *UnitName(); diff --git a/src/ui.h b/src/ui.h index 0ac02b658..fd033d9df 100644 --- a/src/ui.h +++ b/src/ui.h @@ -300,14 +300,15 @@ class TextWindow { CAMERA_TANGENT = 105, GRID_SPACING = 106, DIGITS_AFTER_DECIMAL = 107, - EXPORT_SCALE = 108, - EXPORT_OFFSET = 109, - CANVAS_SIZE = 110, - G_CODE_DEPTH = 120, - G_CODE_PASSES = 121, - G_CODE_FEED = 122, - G_CODE_PLUNGE_FEED = 123, - AUTOSAVE_INTERVAL = 124, + DIGITS_AFTER_DECIMAL_DEGREE = 108, + EXPORT_SCALE = 109, + EXPORT_OFFSET = 110, + CANVAS_SIZE = 111, + G_CODE_DEPTH = 112, + G_CODE_PASSES = 113, + G_CODE_FEED = 114, + G_CODE_PLUNGE_FEED = 115, + AUTOSAVE_INTERVAL = 116, // For TTF text TTF_TEXT = 300, // For the step dimension screen @@ -467,6 +468,7 @@ class TextWindow { static void ScreenChangeCameraTangent(int link, uint32_t v); static void ScreenChangeGridSpacing(int link, uint32_t v); static void ScreenChangeDigitsAfterDecimal(int link, uint32_t v); + static void ScreenChangeDigitsAfterDecimalDegree(int link, uint32_t v); static void ScreenChangeExportScale(int link, uint32_t v); static void ScreenChangeExportOffset(int link, uint32_t v); static void ScreenChangeGCodeParameter(int link, uint32_t v);