From 2fb6119de8814179feaeae44194c2c8f8d3f65a7 Mon Sep 17 00:00:00 2001 From: Tom Sutcliffe Date: Thu, 12 Aug 2021 12:35:44 +0100 Subject: [PATCH] Add option for displaying dimensions in feet and inches --- src/graphicswin.cpp | 11 +++++++++++ src/mouse.cpp | 2 +- src/solvespace.cpp | 42 +++++++++++++++++++++++++++++++++++------- src/solvespace.h | 5 +++-- src/ui.h | 2 ++ 5 files changed, 52 insertions(+), 10 deletions(-) diff --git a/src/graphicswin.cpp b/src/graphicswin.cpp index 84e83d6f..bae48438 100644 --- a/src/graphicswin.cpp +++ b/src/graphicswin.cpp @@ -98,6 +98,7 @@ const MenuEntry Menu[] = { { 2, N_("Dimensions in &Millimeters"), Command::UNITS_MM, 0, KR, mView }, { 2, N_("Dimensions in M&eters"), Command::UNITS_METERS, 0, KR, mView }, { 2, N_("Dimensions in &Inches"), Command::UNITS_INCHES, 0, KR, mView }, +{ 2, N_("Dimensions in &Feet and Inches"), Command::UNITS_FEET_INCHES, 0, KR, mView }, { 1, NULL, Command::NONE, 0, KN, NULL }, { 1, N_("Show &Toolbar"), Command::SHOW_TOOLBAR, 0, KC, mView }, { 1, N_("Show Property Bro&wser"), Command::SHOW_TEXT_WND, '\t', KC, mView }, @@ -329,6 +330,8 @@ void GraphicsWindow::PopulateMainMenu() { unitsMetersMenuItem = menuItem; } else if(Menu[i].cmd == Command::UNITS_INCHES) { unitsInchesMenuItem = menuItem; + } else if(Menu[i].cmd == Command::UNITS_FEET_INCHES) { + unitsFeetInchesMenuItem = menuItem; } else if(Menu[i].cmd == Command::SEL_WORKPLANE) { inWorkplaneMenuItem = menuItem; } else if(Menu[i].cmd == Command::FREE_IN_3D) { @@ -843,6 +846,12 @@ void GraphicsWindow::MenuView(Command id) { SS.GW.EnsureValidActives(); break; + case Command::UNITS_FEET_INCHES: + SS.viewUnits = Unit::FEET_INCHES; + SS.ScheduleShowTW(); + SS.GW.EnsureValidActives(); + break; + case Command::UNITS_MM: SS.viewUnits = Unit::MM; SS.ScheduleShowTW(); @@ -925,6 +934,7 @@ void GraphicsWindow::EnsureValidActives() { case Unit::MM: case Unit::METERS: case Unit::INCHES: + case Unit::FEET_INCHES: break; default: SS.viewUnits = Unit::MM; @@ -933,6 +943,7 @@ void GraphicsWindow::EnsureValidActives() { unitsMmMenuItem->SetActive(SS.viewUnits == Unit::MM); unitsMetersMenuItem->SetActive(SS.viewUnits == Unit::METERS); unitsInchesMenuItem->SetActive(SS.viewUnits == Unit::INCHES); + unitsFeetInchesMenuItem->SetActive(SS.viewUnits == Unit::FEET_INCHES); if(SS.TW.window) SS.TW.window->SetVisible(SS.GW.showTextWindow); showTextWndMenuItem->SetActive(SS.GW.showTextWindow); diff --git a/src/mouse.cpp b/src/mouse.cpp index a88d34f8..373e6ea2 100644 --- a/src/mouse.cpp +++ b/src/mouse.cpp @@ -1378,7 +1378,7 @@ void GraphicsWindow::EditConstraint(hConstraint constraint) { } else if(c->type == Constraint::Type::ANGLE) { editValue = SS.DegreeToString(value); } else { - editValue = SS.MmToString(value); + editValue = SS.MmToString(value, true); value /= SS.MmPerUnit(); } // If that's not enough to represent it exactly, show the value with as many diff --git a/src/solvespace.cpp b/src/solvespace.cpp index ccea271a..7d63403c 100644 --- a/src/solvespace.cpp +++ b/src/solvespace.cpp @@ -315,6 +315,7 @@ void SolveSpaceUI::ScheduleAutosave() { double SolveSpaceUI::MmPerUnit() { switch(viewUnits) { case Unit::INCHES: return 25.4; + case Unit::FEET_INCHES: return 25.4; // The 'unit' is still inches case Unit::METERS: return 1000.0; case Unit::MM: return 1.0; } @@ -323,21 +324,41 @@ double SolveSpaceUI::MmPerUnit() { const char *SolveSpaceUI::UnitName() { switch(viewUnits) { case Unit::INCHES: return "in"; + case Unit::FEET_INCHES: return "in"; case Unit::METERS: return "m"; case Unit::MM: return "mm"; } return ""; } -std::string SolveSpaceUI::MmToString(double v) { +std::string SolveSpaceUI::MmToString(double v, bool editable) { v /= MmPerUnit(); + int feet = 0; + // The syntax 2' 6" for feet and inches is not something we can (currently) + // parse back from a string so if editable is true, we treat FEET_INCHES the + // same as INCHES and just return the unadorned decimal number of inches. + if(viewUnits == Unit::FEET_INCHES && !editable) { + // v is in inches at this point + feet = (int)(v / 12.0); + v = v - (feet * 12.0); + // v is now the remainder in inches + } int digits = UnitDigitsAfterDecimal(); double minimum = 0.5 * pow(10,-digits); - while ((v < minimum) && (v > LENGTH_EPS)) { + while ((feet == 0) && (v < minimum) && (v > LENGTH_EPS)) { digits++; minimum *= 0.1; } - return ssprintf("%.*f", digits, v); + + if(viewUnits == Unit::FEET_INCHES && !editable) { + if(feet != 0) { + return ssprintf("%d' %.*f\"", feet, digits, v); + } else { + return ssprintf("%.*f\"", digits, v); + } + } else { + return ssprintf("%.*f", digits, v); + } } static const char *DimToString(int dim) { switch(dim) { @@ -394,17 +415,22 @@ std::string SolveSpaceUI::MmToStringSI(double v, int dim) { dim = 1; } - v /= pow((viewUnits == Unit::INCHES) ? 25.4 : 1000, dim); + bool inches = (viewUnits == Unit::INCHES) || (viewUnits == Unit::FEET_INCHES); + v /= pow(inches ? 25.4 : 1000, dim); int vdeg = (int)(log10(fabs(v))); std::string unit; if(fabs(v) > 0.0) { int sdeg = 0; std::tie(sdeg, unit) = - (viewUnits == Unit::INCHES) + inches ? SelectSIPrefixInch(vdeg/dim) : SelectSIPrefixMm(vdeg, dim); v /= pow(10.0, sdeg * dim); } + if(viewUnits == Unit::FEET_INCHES && fabs(v) > pow(12.0, dim)) { + unit = "ft"; + v /= pow(12.0, dim); + } int pdeg = (int)ceil(log10(fabs(v) + 1e-10)); return ssprintf("%.*g%s%s%s", pdeg + UnitDigitsAfterDecimal(), v, compact ? "" : " ", unit.c_str(), DimToString(dim)); @@ -434,10 +460,11 @@ int SolveSpaceUI::GetMaxSegments() { return maxSegments; } int SolveSpaceUI::UnitDigitsAfterDecimal() { - return (viewUnits == Unit::INCHES) ? afterDecimalInch : afterDecimalMm; + return (viewUnits == Unit::INCHES || viewUnits == Unit::FEET_INCHES) ? + afterDecimalInch : afterDecimalMm; } void SolveSpaceUI::SetUnitDigitsAfterDecimal(int v) { - if(viewUnits == Unit::INCHES) { + if(viewUnits == Unit::INCHES || viewUnits == Unit::FEET_INCHES) { afterDecimalInch = v; } else { afterDecimalMm = v; @@ -1036,6 +1063,7 @@ void SolveSpaceUI::Clear() { GW.unitsMmMenuItem = NULL; GW.unitsMetersMenuItem = NULL; GW.unitsInchesMenuItem = NULL; + GW.unitsFeetInchesMenuItem = NULL; GW.inWorkplaneMenuItem = NULL; GW.in3dMenuItem = NULL; GW.undoMenuItem = NULL; diff --git a/src/solvespace.h b/src/solvespace.h index d4caab2b..21297712 100644 --- a/src/solvespace.h +++ b/src/solvespace.h @@ -138,7 +138,8 @@ enum class Command : uint32_t; enum class Unit : uint32_t { MM = 0, INCHES, - METERS + METERS, + FEET_INCHES }; template @@ -609,7 +610,7 @@ public: bool useSIPrefixes; int autosaveInterval; // in minutes - std::string MmToString(double v); + std::string MmToString(double v, bool editable=false); std::string MmToStringSI(double v, int dim = 0); std::string DegreeToString(double v); double ExprToMm(Expr *e); diff --git a/src/ui.h b/src/ui.h index ace4ddd8..90cef9f1 100644 --- a/src/ui.h +++ b/src/ui.h @@ -89,6 +89,7 @@ enum class Command : uint32_t { SHOW_TOOLBAR, SHOW_TEXT_WND, UNITS_INCHES, + UNITS_FEET_INCHES, UNITS_MM, UNITS_METERS, FULL_SCREEN, @@ -546,6 +547,7 @@ public: Platform::MenuItemRef unitsMmMenuItem; Platform::MenuItemRef unitsMetersMenuItem; Platform::MenuItemRef unitsInchesMenuItem; + Platform::MenuItemRef unitsFeetInchesMenuItem; Platform::MenuItemRef inWorkplaneMenuItem; Platform::MenuItemRef in3dMenuItem;