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");
}