Android地图效果与> 800个KML数据叠加

时间:2012-04-13 12:05:41

标签: android performance overlay kml qgis

我有一个形状文件,我已经转换为KML文件,我希望从中读取坐标,然后在MapView上的坐标之间绘制路径。在这篇伟大的帖子的帮助下:How to draw a path on a map using kml file?我已经能够将KML读入“地标”的ArrayList中。这篇精彩的博文随后展示了如何获取GeoPoints列表并绘制路径:http://djsolid.net/blog/android---draw-a-path-array-of-points-in-mapview

上面的帖子中的示例仅在某些点之间绘制了一条路径,因为我有比路径更多的路径遇到一些性能问题。我正在为每个单独的路径添加一个新的RouteOverlay。这导致我在添加全部时覆盖800多个叠加层。这有一个性能影响,我希望我能做些什么来改进它。

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

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

  2. 简化KML或SHP。而不是拥有超过700条不同的路径,或许有可能将它们合并到100条或更少的路径中?由于很多路径在某​​些点交叉,因此应该可以修改原始SHP文件,以便合并所有交叉点。因为在我无法在GQIS中找到这样的方法之前,我从未使用过这些类型的文件。如果有人知道如何做到这一点我会喜欢这方面的一些意见。如果您有兴趣,可以使用以下链接指向形状文件组:

  3. 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

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

    RoutePathOverlay.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;
        }
    }
    

    MyMapActivity

    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

1 个答案:

答案 0 :(得分:1)

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