1

I have big street shape file of all California roads. It takes a very long time whenever I make the map window to redraw the map (zoom in, zoom out, moving the map around ...) . I wonder if there is any ways to tell the map windows to render only a certain number of streets based on a specific extent. That way I can improve the overall performance of my application. Any help would be appreciated.

Vu Tran,

4

1 回答 1

1

DotSpatial 等地图应用程序将尝试在屏幕上为您加载的 shapefile 渲染所有矢量。它们不会尝试绘制任何不在当前范围内的线。但是当您缩小时,他们会尝试准确地绘制所有线条,这很慢。一种可能有帮助的策略是设置可见性比例,以便仅在放大后绘制图层。DotSpatial 中的图层类允许您为图层设置动态可见性,以便仅在放大时绘制完整的 shapefile某一点。

myLayer.UseDynamicVisiblity = true;
myLayer.DynamicVisibilityMode = DynamicVisibilityMode.ZoomedIn;
myLayer.DynamicVisibiltyWidth = .2; // eg. .2 degrees of longitude in WGS84 

此策略的唯一缺点是,在放大到指定范围之前,您根本看不到任何道路。因此,一种选择是创建一个低分辨率版本的道路形状,当您缩小时看起来还不错,但不包含任何“重复”点以用于更大的网格尺寸。您可以通过使用另一个线 shapefile 或通过创建图像或创建图像平铺来执行此操作。下面的第一个示例使用 1000 x 1000 的网格大小,以便将冗余点减少到最小表示。使用不同网格大小和动态可见性的组合,您应该能够更有效地渲染大型线条 shapefile。栅格通常具有概览,但矢量通常没有,因此这是为矢量创建人工概览的一种方法。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using DotSpatial.Data;
using DotSpatial.Projections;
using DotSpatial.Topology;

namespace WindowsFormsApplication3
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Shapefile source = new Shapefile();
            source = Shapefile.OpenFile(@"C:\Data\Rivers\River.shp");

            bool[,] pointRepresented = new bool[1000, 1000];
            double width = source.Extent.Width;
            double height = source.Extent.Height;
            double dx = width / 1000;
            double dy = height / 1000;
            FeatureSet result = new FeatureSet(FeatureType.Line);
            result.Projection = KnownCoordinateSystems.Geographic.World.WGS1984; // lat lon in WGS84
            result.DataTable.Columns.Add("Index", typeof(int));
            int index = 0;
            foreach (ShapeRange shape in source.ShapeIndices) {

                bool started = false;
                List<LineString> linestrings = new List<LineString>();
                foreach (PartRange part in shape.Parts) {
                    List<Coordinate> coords = new List<Coordinate>();
                    foreach (Vertex vert in part) {
                        int i = (int)((vert.X - source.Extent.MinX) / dx);
                        int j = (int)((vert.Y - source.Extent.MinY) / dy);
                        if (i > 999) {
                            i = 999;
                        }
                        if (j > 999) {
                            j = 999;
                        }
                        if (pointRepresented[i, j] == true) continue;
                        coords.Add(new Coordinate(vert.X, vert.Y));
                        pointRepresented[i, j] = true;
                    }
                    if (coords.Count > 0) {
                        if (coords.Count == 1) {
                            coords.Add(coords[0]); // add a duplicate "endpoint" to the line if we only have one point.
                        }
                        linestrings.Add(new LineString(coords));
                    }
                }
                if (linestrings.Count > 0) {
                    IFeature feature;
                    if (linestrings.Count > 1)
                    {
                        feature = result.AddFeature(new MultiLineString(linestrings));
                    }
                    else {
                        feature = result.AddFeature(linestrings[0]);
                    }
                    feature.DataRow["Index"] = index;
                    index++;
                }
                result.SaveAs(@"C:\Data\Rivers\RiverPreview.shp", true);
            }

            MessageBox.Show(@"Finished creating file: C:\Data\Rivers\RiverPreview.shp");
        }
    }

}

第二种方法使用 DP 线简化,不会删除形状,而是简单地减少用于表示每个形状的点数。必须调整容差以匹配您的数据集和坐标。

        /// <summary>
        /// This alternative uses DP line simplification, which keeps every shape, but "simplifies" the shape, simply reducing
        /// the number of points.  This will not accomplish the goal of reducing the number of shapes, but will
        /// give you a reduced representation that matches the original features in cases where slowness is caused
        /// by too much detail, which can be useful if you still want to keep all your features.
        /// </summary>
        private void button2_Click(object sender, EventArgs e)
        {
            Shapefile source = new Shapefile();
            source = Shapefile.OpenFile(@"C:\Data\Rivers\River.shp");
            FeatureSet result = new FeatureSet(FeatureType.Line);
            result.Projection = source.Projection;
            result.CopyTableSchema(source);
            foreach (IFeature feature in source.Features) {
                LineString linestring = feature.BasicGeometry as LineString;

                if (linestring != null)
                {
                    IList<Coordinate> points = linestring.Coordinates;
                    IList<Coordinate> simplified = DouglasPeuckerLineSimplifier.Simplify(points, .00002);
                    IFeature resultFeature = result.AddFeature(new LineString(simplified));
                    resultFeature.CopyAttributes(feature);
                }
                else {
                    MultiLineString multipleLines = feature.BasicGeometry as MultiLineString;

                    if (multipleLines != null)
                    {
                        List<LineString> resultLines = new List<LineString>();
                        foreach (IGeometry line in multipleLines.Geometries)
                        {
                            IList<Coordinate> points = line.Coordinates;
                            IList<Coordinate> simplified = DouglasPeuckerLineSimplifier.Simplify(points, .00002);
                            resultLines.Add(new LineString(simplified));
                        }
                        IFeature resultFeature = result.AddFeature(new MultiLineString(resultLines));
                        resultFeature.CopyAttributes(feature);
                    }
                }
            }

            result.SaveAs(@"C:\Data\Rivers\RiverSimplified.shp", true);
            MessageBox.Show(@"Finished creating file: C:\Data\Rivers\RiverSimplified.shp");
        }
于 2013-08-15T16:32:25.670 回答