Add a setting to format constraint labels using SI prefixes.
Supported metric units: km, m, cm, mm, µm, nm. Supported USCS units: in, mil, µin. Also, use the newly introduced unit formatting machinery in tools for measuring perimeter, area and volume, so that e.g. volume is not displayed in millions of cubic millimeters.
This commit is contained in:
parent
9faa7cb0ca
commit
9d1c295495
@ -33,6 +33,8 @@ New constraint features:
|
||||
in the text window.
|
||||
* When selecting an entity, the constraints applied to it can be selected
|
||||
in the text window.
|
||||
* Distance constraint labels can now be formatted to use SI prefixes.
|
||||
Values are edited in the configured unit regardless of label format.
|
||||
* It is now possible to turn off automatic creation of horizontal/vertical
|
||||
constraints on line segments.
|
||||
|
||||
|
@ -69,6 +69,11 @@ void TextWindow::ScreenChangeDigitsAfterDecimalDegree(int link, uint32_t v) {
|
||||
SS.TW.edit.meaning = Edit::DIGITS_AFTER_DECIMAL_DEGREE;
|
||||
}
|
||||
|
||||
void TextWindow::ScreenChangeUseSIPrefixes(int link, uint32_t v) {
|
||||
SS.useSIPrefixes = !SS.useSIPrefixes;
|
||||
SS.GW.Invalidate();
|
||||
}
|
||||
|
||||
void TextWindow::ScreenChangeExportScale(int link, uint32_t v) {
|
||||
SS.TW.ShowEditControl(5, ssprintf("%.3f", (double)SS.exportScale));
|
||||
SS.TW.edit.meaning = Edit::EXPORT_SCALE;
|
||||
@ -239,15 +244,20 @@ void TextWindow::ShowConfiguration() {
|
||||
Printf(false, "%Ba %s %Fl%Ll%f%D[change]%E",
|
||||
SS.MmToString(SS.gridSpacing).c_str(),
|
||||
&ScreenChangeGridSpacing, 0);
|
||||
|
||||
Printf(false, "");
|
||||
Printf(false, "%Ft digits after decimal point to show%E");
|
||||
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')",
|
||||
Printf(false, "%Bd%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, " %Fd%f%Ll%s use SI prefixes for distances%E",
|
||||
&ScreenChangeUseSIPrefixes,
|
||||
SS.useSIPrefixes ? CHECK_TRUE : CHECK_FALSE);
|
||||
|
||||
Printf(false, "");
|
||||
Printf(false, "%Ft export scale factor (1:1=mm, 1:25.4=inch)");
|
||||
|
@ -18,13 +18,13 @@ std::string Constraint::Label() const {
|
||||
result = comment;
|
||||
} else if(type == Type::DIAMETER) {
|
||||
if(!other) {
|
||||
result = "⌀" + SS.MmToString(valA);
|
||||
result = "⌀" + SS.MmToStringSI(valA);
|
||||
} else {
|
||||
result = "R" + SS.MmToString(valA / 2);
|
||||
result = "R" + SS.MmToStringSI(valA / 2);
|
||||
}
|
||||
} else {
|
||||
// valA has units of distance
|
||||
result = SS.MmToString(fabs(valA));
|
||||
result = SS.MmToStringSI(fabs(valA));
|
||||
}
|
||||
if(reference) {
|
||||
result += " REF";
|
||||
|
@ -57,6 +57,7 @@ void SolveSpaceUI::Init() {
|
||||
afterDecimalMm = settings->ThawInt("AfterDecimalMm", 2);
|
||||
afterDecimalInch = settings->ThawInt("AfterDecimalInch", 3);
|
||||
afterDecimalDegree = settings->ThawInt("AfterDecimalDegree", 2);
|
||||
useSIPrefixes = settings->ThawBool("UseSIPrefixes", false);
|
||||
// Camera tangent (determines perspective)
|
||||
cameraTangent = settings->ThawFloat("CameraTangent", 0.3f/1e3);
|
||||
// Grid spacing
|
||||
@ -231,6 +232,7 @@ void SolveSpaceUI::Exit() {
|
||||
settings->FreezeInt("AfterDecimalMm", (uint32_t)afterDecimalMm);
|
||||
settings->FreezeInt("AfterDecimalInch", (uint32_t)afterDecimalInch);
|
||||
settings->FreezeInt("AfterDecimalDegree", (uint32_t)afterDecimalDegree);
|
||||
settings->FreezeBool("UseSIPrefixes", useSIPrefixes);
|
||||
// Camera tangent (determines perspective)
|
||||
settings->FreezeFloat("CameraTangent", (float)cameraTangent);
|
||||
// Grid spacing
|
||||
@ -307,7 +309,7 @@ double SolveSpaceUI::MmPerUnit() {
|
||||
}
|
||||
const char *SolveSpaceUI::UnitName() {
|
||||
switch(viewUnits) {
|
||||
case Unit::INCHES: return "inch";
|
||||
case Unit::INCHES: return "in";
|
||||
case Unit::METERS: return "m";
|
||||
case Unit::MM: return "mm";
|
||||
}
|
||||
@ -315,13 +317,60 @@ const char *SolveSpaceUI::UnitName() {
|
||||
}
|
||||
|
||||
std::string SolveSpaceUI::MmToString(double v) {
|
||||
v /= MmPerUnit();
|
||||
switch(viewUnits) {
|
||||
case Unit::INCHES: return ssprintf("%.*f", afterDecimalInch, v / 25.4);
|
||||
case Unit::METERS: return ssprintf("%.*f", afterDecimalMm, v / 1000.0);
|
||||
case Unit::MM: return ssprintf("%.*f", afterDecimalMm, v);
|
||||
case Unit::INCHES:
|
||||
return ssprintf("%.*f", afterDecimalInch, v);
|
||||
case Unit::METERS:
|
||||
case Unit::MM:
|
||||
return ssprintf("%.*f", afterDecimalMm, v);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
static const char *DimToString(int dim) {
|
||||
switch(dim) {
|
||||
case 3: return "³";
|
||||
case 2: return "²";
|
||||
case 1: return "";
|
||||
default: ssassert(false, "Unexpected dimension");
|
||||
}
|
||||
}
|
||||
static std::pair<int, std::string> SelectSIPrefixMm(int deg) {
|
||||
if(deg >= 3) return { 3, "km" };
|
||||
else if(deg >= 0) return { 0, "m" };
|
||||
else if(deg >= -2) return { -2, "cm" };
|
||||
else if(deg >= -3) return { -3, "mm" };
|
||||
else if(deg >= -6) return { -6, "µm" };
|
||||
else return { -9, "nm" };
|
||||
}
|
||||
static std::pair<int, std::string> SelectSIPrefixInch(int deg) {
|
||||
if(deg >= 0) return { 0, "in" };
|
||||
else if(deg >= -3) return { -3, "mil" };
|
||||
else return { -6, "µin" };
|
||||
}
|
||||
std::string SolveSpaceUI::MmToStringSI(double v, int dim) {
|
||||
bool compact = false;
|
||||
if(dim == 0) {
|
||||
if(!useSIPrefixes) return MmToString(v);
|
||||
compact = true;
|
||||
dim = 1;
|
||||
}
|
||||
|
||||
v /= pow((viewUnits == Unit::INCHES) ? 25.4 : 1000, dim);
|
||||
int vdeg = floor((log10(fabs(v))) / dim);
|
||||
std::string unit;
|
||||
if(fabs(v) > 0.0) {
|
||||
int sdeg = 0;
|
||||
std::tie(sdeg, unit) =
|
||||
(viewUnits == Unit::INCHES)
|
||||
? SelectSIPrefixInch(vdeg)
|
||||
: SelectSIPrefixMm(vdeg);
|
||||
v /= pow(10.0, sdeg * dim);
|
||||
}
|
||||
int pdeg = ceil(log10(fabs(v) + 1e-10));
|
||||
return ssprintf("%#.*g%s%s%s", pdeg + UnitDigitsAfterDecimal(), v,
|
||||
compact ? "" : " ", unit.c_str(), DimToString(dim));
|
||||
}
|
||||
std::string SolveSpaceUI::DegreeToString(double v) {
|
||||
if(fabs(v - floor(v)) > 1e-10) {
|
||||
return ssprintf("%.*f", afterDecimalDegree, v);
|
||||
@ -777,18 +826,11 @@ void SolveSpaceUI::MenuAnalyze(Command id) {
|
||||
|
||||
vol += integral;
|
||||
}
|
||||
|
||||
std::string msg = ssprintf(_("The volume of the solid model is:\n\n"
|
||||
" %.3f %s^3"),
|
||||
vol / pow(SS.MmPerUnit(), 3),
|
||||
SS.UnitName());
|
||||
|
||||
if(SS.viewUnits == Unit::MM) {
|
||||
msg += ssprintf("\n %.2f mL", vol/(10*10*10));
|
||||
}
|
||||
msg += _("\n\nCurved surfaces have been approximated as triangles.\n"
|
||||
"This introduces error, typically of around 1%.");
|
||||
Message("%s", msg.c_str());
|
||||
Message(_("The volume of the solid model is:\n\n"
|
||||
" %s\n\n"
|
||||
"Curved surfaces have been approximated as triangles.\n"
|
||||
"This introduces error, typically of around 1%%."),
|
||||
SS.MmToStringSI(vol, /*dim=*/3).c_str());
|
||||
break;
|
||||
}
|
||||
|
||||
@ -807,13 +849,11 @@ void SolveSpaceUI::MenuAnalyze(Command id) {
|
||||
sp.normal = sp.ComputeNormal();
|
||||
sp.FixContourDirections();
|
||||
double area = sp.SignedArea();
|
||||
double scale = SS.MmPerUnit();
|
||||
Message(_("The area of the region sketched in this group is:\n\n"
|
||||
" %.3f %s^2\n\n"
|
||||
" %s\n\n"
|
||||
"Curves have been approximated as piecewise linear.\n"
|
||||
"This introduces error, typically of around 1%%."),
|
||||
area / (scale*scale),
|
||||
SS.UnitName());
|
||||
SS.MmToStringSI(area, /*dim=*/2).c_str());
|
||||
sel.Clear();
|
||||
sp.Clear();
|
||||
break;
|
||||
@ -829,14 +869,11 @@ void SolveSpaceUI::MenuAnalyze(Command id) {
|
||||
perimeter += e.b.Minus(e.a).Magnitude();
|
||||
}
|
||||
}
|
||||
|
||||
double scale = SS.MmPerUnit();
|
||||
Message(_("The total length of the selected entities is:\n\n"
|
||||
" %.3f %s\n\n"
|
||||
" %s\n\n"
|
||||
"Curves have been approximated as piecewise linear.\n"
|
||||
"This introduces error, typically of around 1%%."),
|
||||
perimeter / scale,
|
||||
SS.UnitName());
|
||||
SS.MmToStringSI(perimeter, /*dim=*/1).c_str());
|
||||
} else {
|
||||
Error(_("Bad selection for perimeter; select line segments, arcs, and curves."));
|
||||
}
|
||||
|
@ -621,9 +621,11 @@ public:
|
||||
int afterDecimalMm;
|
||||
int afterDecimalInch;
|
||||
int afterDecimalDegree;
|
||||
bool useSIPrefixes;
|
||||
int autosaveInterval; // in minutes
|
||||
|
||||
std::string MmToString(double v);
|
||||
std::string MmToStringSI(double v, int dim = 0);
|
||||
std::string DegreeToString(double v);
|
||||
double ExprToMm(Expr *e);
|
||||
double StringToMm(const std::string &s);
|
||||
|
1
src/ui.h
1
src/ui.h
@ -469,6 +469,7 @@ public:
|
||||
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 ScreenChangeUseSIPrefixes(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);
|
||||
|
Loading…
Reference in New Issue
Block a user