KOSMIndoorMap

geomath.cpp
1 /*
2  SPDX-FileCopyrightText: 2020 Volker Krause <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6 
7 #include "geomath.h"
8 
9 #include <QLineF>
10 
11 #include <cmath>
12 #include <limits>
13 
14 using namespace OSM;
15 
16 // see https://en.wikipedia.org/wiki/Haversine_formula
17 double OSM::distance(double lat1, double lon1, double lat2, double lon2)
18 {
19  constexpr const auto earthRadius = 6371000.0; // in meters
20 
21  const auto d_lat = degToRad(lat1 - lat2);
22  const auto d_lon = degToRad(lon1 - lon2);
23 
24  const auto a = pow(sin(d_lat / 2.0), 2) + cos(degToRad(lat1)) * cos(degToRad(lat2)) * pow(sin(d_lon / 2.0), 2);
25  return 2.0 * earthRadius * atan2(sqrt(a), sqrt(1.0 - a));
26 }
27 
28 double OSM::distance(Coordinate coord1, Coordinate coord2)
29 {
30  return distance(coord1.latF(), coord1.lonF(), coord2.latF(), coord2.lonF());
31 }
32 
34 {
35  QLineF line(l1.lonF(), l1.latF(), l2.lonF(), l2.latF());
36  const auto len = line.length();
37  if (len == 0.0) {
38  return OSM::distance(l1, p);
39  }
40 
41  // project p on a line extending the line segment given by @p l1 and @p l2, and clamp to that to the segment
42  QPointF pf(p.lonF(), p.latF());
43  const auto r = qBound(0.0, QPointF::dotProduct(pf - line.p1(), line.p2() - line.p1()) / (len*len), 1.0);
44  const auto intersection = line.p1() + r * (line.p2() - line.p1());
45  return OSM::distance(OSM::Coordinate(intersection.y(), intersection.x()), p);
46 }
47 
48 double OSM::distance(const std::vector<const OSM::Node*> &path, OSM::Coordinate coord)
49 {
50  if (path.empty()) {
51  return std::numeric_limits<double>::max();
52  }
53 
54  if (path.size() == 1) {
55  return distance(path[0]->coordinate, coord);
56  }
57 
58  auto dist = std::numeric_limits<double>::max();
59  OSM::Id firstNode = 0;
60  for (auto it = path.begin(); it != std::prev(path.end()) && it != path.end(); ++it) {
61  const auto nextIt = std::next(it);
62  if (firstNode == 0) { // starting a new loop
63  firstNode = (*it)->id;
64  }
65 
66  // compute distance between line segment and coord
67  dist = std::min(dist, OSM::distance((*it)->coordinate, (*nextIt)->coordinate, coord));
68 
69  if ((*nextIt)->id == firstNode) { // just closed a loop, so this is not a line on the path
70  firstNode = 0;
71  ++it;
72  }
73  }
74  return dist;
75 }
Coordinate, stored as 1e7 * degree to avoid floating point precision issues, and offset to unsigned v...
Definition: datatypes.h:37
qreal length() const const
constexpr double degToRad(double deg)
Degree to radian conversion.
Definition: geomath.h:19
int64_t Id
OSM element identifier.
Definition: datatypes.h:27
qreal dotProduct(const QPointF &p1, const QPointF &p2)
KOSM_EXPORT double distance(double lat1, double lon1, double lat2, double lon2)
Distance between two coordinates.
Definition: geomath.cpp:17
Low-level types and functions to work with raw OSM data as efficiently as possible.
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Tue Oct 19 2021 23:05:46 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.