使用 SharpMap 在 ASP.NET 2.0 中创建交互式地图






4.76/5 (34投票s)
一篇关于如何使用 SharpMap 在 ASP.NET 2.0 中创建 Web 地图应用程序的文章。

引言
在网上展示地图正变得越来越普遍。其中最著名的有 Google Maps 和 Microsoft 的 Virtual Earth。创建自己的交互式地图网站需要您掌握地图数据,并将这些数据转换为动态生成的图像以在网页上显示。本文将介绍地图数据的基础知识,并使用免费的 .NET 2.0 地图引擎 SharpMap 在 ASP.NET 2.0 应用程序中生成地图。
背景
尽管本文并非旨在成为地理信息系统和地图数据工作原理的大型教程,但如果对该领域不熟悉,一些基本知识是必要的。地图数据可分为两类:矢量数据和栅格数据。栅格数据的一个例子是卫星图像,就像 Google Maps 上提供的那些。尽管存在其他几种类型的栅格数据,但真实世界的图像是最常见的。
我们所知道的许多地图数据只是我们所知世界的简单表示。例如,道路可以表示为一条线,湖泊可以表示为一个多边形,火车站可以表示为一个点。拥有矢量数据可以轻松地以您自己的颜色和样式、大小和缩放级别渲染您自己的地图,并且您可以自由选择您想要的数据,或者省略您不想包含的数据。
最大的问题通常是获取数据(尤其是好的、详细的数据)。制作和维护这些数据成本高昂,因此数据所有者通常会要求付费。有几个国家(包括美国)免费提供其国家地图,因此请向您的国家地籍局查询,看看他们是否提供任何数据。还有一些网站提供免费的地图数据。示例中未包含任何地图数据,因为我不想冒险忽略网上提供的免费数据的任何限制,因此您需要自己找到一些数据来测试本文中的示例。
有一点您需要注意,即使您从不同来源获取数据,它们也存储在相同的坐标系统、基准和投影中。如果不是这样,将它们放在一起时它们将无法匹配。
最著名的坐标系统是经纬度系统,它使用十进制度数表示地球上任何位置的坐标。其他系统仅用于本地区域,使用米作为单位,依此类推。基准通过将地球近似为一个椭球体来定义地球的形状。由于地球不是一个椭球体,因此创建了一些基准来拟合局部区域并产生较小的误差,而另一些基准则试图拟合整个地球的平均值。最受欢迎的是 WGS84(1984 年世界大地测量基准),全球定位系统使用的是它。拥有不同基准的数据可能会导致数据的大幅偏移,因此让所有数据都采用相同的基准至关重要。您应该注意的最后一件事是投影。投影定义了椭球体如何映射到一张平纸上。有很多投影,有些旨在保留角度,有些旨在保留面积,等等。
将矢量数据转换为可在浏览器中查看的位图,需要将多边形、线和点从世界坐标系转换为图像坐标系,并逐个对象地在位图上渲染。
SharpMap 是一个帮助您将矢量数据渲染到位图的引擎,该位图可以存储在磁盘上或发送到浏览器。SharpMap 是在 .NET 2.0 平台上开发的,它使用 GDI+ 来渲染您指定的对象,并且您可以使用所有出色的 GDI+ 画笔和钢笔。目前,它支持读取 ESRI Shapefile 格式(这是最常见的格式)或直接从 PostGreSQL Spatial 数据库读取,但可以通过其提供程序模型轻松扩展以读取更多格式。SharpMap 还支持 ECW 和 JPEG2000 栅格图像,以及从外部 WMS 服务器检索数据,这些内容在此不作介绍。
SharpMap 是免费的,可以从其 网页 下载。
Using the Code
SharpMap 的基本用法包括定义数据层、它们的渲染样式、定义视图以及最终的地图实际渲染。创建交互式地图应用程序需要您将地图发送到浏览器,并处理图像上的单击事件,以便用户可以缩放或平移地图。
//Defining a layer
SharpMap.Layers.VectorLayer layCountries =
new SharpMap.Layers.VectorLayer("Countries");
//Set the datasource to a shapefile in the App_data folder
layCountries.DataSource = new SharpMap.Providers.ShapeFile(
Server.MapPath(@"~\App_data\countries.shp"), true);
上面的代码定义了一个名为“Countries
”的新数据层,并将 DataSource
指向一个包含世界各国的 ShapeFile
。DataSource
中的 true 参数指定 SharpMap
使用基于文件的空间索引器。空间索引将帮助 SharpMap
通过使用空间索引快速查找视图中可见的对象来更快地渲染地图。索引的创建可能需要几秒钟,因此使用基于文件的索引将允许 SharpMap
将空间索引存储在磁盘上,以便在应用程序重新启动后更快地加载。在 ASP.NET 上下文中工作时,索引在应用程序的整个生命周期内都存储在内存中,因此这是 application_start
事件之后的一个问题。其次,我们需要定义层的样式。
//Set fill-style to green
layCountries.Style.Fill = new SolidBrush(Color.Green);
//Set the polygons to have a black outline
layCountries.Style.Outline = System.Drawing.Pens.Black;
layCountries.Style.EnableOutline = true;
国家层将以绿色填充、黑色边框呈现。您也可以使用 TextureBrush
用图像或其他 GDI+ 提供的画笔填充。让我们也添加一个铁路主题。通常,铁路表示为粗实的点状线。我们可以通过添加以下代码来实现:
//Defining a railroad
layer SharpMap.Layers.VectorLayer layRail = new
//Set the datasource to a shapefile in the App_data
SharpMap.Layers.VectorLayer("Railroads");
folder layRail.DataSource =
new SharpMap.Providers.ShapeFile(
Server.MapPath(@"~\App_data\railroads.shp"), true);
//Define a black 3px wide pen
myRail.Style.Line = new Pen(Color.Black,3);
//Set a dash-pattern
myRail.Style.Line.DashPattern = new float[] { 4.0f, 2.0f };
最后,我们需要定义我们的地图并添加图层
//Create a map rendering initialized 400 x 200 pixels
SharpMap.Map myMap = new SharpMap.Map(new Size(400,200));
//Add the layer
myMap.Layers.Add(layCountried);
//Zoom the map to the extents of all added layers:
myMap.ZoomToExtents();
//Render the map
Image imgMap = myMap.GetMap();
就这些!现在,您可以随意使用 imgMap
。您可以将其流式传输到浏览器、保存到磁盘、打印等。幸运的是,SharpMap
提供了一些将图像发送到浏览器的辅助类,并且标准的 ASP.NET 方法可以帮助我们在浏览器中轻松创建交互式地图。SharpMap
具有用于将地图存储在缓存中的类,以及一个用于将其再次检索的 HttpHandler
。要启用 HttpHandler
,请在您的 web.config 文件中添加以下处理程序,通过向 HttpHandler
设置添加一个 verb:
<?xml version="1.0"?>
<configuration>
<system.web>
<httpHandlers>
<add verb="*" path="GetMap.aspx"
type="SharpMap.Web.HttpHandler,SharpMap"/>
</httpHandlers>
</system.web>
</configuration>
这将使 SharpMap
处理对 GetMap.aspx 文件的任何请求。当然,您可以更改 path
属性以避免与现有页面发生任何冲突。现在,我们所要做的就是将生成的图像馈送到 SharpMap
的缓存中,并向浏览器返回一个路径。在将图像存储在缓存中时,SharpMap
会返回一个地图 ID,您可以使用该 ID 将其发送到客户端,如下所示:
//Place the map in the cache and leave it
//there for 5 minutes
string imgID = SharpMap.Web.Caching.InsertIntoCache(5,
imgMap, Session.SessionID, Context);
//Set the ImageUrl of our ASP.NET image-control to the
//handler and the returned ID
imgMap.ImageUrl =
"getmap.aspx?ID=" + HttpUtility.UrlEncode(imgID);
如果您将 ASP.NET 图像更改为 ImageButton
,客户端可以单击地图,您可以请求客户端单击的点。因此,要响应单击,我们所要做的就是从事件中获取单击坐标,将其从图像坐标转换为世界坐标,并相应地做出反应。单击地图通常会导致将单击点居中,并在用户选择缩放时进行放大/缩小。这可以通过设置地图的 Zoom
和 Center
属性来完成。
protected void imgMap_Click(object sender, ImageClickEventArgs e)
{
//Center map
myMap.Center = SharpMap.Utilities.Transform.MapToWorld(
new System.Drawing.Point(e.X, e.Y), myMap);
//Zoom in 2x
myMap.Zoom *= 0.5;
//Call function that renders the map and returns
//it to the client
CreateMap();
}
Zoom
值定义了以世界坐标单位表示的地图宽度。在基于经纬度的地图中,缩放到世界范围需要将缩放值设置为 360。我们可以轻松添加一组单选按钮,用户可以在其中选择“平移”、“放大”或“缩小”。然后根据所选工具设置 Zoom
值。我在示例中实现了这种方法。
关注点
SharpMap 中还有许多尚未涵盖的功能,我将在之后介绍一些有关调整渲染速度、创建高级布局、利用连接池以及将地图与在线资源和 AJAX 方法结合使用等方面的内容。开发 SharpMap 是一次很棒的经历,实践让我对 API 设计、泛型、其他新的 .NET 2.0 功能有了比任何书本都多的了解(而且还有很多工作要做,还有很多需要学习)。我同样对仅仅使用 GDI+ 进行地图渲染所能获得的性能和质量感到惊讶。
历史
- 2005 年 11 月 24 日 - 初始文章版本