/***************************************************************************************** * * * OpenSpace * * * * Copyright (c) 2014-2024 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * * without restriction, including without limitation the rights to use, copy, modify, * * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * * permit persons to whom the Software is furnished to do so, subject to the following * * conditions: * * * * The above copyright notice and this permission notice shall be included in all copies * * or substantial portions of the Software. * * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ #ifndef __OPENSPACE_CORE___DISTANCECONVERSION___H__ #define __OPENSPACE_CORE___DISTANCECONVERSION___H__ #include #include #include #include #include #include namespace openspace { enum class DistanceUnit { Nanometer = 0, Micrometer, Millimeter, Centimeter, Decimeter, Meter, Kilometer, AU, Lighthour, Lightday, Lightmonth, Lightyear, Parsec, Kiloparsec, Megaparsec, Gigaparsec, Gigalightyear, // Weird units Thou, Inch, Foot, Yard, Chain, Furlong, Mile, League }; // Assumption: Unit names are sequential in memory constexpr std::string_view DistanceUnitNanometer = "nanometer"; constexpr std::string_view DistanceUnitMicrometer = "micrometer"; constexpr std::string_view DistanceUnitMillimeter = "millimeter"; constexpr std::string_view DistanceUnitCentimeter = "centimeter"; constexpr std::string_view DistanceUnitDecimeter = "decimeter"; constexpr std::string_view DistanceUnitMeter = "meter"; constexpr std::string_view DistanceUnitKilometer = "km"; constexpr std::string_view DistanceUnitAU = "AU"; constexpr std::string_view DistanceUnitLighthour = "lighthour"; constexpr std::string_view DistanceUnitLightday = "lightday"; constexpr std::string_view DistanceUnitLightmonth = "lightmonth"; constexpr std::string_view DistanceUnitLightyear = "lightyear"; constexpr std::string_view DistanceUnitParsec = "parsec"; constexpr std::string_view DistanceUnitKiloparsec = "kiloparsec"; constexpr std::string_view DistanceUnitMegaparsec = "megaparsec"; constexpr std::string_view DistanceUnitGigaparsec = "gigaparsec"; constexpr std::string_view DistanceUnitGigalightyear = "gigalightyear"; constexpr std::string_view DistanceUnitThou = "thou"; constexpr std::string_view DistanceUnitInch = "inch"; constexpr std::string_view DistanceUnitFoot = "foot"; constexpr std::string_view DistanceUnitYard = "yard"; constexpr std::string_view DistanceUnitChain = "chain"; constexpr std::string_view DistanceUnitFurlong = "furlong"; constexpr std::string_view DistanceUnitMile = "mile"; constexpr std::string_view DistanceUnitLeague = "league"; // Assumption: Unit names are sequential in memory constexpr std::string_view DistanceUnitNanometers = "nanometers"; constexpr std::string_view DistanceUnitMicrometers = "micrometers"; constexpr std::string_view DistanceUnitMillimeters = "millimeters"; constexpr std::string_view DistanceUnitCentimeters = "centimeters"; constexpr std::string_view DistanceUnitDecimeters = "decimeters"; constexpr std::string_view DistanceUnitMeters = "meters"; constexpr std::string_view DistanceUnitKilometers = "km"; constexpr std::string_view DistanceUnitAUs = "AU"; constexpr std::string_view DistanceUnitLighthours = "lighthours"; constexpr std::string_view DistanceUnitLightdays = "lightdays"; constexpr std::string_view DistanceUnitLightmonths = "lightmonths"; constexpr std::string_view DistanceUnitLightyears = "lightyears"; constexpr std::string_view DistanceUnitParsecs = "parsecs"; constexpr std::string_view DistanceUnitKiloparsecs = "kiloparsecs"; constexpr std::string_view DistanceUnitMegaparsecs = "megaparsecs"; constexpr std::string_view DistanceUnitGigaparsecs = "gigaparsecs"; constexpr std::string_view DistanceUnitGigalightyears = "gigalightyears"; constexpr std::string_view DistanceUnitThous = "thou"; constexpr std::string_view DistanceUnitInches = "inches"; constexpr std::string_view DistanceUnitFeet = "feet"; constexpr std::string_view DistanceUnitYards = "yards"; constexpr std::string_view DistanceUnitChains = "chains"; constexpr std::string_view DistanceUnitFurlongs = "furlongs"; constexpr std::string_view DistanceUnitMiles = "miles"; constexpr std::string_view DistanceUnitLeagues = "leagues"; constexpr std::array(DistanceUnit::League) + 1> DistanceUnits = { DistanceUnit::Nanometer, DistanceUnit::Micrometer, DistanceUnit::Millimeter, DistanceUnit::Centimeter, DistanceUnit::Decimeter, DistanceUnit::Meter, DistanceUnit::Kilometer, DistanceUnit::AU, DistanceUnit::Lighthour, DistanceUnit::Lightday, DistanceUnit::Lightmonth, DistanceUnit::Lightyear, DistanceUnit::Parsec, DistanceUnit::Kiloparsec, DistanceUnit::Megaparsec, DistanceUnit::Gigaparsec, DistanceUnit::Gigalightyear, DistanceUnit::Thou, DistanceUnit::Inch, DistanceUnit::Foot, DistanceUnit::Yard, DistanceUnit::Chain, DistanceUnit::Furlong, DistanceUnit::Mile, DistanceUnit::League }; constexpr std::array(DistanceUnit::League) + 1> DistanceUnitNamesSingular = { DistanceUnitNanometer, DistanceUnitMicrometer, DistanceUnitMillimeter, DistanceUnitCentimeter, DistanceUnitDecimeter, DistanceUnitMeter, DistanceUnitKilometer, DistanceUnitAU, DistanceUnitLighthour, DistanceUnitLightday, DistanceUnitLightmonth, DistanceUnitLightyear, DistanceUnitParsec, DistanceUnitKiloparsec, DistanceUnitMegaparsec, DistanceUnitGigaparsec, DistanceUnitGigalightyear, DistanceUnitThou, DistanceUnitInch, DistanceUnitFoot, DistanceUnitYard, DistanceUnitChain, DistanceUnitFurlong, DistanceUnitMile, DistanceUnitLeague }; constexpr std::array(DistanceUnit::League) + 1> DistanceUnitNamesPlural = { DistanceUnitNanometers, DistanceUnitMicrometers, DistanceUnitMillimeters, DistanceUnitCentimeters, DistanceUnitDecimeters, DistanceUnitMeters, DistanceUnitKilometers, DistanceUnitAUs, DistanceUnitLighthours, DistanceUnitLightdays, DistanceUnitLightmonths, DistanceUnitLightyears, DistanceUnitParsecs, DistanceUnitKiloparsecs, DistanceUnitMegaparsecs, DistanceUnitGigaparsecs, DistanceUnitGigalightyears, DistanceUnitThous, DistanceUnitInches, DistanceUnitFeet, DistanceUnitYards, DistanceUnitChains, DistanceUnitFurlongs, DistanceUnitMile, DistanceUnitLeague }; constexpr bool isValidDistanceUnitName(std::string_view name) { for (std::string_view val : DistanceUnitNamesSingular) { if (val == name) { return true; } } for (std::string_view val : DistanceUnitNamesPlural) { if (val == name) { return true; } } return false; } constexpr std::string_view nameForDistanceUnit(DistanceUnit unit, bool pluralForm = false) { switch (unit) { case DistanceUnit::Nanometer: case DistanceUnit::Micrometer: case DistanceUnit::Millimeter: case DistanceUnit::Centimeter: case DistanceUnit::Decimeter: case DistanceUnit::Meter: case DistanceUnit::Kilometer: case DistanceUnit::AU: case DistanceUnit::Lighthour: case DistanceUnit::Lightday: case DistanceUnit::Lightmonth: case DistanceUnit::Lightyear: case DistanceUnit::Parsec: case DistanceUnit::Kiloparsec: case DistanceUnit::Megaparsec: case DistanceUnit::Gigaparsec: case DistanceUnit::Gigalightyear: case DistanceUnit::Thou: case DistanceUnit::Inch: case DistanceUnit::Foot: case DistanceUnit::Yard: case DistanceUnit::Chain: case DistanceUnit::Furlong: case DistanceUnit::Mile: case DistanceUnit::League: if (pluralForm) { return DistanceUnitNamesPlural[static_cast(unit)]; } else { return DistanceUnitNamesSingular[static_cast(unit)]; } default: throw ghoul::MissingCaseException(); } } constexpr DistanceUnit distanceUnitFromString(std::string_view unitName) { int found = -1; int i = 0; for (std::string_view val : DistanceUnitNamesSingular) { if (val == unitName) { found = i; break; } i++; } i = 0; for (std::string_view val : DistanceUnitNamesPlural) { if (val == unitName) { found = i; break; } i++; } if (found != -1) { return static_cast(found); } else { throw ghoul::MissingCaseException(); } } std::pair simplifyDistance(double meters, bool forceSingularForm = false); constexpr double convertMeters(double meters, DistanceUnit requestedUnit) { switch (requestedUnit) { case DistanceUnit::Nanometer: return meters / 1e-9; case DistanceUnit::Micrometer: return meters / 1e-6; case DistanceUnit::Millimeter: return meters / 1e-3; case DistanceUnit::Centimeter: return meters / 1e-2; case DistanceUnit::Decimeter: return meters / 1e-1; case DistanceUnit::Meter: return meters; case DistanceUnit::Kilometer: return meters / 1000.0; case DistanceUnit::AU: return meters / distanceconstants::AstronomicalUnit; case DistanceUnit::Lighthour: return meters / distanceconstants::LightHour; case DistanceUnit::Lightday: return meters / distanceconstants::LightDay; case DistanceUnit::Lightmonth: return meters / distanceconstants::LightMonth; case DistanceUnit::Lightyear: return meters / distanceconstants::LightYear; case DistanceUnit::Parsec: return meters / distanceconstants::Parsec; case DistanceUnit::Kiloparsec: return meters / (1e3 * distanceconstants::Parsec); case DistanceUnit::Megaparsec: return meters / (1e6 * distanceconstants::Parsec); case DistanceUnit::Gigaparsec: return meters / (1e9 * distanceconstants::Parsec); case DistanceUnit::Gigalightyear: return meters / (1e9 * distanceconstants::LightYear); case DistanceUnit::Thou: return meters / (1e-3 * distanceconstants::Inch); case DistanceUnit::Inch: return meters / distanceconstants::Inch; case DistanceUnit::Foot: return meters / distanceconstants::Foot; case DistanceUnit::Yard: return meters / distanceconstants::Yard; case DistanceUnit::Chain: return meters / distanceconstants::Chain; case DistanceUnit::Furlong: return meters / (10.0 * distanceconstants::Chain); case DistanceUnit::Mile: return meters / distanceconstants::Mile; case DistanceUnit::League: return meters / (3.0 * distanceconstants::Mile); default: throw ghoul::MissingCaseException(); } } constexpr double toMeter(DistanceUnit unit) { switch (unit) { case DistanceUnit::Nanometer: return 1e-9; case DistanceUnit::Micrometer: return 1e-6; case DistanceUnit::Millimeter: return 1e-3; case DistanceUnit::Centimeter: return 1e-2; case DistanceUnit::Decimeter: return 1e-1; case DistanceUnit::Meter: return 1.0; case DistanceUnit::Kilometer: return 1000.0; case DistanceUnit::AU: return distanceconstants::AstronomicalUnit; case DistanceUnit::Lighthour: return distanceconstants::LightHour; case DistanceUnit::Lightday: return distanceconstants::LightDay; case DistanceUnit::Lightmonth: return distanceconstants::LightMonth; case DistanceUnit::Lightyear: return distanceconstants::LightYear; case DistanceUnit::Parsec: return distanceconstants::Parsec; case DistanceUnit::Kiloparsec: return 1e3 * distanceconstants::Parsec; case DistanceUnit::Megaparsec: return 1e6 * distanceconstants::Parsec; case DistanceUnit::Gigaparsec: return 1e9 * distanceconstants::Parsec; case DistanceUnit::Gigalightyear: return 1e9 * distanceconstants::LightYear; case DistanceUnit::Thou: return 1e-3 * distanceconstants::Inch; case DistanceUnit::Inch: return distanceconstants::Inch; case DistanceUnit::Foot: return distanceconstants::Foot; case DistanceUnit::Yard: return distanceconstants::Yard; case DistanceUnit::Chain: return distanceconstants::Chain; case DistanceUnit::Furlong: return 10.0 * distanceconstants::Chain; case DistanceUnit::Mile: return distanceconstants::Mile; case DistanceUnit::League: return 3.0 * distanceconstants::Mile; default: throw ghoul::MissingCaseException(); } } constexpr double convertUnit(DistanceUnit fromUnit, DistanceUnit toUnit) { return convertMeters(toMeter(fromUnit), toUnit); } constexpr double convertDistance(double distance, DistanceUnit fromUnit, DistanceUnit toUnit) { return distance * convertUnit(fromUnit, toUnit); } float convertMasPerYearToMeterPerSecond(float masPerYear, float parallax); } // namespace openspace #endif // __OPENSPACE_CORE___DISTANCECONVERSION___H__