具有 > 800 个 KML 数据叠加层的 Android 地图性能



我有一些形状文件,我已经将其转换为KML文件,我希望从中读取坐标,然后在MapView上的坐标之间绘制路径。在这篇精彩文章的帮助下: 如何使用 kml 文件在地图上绘制路径?我已经能够将 KML 读取到"地标"的数组列表中。然后,这篇很棒的博客文章展示了如何获取地理点列表并绘制路径:http://djsolid.net/blog/android---draw-a-path-array-of-points-in-mapview

然而,上面帖子中的示例只在某些点之间绘制了一条路径,并且由于我的路径比这多得多,因此我遇到了一些性能问题。我目前正在为每个单独的路径添加新的路由覆盖。这导致我在全部添加后有超过 800 个叠加层。这对性能有影响,我希望对我可以做些什么来改进它提供一些意见。

以下是我考虑过的一些选项:

  1. 尝试将所有点添加到列表中,然后可以将其传递到将扩展覆盖的类中。在那个新类中,也许可以在单个叠加层中添加和绘制路径?我不确定如何实现这一点,因为路径并不总是相交的,并且它们有不同的起点和终点。目前,我正在将具有多个点的每个路径添加到其自己的列表中,然后将其添加到叠加层中。这导致超过 700 个叠加层...

  2. 简化 KML 或 SHP。与其有 700 多条不同的路径,也许有某种方法将它们合并成 100 条或更少的路径?由于许多路径在某些点相交,因此应该可以修改原始SHP文件,以便它合并所有相交。由于我以前从未使用过此类文件,因此无法在 GQIS 中找到执行此操作的方法。如果有人知道如何做到这一点,我希望对此提供一些意见。如果您有兴趣,这里是形状文件组的链接:

http://danielkvist.net/cprg_bef_cbana_polyline.shp

http://danielkvist.net/cprg_bef_cbana_polyline.shx

http://danielkvist.net/cprg_bef_cbana_polyline.dbf

http://danielkvist.net/cprg_bef_cbana_polyline.prj

无论如何,这是我用来添加覆盖的代码。提前非常感谢。

路由路径叠加.java

package net.danielkvist;
import java.util.List;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.RectF;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.Projection;
public class RoutePathOverlay extends Overlay
{
    private int _pathColor;
    private final List<GeoPoint> _points;
    private boolean _drawStartEnd;
    public RoutePathOverlay(List<GeoPoint> points)
    {
        this(points, Color.RED, false);
    }
    public RoutePathOverlay(List<GeoPoint> points, int pathColor, boolean drawStartEnd)
    {
        _points = points;
        _pathColor = pathColor;
        _drawStartEnd = drawStartEnd;
    }
    private void drawOval(Canvas canvas, Paint paint, Point point)
    {
        Paint ovalPaint = new Paint(paint);
        ovalPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        ovalPaint.setStrokeWidth(2);
        int _radius = 6;
        RectF oval = new RectF(point.x - _radius, point.y - _radius, point.x + _radius, point.y + _radius);
        canvas.drawOval(oval, ovalPaint);
    }
    public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when)
    {
        Projection projection = mapView.getProjection();
        if (shadow == false && _points != null)
        {
            Point startPoint = null, endPoint = null;
            Path path = new Path();
            // We are creating the path
            for (int i = 0; i < _points.size(); i++)
            {
                GeoPoint gPointA = _points.get(i);
                Point pointA = new Point();
                projection.toPixels(gPointA, pointA);
                if (i == 0)
                { // This is the start point
                    startPoint = pointA;
                    path.moveTo(pointA.x, pointA.y);
                }
                else
                {
                    if (i == _points.size() - 1)// This is the end point
                        endPoint = pointA;
                    path.lineTo(pointA.x, pointA.y);
                }
            }
            Paint paint = new Paint();
            paint.setAntiAlias(true);
            paint.setColor(_pathColor);
            paint.setStyle(Paint.Style.STROKE);
            paint.setStrokeWidth(3);
            paint.setAlpha(90);
            if (getDrawStartEnd())
            {
                if (startPoint != null)
                {
                    drawOval(canvas, paint, startPoint);
                }
                if (endPoint != null)
                {
                    drawOval(canvas, paint, endPoint);
                }
            }
            if (!path.isEmpty())
                canvas.drawPath(path, paint);
        }
        return super.draw(canvas, mapView, shadow, when);
    }
    public boolean getDrawStartEnd()
    {
        return _drawStartEnd;
    }
    public void setDrawStartEnd(boolean markStartEnd)
    {
        _drawStartEnd = markStartEnd;
    }
}

我的地图活动

package net.danielkvist;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapView;
public class MyMapActivity extends MapActivity
{
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        MapView mapView = (MapView) findViewById(R.id.mapview);
        mapView.setBuiltInZoomControls(true);
        String url = "http://danielkvist.net/cprg_bef_cbana_polyline_simp1600.kml";
        NavigationDataSet set = MapService.getNavigationDataSet(url);
        drawPath(set, Color.parseColor("#6C8715"), mapView);
    }
    /**
     * Does the actual drawing of the route, based on the geo points provided in
     * the nav set
     * 
     * @param navSet
     *            Navigation set bean that holds the route information, incl.
     *            geo pos
     * @param color
     *            Color in which to draw the lines
     * @param mMapView01
     *            Map view to draw onto
     */
    public void drawPath(NavigationDataSet navSet, int color, MapView mMapView01)
{
    ArrayList<GeoPoint> geoPoints = new ArrayList<GeoPoint>();
    Collection overlaysToAddAgain = new ArrayList();
    for (Iterator iter = mMapView01.getOverlays().iterator(); iter.hasNext();)
    {
        Object o = iter.next();
        Log.d(BikeApp.APP, "overlay type: " + o.getClass().getName());
        if (!RouteOverlay.class.getName().equals(o.getClass().getName()))
        {
            overlaysToAddAgain.add(o);
        }
    }
    mMapView01.getOverlays().clear();
    mMapView01.getOverlays().addAll(overlaysToAddAgain);
    int totalNumberOfOverlaysAdded = 0;
    for(Placemark placemark : navSet.getPlacemarks())
    {
        String path = placemark.getCoordinates();
        if (path != null && path.trim().length() > 0)
        {
            String[] pairs = path.trim().split(" ");
            String[] lngLat = pairs[0].split(","); // lngLat[0]=longitude
                                                   // lngLat[1]=latitude
                                                   // lngLat[2]=height
            try
            {
                if(lngLat.length > 1 && !lngLat[0].equals("") && !lngLat[1].equals(""))
                {
                    GeoPoint startGP = new GeoPoint(
                            (int) (Double.parseDouble(lngLat[1]) * 1E6),
                            (int) (Double.parseDouble(lngLat[0]) * 1E6));
                    GeoPoint gp1;
                    GeoPoint gp2 = startGP;
                    geoPoints = new ArrayList<GeoPoint>();
                    geoPoints.add(startGP);
                    for (int i = 1; i < pairs.length; i++)
                    {
                        lngLat = pairs[i].split(",");
                        gp1 = gp2;
                        if (lngLat.length >= 2 && gp1.getLatitudeE6() > 0
                                && gp1.getLongitudeE6() > 0
                                && gp2.getLatitudeE6() > 0
                                && gp2.getLongitudeE6() > 0)
                        {
                            // for GeoPoint, first:latitude, second:longitude
                            gp2 = new GeoPoint(
                                    (int) (Double.parseDouble(lngLat[1]) * 1E6),
                                    (int) (Double.parseDouble(lngLat[0]) * 1E6));
                            if (gp2.getLatitudeE6() != 22200000)
                            {
                                geoPoints.add(gp2);
                            }
                        }
                    }
                    totalNumberOfOverlaysAdded++;
                    mMapView01.getOverlays().add(new RoutePathOverlay(geoPoints));
                }
            }
            catch (NumberFormatException e)
            {
                Log.e(BikeApp.APP, "Cannot draw route.", e);
            }
        }
    }
    Log.d(BikeApp.APP, "Total overlays: " + totalNumberOfOverlaysAdded);
    mMapView01.setEnabled(true);
}
    @Override
    protected boolean isRouteDisplayed()
    {
        // TODO Auto-generated method stub
        return false;
    }
}

编辑:当然还有更多文件我正在使用,但我还没有发布。您可以在此处下载完整的 Eclipse 项目:http://danielkvist.net/se.zip

您是否考虑过渲染位图的所有路径,然后将其用作叠加层,当然,如果用户放大或缩小或移动地图很多,则需要再次渲染它。使位图大到屏幕的 2 或 4 倍(请注意不要在这里用完所有内存),您应该能够进行一些放大和缩小膨胀,并允许一些平移,直到您需要再次渲染它。将其呈现为四叉树(对树中的位图引用周)将允许一些缓存和可能的重大性能改进。使用四叉树不是一个简单的方法,但如果你有时间和知识,可能值得付出努力。我相信这大致就是谷歌地图处理其地图图块的方式。

最新更新