Skip to content

Commit

Permalink
First commit
Browse files Browse the repository at this point in the history
  • Loading branch information
joto committed Apr 20, 2020
0 parents commit dadfe0f
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 0 deletions.
23 changes: 23 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
Boost Software License - Version 1.0 - August 17th, 2003

Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:

The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.

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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Projection class for Libosmium

This repository contains code for projecting OSM locations to arbitrary
coordinate reference systems. It is based on the PROJ library. Unlike
the code which is included in libosmium which only supports older
PROJ versions, this one is for PROJ version 6 and above.

**This is untested code just provided as a starting point, because libosmium
doesn't support PROJ 6 and above.**

To use this include `projection.hpp` in your program and instantiate the
`osmium::geom::GeometryFactory` class with the class `PROJ_Projection` as
template parameter. See the libosmium documentation for details of how to
use the `GeometryFactory` class.

You need to compile with `libproj`.

100 changes: 100 additions & 0 deletions projection.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#once

#include <osmium/geom/coordinates.hpp>
#include <osmium/geom/mercator_projection.hpp>
#include <osmium/geom/util.hpp>
#include <osmium/osm/location.hpp>

#include <proj.h>

#include <cassert>
#include <memory>
#include <string>


/**
* Functor that does projection from WGS84 (EPSG:4326) to the given
* CRS.
*
* If this Projection is initialized with the constructor taking
* an integer with the epsg code 4326, no projection is done. If it
* is initialized with epsg code 3857 the Osmium-internal
* implementation of the Mercator projection is used, otherwise this
* falls back to using the PROJ library. Note that this "magic" does
* not work if you use any of the constructors taking a string.
*/
class PROJ_Projection {

struct ProjDestroyer {
void operator()(PJ* crs) {
proj_destroy(crs);
}
}; // struct ProjDestroyer

std::string m_proj_string;
std::unique_ptr<PJ, ProjDestroyer> m_proj;
int m_epsg = -1;

PJ* make_proj(const char* to_crs) {
PJ* p = proj_create_crs_to_crs(PJ_DEFAULT_CTX,
"EPSG:4326", to_crs,
nullptr);
if (p) {
return p;
}

throw osmium::projection_error{std::string{"Creating PROJ projection failed: "} +
proj_errno_string(proj_errno(p))};
}

public:

explicit Projection(const char* proj_string) :
m_proj_string(proj_string),
m_proj(make_proj(proj_string)) {
}

explicit Projection(const std::string& proj_string) :
Projection(proj_string.c_str()) {
}

explicit Projection(int epsg) :
m_proj_string(std::string{"EPSG:"} + std::to_string(epsg)),
m_proj((epsg == 4326 || epsg == 3857) ? nullptr
: make_proj(m_proj_string.c_str())),
m_epsg(epsg) {
}

/**
* Do coordinate transformation.
*
* @pre Location must be in valid range (depends on projection used).
*/
Coordinates operator()(osmium::Location location) const {
if (m_epsg == 4326) {
return Coordinates{location.lon(), location.lat()};
}

if (m_epsg == 3857) {
return Coordinates{detail::lon_to_x(location.lon()),
detail::lat_to_y(location.lat())};
}

PJ_COORD from;
from.lpzt.z = 0.0;
from.lpzt.t = HUGE_VAL;
from.lpzt.lam = location.lon();
from.lpzt.phi = location.lat();

assert(m_proj);
PJ_COORD to = proj_trans(m_proj.get(), PJ_FWD, from);

return Coordinates{to.xy.x, to.xy.y};
}

int epsg() const noexcept {
return m_epsg;
}

}; // class PROJ_Projection

0 comments on commit dadfe0f

Please sign in to comment.