QGCMapPolygon.cc 4.49 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
/****************************************************************************
 *
 *   (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/

#include "QGCMapPolygon.h"
#include "QGCGeo.h"
12
#include "JsonHelper.h"
13 14 15

#include <QGeoRectangle>
#include <QDebug>
16 17 18
#include <QJsonArray>

const char* QGCMapPolygon::_jsonPolygonKey = "polygon";
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

QGCMapPolygon::QGCMapPolygon(QObject* parent)
    : QObject(parent)
    , _dirty(false)
{

}

const QGCMapPolygon& QGCMapPolygon::operator=(const QGCMapPolygon& other)
{
    _polygonPath = other._polygonPath;
    setDirty(true);

    emit pathChanged();

    return *this;
}

void QGCMapPolygon::clear(void)
{
    // Bug workaround, see below
    while (_polygonPath.count() > 1) {
        _polygonPath.takeLast();
    }
    emit pathChanged();

    // Although this code should remove the polygon from the map it doesn't. There appears
    // to be a bug in QGCMapPolygon which causes it to not be redrawn if the list is empty. So
    // we work around it by using the code above to remove all but the last point which in turn
    // will cause the polygon to go away.
    _polygonPath.clear();

    setDirty(true);
}

void QGCMapPolygon::adjustCoordinate(int vertexIndex, const QGeoCoordinate coordinate)
{
    _polygonPath[vertexIndex] = QVariant::fromValue(coordinate);
    emit pathChanged();
    setDirty(true);
}

void QGCMapPolygon::setDirty(bool dirty)
{
    if (_dirty != dirty) {
        _dirty = dirty;
        emit dirtyChanged(dirty);
    }
}

69
QGeoCoordinate QGCMapPolygon::_coordFromPointF(const QPointF& point) const
70
{
71 72 73 74 75 76
    QGeoCoordinate coord;

    if (_polygonPath.count() > 0) {
        QGeoCoordinate tangentOrigin = _polygonPath[0].value<QGeoCoordinate>();
        convertNedToGeo(-point.y(), point.x(), 0, tangentOrigin, &coord);
    }
77

78 79
    return coord;
}
80

81 82 83
QPointF QGCMapPolygon::_pointFFromCoord(const QGeoCoordinate& coordinate) const
{
    if (_polygonPath.count() > 0) {
84
        double y, x, down;
85
        QGeoCoordinate tangentOrigin = _polygonPath[0].value<QGeoCoordinate>();
86

87 88
        convertGeoToNed(coordinate, tangentOrigin, &y, &x, &down);
        return QPointF(x, -y);
89 90
    }

91 92
    return QPointF();
}
93

94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
QPolygonF QGCMapPolygon::_toPolygonF(void) const
{
    QPolygonF polygon;

    if (_polygonPath.count() > 2) {
        for (int i=0; i<_polygonPath.count(); i++) {
            polygon.append(_pointFFromCoord(_polygonPath[i].value<QGeoCoordinate>()));
        }
    }

    return polygon;
}

bool QGCMapPolygon::containsCoordinate(const QGeoCoordinate& coordinate) const
{
    if (_polygonPath.count() > 2) {
        return _toPolygonF().containsPoint(_pointFFromCoord(coordinate), Qt::OddEvenFill);
    } else {
        return false;
    }
}

QGeoCoordinate QGCMapPolygon::center(void) const
{
    if (_polygonPath.count() > 2) {
        QPointF centerPoint = _toPolygonF().boundingRect().center();
        return _coordFromPointF(centerPoint);
    } else {
        return QGeoCoordinate();
    }
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
}

void QGCMapPolygon::setPath(const QList<QGeoCoordinate>& path)
{
    _polygonPath.clear();
    foreach(const QGeoCoordinate& coord, path) {
        _polygonPath << QVariant::fromValue(coord);
    }
    setDirty(true);
    emit pathChanged();
}

void QGCMapPolygon::setPath(const QVariantList& path)
{
    _polygonPath = path;
    setDirty(true);
    emit pathChanged();
}
142 143 144

void QGCMapPolygon::saveToJson(QJsonObject& json)
{
145
    QJsonValue jsonValue;
146

147 148
    JsonHelper::saveGeoCoordinateArray(_polygonPath, false /* writeAltitude*/, jsonValue);
    json.insert(_jsonPolygonKey, jsonValue);
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
    setDirty(false);
}

bool QGCMapPolygon::loadFromJson(const QJsonObject& json, bool required, QString& errorString)
{
    errorString.clear();
    clear();

    if (required) {
        if (!JsonHelper::validateRequiredKeys(json, QStringList(_jsonPolygonKey), errorString)) {
            return false;
        }
    } else if (!json.contains(_jsonPolygonKey)) {
        return true;
    }

165
    if (!JsonHelper::loadGeoCoordinateArray(json[_jsonPolygonKey], false /* altitudeRequired */, _polygonPath, errorString)) {
166 167 168
        return false;
    }
    setDirty(false);
169
    emit pathChanged();
170 171 172 173

    return true;
}

174 175 176 177 178 179 180 181 182 183
QList<QGeoCoordinate> QGCMapPolygon::coordinateList(void) const
{
    QList<QGeoCoordinate> coords;

    for (int i=0; i<count(); i++) {
        coords.append((*this)[i]);
    }

    return coords;
}