AmonRaNet / QGeoView

QGeoView is a Qt / C ++ widget for visualizing geographic data.
GNU Lesser General Public License v3.0
155 stars 60 forks source link

Items selection by mouse rectangle with map not facing north #29

Closed JaiPasdeBol closed 2 years ago

JaiPasdeBol commented 2 years ago

Hi,

I noticed a very little problem that I think I solved. When you select items by drawing a rectangle with the SHIFT key pushed: it works perfectly when the map is north oriented. But it doesn't really well when your map is oriented at 45° for exemple. (The rectangle we use for the selection isn't oriented correctly) So I had this method in QGVMap class:

QList<QGVDrawItem*> QGVMap::search(const QPolygonF& projPolygon, Qt::ItemSelectionMode mode) const
{
    QList<QGVDrawItem*> result;
    for (QGraphicsItem* item : geoView()->scene()->items(projPolygon, mode)) {
        QGVDrawItem* geoObject = QGVMapQGItem::geoObjectFromQGItem(item);
        if (geoObject)
            result << geoObject;
    }
    return result;
}

And I add some code in QGVMapQGView::selectObjectsByRect(QMouseEvent* event, QRect selRect)

void QGVMapQGView::selectObjectsByRect(QMouseEvent* event, QRect selRect)
{
    if (!mMouseActions.testFlag(QGV::MouseAction::Selection)) {
        changeState(QGV::MapState::Idle);
        return;
    }
    event->accept();
    if (event->modifiers() == Qt::ShiftModifier) {
        mGeoMap->unselectAll();
    }
    const QRectF projSelRect = QRectF(mapToScene(selRect.topLeft()), mapToScene(selRect.bottomRight()));
    //Construction of the polygon
    QPolygonF projSelPolygon;
        projSelPolygon<<mapToScene(selRect.topLeft());
        projSelPolygon<<mapToScene(selRect.bottomRight());
    QPointF centreRect((selRect.topLeft().x()+selRect.bottomRight().x())/2,(selRect.topLeft().y()+selRect.bottomRight().y())/2.);
    QPolygonF projSelPolygon2 = QTransform().rotate(-mAzimuth).translate(-centreRect.x(),-centreRect.y()).map(projSelPolygon);
    projSelPolygon.clear();
    projSelPolygon<<projSelPolygon2[0];
    projSelPolygon<<QPointF(projSelPolygon2[1].x(),projSelPolygon2[0].y());
    projSelPolygon<<projSelPolygon2[1];
    projSelPolygon<<QPointF(projSelPolygon2[0].x(),projSelPolygon2[1].y());
    projSelPolygon = QTransform().translate(centreRect.x(),centreRect.y()).rotate(mAzimuth).map(projSelPolygon);

    auto selList = mGeoMap->search(projSelPolygon, Qt::ContainsItemShape);
    for (auto* geoObject : selList) {
        geoObject->setSelected(!geoObject->isSelected());
    }
}

I think it works fine with this, but you may have a better solution. Thanks for your work on this library.

AmonRaNet commented 2 years ago

I have pushed fix to master. Technically is easier to map every corner of selection rect to scene coordinates (rotation will be included) and then simply select nodes by closed polygon containing these points. P.S. Now selection by polygon is public interface for QGVMap.