Google Maps v2 Projection.toScreenLocation() очень медленный

Я обновил Google Maps v1 до v2 в своем приложении для Android.

И v2 был хорош, и так далее, НО один метод кажется самым медленным в моей жизни.

Projection proj = map.getProjection();
Point point = proj.toScreenLocation(example.m_geopoint);

toScreenLocation(...) настолько медленный, что приложение замедляется до непригодного для использования замедленного движения. Метод обновляется, может быть, 100 раз за кадр, но он отлично работает в Google Maps v1.

И когда я проверяю консоль Android, я вижу это:

10-06 13:53:04.460: D/dalvikvm(4889): GC_EXPLICIT freed 251K, 14% free 14622K/16839K, paused 3ms+5ms
10-06 13:53:05.859: D/dalvikvm(4889): GC_EXPLICIT freed 252K, 14% free 14622K/16839K, paused 2ms+5ms
10-06 13:53:07.222: D/dalvikvm(4889): GC_EXPLICIT freed 251K, 14% free 14622K/16839K, paused 3ms+6ms
...

Это сообщение появляется все время, пока вызывается метод.

И разница между v2 и v1 заключается в следующем:

pointOut = proj.toScreenLocation(geopointIn); // v2
projection.toPixels(geopointIn, pointOut); // v1

И v1 кажется более оптимизированным решением. Есть ли способ получить его быстрее? Это ошибка производительности?


person Alexander    schedule 06.10.2014    source источник
comment
Это было довольно давно, но в настоящее время я испытываю некоторые проблемы с производительностью, очень похожие на описанные здесь. Вы нашли решение для этого в какой-то момент?   -  person saberrider    schedule 18.01.2017


Ответы (2)


Я очень-очень опаздываю на вечеринку, но у меня есть ответ с помощью android.graphics.Matrix:

float getYMercator(double latitude){
    return (float)Math.log(Math.tan(Math.PI*(0.25+latitude/360.0)));
}
float [] fastToScreenLocation(GoogleMap map, List<LatLng> coordinates,int viewHeight, int viewWidth){
    VisibleRegion visibleRegion = map.getProjection().getVisibleRegion();
    Matrix transformMatrix = new Matrix();
    boolean ok = transformMatrix.setPolyToPoly(
            new float[] {
                    (float)visibleRegion.farLeft.longitude, getYMercator(visibleRegion.farLeft.latitude),
                    (float)visibleRegion.farRight.longitude, getYMercator(visibleRegion.farRight.latitude),
                    (float)visibleRegion.nearRight.longitude, getYMercator(visibleRegion.nearRight.latitude),
                    (float)visibleRegion.nearLeft.longitude, getYMercator(visibleRegion.nearLeft.latitude)
            },0,
            new float[] {
                    0, 0,
                    viewWidth, 0,
                    viewWidth,viewHeight,
                    0, viewHeight
            }, 0,
            4);
    if(!ok) return null;
    float[] points = new float[2*coordinates.size()];
    for(int i=0;i<coordinates.size();++i){
        LatLng location = coordinates.get(i);
        points[2*i]=(float)location.longitude;
        points[2*i+1]=getYMercator(location.latitude);
    }
    transformMatrix.mapPoints(points);
    return points;
}

По сути, он проецирует LatLng в псевдокоординаты WebMercator (координаты WebMercator линейно преобразуются для экономии некоторых вычислений). Затем вычисляет необходимую матрицу для преобразования видимой области в экранные координаты и применяет найденную матрицу к точкам в списке координат. Примерно в 300 раз быстрее, чем в моих тестах для списка из 150 координат на моем Samsung J3 (избегая перераспределения массива для нескольких вызовов).

person chubakueno    schedule 11.07.2018
comment
Большое спасибо! Судя по моим тестам, это действительно намного быстрее для нескольких координат и немного медленнее для одной координаты. У вас есть обратная операция (от местоположения экрана до долготы)? - person Tim Autin; 30.03.2020
comment
Кроме того, знаете ли вы, как принять текущий наклон и вращение карты? - person Tim Autin; 30.03.2020

Этот ответ приходит, вероятно, слишком поздно, но если кто-то еще столкнется с такими же проблемами, как я, решением может быть предварительный рендеринг изображения на собственном сервере с помощью Java Graphics2D (который работает почти так же, как рисование на холсте) и скачать его в приложении. Вы должны преобразовать гео точки в декартовы координаты. В приложении вам нужно только позиционировать изображение как GroundOverlay с LatLngBounds: https://developers.google.com/maps/documentation/android/groundoverlay#use_latlngbounds_to_position_an_image

и добавьте его на карту... https://developers.google.com/maps/documentation/android/groundoverlay#change_an_overlay

Для меня этот подход работает довольно быстро. По крайней мере так же быстро, как подход Google Maps V1.

person Bevor    schedule 21.02.2015