コード例 #1
0
QGeoShape QDeclarativeGeoMap::visibleRegion() const
{
    if (!m_map || !width() || !height())
        return m_region;

    QGeoCoordinate tl = m_map->itemPositionToCoordinate(QDoubleVector2D(0, 0));
    QGeoCoordinate br = m_map->itemPositionToCoordinate(QDoubleVector2D(width(), height()));

    return QGeoRectangle(tl, br);
}
コード例 #2
0
/*!
    \internal
*/
void QDeclarativeCircleMapItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
    if (updatingGeometry_ || newGeometry == oldGeometry) {
        QDeclarativeGeoMapItemBase::geometryChanged(newGeometry, oldGeometry);
        return;
    }

    QDoubleVector2D newPoint = QDoubleVector2D(x(),y()) + QDoubleVector2D(width(), height()) / 2;
    QGeoCoordinate newCoordinate = map()->itemPositionToCoordinate(newPoint, false);
    if (newCoordinate.isValid())
        setCenter(newCoordinate);

    // Not calling QDeclarativeGeoMapItemBase::geometryChanged() as it will be called from a nested
    // call to this function.
}
コード例 #3
0
/*!
    \qmlmethod coordinate QtLocation::Map::toCoordinate(QPointF position, bool clipToViewPort)

    Returns the coordinate which corresponds to the \a position relative to the map item.

    If \a cliptoViewPort is \c true, or not supplied then returns an invalid coordinate if
    \a position is not within the current viewport.
*/
QGeoCoordinate QDeclarativeGeoMap::toCoordinate(const QPointF &position, bool clipToViewPort) const
{
    if (m_map)
        return m_map->itemPositionToCoordinate(QDoubleVector2D(position), clipToViewPort);
    else
        return QGeoCoordinate();
}
コード例 #4
0
QGeoCoordinate QDeclarativeGeoMap::toCoordinate(const QPointF &screenPosition) const
{
    if (map_)
        return map_->screenPositionToCoordinate(QDoubleVector2D(screenPosition));
    else
        return QGeoCoordinate();
}
コード例 #5
0
QGeoCoordinate QGeoProjection::coordinateInterpolation(const QGeoCoordinate &from, const QGeoCoordinate &to, qreal progress)
{
    QDoubleVector2D s = QGeoProjection::coordToMercator(from);
    QDoubleVector2D e = QGeoProjection::coordToMercator(to);

    double x = s.x();

    if (0.5 < qAbs(e.x() - s.x())) {
        // handle dateline crossing
        double ex = e.x();
        double sx = s.x();
        if (ex < sx)
            sx -= 1.0;
        else if (sx < ex)
            ex -= 1.0;

        x = (1.0 - progress) * sx + progress * ex;

        if (!qFuzzyIsNull(x) && (x < 0.0))
            x += 1.0;

    } else {
        x = (1.0 - progress) * s.x() + progress * e.x();
    }

    double y = (1.0 - progress) * s.y() + progress * e.y();

    QGeoCoordinate result = QGeoProjection::mercatorToCoord(QDoubleVector2D(x, y));
    result.setAltitude((1.0 - progress) * from.altitude() + progress * to.altitude());

    return result;
}
コード例 #6
0
/*!
    \internal
*/
void QDeclarativeGeoMapGestureArea::touchPointStateMachine()
{
    // Transitions:
    switch (touchPointState_) {
    case touchPoints0:
        if (touchPoints_.count() == 1) {
            clearTouchData();
            startOneTouchPoint();
            touchPointState_ = touchPoints1;
        } else if (touchPoints_.count() >= 2) {
            clearTouchData();
            startTwoTouchPoints();
            touchPointState_ = touchPoints2;
        }
        break;
    case touchPoints1:
        if (touchPoints_.count() == 0) {
            touchPointState_ = touchPoints0;
        } else if (touchPoints_.count() >= 2) {
            touchCenterCoord_ = map_->screenPositionToCoordinate(QDoubleVector2D(sceneCenter_), false);
            startTwoTouchPoints();
            touchPointState_ = touchPoints2;
        }
        break;
    case touchPoints2:
        if (touchPoints_.count() == 0) {
            touchPointState_ = touchPoints0;
        } else if (touchPoints_.count() == 1) {
            touchCenterCoord_ = map_->screenPositionToCoordinate(QDoubleVector2D(sceneCenter_), false);
            startOneTouchPoint();
            touchPointState_ = touchPoints1;
        }
        break;
    };

    // Update
    switch (touchPointState_) {
    case touchPoints0:
        break; // do nothing if no touch points down
    case touchPoints1:
        updateOneTouchPoint();
        break;
    case touchPoints2:
        updateTwoTouchPoints();
        break;
    }
}
コード例 #7
0
/*!
    \internal
*/
void QDeclarativePolylineMapItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
    if (updatingGeometry_ || newGeometry.topLeft() == oldGeometry.topLeft()) {
        QDeclarativeGeoMapItemBase::geometryChanged(newGeometry, oldGeometry);
        return;
    }

    QDoubleVector2D newPoint = QDoubleVector2D(x(),y()) + QDoubleVector2D(geometry_.firstPointOffset());
    QGeoCoordinate newCoordinate = map()->screenPositionToCoordinate(newPoint, false);
    if (newCoordinate.isValid()) {
        double firstLongitude = path_.at(0).longitude();
        double firstLatitude = path_.at(0).latitude();
        double minMaxLatitude = firstLatitude;
        // prevent dragging over valid min and max latitudes
        for (int i = 0; i < path_.count(); ++i) {
            double newLatitude = path_.at(i).latitude()
                    + newCoordinate.latitude() - firstLatitude;
            if (!QLocationUtils::isValidLat(newLatitude)) {
                if (qAbs(newLatitude) > qAbs(minMaxLatitude)) {
                    minMaxLatitude = newLatitude;
                }
            }
        }
        // calculate offset needed to re-position the item within map border
        double offsetLatitude = minMaxLatitude - QLocationUtils::clipLat(minMaxLatitude);
        for (int i = 0; i < path_.count(); ++i) {
            QGeoCoordinate coord = path_.at(i);
            // handle dateline crossing
            coord.setLongitude(QLocationUtils::wrapLong(coord.longitude()
                               + newCoordinate.longitude() - firstLongitude));
            coord.setLatitude(coord.latitude()
                              + newCoordinate.latitude() - firstLatitude - offsetLatitude);
            path_.replace(i, coord);
        }

        QGeoCoordinate leftBoundCoord = geometry_.geoLeftBound();
        leftBoundCoord.setLongitude(QLocationUtils::wrapLong(leftBoundCoord.longitude()
                           + newCoordinate.longitude() - firstLongitude));
        geometry_.setPreserveGeometry(true, leftBoundCoord);
        geometry_.markSourceDirty();
        updateMapItem();
        emit pathChanged();
    }

    // Not calling QDeclarativeGeoMapItemBase::geometryChanged() as it will be called from a nested
    // call to this function.
}
コード例 #8
0
/*!
    \internal
*/
void QDeclarativeGeoMapGestureArea::updatePan()
{
    QPointF startPoint = map_->coordinateToScreenPosition(startCoord_, false).toPointF();
    int dx = static_cast<int>(sceneCenter_.x() - startPoint.x());
    int dy = static_cast<int>(sceneCenter_.y() - startPoint.y());
    QPointF mapCenterPoint;
    mapCenterPoint.setY(map_->height() / 2.0  - dy);
    mapCenterPoint.setX(map_->width() / 2.0 - dx);
    QGeoCoordinate animationStartCoordinate = map_->screenPositionToCoordinate(QDoubleVector2D(mapCenterPoint), false);
    map_->mapController()->setCenter(animationStartCoordinate);
}
コード例 #9
0
QDoubleVector2D QDoubleVector2D::normalized() const
{
    // Need some extra precision if the length is very small.
    double len = double(xp) * double(xp) +
                 double(yp) * double(yp);
    if (qFuzzyIsNull(len - 1.0))
        return *this;
    else if (!qFuzzyIsNull(len))
        return *this / (double)qSqrt(len);
    else
        return QDoubleVector2D();
}
コード例 #10
0
/*!
    \internal
*/
void QDeclarativeGeoMapGestureArea::startOneTouchPoint()
{
    sceneStartPoint1_ = touchPoints_.at(0).scenePos();
    lastPos_ = sceneStartPoint1_;
    lastPosTime_.start();
    QGeoCoordinate startCoord = map_->screenPositionToCoordinate(QDoubleVector2D(sceneStartPoint1_), false);
    // ensures a smooth transition for panning
    startCoord_.setLongitude(startCoord_.longitude() + startCoord.longitude() -
                             touchCenterCoord_.longitude());
    startCoord_.setLatitude(startCoord_.latitude() + startCoord.latitude() -
                            touchCenterCoord_.latitude());
}
コード例 #11
0
/*!
    \internal
*/
void QDeclarativeGeoMapGestureArea::startTwoTouchPoints()
{
    sceneStartPoint1_ = touchPoints_.at(0).scenePos();
    sceneStartPoint2_ = touchPoints_.at(1).scenePos();
    QPointF startPos = (sceneStartPoint1_ + sceneStartPoint2_) * 0.5;
    lastPos_ = startPos;
    lastPosTime_.start();
    QGeoCoordinate startCoord = map_->screenPositionToCoordinate(QDoubleVector2D(startPos), false);
    startCoord_.setLongitude(startCoord_.longitude() + startCoord.longitude() -
                             touchCenterCoord_.longitude());
    startCoord_.setLatitude(startCoord_.latitude() + startCoord.latitude() -
                            touchCenterCoord_.latitude());
}
コード例 #12
0
QT_BEGIN_NAMESPACE

QDoubleVector2D QGeoProjection::coordToMercator(const QGeoCoordinate &coord)
{
    const double pi = M_PI;

    double lon = coord.longitude() / 360.0 + 0.5;

    double lat = coord.latitude();
    lat = 0.5 - (std::log(std::tan((pi / 4.0) + (pi / 2.0) * lat / 180.0)) / pi) / 2.0;
    lat = qBound(0.0, lat, 1.0);

    return QDoubleVector2D(lon, lat);
}
コード例 #13
0
QDoubleVector2D QGeoTiledMapData::coordinateToScreenPosition(const QGeoCoordinate &coordinate, bool clipToViewport) const
{
    Q_D(const QGeoTiledMapData);
    QDoubleVector2D pos = d->coordinateToScreenPosition(coordinate);

    if (clipToViewport) {
        int w = width();
        int h = height();

        if ((pos.x() < 0) || (w < pos.x()) || (pos.y() < 0) || (h < pos.y()))
            return QDoubleVector2D(qQNaN(), qQNaN());
    }

    return pos;
}
コード例 #14
0
/*!
    \internal
*/
void QDeclarativeGeoMapQuickItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
    if (!mapAndSourceItemSet_ || updatingGeometry_ ||
        newGeometry.topLeft() == oldGeometry.topLeft()) {
        QDeclarativeGeoMapItemBase::geometryChanged(newGeometry, oldGeometry);
        return;
    }

    QGeoCoordinate newCoordinate = map()->itemPositionToCoordinate(QDoubleVector2D(x(), y()) + (scaleFactor() * QDoubleVector2D(anchorPoint_)), false);
    if (newCoordinate.isValid())
        setCoordinate(newCoordinate);

    // Not calling QDeclarativeGeoMapItemBase::geometryChanged() as it will be called from a nested
    // call to this function.
}
コード例 #15
0
/*!
    \internal
*/
void QDeclarativeGeoMapGestureArea::panStateMachine()
{
    PanState lastState = panState_;

    // Transitions
    switch (panState_) {
    case panInactive:
        if (canStartPan()) {
            // Update startCoord_ to ensure smooth start for panning when going over startDragDistance
            QGeoCoordinate newStartCoord = map_->screenPositionToCoordinate(QDoubleVector2D(lastPos_), false);
            startCoord_.setLongitude(newStartCoord.longitude());
            startCoord_.setLatitude(newStartCoord.latitude());
            panState_ = panActive;
        }
        break;
    case panActive:
        if (touchPoints_.count() == 0) {
            panState_ = panFlick;
            if (!tryStartFlick())
            {
                panState_ = panInactive;
                // mark as inactive for use by camera
                if (pinchState_ == pinchInactive)
                    emit movementStopped();
            }
        }
        break;
    case panFlick:
        if (touchPoints_.count() > 0) { // re touched before movement ended
            endFlick();
            panState_ = panActive;
        }
        break;
    }
    // Update
    switch (panState_) {
    case panInactive: // do nothing
        break;
    case panActive:
        updatePan();
        // this ensures 'panStarted' occurs after the pan has actually started
        if (lastState != panActive)
            emit panStarted();
        break;
    case panFlick:
        break;
    }
}
コード例 #16
0
void QGeoMapController::pan(qreal dx, qreal dy)
{
    if (dx == 0 && dy == 0)
        return;
    QGeoCameraData cd = map_->cameraData();
    QGeoCoordinate coord = map_->itemPositionToCoordinate(
                                QDoubleVector2D(map_->width() / 2 + dx,
                                        map_->height() / 2 + dy));


    // keep altitude as it was
    coord.setAltitude(cd.center().altitude());
    if (coord.isValid()) {
        cd.setCenter(coord);
        map_->setCameraData(cd);
    }
}
コード例 #17
0
void tst_doubleVectors::constructor2dTest()
{
    // empty constructor, since it sets to 0, we should check, in case people rely on it
    QDoubleVector2D v1;
    QCOMPARE(v1.x(), 0.0);
    QCOMPARE(v1.y(), 0.0);
    QCOMPARE(v1.isNull(), true);
    v1 = QDoubleVector2D(1.1, -2.5); // assignment and constructor
    QCOMPARE(v1.x(), 1.1);
    QCOMPARE(v1.y(), -2.5);
    QDoubleVector2D v2(v1); // copy constructor
    QCOMPARE(v2.x(), 1.1);
    QCOMPARE(v2.y(), -2.5);
    const QDoubleVector3D v3d(2.2, 3.3, 4.4);
    QDoubleVector2D v3(v3d); // constructor from 3d vector, just copies x and y
    QCOMPARE(v3.x(), 2.2);
    QCOMPARE(v3.y(), 3.3);
    QCOMPARE(v3.isNull(), false);
}
コード例 #18
0
QGeoCoordinate QGeoCoordinateInterpolator2D::interpolate(const QGeoCoordinate &start, const QGeoCoordinate &end, qreal progress)
{
    if (start == end) {
        if (progress < 0.5) {
            return start;
        } else {
            return end;
        }
    }

    QGeoCoordinate s2 = start;
    QGeoCoordinate e2 = end;
    QDoubleVector2D s = QGeoProjection::coordToMercator(s2);
    QDoubleVector2D e = QGeoProjection::coordToMercator(e2);

    double x = s.x();

    if (0.5 < qAbs(e.x() - s.x())) {
        // handle dateline crossing
        double ex = e.x();
        double sx = s.x();
        if (ex < sx)
            sx -= 1.0;
        else if (sx < ex)
            ex -= 1.0;

        x = (1.0 - progress) * sx + progress * ex;

        if (!qFuzzyIsNull(x) && (x < 0.0))
            x += 1.0;

    } else {
        x = (1.0 - progress) * s.x() + progress * e.x();
    }

    double y = (1.0 - progress) * s.y() + progress * e.y();

    QGeoCoordinate result = QGeoProjection::mercatorToCoord(QDoubleVector2D(x, y));
    result.setAltitude((1.0 - progress) * start.altitude() + progress * end.altitude());
    return result;
}
コード例 #19
0
/*!
    \internal
*/
void QDeclarativeRectangleMapItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
    if (updatingGeometry_ || newGeometry.topLeft() == oldGeometry.topLeft()) {
        QDeclarativeGeoMapItemBase::geometryChanged(newGeometry, oldGeometry);
        return;
    }

    QDoubleVector2D newTopLeftPoint = QDoubleVector2D(x(),y());
    QGeoCoordinate newTopLeft = map()->itemPositionToCoordinate(newTopLeftPoint, false);
    if (newTopLeft.isValid()) {
        // calculate new geo width while checking for dateline crossing
        const double lonW = bottomRight_.longitude() > topLeft_.longitude() ?
                    bottomRight_.longitude() - topLeft_.longitude() :
                    bottomRight_.longitude() + 360 - topLeft_.longitude();
        const double latH = qAbs(bottomRight_.latitude() - topLeft_.latitude());
        QGeoCoordinate newBottomRight;
        // prevent dragging over valid min and max latitudes
        if (QLocationUtils::isValidLat(newTopLeft.latitude() - latH)) {
            newBottomRight.setLatitude(newTopLeft.latitude() - latH);
        } else {
            newBottomRight.setLatitude(QLocationUtils::clipLat(newTopLeft.latitude() - latH));
            newTopLeft.setLatitude(newBottomRight.latitude() + latH);
        }
        // handle dateline crossing
        newBottomRight.setLongitude(QLocationUtils::wrapLong(newTopLeft.longitude() + lonW));
        newBottomRight.setAltitude(newTopLeft.altitude());
        topLeft_ = newTopLeft;
        bottomRight_ = newBottomRight;
        geometry_.setPreserveGeometry(true, newTopLeft);
        borderGeometry_.setPreserveGeometry(true, newTopLeft);
        markSourceDirtyAndUpdate();
        emit topLeftChanged(topLeft_);
        emit bottomRightChanged(bottomRight_);
    }

    // Not calling QDeclarativeGeoMapItemBase::geometryChanged() as it will be called from a nested
    // call to this function.
}
コード例 #20
0
QDoubleVector2D QGeoTiledMapGoogle::coordinateToItemPosition(const QGeoCoordinate &coordinate, bool clipToViewport) const
{
    QGeoCoordinate coor = coordinate;
    //WGS84 to GCJ-02  
    if("cn" == m_szLocale)
    {
        //qDebug() << "transformFromWGSToGCJ:";
        //qDebug() << "lat:" << coor.latitude() << ";lng:" << coor.longitude();
        coor = QCoordTrans::WGSToGCJ(coor);
        //qDebug() << "lat:" << coor.latitude() << ";lng:" << coor.longitude();
    }
    QDoubleVector2D pos = QGeoTiledMap::coordinateToItemPosition(coor, clipToViewport);

    if (clipToViewport) {
        int w = width();
        int h = height();

        if ((pos.x() < 0) || (w < pos.x()) || (pos.y() < 0) || (h < pos.y()))
            return QDoubleVector2D(qQNaN(), qQNaN());
    }

    return pos;
}
コード例 #21
0
/*!
    \internal
*/
void QGeoMapCircleGeometry::updateScreenPointsInvert(const QGeoMap &map)
{
    if (!screenDirty_)
        return;

    if (map.width() == 0 || map.height() == 0) {
        clear();
        return;
    }

    QPointF origin = map.coordinateToItemPosition(srcOrigin_, false).toPointF();

    QPainterPath ppi = srcPath_;

    clear();

    // a circle requires at least 3 points;
    if (ppi.elementCount() < 3)
        return;

    // translate the path into top-left-centric coordinates
    QRectF bb = ppi.boundingRect();
    ppi.translate(-bb.left(), -bb.top());
    firstPointOffset_ = -1 * bb.topLeft();

    ppi.closeSubpath();

    // calculate actual width of map on screen in pixels
    QGeoCoordinate mapCenter(0, map.cameraData().center().longitude());
    QDoubleVector2D midPoint = map.coordinateToItemPosition(mapCenter, false);
    QDoubleVector2D midPointPlusOne = QDoubleVector2D(midPoint.x() + 1.0, midPoint.y());
    QGeoCoordinate coord1 = map.itemPositionToCoordinate(midPointPlusOne, false);
    double geoDistance = coord1.longitude() - map.cameraData().center().longitude();
    if ( geoDistance < 0 )
        geoDistance += 360.0;
    double mapWidth = 360.0 / geoDistance;

    qreal leftOffset = origin.x() - (map.width()/2.0 - mapWidth/2.0) - firstPointOffset_.x();
    qreal topOffset = origin.y() - (midPoint.y() - mapWidth/2.0) - firstPointOffset_.y();
    QPainterPath ppiBorder;
    ppiBorder.moveTo(QPointF(-leftOffset, -topOffset));
    ppiBorder.lineTo(QPointF(mapWidth - leftOffset, -topOffset));
    ppiBorder.lineTo(QPointF(mapWidth - leftOffset, mapWidth - topOffset));
    ppiBorder.lineTo(QPointF(-leftOffset, mapWidth - topOffset));

    screenOutline_ = ppiBorder;

    std::vector<p2t::Point*> borderPts;
    borderPts.reserve(4);

    std::vector<p2t::Point*> curPts;
    curPts.reserve(ppi.elementCount());
    for (int i = 0; i < ppi.elementCount(); ++i) {
        const QPainterPath::Element e = ppi.elementAt(i);
        if (e.isMoveTo() || i == ppi.elementCount() - 1
                || (qAbs(e.x - curPts.front()->x) < 0.1
                    && qAbs(e.y - curPts.front()->y) < 0.1)) {
            if (curPts.size() > 2) {
                for (int j = 0; j < 4; ++j) {
                    const QPainterPath::Element e2 = ppiBorder.elementAt(j);
                    borderPts.push_back(new p2t::Point(e2.x, e2.y));
                }
                p2t::CDT *cdt = new p2t::CDT(borderPts);
                cdt->AddHole(curPts);
                cdt->Triangulate();
                std::vector<p2t::Triangle*> tris = cdt->GetTriangles();
                screenVertices_.reserve(screenVertices_.size() + int(tris.size()));
                for (size_t i = 0; i < tris.size(); ++i) {
                    p2t::Triangle *t = tris.at(i);
                    for (int j = 0; j < 3; ++j) {
                        p2t::Point *p = t->GetPoint(j);
                        screenVertices_ << QPointF(p->x, p->y);
                    }
                }
                delete cdt;
            }
            curPts.clear();
            curPts.reserve(ppi.elementCount() - i);
            curPts.push_back(new p2t::Point(e.x, e.y));
        } else if (e.isLineTo()) {
            curPts.push_back(new p2t::Point(e.x, e.y));
        } else {
            qWarning("Unhandled element type in circle painterpath");
        }
    }

    if (curPts.size() > 0) {
        qDeleteAll(curPts.begin(), curPts.end());
        curPts.clear();
    }

    if (borderPts.size() > 0) {
        qDeleteAll(borderPts.begin(), borderPts.end());
        borderPts.clear();
    }

    screenBounds_ = ppiBorder.boundingRect();

}
コード例 #22
0
/*!
    \internal
*/
void QGeoMapPolylineGeometry::updateSourcePoints(const QGeoMap &map,
                                                 const QList<QGeoCoordinate> &path)
{
    bool foundValid = false;
    double minX = -1.0;
    double minY = -1.0;
    double maxX = -1.0;
    double maxY = -1.0;

    if (!sourceDirty_)
        return;

    // clear the old data and reserve enough memory
    srcPoints_.clear();
    srcPoints_.reserve(path.size() * 2);
    srcPointTypes_.clear();
    srcPointTypes_.reserve(path.size());

    QDoubleVector2D origin, lastPoint, lastAddedPoint;

    double unwrapBelowX = 0;
    if (preserveGeometry_)
        unwrapBelowX = map.coordinateToScreenPosition(geoLeftBound_, false).x();

    for (int i = 0; i < path.size(); ++i) {
        const QGeoCoordinate &coord = path.at(i);

        if (!coord.isValid())
            continue;

        QDoubleVector2D point = map.coordinateToScreenPosition(coord, false);

        // We can get NaN if the map isn't set up correctly, or the projection
        // is faulty -- probably best thing to do is abort
        if (!qIsFinite(point.x()) || !qIsFinite(point.y()))
            return;

        // unwrap x to preserve geometry if moved to border of map
        if (preserveGeometry_ && point.x() < unwrapBelowX && !qFuzzyCompare(point.x(), unwrapBelowX))
            point.setX(unwrapBelowX + geoDistanceToScreenWidth(map, geoLeftBound_, coord));

        if (!foundValid) {
            foundValid = true;
            srcOrigin_ = coord;
            origin = point;
            point = QDoubleVector2D(0,0);

            minX = point.x();
            maxX = minX;
            minY = point.y();
            maxY = minY;

            srcPoints_ << point.x() << point.y();
            srcPointTypes_ << QPainterPath::MoveToElement;
            lastAddedPoint = point;
        } else {
            point -= origin;

            minX = qMin(point.x(), minX);
            minY = qMin(point.y(), minY);
            maxX = qMax(point.x(), maxX);
            maxY = qMax(point.y(), maxY);

            if ((point - lastAddedPoint).manhattanLength() > 3 ||
                    i == path.size() - 1) {
                srcPoints_ << point.x() << point.y();
                srcPointTypes_ << QPainterPath::LineToElement;
                lastAddedPoint = point;
            }
        }

        lastPoint = point;
    }

    sourceBounds_ = QRectF(QPointF(minX, minY), QPointF(maxX, maxY));
    geoLeftBound_ = map.screenPositionToCoordinate(
                                    QDoubleVector2D(minX + origin.x(), minY + origin.y()), false);
}
コード例 #23
0
/*!
    \internal
*/
void QDeclarativeGeoMap::fitViewportToMapItemsRefine(bool refine)
{
    if (mapItems_.size() == 0)
        return;

    double minX = 0;
    double maxX = 0;
    double minY = 0;
    double maxY = 0;
    double topLeftX = 0;
    double topLeftY = 0;
    double bottomRightX = 0;
    double bottomRightY = 0;
    bool haveQuickItem = false;

    // find bounds of all map items
    int itemCount = 0;
    for (int i = 0; i < mapItems_.count(); ++i) {
        if (!mapItems_.at(i))
            continue;
        QDeclarativeGeoMapItemBase *item = mapItems_.at(i).data();
        if (!item)
            continue;

        // skip quick items in the first pass and refine the fit later
        if (refine) {
            QDeclarativeGeoMapQuickItem *quickItem =
                    qobject_cast<QDeclarativeGeoMapQuickItem*>(item);
            if (quickItem) {
                haveQuickItem = true;
                continue;
            }
        }

        topLeftX = item->position().x();
        topLeftY = item->position().y();
        bottomRightX = topLeftX + item->width();
        bottomRightY = topLeftY + item->height();

        if (itemCount == 0) {
            minX = topLeftX;
            maxX = bottomRightX;
            minY = topLeftY;
            maxY = bottomRightY;
        } else {
            minX = qMin(minX, topLeftX);
            maxX = qMax(maxX, bottomRightX);
            minY = qMin(minY, topLeftY);
            maxY = qMax(maxY, bottomRightY);
        }
        ++itemCount;
    }

    if (itemCount == 0) {
        if (haveQuickItem)
            fitViewportToMapItemsRefine(false);
        return;
    }
    double bboxWidth = maxX - minX;
    double bboxHeight = maxY - minY;
    double bboxCenterX = minX + (bboxWidth / 2.0);
    double bboxCenterY = minY + (bboxHeight / 2.0);

    // position camera to the center of bounding box
    QGeoCoordinate coordinate;
    coordinate = map_->screenPositionToCoordinate(QDoubleVector2D(bboxCenterX, bboxCenterY), false);
    setProperty("center", QVariant::fromValue(coordinate));

    // adjust zoom
    double bboxWidthRatio = bboxWidth / (bboxWidth + bboxHeight);
    double mapWidthRatio = width() / (width() + height());
    double zoomRatio;

    if (bboxWidthRatio > mapWidthRatio)
        zoomRatio = bboxWidth / width();
    else
        zoomRatio = bboxHeight / height();

    qreal newZoom = log10(zoomRatio) / log10(0.5);
    newZoom = floor(qMax(minimumZoomLevel(), (map_->mapController()->zoom() + newZoom)));
    setProperty("zoomLevel", QVariant::fromValue(newZoom));

    // as map quick items retain the same screen size after the camera zooms in/out
    // we refine the viewport again to achieve better results
    if (refine)
        fitViewportToMapItemsRefine(false);
}