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.pull/434/head
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