Revision control

++ // Copyright (C) 2016 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
++ // Qt-Security score:significant reason:default
++
++ #ifndef QGEOPATH_P_H
++ #define QGEOPATH_P_H
++
++ //
++ // W A R N I N G
++ // -------------
++ //
++ // This file is not part of the Qt API. It exists purely as an
++ // implementation detail. This header file may change from version to
++ // version without notice, or even be removed.
++ //
++ // We mean it.
++ //
++
++ #include <QtPositioning/private/qpositioningglobal_p.h>
++ #include "qgeoshape_p.h"
++ #include "qgeocoordinate.h"
++ #include "qlocationutils_p.h"
++ #include <QtPositioning/qgeopath.h>
++ #include <QtCore/QList>
++
++ QT_BEGIN_NAMESPACE
++
++ inline static void computeBBox(const QList<QGeoCoordinate> &m_path, QList<double> &m_deltaXs,
++ double &m_minX, double &m_maxX, double &m_minLati, double &m_maxLati,
++ QGeoRectangle &m_bbox)
++ {
++ if (m_path.isEmpty()) {
++ m_deltaXs.clear();
++ m_minX = qInf();
++ m_maxX = -qInf();
++ m_minLati = qInf();
++ m_maxLati = -qInf();
++ m_bbox = QGeoRectangle();
++ return;
++ }
++
++ m_minLati = m_maxLati = m_path.at(0).latitude();
++ qsizetype minId = 0;
++ qsizetype maxId = 0;
++ m_deltaXs.resize(m_path.size());
++ m_deltaXs[0] = m_minX = m_maxX = 0.0;
++
++ for (qsizetype i = 1; i < m_path.size(); i++) {
++ const QGeoCoordinate &geoFrom = m_path.at(i-1);
++ const QGeoCoordinate &geoTo = m_path.at(i);
++ double longiFrom = geoFrom.longitude();
++ double longiTo = geoTo.longitude();
++ double deltaLongi = longiTo - longiFrom;
++ if (qAbs(deltaLongi) > 180.0) {
++ if (longiTo > 0.0)
++ longiTo -= 360.0;
++ else
++ longiTo += 360.0;
++ deltaLongi = longiTo - longiFrom;
++ }
++ m_deltaXs[i] = m_deltaXs[i-1] + deltaLongi;
++ if (m_deltaXs[i] < m_minX) {
++ m_minX = m_deltaXs[i];
++ minId = i;
++ }
++ if (m_deltaXs[i] > m_maxX) {
++ m_maxX = m_deltaXs[i];
++ maxId = i;
++ }
++ if (geoTo.latitude() > m_maxLati)
++ m_maxLati = geoTo.latitude();
++ if (geoTo.latitude() < m_minLati)
++ m_minLati = geoTo.latitude();
++ }
++
++ m_bbox = QGeoRectangle(QGeoCoordinate(m_maxLati, m_path.at(minId).longitude()),
++ QGeoCoordinate(m_minLati, m_path.at(maxId).longitude()));
++ }
++
++ inline static void updateBBox(const QList<QGeoCoordinate> &m_path, QList<double> &m_deltaXs,
++ double &m_minX, double &m_maxX, double &m_minLati, double &m_maxLati,
++ QGeoRectangle &m_bbox)
++ {
++ if (m_path.isEmpty()) {
++ m_deltaXs.clear();
++ m_minX = qInf();
++ m_maxX = -qInf();
++ m_minLati = qInf();
++ m_maxLati = -qInf();
++ m_bbox = QGeoRectangle();
++ return;
++ } else if (m_path.size() == 1) { // was 0 now is 1
++ m_deltaXs.resize(1);
++ m_deltaXs[0] = m_minX = m_maxX = 0.0;
++ m_minLati = m_maxLati = m_path.at(0).latitude();
++ m_bbox = QGeoRectangle(QGeoCoordinate(m_maxLati, m_path.at(0).longitude()),
++ QGeoCoordinate(m_minLati, m_path.at(0).longitude()));
++ return;
++ } else if ( m_path.size() != m_deltaXs.size() + 1 ) { // this case should not happen
++ computeBBox(m_path, m_deltaXs, m_minX, m_maxX, m_minLati, m_maxLati, m_bbox); // something went wrong
++ return;
++ }
++
++ const QGeoCoordinate &geoFrom = m_path.at(m_path.size()-2);
++ const QGeoCoordinate &geoTo = m_path.last();
++ double longiFrom = geoFrom.longitude();
++ double longiTo = geoTo.longitude();
++ double deltaLongi = longiTo - longiFrom;
++ if (qAbs(deltaLongi) > 180.0) {
++ if (longiTo > 0.0)
++ longiTo -= 360.0;
++ else
++ longiTo += 360.0;
++ deltaLongi = longiTo - longiFrom;
++ }
++
++ m_deltaXs.push_back(m_deltaXs.last() + deltaLongi);
++ double currentMinLongi = m_bbox.topLeft().longitude();
++ double currentMaxLongi = m_bbox.bottomRight().longitude();
++ if (m_deltaXs.last() < m_minX) {
++ m_minX = m_deltaXs.last();
++ currentMinLongi = geoTo.longitude();
++ }
++ if (m_deltaXs.last() > m_maxX) {
++ m_maxX = m_deltaXs.last();
++ currentMaxLongi = geoTo.longitude();
++ }
++ if (geoTo.latitude() > m_maxLati)
++ m_maxLati = geoTo.latitude();
++ if (geoTo.latitude() < m_minLati)
++ m_minLati = geoTo.latitude();
++ m_bbox = QGeoRectangle(QGeoCoordinate(m_maxLati, currentMinLongi),
++ QGeoCoordinate(m_minLati, currentMaxLongi));
++ }
++
++ // Pure virtual base that can be used in both
++ // QGeoPathPrivate and QGeoPolygonPrivate.
++ // Does not implement QGeoShape::contains(), because both derived classes
++ // have their own implementations. As a result, also does not implement
++ // QGeoShape::clone().
++ class Q_POSITIONING_EXPORT QGeoPathPrivateBase : public QGeoShapePrivate
++ {
++ public:
++ QGeoPathPrivateBase();
++ QGeoPathPrivateBase(const QList<QGeoCoordinate> &path);
++ QGeoPathPrivateBase(const QGeoPathPrivateBase &other);
++ ~QGeoPathPrivateBase() override;
++
++ // QGeoShape API
++ bool isValid() const override;
++ bool isEmpty() const override;
++ QGeoCoordinate center() const override;
++ bool operator==(const QGeoShapePrivate &other) const override;
++ QGeoRectangle boundingGeoRectangle() const override;
++ size_t hash(size_t seed) const override;
++
++ // QGeoPathPrivateBase API
++ virtual const QList<QGeoCoordinate> &path() const;
++ virtual double length(qsizetype indexFrom, qsizetype indexTo) const;
++ virtual qsizetype size() const;
++ virtual QGeoCoordinate coordinateAt(qsizetype index) const;
++ virtual bool containsCoordinate(const QGeoCoordinate &coordinate) const;
++ virtual void translate(double degreesLatitude, double degreesLongitude);
++ virtual void setPath(const QList<QGeoCoordinate> &path);
++ virtual void clearPath();
++ virtual void addCoordinate(const QGeoCoordinate &coordinate);
++ virtual void insertCoordinate(qsizetype index, const QGeoCoordinate &coordinate);
++ virtual void replaceCoordinate(qsizetype index, const QGeoCoordinate &coordinate);
++ virtual void removeCoordinate(const QGeoCoordinate &coordinate);
++ virtual void removeCoordinate(qsizetype index);
++ virtual void markDirty();
++
++ void ensureBoundingBoxUpdated() const;
++
++ // data members
++ QList<QGeoCoordinate> m_path;
++ mutable QGeoRectangle m_bbox; // cached
++ mutable std::atomic<bool> m_bboxDirty = true; // default is dirty!
++ };
++
++ // Lazy by default. Eager, within the module, used only in MapItems/MapObjectsQSG
++ class Q_POSITIONING_EXPORT QGeoPathPrivate : public QGeoPathPrivateBase
++ {
++ public:
++ QGeoPathPrivate();
++ QGeoPathPrivate(const QList<QGeoCoordinate> &path, const qreal width = 0.0);
++ ~QGeoPathPrivate();
++
++ // QGeoShape API
++ QGeoShapePrivate *clone() const override;
++ bool operator==(const QGeoShapePrivate &other) const override;
++ bool contains(const QGeoCoordinate &coordinate) const override;
++ size_t hash(size_t seed) const override;
++
++ // QGeoPathPrivateBase API: nothing to override
++
++ // QGeoPathPrivate API
++ bool lineContains(const QGeoCoordinate &coordinate) const;
++ qreal width() const;
++ void setWidth(const qreal &width);
++
++ // data members
++ qreal m_width = 0;
++ };
++
++ class Q_POSITIONING_EXPORT QGeoPathPrivateEager final : public QGeoPathPrivate
++ {
++ public:
++ QGeoPathPrivateEager();
++ QGeoPathPrivateEager(const QList<QGeoCoordinate> &path, const qreal width = 0.0);
++ QGeoPathPrivateEager(const QGeoPathPrivateEager &other);
++ ~QGeoPathPrivateEager();
++
++ // QGeoShapePrivate API
++ QGeoShapePrivate *clone() const override;
++
++ // QGeoPathPrivateBase API
++ void translate(double degreesLatitude, double degreesLongitude) override;
++ void markDirty() override;
++ void addCoordinate(const QGeoCoordinate &coordinate) override;
++
++ // *Eager API
++ void updateBoundingBox();
++
++ // data members
++ QList<double> m_deltaXs; // longitude deltas from m_path[0]
++ double m_minX = 0; // minimum value inside deltaXs
++ double m_maxX = 0; // maximum value inside deltaXs
++ double m_minLati = 0; // minimum latitude. paths do not wrap around through the poles
++ double m_maxLati = 0; // minimum latitude. paths do not wrap around through the poles
++ };
++
++ // This is a mean of creating a QGeoPathPrivateEager and injecting it into QGeoPaths via operator=
++ class Q_POSITIONING_EXPORT QGeoPathEager : public QGeoPath
++ {
++ Q_GADGET
++ public:
++
++ QGeoPathEager();
++ QGeoPathEager(const QList<QGeoCoordinate> &path, const qreal &width = 0.0);
++ QGeoPathEager(const QGeoPath &other);
++ QGeoPathEager(const QGeoShape &other);
++ ~QGeoPathEager();
++ };
++
++ QT_END_NAMESPACE
++
++ #endif // QGEOPATH_P_H