Welcome to mirror list, hosted at ThFree Co, Russian Federation.

mercator.hpp « geometry - github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: d3e8270e2c148fa71569cda230f69c59aaf3d317 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#pragma once

#include "geometry/latlon.hpp"
#include "geometry/point2d.hpp"
#include "geometry/rect2d.hpp"

#include "base/math.hpp"

struct MercatorBounds
{
  static double constexpr kMinX = -180.0;
  static double constexpr kMaxX = 180.0;
  static double constexpr kMinY = -180.0;
  static double constexpr kMaxY = 180.0;
  static double constexpr kRangeX = kMaxX - kMinX;
  static double constexpr kRangeY = kMaxY - kMinY;

  static m2::RectD FullRect() { return m2::RectD(kMinX, kMinY, kMaxX, kMaxY); }

  static bool ValidLon(double d) { return base::between_s(-180.0, 180.0, d); }
  static bool ValidLat(double d) { return base::between_s(-90.0, 90.0, d); }

  static bool ValidX(double d) { return base::between_s(kMinX, kMaxX, d); }
  static bool ValidY(double d) { return base::between_s(kMinY, kMaxY, d); }

  static double ClampX(double d) { return base::clamp(d, kMinX, kMaxX); }
  static double ClampY(double d) { return base::clamp(d, kMinY, kMaxY); }

  static double YToLat(double y) { return base::RadToDeg(2.0 * atan(tanh(0.5 * base::DegToRad(y)))); }

  static double LatToY(double lat)
  {
    double const sinx = sin(base::DegToRad(base::clamp(lat, -86.0, 86.0)));
    double const res = base::RadToDeg(0.5 * log((1.0 + sinx) / (1.0 - sinx)));
    return ClampY(res);
  }

  static double XToLon(double x) { return x; }

  static double LonToX(double lon) { return lon; }

  static double constexpr degreeInMetres = 360.0 / 40008245;

  /// @name Get rect for center point (lon, lat) and dimensions in metres.
  //@{
  /// @return mercator rect.
  static m2::RectD MetresToXY(double lon, double lat, double lonMetresR, double latMetresR);

  static m2::RectD MetresToXY(double lon, double lat, double metresR)
  {
    return MetresToXY(lon, lat, metresR, metresR);
  }
  //@}

  static m2::RectD RectByCenterXYAndSizeInMeters(double centerX, double centerY, double sizeX,
                                                 double sizeY)
  {
    ASSERT_GREATER_OR_EQUAL(sizeX, 0, ());
    ASSERT_GREATER_OR_EQUAL(sizeY, 0, ());

    return MetresToXY(XToLon(centerX), YToLat(centerY), sizeX, sizeY);
  }

  static m2::RectD RectByCenterXYAndSizeInMeters(m2::PointD const & center, double size)
  {
    return RectByCenterXYAndSizeInMeters(center.x, center.y, size, size);
  }

  static m2::RectD RectByCenterXYAndOffset(m2::PointD const & center, double offset)
  {
    return {ClampX(center.x - offset), ClampY(center.y - offset),
            ClampX(center.x + offset), ClampY(center.y + offset)};
  }

  static m2::PointD GetSmPoint(m2::PointD const & pt, double lonMetresR, double latMetresR);

  static m2::PointD FromLatLon(double lat, double lon)
  {
    return m2::PointD(LonToX(lon), LatToY(lat));
  }

  static m2::PointD FromLatLon(ms::LatLon const & point)
  {
    return FromLatLon(point.lat, point.lon);
  }

  static m2::RectD RectByCenterLatLonAndSizeInMeters(double lat, double lon, double size)
  {
    return RectByCenterXYAndSizeInMeters(FromLatLon(lat, lon), size);
  }

  static ms::LatLon ToLatLon(m2::PointD const & point)
  {
    return {YToLat(point.y), XToLon(point.x)};
  }

  /// Converts lat lon rect to mercator one
  static m2::RectD FromLatLonRect(m2::RectD const & latLonRect)
  {
    return m2::RectD(FromLatLon(latLonRect.minY(), latLonRect.minX()),
                     FromLatLon(latLonRect.maxY(), latLonRect.maxX()));
  }

  static m2::RectD ToLatLonRect(m2::RectD const & mercatorRect)
  {
    return m2::RectD(YToLat(mercatorRect.minY()), XToLon(mercatorRect.minX()),
                     YToLat(mercatorRect.maxY()), XToLon(mercatorRect.maxX()));
  }

  /// Calculates distance on Earth in meters between two mercator points.
  static double DistanceOnEarth(m2::PointD const & p1, m2::PointD const & p2);

  /// Calculates area of a triangle on Earth in m² by three mercator points.
  static double AreaOnEarth(m2::PointD const & p1, m2::PointD const & p2, m2::PointD const & p3);
};