1 /****************************************************************************
2 **
3 ** Qt adaptation of geosimplify.js, https://github.com/mapbox/geosimplify-js, (c) 2017, Mapbox
4 **
5 ** Copyright (C) 2020 Paolo Angelelli <paolo.angelelli@gmail.com>
6 ** Copyright (C) 2020 The Qt Company Ltd.
7 ** Contact: http://www.qt.io/licensing/
8 **
9 ** This file is part of the QtLocation module of the Qt Toolkit.
10 **
11 ** $QT_BEGIN_LICENSE:LGPL3$
12 ** Commercial License Usage
13 ** Licensees holding valid commercial Qt licenses may use this file in
14 ** accordance with the commercial license agreement provided with the
15 ** Software or, alternatively, in accordance with the terms contained in
16 ** a written agreement between you and The Qt Company. For licensing terms
17 ** and conditions see http://www.qt.io/terms-conditions. For further
18 ** information use the contact form at http://www.qt.io/contact-us.
19 **
20 ** GNU Lesser General Public License Usage
21 ** Alternatively, this file may be used under the terms of the GNU Lesser
22 ** General Public License version 3 as published by the Free Software
23 ** Foundation and appearing in the file LICENSE.LGPLv3 included in the
24 ** packaging of this file. Please review the following information to
25 ** ensure the GNU Lesser General Public License version 3 requirements
26 ** will be met: https://www.gnu.org/licenses/lgpl.html.
27 **
28 ** GNU General Public License Usage
29 ** Alternatively, this file may be used under the terms of the GNU
30 ** General Public License version 2.0 or later as published by the Free
31 ** Software Foundation and appearing in the file LICENSE.GPL included in
32 ** the packaging of this file. Please review the following information to
33 ** ensure the GNU General Public License version 2.0 requirements will be
34 ** met: http://www.gnu.org/licenses/gpl-2.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #ifndef QGEOSIMPLIFY_P_H
41 #define QGEOSIMPLIFY_P_H
42 
43 //
44 //  W A R N I N G
45 //  -------------
46 //
47 // This file is not part of the Qt API.  It exists purely as an
48 // implementation detail.  This header file may change from version to
49 // version without notice, or even be removed.
50 //
51 // We mean it.
52 //
53 
54 #include <QtPositioning/QGeoCoordinate>
55 #include <QtPositioning/private/qdoublevector2d_p.h>
56 #include <QtPositioning/private/qwebmercator_p.h>
57 
58 QT_BEGIN_NAMESPACE
59 
60 class QGeoSimplify {
61 protected:
62     // Distance between two points in metres
63     static double getDist(const QGeoCoordinate &p1, const QGeoCoordinate &p2);
64 
65     // p, a and b are intended as "unwrapped" around the left bound
66     static QDoubleVector2D closestPoint( const QDoubleVector2D &p,
67                                   const QDoubleVector2D &a,
68                                   const QDoubleVector2D &b);
69 
70     static QGeoCoordinate closestPoint( const QGeoCoordinate &pc,
71                                  const QGeoCoordinate &ac,
72                                  const QGeoCoordinate &bc,
73                                  const double &leftBound);
74 
75     // Distance from a point to a segment (line between two points) in metres
76     static double getSegDist(const QGeoCoordinate &pc,
77                       const QGeoCoordinate &ac,
78                       const QGeoCoordinate &bc,
79                       const double &leftBound);
80 
81     // doublevectors Intended as wrapped
82     static double getSegDist(const QDoubleVector2D &p,
83                       const QDoubleVector2D &a,
84                       const QDoubleVector2D &b,
85                       const double &leftBound);
86 
87     static void simplifyDPStep(const QList<QGeoCoordinate> &points,
88                         const double &leftBound,
89                         int first,
90                         int last,
91                         double offsetTolerance,
92                         QList<QGeoCoordinate> &simplified);
93 
94     static double getDist(QDoubleVector2D a,
95                    QDoubleVector2D b,
96                    const double &leftBound);
97 
98     static void simplifyDPStep(const QList<QDoubleVector2D> &points,
99                         const double &leftBound,
100                         int first,
101                         int last,
102                         double offsetTolerance,
103                         QList<QDoubleVector2D> &simplified);
104 
105     static void simplifyDPStepZL(const QList<QDoubleVector2D> &points,
106                         const double &leftBound,
107                         int first,
108                         int last,
109                         int zoomLevel,
110                         QList<QDoubleVector2D> &simplified);
111 
112     // simplification using Ramer-Douglas-Peucker algorithm
113     static QList<QGeoCoordinate> simplifyDouglasPeucker(const QList<QGeoCoordinate> &points,
114                                                  const double &leftBound,
115                                                  double offsetTolerance);
116 
117     static QList<QDoubleVector2D> simplifyDouglasPeucker(const QList<QDoubleVector2D> &points,
118                                                  const double &leftBound,
119                                                  double offsetTolerance);
120 
121     static QList<QDoubleVector2D> simplifyDouglasPeuckerZL(const QList<QDoubleVector2D> &points,
122                                                  const double &leftBound,
123                                                  int zoomLevel);
124 
125 public:
126     /*
127         offsetTolerance - how far outside the straight line a point
128                           needs to be for it to be "kept"
129     */
130     static QList<QGeoCoordinate> geoSimplify(const QList<QGeoCoordinate> &points,
131                                    const double &leftBound,
132                                    double offsetTolerance); // in meters
133 
134     static QList<QDoubleVector2D> geoSimplify(const QList<QDoubleVector2D> &points,
135                                    const double &leftBound,
136                                    double offsetTolerance); // in meters
137 
138     // This overload tries to be adaptive in the offsetTolerance across latitudes,
139     // and return a simplification adequate for the given zoomLevel.
140     static QList<QDoubleVector2D> geoSimplifyZL(const QList<QDoubleVector2D> &points,
141                                    const double &leftBound,
142                                    int zoomLevel); // in meters
143 };
144 
145 QT_END_NAMESPACE
146 
147 #endif // QGEOSIMPLIFY_P_H
148