Skip to content

Commit

Permalink
Issue Framstag#1045 - Update projection
Browse files Browse the repository at this point in the history
- Added simple Earth object to centralize some constants
- Changed enum type of LaneTurn
- Centralized gradtorad constant
  • Loading branch information
Framstag authored and DerKleinePunk committed Jul 16, 2023
1 parent 38b2f4c commit 319b378
Show file tree
Hide file tree
Showing 9 changed files with 113 additions and 39 deletions.
6 changes: 4 additions & 2 deletions libosmscout/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,11 @@ set(HEADER_FILES_NAVIGATION
include/osmscout/navigation/LaneAgent.h)

set(HEADER_FILES_OST
include/osmscout/ost/Parser.h
include/osmscout/ost/Scanner.h)
include/osmscout/ost/Parser.h
include/osmscout/ost/Scanner.h)

set(HEADER_FILES_PROJECTION
include/osmscout/projection/Earth.h
include/osmscout/projection/MercatorProjection.h
include/osmscout/projection/Projection.h
include/osmscout/projection/TileProjection.h)
Expand Down Expand Up @@ -150,6 +151,7 @@ set(HEADER_FILES_UTIL
set(SOURCE_FILES
src/osmscout/ost/Parser.cpp
src/osmscout/ost/Scanner.cpp
src/osmscout/projection/Earth.cpp
src/osmscout/projection/MercatorProjection.cpp
src/osmscout/projection/Projection.cpp
src/osmscout/projection/TileProjection.cpp
Expand Down
1 change: 1 addition & 0 deletions libosmscout/include/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ osmscoutHeader = [
'osmscout/CoreImportExport.h',
'osmscout/ost/Parser.h',
'osmscout/ost/Scanner.h',
'osmscout/projection/Earth.h',
'osmscout/projection/MercatorProjection.h',
'osmscout/projection/Projection.h',
'osmscout/projection/TileProjection.h',
Expand Down
44 changes: 44 additions & 0 deletions libosmscout/include/osmscout/projection/Earth.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#ifndef OSMSCOUT_PROJECTION_EARTH_H
#define OSMSCOUT_PROJECTION_EARTH_H

/*
This source is part of the libosmscout library
Copyright (C) 2023 Tim Teulings
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

#include <osmscout/CoreImportExport.h>

namespace osmscout {

/**
* Some general information regarding the earth
*
* To make the stack support other planets, too, one would have
* to define a interface base class, from which Earth inherits and
* implements the interface.
*/
class OSMSCOUT_API Earth
{
public:
static const double radiusMeter;
//< Radius of the earth in meter
static const double extentMeter;
//< Extent of the earth in meter
};
}

#endif
4 changes: 4 additions & 0 deletions libosmscout/include/osmscout/system/Math.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,8 @@

#include <cmath>

namespace osmscout {
static const double gradtorad=2*M_PI/360.0;
}

#endif
5 changes: 4 additions & 1 deletion libosmscout/include/osmscout/util/LaneTurn.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

#include <cstddef>
#include <string>

#include <osmscout/CoreImportExport.h>
Expand All @@ -40,8 +41,10 @@ namespace osmscout {
* Note: Numeric values of variants are used for database serialization,
* do not change them without increasing database format version.
* Just append new variants to the end.
*
* Note: There is no need to export Enums
*/
enum class OSMSCOUT_API LaneTurn: char {
enum class LaneTurn: std::uint8_t {
Null = 0,
None = 1,
Left = 2,
Expand Down
1 change: 1 addition & 0 deletions libosmscout/src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
osmscoutSrc = [
'src/osmscout/ost/Parser.cpp',
'src/osmscout/ost/Scanner.cpp',
'src/osmscout/projection/Earth.cpp',
'src/osmscout/projection/MercatorProjection.cpp',
'src/osmscout/projection/Projection.cpp',
'src/osmscout/projection/TileProjection.cpp',
Expand Down
37 changes: 37 additions & 0 deletions libosmscout/src/osmscout/projection/Earth.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
This source is part of the libosmscout library
Copyright (C) 2023 Tim Teulings
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

#include <osmscout/projection/Earth.h>

#include <osmscout/system/Math.h>

namespace osmscout {

/*
* For the calculations here see:
* http://en.wikipedia.org/wiki/Mercator_projection
* http://en.wikipedia.org/wiki/Web_Mercator
* http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
*/

//< Radius of the earth in meter
const double Earth::radiusMeter=6'378'137.0;
//< Extent of the earth in meter
const double Earth::extentMeter=2*M_PI*Earth::radiusMeter;
}
28 changes: 11 additions & 17 deletions libosmscout/src/osmscout/projection/MercatorProjection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@

#include <algorithm>

#include <osmscout/projection/Earth.h>

#include <osmscout/system/Assert.h>
#include <osmscout/system/Math.h>

Expand All @@ -37,12 +39,6 @@ namespace osmscout {
* http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
*/

//< Radius of the earth in meter
static const double earthRadiusMeter=6'378'137.0;
//< Extent of the earth in meter
static const double earthExtentMeter=2*M_PI*earthRadiusMeter;
//< Width of a tile at the equator for zoom level 0 in meter (equal to extent of the earth at the equator
static const double tileWidthZoom0Aquator=earthExtentMeter;
//< DPI of a classical OSM tile
static const double tileDPI=96.0;

Expand All @@ -55,8 +51,6 @@ namespace osmscout {
static const ALIGN16_BEG double sseGradtorad[] ALIGN16_END = {2*M_PI/360, 2*M_PI/360};
#endif

static const double gradtorad=2*M_PI/360;

bool MercatorProjection::Set(const GeoCoord& coord,
double angle,
const Magnification& magnification,
Expand Down Expand Up @@ -89,8 +83,8 @@ namespace osmscout {
this->height=height;

if (angle!=0.0) {
angleSin=::sin(angle);
angleCos=::cos(angle);
angleSin=std::sin(angle);
angleCos=std::cos(angle);
angleNegSin=-angleSin;
angleNegCos=angleCos;
}
Expand All @@ -102,7 +96,7 @@ namespace osmscout {
}

// Width in meter of a tile of the given magnification at the equator
double equatorTileWidth=tileWidthZoom0Aquator/magnification.GetMagnification();
double equatorTileWidth=Earth::extentMeter/magnification.GetMagnification();

// Resolution (meter/pixel) of a pixel in a classical 256 pixel tile for the given zoom level at the equator
double equatorTileResolution=equatorTileWidth/256.0;
Expand All @@ -114,10 +108,10 @@ namespace osmscout {
double groundWidthEquatorMeter=width*equatorCorrectedEquatorTileResolution;

// Width of the visible area in meter
double groundWidthVisibleMeter=groundWidthEquatorMeter*::cos(lat*gradtorad);
double groundWidthVisibleMeter=groundWidthEquatorMeter*std::cos(lat*gradtorad);

// Resulting projection scale factor
scale=width/(2*M_PI*groundWidthEquatorMeter/earthExtentMeter);
scale=width/(2*M_PI*groundWidthEquatorMeter/Earth::extentMeter);
scaleGradtorad=scale*gradtorad;

// Size of one pixel in meter
Expand All @@ -130,7 +124,7 @@ namespace osmscout {
meterInMM=meterInPixel*25.4/dpi;

// Absolute Y mercator coordinate for latitude
latOffset=::atanh(::sin(coord.GetLat()*gradtorad));
latOffset=std::atanh(std::sin(coord.GetLat()*gradtorad));

GeoCoord topLeft;

Expand Down Expand Up @@ -160,7 +154,7 @@ namespace osmscout {
std::max(bottomLeft.GetLon(),bottomRight.GetLon())));

// derivation of "latToYPixel" function in projection center
double latDeriv = 1.0 / ::sin( (2 * this->lat * gradtorad + M_PI) / 2);
double latDeriv = 1.0 / std::sin( (2 * this->lat * gradtorad + M_PI) / 2);
scaledLatDeriv = latDeriv * gradtorad * scale;

return true;
Expand All @@ -184,7 +178,7 @@ namespace osmscout {
}

// Transform to absolute geo coordinate
coord.Set(::atan(::sinh(y/scale+latOffset))/gradtorad,
coord.Set(std::atan(std::sinh(y/scale+latOffset))/gradtorad,
this->lon+x/scaleGradtorad);

return IsValidFor(coord);
Expand All @@ -207,7 +201,7 @@ namespace osmscout {
// For values outside this range is better to result projection border
// than some invalid coordinate, like INFINITY
double lat = std::min(std::max(coord.GetLat(), MinLat), MaxLat);
y=(::atanh(::sin(lat*gradtorad))-latOffset)*scale;
y=(std::atanh(std::sin(lat*gradtorad))-latOffset)*scale;
}

if (angle!=0.0) {
Expand Down
26 changes: 7 additions & 19 deletions libosmscout/src/osmscout/projection/TileProjection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

#include <osmscout/projection/TileProjection.h>

#include <osmscout/projection/Earth.h>

#include <osmscout/system/Assert.h>
#include <osmscout/system/Math.h>

Expand All @@ -34,20 +36,6 @@ namespace osmscout {
static const ALIGN16_BEG double sseGradtorad[] ALIGN16_END = {2*M_PI/360, 2*M_PI/360};
#endif

/*
* For the calculations here see:
* http://en.wikipedia.org/wiki/Mercator_projection
* http://en.wikipedia.org/wiki/Web_Mercator
* http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
*/

//< Radius of the earth in meter
static const double earthRadiusMeter=6'378'137.0;
//< Extent of the earth in meter
static const double earthExtentMeter=2*M_PI*earthRadiusMeter;

static const double gradtorad=2*M_PI/360;

bool TileProjection::SetInternal(double lonMin,double latMin,
double lonMax,double latMax,
const Magnification& magnification,
Expand Down Expand Up @@ -86,14 +74,14 @@ namespace osmscout {
scaleGradtorad = scale * gradtorad;

lonOffset=lonMin*scaleGradtorad;
latOffset=scale*::atanh(::sin(latMin*gradtorad));
latOffset=scale*std::atanh(std::sin(latMin*gradtorad));

pixelSize=earthExtentMeter/magnification.GetMagnification()/width;
pixelSize=Earth::extentMeter/magnification.GetMagnification()/width;
meterInPixel=1/pixelSize;
meterInMM=meterInPixel*25.4/pixelSize;

// derivation of "latToYPixel" function in projection center
double latDeriv = 1.0 / ::sin( (2 * this->lat * gradtorad + M_PI) / 2);
double latDeriv = 1.0 / std::sin( (2 * this->lat * gradtorad + M_PI) / 2);
scaledLatDeriv = latDeriv * gradtorad * scale;

#ifdef OSMSCOUT_HAVE_SSE2
Expand Down Expand Up @@ -142,7 +130,7 @@ namespace osmscout {
bool TileProjection::PixelToGeo(double x, double y,
GeoCoord& coord) const
{
coord.Set(::atan(::sinh((height-y+latOffset)/scale))/gradtorad,
coord.Set(std::atan(std::sinh((height-y+latOffset)/scale))/gradtorad,
(x+lonOffset)/(scale*gradtorad));

return IsValidFor(coord);
Expand Down Expand Up @@ -187,7 +175,7 @@ namespace osmscout {
y=(height/2.0)-((coord.GetLat()-this->lat)*scaledLatDeriv);
}
else {
y=height-(scale*::atanh(::sin(coord.GetLat()*gradtorad))-latOffset);
y=height-(scale*std::atanh(std::sin(coord.GetLat()*gradtorad))-latOffset);
}

pixel=Vertex2D(x,y);
Expand Down

0 comments on commit 319b378

Please sign in to comment.