From ec3a255c7f7c384e333919e65df306fb344f8628 Mon Sep 17 00:00:00 2001 From: Aditya Date: Thu, 23 Jun 2022 01:03:44 -0700 Subject: [PATCH 01/13] Added method to set spherical coords ref Signed-off-by: Aditya --- .../include/gz/common/geospatial/Dem.hh | 3 + geospatial/src/Dem.cc | 85 +++++++++++++------ 2 files changed, 60 insertions(+), 28 deletions(-) diff --git a/geospatial/include/gz/common/geospatial/Dem.hh b/geospatial/include/gz/common/geospatial/Dem.hh index 3933441d3..1b2e4671e 100644 --- a/geospatial/include/gz/common/geospatial/Dem.hh +++ b/geospatial/include/gz/common/geospatial/Dem.hh @@ -44,6 +44,9 @@ namespace gz /// \brief Destructor. public: virtual ~Dem(); + /// \brief Sets the spherical coordinates reference object. + public: void SetSphericalCoordinates(const math::SphericalCoordinates); + /// \brief Load a DEM file. /// \param[in] _filename the path to the terrain file. /// \return 0 when the operation succeeds to open a file. diff --git a/geospatial/src/Dem.cc b/geospatial/src/Dem.cc index 664737e4c..70394d2c9 100644 --- a/geospatial/src/Dem.cc +++ b/geospatial/src/Dem.cc @@ -63,6 +63,10 @@ class gz::common::Dem::Implementation /// If true, worldWidth & worldHeight = -1 /// and GeoReference[Origin] can not be used (will return false) public: bool isNonEarthDem = false; + + /// \brief Holds the spherical coordinates object from the world. + public : math::SphericalCoordinates sphericalCoordinates = + math::SphericalCoordinates(); }; ////////////////////////////////////////////////// @@ -82,6 +86,13 @@ Dem::~Dem() GDALClose(reinterpret_cast(this->dataPtr->dataSet)); } +////////////////////////////////////////////////// +void Dem::SetSphericalCoordinates( + const math::SphericalCoordinates _worldSphericalCoordinates) +{ + this->dataPtr->sphericalCoordinates =_worldSphericalCoordinates; +} + ////////////////////////////////////////////////// void Dem::SetNonEarthDEM(bool _isNonEarthDem) { @@ -285,39 +296,57 @@ bool Dem::GeoReference(double _x, double _y, double geoTransf[6]; if (this->dataPtr->dataSet->GetGeoTransform(geoTransf) == CE_None) { - OGRSpatialReference sourceCs; - OGRSpatialReference targetCs; - OGRCoordinateTransformation *cT; - double xGeoDeg, yGeoDeg; - - // Transform the terrain's coordinate system to WGS84 - const char *importString - = strdup(this->dataPtr->dataSet->GetProjectionRef()); - if (importString == nullptr || importString[0] == '\0') + if (this->dataPtr->sphericalCoordinates.Surface() == + math::SphericalCoordinates::EARTH_WGS84) { - gzdbg << "Projection coordinate system undefined." << std::endl; - return false; - } - sourceCs.importFromWkt(&importString); - targetCs.SetWellKnownGeogCS("WGS84"); - cT = OGRCreateCoordinateTransformation(&sourceCs, &targetCs); - if (nullptr == cT) - { - gzerr << "Unable to transform terrain coordinate system to WGS84 for " - << "coordinates (" << _x << "," << _y << ")" << std::endl; + OGRSpatialReference sourceCs; + OGRSpatialReference targetCs; + OGRCoordinateTransformation *cT; + double xGeoDeg, yGeoDeg; + + // Transform the terrain's coordinate system to WGS84 + const char *importString + = strdup(this->dataPtr->dataSet->GetProjectionRef()); + if (importString == nullptr || importString[0] == '\0') + { + gzdbg << "Projection coordinate system undefined." << std::endl; + return false; + } + sourceCs.importFromWkt(&importString); + targetCs.SetWellKnownGeogCS("WGS84"); + cT = OGRCreateCoordinateTransformation(&sourceCs, &targetCs); + if (nullptr == cT) + { + gzerr << "Unable to transform terrain coordinate system to WGS84 for " + << "coordinates (" << _x << "," << _y << ")" << std::endl; + OCTDestroyCoordinateTransformation(cT); + return false; + } + + xGeoDeg = geoTransf[0] + _x * geoTransf[1] + _y * geoTransf[2]; + yGeoDeg = geoTransf[3] + _x * geoTransf[4] + _y * geoTransf[5]; + + cT->Transform(1, &xGeoDeg, &yGeoDeg); + + _latitude.SetDegree(yGeoDeg); + _longitude.SetDegree(xGeoDeg); + OCTDestroyCoordinateTransformation(cT); - return false; } + else if (this->dataPtr->sphericalCoordinates.Surface() == + math::SphericalCoordinates::MOON_SCS) + { + // TODO + auto demSrs = this->dataPtr->dataSet->GetSpatialRef(); - xGeoDeg = geoTransf[0] + _x * geoTransf[1] + _y * geoTransf[2]; - yGeoDeg = geoTransf[3] + _x * geoTransf[4] + _y * geoTransf[5]; - - cT->Transform(1, &xGeoDeg, &yGeoDeg); - - _latitude.SetDegree(yGeoDeg); - _longitude.SetDegree(xGeoDeg); - OCTDestroyCoordinateTransformation(cT); + } + else + { + gzerr << "Unknown surface found in spherical coordinates" + << std::endl; + return false; + } } else { From 4aac42b6d904e85a68b9666b67e6307d53dbef3a Mon Sep 17 00:00:00 2001 From: Aditya Date: Thu, 23 Jun 2022 13:23:46 -0700 Subject: [PATCH 02/13] Lunar coordinate transformation added Signed-off-by: Aditya --- .../include/gz/common/geospatial/Dem.hh | 4 ++- geospatial/src/Dem.cc | 29 +++++++++++++++---- geospatial/src/Dem_TEST.cc | 15 ++++++++++ 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/geospatial/include/gz/common/geospatial/Dem.hh b/geospatial/include/gz/common/geospatial/Dem.hh index 1b2e4671e..4d047d867 100644 --- a/geospatial/include/gz/common/geospatial/Dem.hh +++ b/geospatial/include/gz/common/geospatial/Dem.hh @@ -23,6 +23,7 @@ #include #include +#include "gz/math/SphericalCoordinates.hh" #include #include @@ -45,7 +46,8 @@ namespace gz public: virtual ~Dem(); /// \brief Sets the spherical coordinates reference object. - public: void SetSphericalCoordinates(const math::SphericalCoordinates); + public: void SetSphericalCoordinates( + const math::SphericalCoordinates _worldSphericalCoordinates); /// \brief Load a DEM file. /// \param[in] _filename the path to the terrain file. diff --git a/geospatial/src/Dem.cc b/geospatial/src/Dem.cc index 70394d2c9..734b27f31 100644 --- a/geospatial/src/Dem.cc +++ b/geospatial/src/Dem.cc @@ -22,7 +22,6 @@ #include "gz/common/Console.hh" #include "gz/common/geospatial/Dem.hh" -#include "gz/math/SphericalCoordinates.hh" using namespace gz; using namespace common; @@ -168,11 +167,11 @@ int Dem::Load(const std::string &_filename) { // If successful, set the world width and height this->dataPtr->worldWidth = - math::SphericalCoordinates::Distance(upLeftLat, upLeftLong, - upRightLat, upRightLong); + this->dataPtr->sphericalCoordinates.DistanceBetweenPoints( + upLeftLat, upLeftLong, upRightLat, upRightLong); this->dataPtr->worldHeight = - math::SphericalCoordinates::Distance(upLeftLat, upLeftLong, - lowLeftLat, lowLeftLong); + this->dataPtr->sphericalCoordinates.DistanceBetweenPoints( + upLeftLat, upLeftLong, lowLeftLat, lowLeftLong); } // Assume non-Earth DEM (e.g., moon) else @@ -337,9 +336,27 @@ bool Dem::GeoReference(double _x, double _y, math::SphericalCoordinates::MOON_SCS) { // TODO - auto demSrs = this->dataPtr->dataSet->GetSpatialRef(); + double xGeoDeg, yGeoDeg; + const OGRSpatialReference* demSrs = + this->dataPtr->dataSet->GetSpatialRef(); + OGRSpatialReference moonLatLonSrs = OGRSpatialReference(); + + const char* MOON_LAT_LON_PROJ_STR = + "+proj=latlong +a=1737400 +b=1737400"; + + moonLatLonSrs.importFromProj4(MOON_LAT_LON_PROJ_STR); + auto demToLonLat = OGRCreateCoordinateTransformation( + demSrs, &moonLatLonSrs); + + xGeoDeg = geoTransf[0] + _x * geoTransf[1] + _y * geoTransf[2]; + yGeoDeg = geoTransf[3] + _x * geoTransf[4] + _y * geoTransf[5]; + + demToLonLat->Transform(1, &xGeoDeg, &yGeoDeg); + _latitude.SetDegree(yGeoDeg); + _longitude.SetDegree(xGeoDeg); + OCTDestroyCoordinateTransformation(demToLonLat); } else { diff --git a/geospatial/src/Dem_TEST.cc b/geospatial/src/Dem_TEST.cc index c35a49be4..c0d80f37d 100644 --- a/geospatial/src/Dem_TEST.cc +++ b/geospatial/src/Dem_TEST.cc @@ -254,3 +254,18 @@ TEST_F(DemTest, NonEarthDem) dem.SetNonEarthDEM(false); EXPECT_FALSE(dem.GetNonEarthDEM()); } + +TEST_F(DemTest, LunarDemLoad) +{ + // moon + common::Dem dem; + auto path = common::testing::TestFile("data", "dem_moon.tif"); + // Providing spherical coordinates object. + auto moonSc = math::SphericalCoordinates( + math::SphericalCoordinates::MOON_SCS); + dem.SetSphericalCoordinates(moonSc); + EXPECT_EQ(dem.Load(path), 0); + + std::cout << "WH:" << dem.WorldHeight() << std::endl; + std::cout << "WW:" << dem.WorldWidth() << std::endl; +} From 57a0fed3c5ab80c4deefc5dd3837abb1b2192f35 Mon Sep 17 00:00:00 2001 From: Aditya Date: Thu, 23 Jun 2022 13:42:44 -0700 Subject: [PATCH 03/13] Minor refactor Signed-off-by: Aditya --- geospatial/src/Dem.cc | 65 +++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 39 deletions(-) diff --git a/geospatial/src/Dem.cc b/geospatial/src/Dem.cc index 734b27f31..82023c487 100644 --- a/geospatial/src/Dem.cc +++ b/geospatial/src/Dem.cc @@ -295,14 +295,14 @@ bool Dem::GeoReference(double _x, double _y, double geoTransf[6]; if (this->dataPtr->dataSet->GetGeoTransform(geoTransf) == CE_None) { + OGRCoordinateTransformation *cT; + double xGeoDeg, yGeoDeg; + if (this->dataPtr->sphericalCoordinates.Surface() == math::SphericalCoordinates::EARTH_WGS84) { OGRSpatialReference sourceCs; OGRSpatialReference targetCs; - OGRCoordinateTransformation *cT; - double xGeoDeg, yGeoDeg; - // Transform the terrain's coordinate system to WGS84 const char *importString = strdup(this->dataPtr->dataSet->GetProjectionRef()); @@ -314,56 +314,43 @@ bool Dem::GeoReference(double _x, double _y, sourceCs.importFromWkt(&importString); targetCs.SetWellKnownGeogCS("WGS84"); cT = OGRCreateCoordinateTransformation(&sourceCs, &targetCs); - if (nullptr == cT) - { - gzerr << "Unable to transform terrain coordinate system to WGS84 for " - << "coordinates (" << _x << "," << _y << ")" << std::endl; - OCTDestroyCoordinateTransformation(cT); - return false; - } - - xGeoDeg = geoTransf[0] + _x * geoTransf[1] + _y * geoTransf[2]; - yGeoDeg = geoTransf[3] + _x * geoTransf[4] + _y * geoTransf[5]; - - cT->Transform(1, &xGeoDeg, &yGeoDeg); - - _latitude.SetDegree(yGeoDeg); - _longitude.SetDegree(xGeoDeg); - - OCTDestroyCoordinateTransformation(cT); } else if (this->dataPtr->sphericalCoordinates.Surface() == math::SphericalCoordinates::MOON_SCS) { - // TODO - double xGeoDeg, yGeoDeg; - const OGRSpatialReference* demSrs = - this->dataPtr->dataSet->GetSpatialRef(); - OGRSpatialReference moonLatLonSrs = OGRSpatialReference(); + auto sourceCs = this->dataPtr->dataSet->GetSpatialRef(); + OGRSpatialReference targetCs = OGRSpatialReference(); const char* MOON_LAT_LON_PROJ_STR = "+proj=latlong +a=1737400 +b=1737400"; - moonLatLonSrs.importFromProj4(MOON_LAT_LON_PROJ_STR); - - auto demToLonLat = OGRCreateCoordinateTransformation( - demSrs, &moonLatLonSrs); + targetCs.importFromProj4(MOON_LAT_LON_PROJ_STR); - xGeoDeg = geoTransf[0] + _x * geoTransf[1] + _y * geoTransf[2]; - yGeoDeg = geoTransf[3] + _x * geoTransf[4] + _y * geoTransf[5]; - - demToLonLat->Transform(1, &xGeoDeg, &yGeoDeg); - _latitude.SetDegree(yGeoDeg); - _longitude.SetDegree(xGeoDeg); - - OCTDestroyCoordinateTransformation(demToLonLat); + cT = OGRCreateCoordinateTransformation( + sourceCs, &targetCs); } else { - gzerr << "Unknown surface found in spherical coordinates" - << std::endl; + gzerr << "Unsupported spherical coordinates found" << std::endl; + } + + if (nullptr == cT) + { + gzerr << "Unable to transform terrain coordinate system for " + << "coordinates (" << _x << "," << _y << ")" << std::endl; + OCTDestroyCoordinateTransformation(cT); return false; } + + xGeoDeg = geoTransf[0] + _x * geoTransf[1] + _y * geoTransf[2]; + yGeoDeg = geoTransf[3] + _x * geoTransf[4] + _y * geoTransf[5]; + + cT->Transform(1, &xGeoDeg, &yGeoDeg); + + _latitude.SetDegree(yGeoDeg); + _longitude.SetDegree(xGeoDeg); + + OCTDestroyCoordinateTransformation(cT); } else { From 3625c95e623f2fab1916cba4f2b64f1e9e2fe207 Mon Sep 17 00:00:00 2001 From: Aditya Date: Thu, 23 Jun 2022 17:05:45 -0700 Subject: [PATCH 04/13] Minor refactor Signed-off-by: Aditya --- geospatial/src/Dem.cc | 2 +- geospatial/src/Dem_TEST.cc | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/geospatial/src/Dem.cc b/geospatial/src/Dem.cc index 82023c487..0a4cbe519 100644 --- a/geospatial/src/Dem.cc +++ b/geospatial/src/Dem.cc @@ -173,7 +173,7 @@ int Dem::Load(const std::string &_filename) this->dataPtr->sphericalCoordinates.DistanceBetweenPoints( upLeftLat, upLeftLong, lowLeftLat, lowLeftLong); } - // Assume non-Earth DEM (e.g., moon) + // Assume unknown DEM. else { gzwarn << "Failed to automatically compute DEM size. " diff --git a/geospatial/src/Dem_TEST.cc b/geospatial/src/Dem_TEST.cc index c0d80f37d..5fff7f1ed 100644 --- a/geospatial/src/Dem_TEST.cc +++ b/geospatial/src/Dem_TEST.cc @@ -266,6 +266,6 @@ TEST_F(DemTest, LunarDemLoad) dem.SetSphericalCoordinates(moonSc); EXPECT_EQ(dem.Load(path), 0); - std::cout << "WH:" << dem.WorldHeight() << std::endl; - std::cout << "WW:" << dem.WorldWidth() << std::endl; + EXPECT_NEAR(dem.WorldWidth(), 80.0417); + EXPECT_NEAR(dem.WorldHeight(), 80.0417); } From b9c3c87c2519e9b90540a90d645c6b6e283b6362 Mon Sep 17 00:00:00 2001 From: Aditya Date: Fri, 24 Jun 2022 13:24:11 -0700 Subject: [PATCH 05/13] Updated docstring Signed-off-by: Aditya --- geospatial/include/gz/common/geospatial/Dem.hh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/geospatial/include/gz/common/geospatial/Dem.hh b/geospatial/include/gz/common/geospatial/Dem.hh index 4d047d867..0530f3468 100644 --- a/geospatial/include/gz/common/geospatial/Dem.hh +++ b/geospatial/include/gz/common/geospatial/Dem.hh @@ -46,6 +46,9 @@ namespace gz public: virtual ~Dem(); /// \brief Sets the spherical coordinates reference object. + /// \param[in] _worldSphericalCoordinates The spherical coordiantes + /// object contained in the world. This is used to compute accurate + /// sizes of the DEM object. public: void SetSphericalCoordinates( const math::SphericalCoordinates _worldSphericalCoordinates); From 9a679aabd0bd7616e2261fb4b2de6442419cff45 Mon Sep 17 00:00:00 2001 From: Aditya Date: Fri, 24 Jun 2022 14:19:07 -0700 Subject: [PATCH 06/13] Fixed test Signed-off-by: Aditya --- geospatial/src/Dem_TEST.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/geospatial/src/Dem_TEST.cc b/geospatial/src/Dem_TEST.cc index 5fff7f1ed..13f690522 100644 --- a/geospatial/src/Dem_TEST.cc +++ b/geospatial/src/Dem_TEST.cc @@ -266,6 +266,6 @@ TEST_F(DemTest, LunarDemLoad) dem.SetSphericalCoordinates(moonSc); EXPECT_EQ(dem.Load(path), 0); - EXPECT_NEAR(dem.WorldWidth(), 80.0417); - EXPECT_NEAR(dem.WorldHeight(), 80.0417); + EXPECT_NEAR(dem.WorldWidth(), 80.0417, 1e-2); + EXPECT_NEAR(dem.WorldHeight(), 80.0417, 1e-2); } From 5bb4c5b9de1bd0f5a7be67de17c0cf3a8e71b5f1 Mon Sep 17 00:00:00 2001 From: Aditya Date: Wed, 6 Jul 2022 01:59:16 -0700 Subject: [PATCH 07/13] Changed isNonEarthDem usage, added custom surface support Signed-off-by: Aditya --- .../include/gz/common/geospatial/Dem.hh | 4 +- geospatial/src/Dem.cc | 48 +++++++++++++------ geospatial/src/Dem_TEST.cc | 33 ++++++++++--- 3 files changed, 63 insertions(+), 22 deletions(-) diff --git a/geospatial/include/gz/common/geospatial/Dem.hh b/geospatial/include/gz/common/geospatial/Dem.hh index 0530f3468..3f0b3789e 100644 --- a/geospatial/include/gz/common/geospatial/Dem.hh +++ b/geospatial/include/gz/common/geospatial/Dem.hh @@ -60,12 +60,12 @@ namespace gz /// \brief Indicate that this is a non Earth DEM. /// \param[in] _isNonEarthDem Should be true if this is a /// non earth DEM, otherwise false. - public: void SetNonEarthDEM(bool _isNonEarthDem); + public: void SetUnknownDEM(bool _isNonEarthDem); /// \brief Check if the loaded DEM is not from the Earth. /// \return True if the loaded DEM is from the Earth, otherwise /// returns False. - public: bool GetNonEarthDEM(); + public: bool UnknownDEM(); /// \brief Get the elevation of a terrain's point in meters. /// \param[in] _x X coordinate of the terrain. diff --git a/geospatial/src/Dem.cc b/geospatial/src/Dem.cc index 0a4cbe519..dfe8c8fa4 100644 --- a/geospatial/src/Dem.cc +++ b/geospatial/src/Dem.cc @@ -58,10 +58,10 @@ class gz::common::Dem::Implementation /// \brief Full filename used to load the dem. public: std::string filename; - /// \brief Whether the DEM will be handled as from non-Earth. + /// \brief Whether the DEM will be handled as unknown. /// If true, worldWidth & worldHeight = -1 /// and GeoReference[Origin] can not be used (will return false) - public: bool isNonEarthDem = false; + public: bool isUnknownDem = false; /// \brief Holds the spherical coordinates object from the world. public : math::SphericalCoordinates sphericalCoordinates = @@ -93,15 +93,15 @@ void Dem::SetSphericalCoordinates( } ////////////////////////////////////////////////// -void Dem::SetNonEarthDEM(bool _isNonEarthDem) +void Dem::SetUnknownDEM(bool _isUnknownDem) { - this->dataPtr->isNonEarthDem = _isNonEarthDem; + this->dataPtr->isUnknownDem = _isUnknownDem; } ////////////////////////////////////////////////// -bool Dem::GetNonEarthDEM() +bool Dem::UnknownDEM() { - return this->dataPtr->isNonEarthDem; + return this->dataPtr->isUnknownDem; } ////////////////////////////////////////////////// @@ -181,7 +181,7 @@ int Dem::Load(const std::string &_filename) << std::endl; this->dataPtr->worldWidth = this->dataPtr->worldHeight = -1; - this->dataPtr->isNonEarthDem = true; + this->dataPtr->isUnknownDem = true; } // Set the terrain's side (the terrain will be squared after the padding) @@ -285,9 +285,9 @@ float Dem::MaxElevation() const bool Dem::GeoReference(double _x, double _y, gz::math::Angle &_latitude, gz::math::Angle &_longitude) const { - if (this->dataPtr->isNonEarthDem) + if (this->dataPtr->isUnknownDem) { - gzerr << "Can not retrieve WGS84 coordinates from non-Earth DEM." + gzerr << "Can not retrieve WGS84 coordinates from unknown DEM." << std::endl; return false; } @@ -295,7 +295,7 @@ bool Dem::GeoReference(double _x, double _y, double geoTransf[6]; if (this->dataPtr->dataSet->GetGeoTransform(geoTransf) == CE_None) { - OGRCoordinateTransformation *cT; + OGRCoordinateTransformation *cT = nullptr; double xGeoDeg, yGeoDeg; if (this->dataPtr->sphericalCoordinates.Surface() == @@ -329,6 +329,26 @@ bool Dem::GeoReference(double _x, double _y, cT = OGRCreateCoordinateTransformation( sourceCs, &targetCs); } + else if (this->dataPtr->sphericalCoordinates.Surface() == + math::SphericalCoordinates::CUSTOM_SURFACE) + { + auto sourceCs = this->dataPtr->dataSet->GetSpatialRef(); + OGRSpatialReference targetCs = OGRSpatialReference(); + + int axisEquatorial = + this->dataPtr->sphericalCoordinates.SurfaceAxisEquatorial(); + int axisPolar = + this->dataPtr->sphericalCoordinates.SurfaceAxisPolar(); + + std::string CUSTOM_SURFACE_LAT_LON_PROJ_STR = + "+proj=latlong +a=" + std::to_string(axisEquatorial) + + " +b=" + std::to_string(axisPolar); + + targetCs.importFromProj4(CUSTOM_SURFACE_LAT_LON_PROJ_STR.c_str()); + + cT = OGRCreateCoordinateTransformation( + sourceCs, &targetCs); + } else { gzerr << "Unsupported spherical coordinates found" << std::endl; @@ -383,9 +403,9 @@ unsigned int Dem::Width() const ////////////////////////////////////////////////// double Dem::WorldWidth() const { - if (this->dataPtr->isNonEarthDem) + if (this->dataPtr->isUnknownDem) { - gzwarn << "Unable to determine world width of non-Earth DEM." + gzwarn << "Unable to determine world width of unknown DEM." << std::endl; } return this->dataPtr->worldWidth; @@ -394,9 +414,9 @@ double Dem::WorldWidth() const ////////////////////////////////////////////////// double Dem::WorldHeight() const { - if (this->dataPtr->isNonEarthDem) + if (this->dataPtr->isUnknownDem) { - gzwarn << "Unable to determine world height of non-Earth DEM." + gzwarn << "Unable to determine world height of unknown DEM." << std::endl; } return this->dataPtr->worldHeight; diff --git a/geospatial/src/Dem_TEST.cc b/geospatial/src/Dem_TEST.cc index 13f690522..99a8401c9 100644 --- a/geospatial/src/Dem_TEST.cc +++ b/geospatial/src/Dem_TEST.cc @@ -127,6 +127,18 @@ TEST_F(DemTest, BasicAPI) EXPECT_TRUE(dem.GeoReferenceOrigin(latitude, longitude)); EXPECT_FLOAT_EQ(38.001667f, latitude.Degree()); EXPECT_FLOAT_EQ(-122.22278f, longitude.Degree()); + + // Emulate Earth as a custom surface. + common::Dem demCustomSurface; + auto earthSc = math::SphericalCoordinates(); + auto customSc = math::SphericalCoordinates( + math::SphericalCoordinates::CUSTOM_SURFACE, + earthSc.SurfaceRadius(), + earthSc.SurfaceRadius()); + demCustomSurface.SetSphericalCoordinates(customSc); + EXPECT_EQ(demCustomSurface.Load(path), 0); + EXPECT_FLOAT_EQ(3984.4849f, demCustomSurface.WorldHeight()); + EXPECT_FLOAT_EQ(3139.7456f, demCustomSurface.WorldWidth()); } ///////////////////////////////////////////////// @@ -226,7 +238,7 @@ TEST_F(DemTest, NaNNoData) } ///////////////////////////////////////////////// -TEST_F(DemTest, NonEarthDem) +TEST_F(DemTest, UnknownDem) { // moon common::Dem dem; @@ -247,17 +259,17 @@ TEST_F(DemTest, NonEarthDem) EXPECT_FALSE(dem.GeoReferenceOrigin(latitude, longitude)); // The Load() method in Dem.cc should set the - // isNonEarthDEM flag. - EXPECT_TRUE(dem.GetNonEarthDEM()); + // isUnknownDEM flag. + EXPECT_TRUE(dem.UnknownDEM()); // This flag can be overridden externally. - dem.SetNonEarthDEM(false); - EXPECT_FALSE(dem.GetNonEarthDEM()); + dem.SetUnknownDEM(false); + EXPECT_FALSE(dem.UnknownDEM()); } TEST_F(DemTest, LunarDemLoad) { - // moon + // Load Moon DEM common::Dem dem; auto path = common::testing::TestFile("data", "dem_moon.tif"); // Providing spherical coordinates object. @@ -265,7 +277,16 @@ TEST_F(DemTest, LunarDemLoad) math::SphericalCoordinates::MOON_SCS); dem.SetSphericalCoordinates(moonSc); EXPECT_EQ(dem.Load(path), 0); + EXPECT_NEAR(dem.WorldWidth(), 80.0417, 1e-2); + EXPECT_NEAR(dem.WorldHeight(), 80.0417, 1e-2); + // Use custom spherical coordinates object with same axes as the moon. + auto customSc = math::SphericalCoordinates( + math::SphericalCoordinates::CUSTOM_SURFACE, + moonSc.SurfaceRadius(), + moonSc.SurfaceRadius()); + dem.SetSphericalCoordinates(customSc); + EXPECT_EQ(dem.Load(path), 0); EXPECT_NEAR(dem.WorldWidth(), 80.0417, 1e-2); EXPECT_NEAR(dem.WorldHeight(), 80.0417, 1e-2); } From ffb860717750ac108dae956248956407463c0410 Mon Sep 17 00:00:00 2001 From: Aditya Date: Wed, 6 Jul 2022 13:32:16 -0700 Subject: [PATCH 08/13] Updated error statements, keep eq and polar axes as double Signed-off-by: Aditya --- geospatial/src/Dem.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/geospatial/src/Dem.cc b/geospatial/src/Dem.cc index dfe8c8fa4..e90344515 100644 --- a/geospatial/src/Dem.cc +++ b/geospatial/src/Dem.cc @@ -177,7 +177,6 @@ int Dem::Load(const std::string &_filename) else { gzwarn << "Failed to automatically compute DEM size. " - << "Assuming non-Earth DEM. " << std::endl; this->dataPtr->worldWidth = this->dataPtr->worldHeight = -1; @@ -287,7 +286,7 @@ bool Dem::GeoReference(double _x, double _y, { if (this->dataPtr->isUnknownDem) { - gzerr << "Can not retrieve WGS84 coordinates from unknown DEM." + gzerr << "Can not retrieve coordinates from unknown DEM." << std::endl; return false; } @@ -335,9 +334,9 @@ bool Dem::GeoReference(double _x, double _y, auto sourceCs = this->dataPtr->dataSet->GetSpatialRef(); OGRSpatialReference targetCs = OGRSpatialReference(); - int axisEquatorial = + double axisEquatorial = this->dataPtr->sphericalCoordinates.SurfaceAxisEquatorial(); - int axisPolar = + double axisPolar = this->dataPtr->sphericalCoordinates.SurfaceAxisPolar(); std::string CUSTOM_SURFACE_LAT_LON_PROJ_STR = From e42c08d9e12ccf1902a20f930322f79a89d03238 Mon Sep 17 00:00:00 2001 From: Aditya Date: Thu, 14 Jul 2022 15:37:37 -0700 Subject: [PATCH 09/13] Updated docstrings and minor refactor Signed-off-by: Aditya --- geospatial/include/gz/common/geospatial/Dem.hh | 18 +++++++++--------- geospatial/src/Dem.cc | 16 ++++++---------- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/geospatial/include/gz/common/geospatial/Dem.hh b/geospatial/include/gz/common/geospatial/Dem.hh index 3f0b3789e..a121646ee 100644 --- a/geospatial/include/gz/common/geospatial/Dem.hh +++ b/geospatial/include/gz/common/geospatial/Dem.hh @@ -23,7 +23,7 @@ #include #include -#include "gz/math/SphericalCoordinates.hh" +#include #include #include @@ -50,21 +50,21 @@ namespace gz /// object contained in the world. This is used to compute accurate /// sizes of the DEM object. public: void SetSphericalCoordinates( - const math::SphericalCoordinates _worldSphericalCoordinates); + const math::SphericalCoordinates &_worldSphericalCoordinates); /// \brief Load a DEM file. /// \param[in] _filename the path to the terrain file. /// \return 0 when the operation succeeds to open a file. public: int Load(const std::string &_filename = ""); - /// \brief Indicate that this is a non Earth DEM. - /// \param[in] _isNonEarthDem Should be true if this is a - /// non earth DEM, otherwise false. - public: void SetUnknownDEM(bool _isNonEarthDem); + /// \brief Indicate that the coordinate system of the DEM is unknown. + /// \param[in] _isUnknownDem True if the coordinate system + /// is unknown, otherwise false. + public: void SetUnknownDEM(bool _isUnknownDem); - /// \brief Check if the loaded DEM is not from the Earth. - /// \return True if the loaded DEM is from the Earth, otherwise - /// returns False. + /// \brief Check if the loaded DEM has an unknown coordinate system. + /// \return True if the loaded DEM has an unknown coordinate system, + /// otherwise false. public: bool UnknownDEM(); /// \brief Get the elevation of a terrain's point in meters. diff --git a/geospatial/src/Dem.cc b/geospatial/src/Dem.cc index e90344515..7c26885f5 100644 --- a/geospatial/src/Dem.cc +++ b/geospatial/src/Dem.cc @@ -64,7 +64,7 @@ class gz::common::Dem::Implementation public: bool isUnknownDem = false; /// \brief Holds the spherical coordinates object from the world. - public : math::SphericalCoordinates sphericalCoordinates = + public: math::SphericalCoordinates sphericalCoordinates = math::SphericalCoordinates(); }; @@ -87,7 +87,7 @@ Dem::~Dem() ////////////////////////////////////////////////// void Dem::SetSphericalCoordinates( - const math::SphericalCoordinates _worldSphericalCoordinates) + const math::SphericalCoordinates &_worldSphericalCoordinates) { this->dataPtr->sphericalCoordinates =_worldSphericalCoordinates; } @@ -320,10 +320,10 @@ bool Dem::GeoReference(double _x, double _y, auto sourceCs = this->dataPtr->dataSet->GetSpatialRef(); OGRSpatialReference targetCs = OGRSpatialReference(); - const char* MOON_LAT_LON_PROJ_STR = + std::string moonLatLongProjStr = "+proj=latlong +a=1737400 +b=1737400"; - targetCs.importFromProj4(MOON_LAT_LON_PROJ_STR); + targetCs.importFromProj4(moonLatLongProjStr.c_str()); cT = OGRCreateCoordinateTransformation( sourceCs, &targetCs); @@ -339,19 +339,15 @@ bool Dem::GeoReference(double _x, double _y, double axisPolar = this->dataPtr->sphericalCoordinates.SurfaceAxisPolar(); - std::string CUSTOM_SURFACE_LAT_LON_PROJ_STR = + std::string customSurfaceLatLongProjStr = "+proj=latlong +a=" + std::to_string(axisEquatorial) + " +b=" + std::to_string(axisPolar); - targetCs.importFromProj4(CUSTOM_SURFACE_LAT_LON_PROJ_STR.c_str()); + targetCs.importFromProj4(customSurfaceLatLongProjStr.c_str()); cT = OGRCreateCoordinateTransformation( sourceCs, &targetCs); } - else - { - gzerr << "Unsupported spherical coordinates found" << std::endl; - } if (nullptr == cT) { From 97b1c6d154d8b90bfcb76c5d68ffbddd81171e2e Mon Sep 17 00:00:00 2001 From: Aditya Date: Fri, 15 Jul 2022 12:40:56 -0700 Subject: [PATCH 10/13] Updated comments, codecov Signed-off-by: Aditya --- geospatial/include/gz/common/geospatial/Dem.hh | 14 ++------------ geospatial/src/Dem.cc | 14 ++------------ geospatial/src/Dem_TEST.cc | 8 -------- 3 files changed, 4 insertions(+), 32 deletions(-) diff --git a/geospatial/include/gz/common/geospatial/Dem.hh b/geospatial/include/gz/common/geospatial/Dem.hh index a121646ee..ac4efd4b9 100644 --- a/geospatial/include/gz/common/geospatial/Dem.hh +++ b/geospatial/include/gz/common/geospatial/Dem.hh @@ -57,16 +57,6 @@ namespace gz /// \return 0 when the operation succeeds to open a file. public: int Load(const std::string &_filename = ""); - /// \brief Indicate that the coordinate system of the DEM is unknown. - /// \param[in] _isUnknownDem True if the coordinate system - /// is unknown, otherwise false. - public: void SetUnknownDEM(bool _isUnknownDem); - - /// \brief Check if the loaded DEM has an unknown coordinate system. - /// \return True if the loaded DEM has an unknown coordinate system, - /// otherwise false. - public: bool UnknownDEM(); - /// \brief Get the elevation of a terrain's point in meters. /// \param[in] _x X coordinate of the terrain. /// \param[in] _y Y coordinate of the terrain. @@ -83,7 +73,7 @@ namespace gz public: float MaxElevation() const override; /// \brief Get the georeferenced coordinates (lat, long) of the terrain's - /// origin in WGS84. + /// origin. /// \param[out] _latitude Georeferenced latitude. /// \param[out] _longitude Georeferenced longitude. /// \return True if able to retrieve origin coordinates. False otherwise. @@ -134,7 +124,7 @@ namespace gz std::vector &_heights) const override; /// \brief Get the georeferenced coordinates (lat, long) of a terrain's - /// pixel in WGS84. + /// pixel. /// \param[in] _x X coordinate of the terrain. /// \param[in] _y Y coordinate of the terrain. /// \param[out] _latitude Georeferenced latitude. diff --git a/geospatial/src/Dem.cc b/geospatial/src/Dem.cc index 7c26885f5..a3afd94cb 100644 --- a/geospatial/src/Dem.cc +++ b/geospatial/src/Dem.cc @@ -92,18 +92,6 @@ void Dem::SetSphericalCoordinates( this->dataPtr->sphericalCoordinates =_worldSphericalCoordinates; } -////////////////////////////////////////////////// -void Dem::SetUnknownDEM(bool _isUnknownDem) -{ - this->dataPtr->isUnknownDem = _isUnknownDem; -} - -////////////////////////////////////////////////// -bool Dem::UnknownDEM() -{ - return this->dataPtr->isUnknownDem; -} - ////////////////////////////////////////////////// int Dem::Load(const std::string &_filename) { @@ -307,8 +295,10 @@ bool Dem::GeoReference(double _x, double _y, = strdup(this->dataPtr->dataSet->GetProjectionRef()); if (importString == nullptr || importString[0] == '\0') { + // LCOV_EXCL_START gzdbg << "Projection coordinate system undefined." << std::endl; return false; + // LCOV_EXCL_STOP } sourceCs.importFromWkt(&importString); targetCs.SetWellKnownGeogCS("WGS84"); diff --git a/geospatial/src/Dem_TEST.cc b/geospatial/src/Dem_TEST.cc index 99a8401c9..17fe62af5 100644 --- a/geospatial/src/Dem_TEST.cc +++ b/geospatial/src/Dem_TEST.cc @@ -257,14 +257,6 @@ TEST_F(DemTest, UnknownDem) // unable to get coordinates in WGS84 gz::math::Angle latitude, longitude; EXPECT_FALSE(dem.GeoReferenceOrigin(latitude, longitude)); - - // The Load() method in Dem.cc should set the - // isUnknownDEM flag. - EXPECT_TRUE(dem.UnknownDEM()); - - // This flag can be overridden externally. - dem.SetUnknownDEM(false); - EXPECT_FALSE(dem.UnknownDEM()); } TEST_F(DemTest, LunarDemLoad) From 8ce52da1deb90e97b27922f04cf1f34c4eb19256 Mon Sep 17 00:00:00 2001 From: Aditya Date: Fri, 15 Jul 2022 15:55:32 -0700 Subject: [PATCH 11/13] Minor refactoring Signed-off-by: Aditya --- geospatial/src/Dem.cc | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/geospatial/src/Dem.cc b/geospatial/src/Dem.cc index a3afd94cb..0159d44a2 100644 --- a/geospatial/src/Dem.cc +++ b/geospatial/src/Dem.cc @@ -284,12 +284,12 @@ bool Dem::GeoReference(double _x, double _y, { OGRCoordinateTransformation *cT = nullptr; double xGeoDeg, yGeoDeg; + OGRSpatialReference sourceCs; + OGRSpatialReference targetCs; if (this->dataPtr->sphericalCoordinates.Surface() == math::SphericalCoordinates::EARTH_WGS84) { - OGRSpatialReference sourceCs; - OGRSpatialReference targetCs; // Transform the terrain's coordinate system to WGS84 const char *importString = strdup(this->dataPtr->dataSet->GetProjectionRef()); @@ -302,27 +302,23 @@ bool Dem::GeoReference(double _x, double _y, } sourceCs.importFromWkt(&importString); targetCs.SetWellKnownGeogCS("WGS84"); - cT = OGRCreateCoordinateTransformation(&sourceCs, &targetCs); } else if (this->dataPtr->sphericalCoordinates.Surface() == math::SphericalCoordinates::MOON_SCS) { - auto sourceCs = this->dataPtr->dataSet->GetSpatialRef(); - OGRSpatialReference targetCs = OGRSpatialReference(); + sourceCs = *(this->dataPtr->dataSet->GetSpatialRef()); + targetCs = OGRSpatialReference(); std::string moonLatLongProjStr = "+proj=latlong +a=1737400 +b=1737400"; targetCs.importFromProj4(moonLatLongProjStr.c_str()); - - cT = OGRCreateCoordinateTransformation( - sourceCs, &targetCs); } else if (this->dataPtr->sphericalCoordinates.Surface() == math::SphericalCoordinates::CUSTOM_SURFACE) { - auto sourceCs = this->dataPtr->dataSet->GetSpatialRef(); - OGRSpatialReference targetCs = OGRSpatialReference(); + sourceCs = *(this->dataPtr->dataSet->GetSpatialRef()); + targetCs = OGRSpatialReference(); double axisEquatorial = this->dataPtr->sphericalCoordinates.SurfaceAxisEquatorial(); @@ -334,11 +330,10 @@ bool Dem::GeoReference(double _x, double _y, " +b=" + std::to_string(axisPolar); targetCs.importFromProj4(customSurfaceLatLongProjStr.c_str()); - - cT = OGRCreateCoordinateTransformation( - sourceCs, &targetCs); } + cT = OGRCreateCoordinateTransformation(&sourceCs, &targetCs); + if (nullptr == cT) { gzerr << "Unable to transform terrain coordinate system for " From 870144e878127e90613987ded10691ca3e84a98a Mon Sep 17 00:00:00 2001 From: Aditya Date: Wed, 20 Jul 2022 17:44:49 -0700 Subject: [PATCH 12/13] Use moon a,b instead of radius Signed-off-by: Aditya --- geospatial/src/Dem.cc | 2 +- geospatial/src/Dem_TEST.cc | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/geospatial/src/Dem.cc b/geospatial/src/Dem.cc index 0159d44a2..f13409ea9 100644 --- a/geospatial/src/Dem.cc +++ b/geospatial/src/Dem.cc @@ -310,7 +310,7 @@ bool Dem::GeoReference(double _x, double _y, targetCs = OGRSpatialReference(); std::string moonLatLongProjStr = - "+proj=latlong +a=1737400 +b=1737400"; + "+proj=latlong +a=1738100 +b=1736000"; targetCs.importFromProj4(moonLatLongProjStr.c_str()); } diff --git a/geospatial/src/Dem_TEST.cc b/geospatial/src/Dem_TEST.cc index 17fe62af5..f51c1045a 100644 --- a/geospatial/src/Dem_TEST.cc +++ b/geospatial/src/Dem_TEST.cc @@ -275,8 +275,8 @@ TEST_F(DemTest, LunarDemLoad) // Use custom spherical coordinates object with same axes as the moon. auto customSc = math::SphericalCoordinates( math::SphericalCoordinates::CUSTOM_SURFACE, - moonSc.SurfaceRadius(), - moonSc.SurfaceRadius()); + moonSc.SurfaceAxisEquatorial(), + moonSc.SurfaceAxisPolar()); dem.SetSphericalCoordinates(customSc); EXPECT_EQ(dem.Load(path), 0); EXPECT_NEAR(dem.WorldWidth(), 80.0417, 1e-2); From ba01d65f784848e8e5735affb3f97b8be8a2760e Mon Sep 17 00:00:00 2001 From: Aditya Date: Thu, 21 Jul 2022 12:48:37 -0700 Subject: [PATCH 13/13] Minor refactor Signed-off-by: Aditya --- geospatial/src/Dem.cc | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/geospatial/src/Dem.cc b/geospatial/src/Dem.cc index f13409ea9..4595f3baa 100644 --- a/geospatial/src/Dem.cc +++ b/geospatial/src/Dem.cc @@ -303,19 +303,10 @@ bool Dem::GeoReference(double _x, double _y, sourceCs.importFromWkt(&importString); targetCs.SetWellKnownGeogCS("WGS84"); } - else if (this->dataPtr->sphericalCoordinates.Surface() == - math::SphericalCoordinates::MOON_SCS) - { - sourceCs = *(this->dataPtr->dataSet->GetSpatialRef()); - targetCs = OGRSpatialReference(); - - std::string moonLatLongProjStr = - "+proj=latlong +a=1738100 +b=1736000"; - - targetCs.importFromProj4(moonLatLongProjStr.c_str()); - } - else if (this->dataPtr->sphericalCoordinates.Surface() == - math::SphericalCoordinates::CUSTOM_SURFACE) + else if ((this->dataPtr->sphericalCoordinates.Surface() == + math::SphericalCoordinates::CUSTOM_SURFACE) || + (this->dataPtr->sphericalCoordinates.Surface() == + math::SphericalCoordinates::MOON_SCS)) { sourceCs = *(this->dataPtr->dataSet->GetSpatialRef()); targetCs = OGRSpatialReference(); @@ -325,11 +316,11 @@ bool Dem::GeoReference(double _x, double _y, double axisPolar = this->dataPtr->sphericalCoordinates.SurfaceAxisPolar(); - std::string customSurfaceLatLongProjStr = + std::string surfaceLatLongProjStr = "+proj=latlong +a=" + std::to_string(axisEquatorial) + " +b=" + std::to_string(axisPolar); - targetCs.importFromProj4(customSurfaceLatLongProjStr.c_str()); + targetCs.importFromProj4(surfaceLatLongProjStr.c_str()); } cT = OGRCreateCoordinateTransformation(&sourceCs, &targetCs);