Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

using boost::geometry to convert from Latitude and longitude to UTM

boost::geometry seems to have support to convert from lat/lon to UTM. Unfortunately I couldn't find any example on how exactly to do that. Does someone have an example they are willing to share?

like image 835
jpo234 Avatar asked Sep 20 '25 20:09

jpo234


2 Answers

I just spent an embarrassing amount of time looking for this (multiple hours).

It seems like everything spherical (SRS) is just ... not documented at all. Perhaps there's something broken with the documentation generator.

Regardless, several tedious searches through test code further I stumbled on a working answer.

Here's examples

  • Amsterdam (UTM 629144.77 Easting 5803996.66 Northing in zone 31U)
  • Barcelona (UTM 430887.56 Easting, 4581837.85 Northing, zone 31T)

With even more stumbling I found the corresponding EPSG code on https://epsg.io/?q=UTM+31N: enter image description here

Live On Compiler Explorer

#include <iostream>
#include <boost/geometry.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/geometries/point_xy.hpp>

#include <boost/geometry/srs/epsg.hpp>
#ifdef COLIRU
#include <boost/geometry/srs/projection.hpp>
#endif

namespace bg = boost::geometry;
namespace bm = bg::model::d2;
namespace srs = bg::srs;

using LongLat = bm::point_xy<double, bg::cs::geographic<bg::degree> >;
using UTM     = bm::point_xy<double/*, srs::static_epsg<3043>*/>;

constexpr LongLat Amsterdam() { return { 4.897, 52.371}; }
constexpr LongLat Barcelona() { return { 2.1734, 41.3851 }; }

void report(LongLat src, auto const& prj) {
    UTM r {};
    prj.forward(src, r);
    std::cout << std::fixed << bg::wkt(src) << " -> " << bg::wkt(r) << "\n";
}

int main() {
#ifndef COLIRU
    // dynamic projection factory too heavy on Coliru
    srs::projection<> zone31 = srs::proj4("+proj=utm +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5 +zone=31");
    report(Amsterdam(), zone31);
    report(Barcelona(), zone31);
#endif

    srs::projection<srs::static_epsg<3043> > epsg3043;
    report(Amsterdam(), epsg3043);
    report(Barcelona(), epsg3043);
}

Prints

POINT(4.897000 52.371000) -> POINT(629144.771310 5803996.656944)
POINT(2.173400 41.385100) -> POINT(430887.564331 4581837.853239)
POINT(4.897000 52.371000) -> POINT(629144.771310 5803996.656944)
POINT(2.173400 41.385100) -> POINT(430887.564331 4581837.853239)

Disclaimer:

I'm not actually convinced that the UTM point type I defined makes much sense. I think any point type that can receive 2 coordinates will do. At least the srs::... as the coordinate system doesn't seem to do anything - bg::convert, bg::assign and friends don't magically know how to apply the projection anyways. I think the "doxygen_z_article09" link you included is just badly out of date/not how things were eventually implemented.

like image 146
sehe Avatar answered Sep 22 '25 11:09

sehe


I have some minor modifications to the answer from @sehe to make it compile with VS 2019/C++14:

#include <boost/geometry.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <iostream>

#include <boost/geometry/srs/epsg.hpp>
#ifdef COLIRU
#include <boost/geometry/srs/projection.hpp>
#endif

namespace bg  = boost::geometry;
namespace bm  = bg::model::d2;
namespace srs = bg::srs;

using LongLat = bm::point_xy<double, bg::cs::geographic<bg::degree>>;
using UTM     = bm::point_xy<double /*, srs::static_epsg<3043>*/>;

LongLat Barcelona{2.1734, 41.3851};
LongLat Amsterdam{4.897, 52.371};

template <typename T> void report(LongLat src, T const &prj) {
    UTM r{};
    prj.forward(src, r);
    std::cout << std::fixed << bg::wkt(src) << " -> " << bg::wkt(r) << "\n";
}

int main() {
#ifndef COLIRU
    // dynamic projection factory too heavy on Coliru
    srs::projection<> zone31 = srs::proj4("+proj=utm +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5 +zone=31");
    report(Amsterdam, zone31);
    report(Barcelona, zone31);
#endif

    srs::projection<srs::static_epsg<3043>> epsg3043;
    report(Amsterdam, epsg3043);
    report(Barcelona, epsg3043);
}
like image 42
jpo234 Avatar answered Sep 22 '25 10:09

jpo234



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!