AmonRaNet / QGeoView

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

Question: bad perfomance when draw lines on big zoom #45

Open poe6umba opened 8 months ago

poe6umba commented 8 months ago

Hi! First of all, thanks for your awesome project!

I'm making a map with the ability to build a route. The following problem occurred: At high zoom, when moving an element of the route, FPS drops very significantly. Also (sometimes) FPS drops very significantly when changing the zoom, when the zoom is already quite large. The route itself is a layer (the RouteLayer class which is inherited by QGVLayer), to which I add point and line objects. Points and lines are inherited from QGVDrawItem.

When I move a point, only the lines that connect to this point are redrawn.

Here is the line code:

//This method is called when I move the point
void RouteLine::updatePoints(const QGV::GeoPos &geoPos_start, const QGV::GeoPos &geoPos_stop)
{
    mGeoStart = geoPos_start;
    mGeoStop = geoPos_stop;
    mProjStart = getMap()->getProjection()->geoToProj(mGeoStart);
    mProjStop = getMap()->getProjection()->geoToProj(mGeoStop);
    resetBoundary();
    refresh();
}

QPainterPath RouteLine::projShape() const
{
    QPainterPath path;

    auto scale = 1.5 / getMap()->getCamera().scale();

    qreal dx = mProjStart.x() - mProjStop.x();
    qreal dy = mProjStart.y() - mProjStop.y();
    qreal length = sqrt(pow(dx,2) + pow(dy,2));

    path.moveTo(mProjStart.x(), mProjStart.y());
    path.lineTo(mProjStart.x() - dy/length*scale, mProjStart.y() + dx/length*scale);
    path.lineTo(mProjStop.x() - dy/length*scale, mProjStop.y() + dx/length*scale);
    path.lineTo(mProjStop.x(), mProjStop.y());
    path.closeSubpath();

    return path;
}

void RouteLine::projPaint(QPainter* painter)
{
    painter->setBrush(mColor);
    painter->drawPath(projShape());
}

and this is how the logic for changing route lines works:

//i have connect
connect(routePoint, &RoutePoint::posChanged, this, &RouteLayer::onRoutePointPosChanged);

void RouteLayer::onRoutePointPosChanged()
{
    redrawLinesForPoint(dynamic_cast<RoutePoint*>(sender()));
}

//and when point move i set new points for line
void RouteLayer::redrawLinesForPoint(const RoutePoint *p)
{
   auto index = p->getIndex()-1;

   if(index>=1)
   {
       mLineBetweenPoints.at(index-1)->updatePoints(mRoutePoints.at(index-1)->getCenter(), mRoutePoints.at(index)->getCenter());
   }
   if(index<mLineBetweenPoints.size())
   {
        mLineBetweenPoints.at(index)->updatePoints(mRoutePoints.at(index)->getCenter(), mRoutePoints.at(index+1)->getCenter());
   }
}

In this video you can see how performance differs at different zoom levels https://youtu.be/617_31R_3xg

I think this has something to do with lines boundingRect() and what exactly View updates. I trying change setViewportUpdateMode, but no effect. And this problem is precisely because of the lines, if don’t draw them everything works quickly Could you help with any advice?

UPDATE:

If redraw line like this:

void RouteLine::projPaint(QPainter* painter)
{
    auto scale = 1.5 / getMap()->getCamera().scale();
    painter->setPen(QPen(mColor, scale));
    painter->setBrush(mColor);
    painter->drawLine(mProjStart.x(), mProjStart.y(),mProjStop.x(), mProjStop.y());
    //painter->drawPath(projShape());
}

Now performance better than before on big zoom, but i don`t completely understand why :)

poe6umba commented 8 months ago

https://youtu.be/1R4kteiqwRs

one more video