Changeset View
Standalone View
source/blender/blenkernel/intern/unit.c
| Show First 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | |||||
| #define UN_SC_MG 0.000001f | #define UN_SC_MG 0.000001f | ||||
| #define UN_SC_ITON 907.18474f /* imperial ton */ | #define UN_SC_ITON 907.18474f /* imperial ton */ | ||||
| #define UN_SC_CWT 45.359237f | #define UN_SC_CWT 45.359237f | ||||
| #define UN_SC_ST 6.35029318f | #define UN_SC_ST 6.35029318f | ||||
| #define UN_SC_LB 0.45359237f | #define UN_SC_LB 0.45359237f | ||||
| #define UN_SC_OZ 0.028349523125f | #define UN_SC_OZ 0.028349523125f | ||||
| #define UN_SC_CEL 1.0f | |||||
| #define UN_SC_FAH 0.555555555555f | |||||
JacquesLucke: You can add a couple more 5s here. | |||||
| /* clang-format on */ | /* clang-format on */ | ||||
| /* define a single unit */ | /* define a single unit */ | ||||
| typedef struct bUnitDef { | typedef struct bUnitDef { | ||||
| const char *name; | const char *name; | ||||
| /** abused a bit for the display name */ | /** abused a bit for the display name */ | ||||
| const char *name_plural; | const char *name_plural; | ||||
| /** this is used for display*/ | /** this is used for display*/ | ||||
| ▲ Show 20 Lines • Show All 82 Lines • ▼ Show 20 Lines | |||||
| /* Areas */ | /* Areas */ | ||||
| static struct bUnitDef buMetricAreaDef[] = { | static struct bUnitDef buMetricAreaDef[] = { | ||||
| {"square kilometer", "square kilometers", "km²", "km2", "Square Kilometers", NULL, UN_SC_KM * UN_SC_KM, 0.0, B_UNIT_DEF_NONE}, | {"square kilometer", "square kilometers", "km²", "km2", "Square Kilometers", NULL, UN_SC_KM * UN_SC_KM, 0.0, B_UNIT_DEF_NONE}, | ||||
| {"square hectometer", "square hectometers", "hm²", "hm2", "Square Hectometers", NULL, UN_SC_HM * UN_SC_HM, 0.0, B_UNIT_DEF_SUPPRESS}, /* hectare */ | {"square hectometer", "square hectometers", "hm²", "hm2", "Square Hectometers", NULL, UN_SC_HM * UN_SC_HM, 0.0, B_UNIT_DEF_SUPPRESS}, /* hectare */ | ||||
| {"square dekameter", "square dekameters", "dam²", "dam2", "Square Dekameters", NULL, UN_SC_DAM * UN_SC_DAM, 0.0, B_UNIT_DEF_SUPPRESS}, /* are */ | {"square dekameter", "square dekameters", "dam²", "dam2", "Square Dekameters", NULL, UN_SC_DAM * UN_SC_DAM, 0.0, B_UNIT_DEF_SUPPRESS}, /* are */ | ||||
| {"square meter", "square meters", "m²", "m2", "Square Meters", NULL, UN_SC_M * UN_SC_M, 0.0, B_UNIT_DEF_NONE}, /* base unit */ | {"square meter", "square meters", "m²", "m2", "Square Meters", NULL, UN_SC_M * UN_SC_M, 0.0, B_UNIT_DEF_NONE}, /* base unit */ | ||||
| {"square decimeter", "square decimetees", "dm²", "dm2", "Square Decimeters", NULL, UN_SC_DM * UN_SC_DM, 0.0, B_UNIT_DEF_SUPPRESS}, | {"square decimeter", "square decimetees", "dm²", "dm2", "Square Decimeters", NULL, UN_SC_DM * UN_SC_DM, 0.0, B_UNIT_DEF_SUPPRESS}, | ||||
| {"square centimeter", "square centimeters", "cm²", "cm2", "Square Centimeters", NULL, UN_SC_CM * UN_SC_CM, 0.0, B_UNIT_DEF_NONE}, | {"square centimeter", "square centimeters", "cm²", "cm2", "Square Centimeters", NULL, UN_SC_CM * UN_SC_CM, 0.0, B_UNIT_DEF_NONE}, | ||||
| {"square millimeter", "square millimeters", "mm²", "mm2", "Square Millimeters", NULL, UN_SC_MM * UN_SC_MM, 0.0, B_UNIT_DEF_NONE | B_UNIT_DEF_TENTH}, | {"square millimeter", "square millimeters", "mm²", "mm2", "Square Millimeters", NULL, UN_SC_MM * UN_SC_MM, 0.0, B_UNIT_DEF_NONE | B_UNIT_DEF_TENTH}, | ||||
Done Inline ActionsThanks for those typo fixes. I'll commit those separately. JacquesLucke: Thanks for those typo fixes. I'll commit those separately. | |||||
| {"square micrometer", "square micrometers", "µm²", "um2", "Square Micrometers", NULL, UN_SC_UM * UN_SC_UM, 0.0, B_UNIT_DEF_NONE}, | {"square micrometer", "square micrometers", "µm²", "um2", "Square Micrometers", NULL, UN_SC_UM * UN_SC_UM, 0.0, B_UNIT_DEF_NONE}, | ||||
| NULL_UNIT, | NULL_UNIT, | ||||
| }; | }; | ||||
| static struct bUnitCollection buMetricAreaCollection = {buMetricAreaDef, 3, 0, UNIT_COLLECTION_LENGTH(buMetricAreaDef)}; | static struct bUnitCollection buMetricAreaCollection = {buMetricAreaDef, 3, 0, UNIT_COLLECTION_LENGTH(buMetricAreaDef)}; | ||||
| static struct bUnitDef buImperialAreaDef[] = { | static struct bUnitDef buImperialAreaDef[] = { | ||||
| {"square mile", "square miles", "sq mi", "sq m", "Square Miles", NULL, UN_SC_MI * UN_SC_MI, 0.0, B_UNIT_DEF_NONE}, | {"square mile", "square miles", "sq mi", "sq m", "Square Miles", NULL, UN_SC_MI * UN_SC_MI, 0.0, B_UNIT_DEF_NONE}, | ||||
| {"square furlong", "square furlongs", "sq fur", NULL, "Square Furlongs", NULL, UN_SC_FUR * UN_SC_FUR, 0.0, B_UNIT_DEF_SUPPRESS}, | {"square furlong", "square furlongs", "sq fur", NULL, "Square Furlongs", NULL, UN_SC_FUR * UN_SC_FUR, 0.0, B_UNIT_DEF_SUPPRESS}, | ||||
| ▲ Show 20 Lines • Show All 119 Lines • ▼ Show 20 Lines | static struct bUnitDef buCameraLenDef[] = { | ||||
| {"millimeter", "millimeters", "mm", NULL, "Millimeters", NULL, UN_SC_M, 0.0, B_UNIT_DEF_NONE}, | {"millimeter", "millimeters", "mm", NULL, "Millimeters", NULL, UN_SC_M, 0.0, B_UNIT_DEF_NONE}, | ||||
| {"micrometer", "micrometers", "µm", "um", "Micrometers", NULL, UN_SC_MM, 0.0, B_UNIT_DEF_SUPPRESS}, | {"micrometer", "micrometers", "µm", "um", "Micrometers", NULL, UN_SC_MM, 0.0, B_UNIT_DEF_SUPPRESS}, | ||||
| NULL_UNIT, | NULL_UNIT, | ||||
| }; | }; | ||||
| static struct bUnitCollection buCameraLenCollection = {buCameraLenDef, 3, 0, UNIT_COLLECTION_LENGTH(buCameraLenDef)}; | static struct bUnitCollection buCameraLenCollection = {buCameraLenDef, 3, 0, UNIT_COLLECTION_LENGTH(buCameraLenDef)}; | ||||
| /* (Light) Power */ | /* (Light) Power */ | ||||
| static struct bUnitDef buPowerDef[] = { | static struct bUnitDef buPowerDef[] = { | ||||
| {"gigawatt", "gigawatts", "GW", NULL, "Gigawatts", NULL, 1e9f, 0.0, B_UNIT_DEF_NONE}, | {"gigawatt", "gigawatts", "GW", NULL, "Gigawatts", NULL, 1e9f, 0.0, B_UNIT_DEF_NONE}, | ||||
Done Inline ActionsI wonder if we should use oC or just C. The latter is more comfortable to type. JacquesLucke: I wonder if we should use `oC` or just `C`. The latter is more comfortable to type. | |||||
| {"megawatt", "megawatts", "MW", NULL, "Megawatts", NULL, 1e6f, 0.0, B_UNIT_DEF_CASE_SENSITIVE}, | {"megawatt", "megawatts", "MW", NULL, "Megawatts", NULL, 1e6f, 0.0, B_UNIT_DEF_CASE_SENSITIVE}, | ||||
| {"kilowatt", "kilowatts", "kW", NULL, "Kilowatts", NULL, 1e3f, 0.0, B_UNIT_DEF_SUPPRESS}, | {"kilowatt", "kilowatts", "kW", NULL, "Kilowatts", NULL, 1e3f, 0.0, B_UNIT_DEF_SUPPRESS}, | ||||
| {"watt", "watts", "W", NULL, "Watts", NULL, 1.0f, 0.0, B_UNIT_DEF_NONE}, /* base unit */ | {"watt", "watts", "W", NULL, "Watts", NULL, 1.0f, 0.0, B_UNIT_DEF_NONE}, /* base unit */ | ||||
| {"milliwatt", "milliwatts", "mW", NULL, "Milliwatts", NULL, 1e-3f, 0.0, B_UNIT_DEF_CASE_SENSITIVE}, | {"milliwatt", "milliwatts", "mW", NULL, "Milliwatts", NULL, 1e-3f, 0.0, B_UNIT_DEF_CASE_SENSITIVE}, | ||||
| {"microwatt", "microwatts", "µW", "uW", "Microwatts", NULL, 1e-6f, 0.0, B_UNIT_DEF_NONE}, | {"microwatt", "microwatts", "µW", "uW", "Microwatts", NULL, 1e-6f, 0.0, B_UNIT_DEF_NONE}, | ||||
| {"nanowatt", "nanowatts", "nW", NULL, "Nanowatts", NULL, 1e-9f, 0.0, B_UNIT_DEF_NONE}, | {"nanowatt", "nanowatts", "nW", NULL, "Nanowatts", NULL, 1e-9f, 0.0, B_UNIT_DEF_NONE}, | ||||
Done Inline ActionsUnfortunately, the conversion is not that simple. Currently switching between the unit systems changes the absolute value of the temperature, i.e. it thinks 5C = 5F. A bit more work has to be done to get this conversion working, because it is different from all the other conversions we have so far. Also there is a missing white space. JacquesLucke: Unfortunately, the conversion is not that simple. Currently switching between the unit systems… | |||||
| NULL_UNIT, | NULL_UNIT, | ||||
| }; | }; | ||||
| static struct bUnitCollection buPowerCollection = {buPowerDef, 3, 0, UNIT_COLLECTION_LENGTH(buPowerDef)}; | static struct bUnitCollection buPowerCollection = {buPowerDef, 3, 0, UNIT_COLLECTION_LENGTH(buPowerDef)}; | ||||
| /* Temperature */ | |||||
| static struct bUnitDef buMetricTempDef[] = { | |||||
| {"celsius", "celsius", "°C", "C", "Celsius", NULL, UN_SC_CEL, 0.0, B_UNIT_DEF_NONE}, /* base unit */ | |||||
| NULL_UNIT, | |||||
Done Inline ActionsIt's probably a good time to split this into multiple lines now, one line per unit collection. JacquesLucke: It's probably a good time to split this into multiple lines now, one line per unit collection. | |||||
| }; | |||||
| static struct bUnitCollection buMetricTempCollection = {buMetricTempDef, 0, 0, UNIT_COLLECTION_LENGTH(buMetricTempDef)}; | |||||
| static struct bUnitDef buImperialTempDef[] = { | |||||
| {"fahrenheit", "fahrenheit", "°F", "F", "Fahrenheit", NULL, UN_SC_FAH, 32.0, B_UNIT_DEF_NONE}, /* base unit */ | |||||
| NULL_UNIT, | |||||
Done Inline ActionsI think Kelvin should also be the base unit in imperial? Something like color temperature you would still want to see as Kelvin even if you use imperial length units. brecht: I think Kelvin should also be the base unit in imperial? Something like color temperature you… | |||||
Done Inline ActionsI was thinking about that too, I'll add that. HooglyBoogly: I was thinking about that too, I'll add that. | |||||
| }; | |||||
| static struct bUnitCollection buImperialTempCollection = {buImperialTempDef, 0, 0, UNIT_COLLECTION_LENGTH(buImperialTempDef)}; | |||||
| #define UNIT_SYSTEM_TOT (((sizeof(bUnitSystems) / B_UNIT_TYPE_TOT) / sizeof(void *)) - 1) | #define UNIT_SYSTEM_TOT (((sizeof(bUnitSystems) / B_UNIT_TYPE_TOT) / sizeof(void *)) - 1) | ||||
| static const struct bUnitCollection *bUnitSystems[][B_UNIT_TYPE_TOT] = { | static const struct bUnitCollection *bUnitSystems[][B_UNIT_TYPE_TOT] = { | ||||
| {NULL, NULL, NULL, NULL, NULL, &buNaturalRotCollection, &buNaturalTimeCollection, NULL, NULL, NULL, NULL}, | {NULL, NULL, NULL, NULL, NULL, &buNaturalRotCollection, &buNaturalTimeCollection, NULL, NULL, NULL, NULL, NULL}, | ||||
| {NULL, &buMetricLenCollection, &buMetricAreaCollection, &buMetricVolCollection, &buMetricMassCollection, &buNaturalRotCollection, &buNaturalTimeCollection, &buMetricVelCollection, &buMetricAclCollection, &buCameraLenCollection, &buPowerCollection}, /* metric */ | {NULL, &buMetricLenCollection, &buMetricAreaCollection, &buMetricVolCollection, &buMetricMassCollection, &buNaturalRotCollection, &buNaturalTimeCollection, &buMetricVelCollection, &buMetricAclCollection, &buCameraLenCollection, &buPowerCollection, &buMetricTempCollection}, /* metric */ | ||||
| {NULL, &buImperialLenCollection, &buImperialAreaCollection, &buImperialVolCollection, &buImperialMassCollection, &buNaturalRotCollection, &buNaturalTimeCollection, &buImperialVelCollection, &buImperialAclCollection, &buCameraLenCollection, &buPowerCollection}, /* imperial */ | {NULL, &buImperialLenCollection, &buImperialAreaCollection, &buImperialVolCollection, &buImperialMassCollection, &buNaturalRotCollection, &buNaturalTimeCollection, &buImperialVelCollection, &buImperialAclCollection, &buCameraLenCollection, &buPowerCollection, &buImperialTempCollection}, /* imperial */ | ||||
| {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, | {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, | ||||
| }; | }; | ||||
| /* clang-format on */ | /* clang-format on */ | ||||
| /* internal, has some option not exposed */ | /* internal, has some option not exposed */ | ||||
| static const bUnitCollection *unit_get_system(int system, int type) | static const bUnitCollection *unit_get_system(int system, int type) | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 78 Lines • ▼ Show 20 Lines | static size_t unit_as_string(char *str, | ||||
| else if (value == 0.0) { | else if (value == 0.0) { | ||||
| /* use the default units since there is no way to convert */ | /* use the default units since there is no way to convert */ | ||||
| unit = unit_default(usys); | unit = unit_default(usys); | ||||
| } | } | ||||
| else { | else { | ||||
| unit = unit_best_fit(value, usys, NULL, 1); | unit = unit_best_fit(value, usys, NULL, 1); | ||||
| } | } | ||||
| value_conv = value / unit->scalar; | value_conv = (value / unit->scalar) + unit->bias; | ||||
| /* Adjust precision to expected number of significant digits. | /* Adjust precision to expected number of significant digits. | ||||
| * Note that here, we shall not have to worry about very big/small numbers, units are expected to | * Note that here, we shall not have to worry about very big/small numbers, units are expected to | ||||
| * replace 'scientific notation' in those cases. */ | * replace 'scientific notation' in those cases. */ | ||||
| prec -= integer_digits_d(value_conv); | prec -= integer_digits_d(value_conv); | ||||
| CLAMP(prec, 0, 6); | CLAMP(prec, 0, 6); | ||||
| /* Convert to a string */ | /* Convert to a string */ | ||||
| ▲ Show 20 Lines • Show All 381 Lines • ▼ Show 20 Lines | static bool unit_distribute_negatives(char *str, const int len_max) | ||||
| return changed; | return changed; | ||||
| } | } | ||||
| static int unit_scale_str(char *str, | static int unit_scale_str(char *str, | ||||
| int len_max, | int len_max, | ||||
| char *str_tmp, | char *str_tmp, | ||||
| double scale_pref, | double scale_pref, | ||||
| const bUnitDef *unit, | const bUnitDef *unit, | ||||
Not Done Inline ActionsBased on the name, I'd expect this function to compare chars to digits, but that does not seem to be what it is doing. JacquesLucke: Based on the name, I'd expect this function to compare chars to digits, but that does not seem… | |||||
Done Inline ActionsI used "value" instead for both the helper functions. Hopefully that's more clear. HooglyBoogly: I used "value" instead for both the helper functions. Hopefully that's more clear. | |||||
| const char *replace_str, | const char *replace_str, | ||||
| bool case_sensitive) | bool case_sensitive) | ||||
| { | { | ||||
| char *str_found; | char *str_found; | ||||
| if ((len_max > 0) && (str_found = (char *)unit_find_str(str, replace_str, case_sensitive))) { | if ((len_max > 0) && (str_found = (char *)unit_find_str(str, replace_str, case_sensitive))) { | ||||
| /* XXX - investigate, does not respect len_max properly */ | /* XXX - investigate, does not respect len_max properly */ | ||||
| int len, len_num, len_name, len_move, found_ofs; | int len, len_num, len_name, len_move, found_ofs; | ||||
| found_ofs = (int)(str_found - str); | found_ofs = (int)(str_found - str); | ||||
| len = strlen(str); | len = strlen(str); | ||||
| len_name = strlen(replace_str); | len_name = strlen(replace_str); | ||||
| len_move = (len - (found_ofs + len_name)) + 1; /* 1+ to copy the string terminator */ | len_move = (len - (found_ofs + len_name)) + 1; /* 1+ to copy the string terminator */ | ||||
| /* # removed later */ | /* # removed later */ | ||||
| len_num = BLI_snprintf(str_tmp, TEMP_STR_SIZE, "*%.9g" SEP_STR, unit->scalar / scale_pref); | len_num = BLI_snprintf(str_tmp, TEMP_STR_SIZE, "*%.9g" SEP_STR, unit->scalar / scale_pref); | ||||
| if (len_num > len_max) { | if (len_num > len_max) { | ||||
Done Inline Actionstypo JacquesLucke: typo | |||||
| len_num = len_max; | len_num = len_max; | ||||
| } | } | ||||
| if (found_ofs + len_num + len_move > len_max) { | if (found_ofs + len_num + len_move > len_max) { | ||||
| /* can't move the whole string, move just as much as will fit */ | /* can't move the whole string, move just as much as will fit */ | ||||
| len_move -= (found_ofs + len_num + len_move) - len_max; | len_move -= (found_ofs + len_num + len_move) - len_max; | ||||
| } | } | ||||
| if (len_move > 0) { | if (len_move > 0) { | ||||
| /* resize the last part of the string */ | /* resize the last part of the string */ | ||||
Done Inline Actionstypo JacquesLucke: typo | |||||
| /* May grow or shrink the string. */ | /* May grow or shrink the string. */ | ||||
| memmove(str_found + len_num, str_found + len_name, len_move); | memmove(str_found + len_num, str_found + len_name, len_move); | ||||
| } | } | ||||
| if (found_ofs + len_num > len_max) { | if (found_ofs + len_num > len_max) { | ||||
| /* not even the number will fit into the string, only copy part of it */ | /* not even the number will fit into the string, only copy part of it */ | ||||
| len_num -= (found_ofs + len_num) - len_max; | len_num -= (found_ofs + len_num) - len_max; | ||||
| ▲ Show 20 Lines • Show All 349 Lines • Show Last 20 Lines | |||||
You can add a couple more 5s here.