瓦片模式

作者

Paul Ramsey

联系方式

pramsey at cleverelephant.ca

最后更新

2008-04-30

介绍

MapServer可以使用CGI的“tile模式”直接为基于tile的地图客户端提供数据。基于图块的地图客户端通过将世界地图分为若干个不连续的缩放级别来工作,每个级别分为若干大小相同的“图块”。而不是通过请求边界框来访问地图,图块客户端通过访问单个图块来构建地图。

配置

“mapserv”cgi程序处理tile请求。为了在正确的投影中返回图块,必须在打开--use proj选项的情况下构建mapserver。通过使用“-v”选项运行它并查找“supports=proj”,可以检查您的“mapserv”版本是否具有投影支持。

例1。在UNIX上::

$ ./mapserv -v
MapServer version 4.6.1 OUTPUT=GIF OUTPUT=PNG OUTPUT=JPEG OUTPUT=WBMP OUTPUT=PDF
OUTPUT=SWF OUTPUT=SVG SUPPORTS=PROJ SUPPORTS=FREETYPE SUPPORTS=WMS_SERVER
SUPPORTS=WMS_CLIENT SUPPORTS=WFS_SERVER SUPPORTS=WFS_CLIENT SUPPORTS=WCS_SERVER
INPUT=JPEG INPUT=POSTGIS INPUT=OGR INPUT=GDAL INPUT=SHAPEFILE DEBUG=MSDEBUG

例2。在Windows上::

C:\apache\cgi-bin> mapserv -v
MapServer version 4.6.1 OUTPUT=GIF OUTPUT=PNG OUTPUT=JPEG OUTPUT=WBMP OUTPUT=PDF
OUTPUT=SWF OUTPUT=SVG SUPPORTS=PROJ SUPPORTS=FREETYPE SUPPORTS=WMS_SERVER
SUPPORTS=WMS_CLIENT SUPPORTS=WFS_SERVER SUPPORTS=WFS_CLIENT SUPPORTS=WCS_SERVER
INPUT=JPEG INPUT=POSTGIS INPUT=OGR INPUT=GDAL INPUT=SHAPEFILE DEBUG=MSDEBUG

MapServer要求 Mapfile 中的每个层都有一个有效的投影块来支持重投影。因为平铺模式使用重投影,所以必须确保每个层都有一个有效的投影块。

配置检查表:

从MapServer 6.0开始,有两个额外参数可用于配置平铺模式。

  • *tile_map_edge_buffer*将tile渲染到缓冲渲染帧中,然后剪辑出最终的tile。这将减少绘制大符号或宽线时的边缘效果。建议值: Mapfile 中最大符号或线条宽度的大小。

  • *tile_-metatile_-level*将切片渲染为固定的metatile,然后剪切出最终的切片。这将减少标签重复,但会降低渲染成本。建议值:如果您正在为层中的大型功能添加标签,则为1,否则为0。

如果两者都使用 tile_map_edge_buffertile_metatile_level 同时,缓冲区将在meta-tile级别应用。

利用

mapserver tile支持为CGI接口添加了三个新指令:

  • *模式=tile*告诉服务器根据其他tile模式参数生成tile

  • *tilemode=gmap*告诉服务器使用google maps tile方案

  • tile=x+y+z使用google maps tile寻址系统告诉服务器要检索什么tile

  • *tilemode=ve*告诉服务器使用虚拟地球tile命名方案来命名tiles

  • tile=10231使用虚拟地球tile寻址系统告诉服务器要检索什么tile

关于球形墨卡托

Spherical Mercator (也被一些人称为“网络墨卡托”)是一个世界投影。所有主要的基于图块的地图界面(谷歌地图、微软虚拟地球、雅虎地图、Openlayers)都使用球面墨卡托系统来处理图块。

球形墨卡托切片集具有以下特性:

  • 利用球面墨卡托算法将地图重新投影到墨卡托

  • 在顶部缩放级别中有一个图块,缩放级别为零

  • 每个连续缩放级别(Z)沿每个轴具有2^Z平铺

  • 切片尺寸为256x256

谷歌地图和虚拟地球都使用球面墨卡托作为底层切片投影,但使用不同的格式来处理各个切片。

谷歌地图使用“x”、“y”、“zoom”格式。缩放指示要从哪个级别拖动切片,“X”和“Y”指示要从哪个缩放级别拖动切片。

虚拟地球使用一个字符串来寻址每个图块。虚拟地球的最高缩放级别有四个图块(相当于谷歌的缩放级别1)。虚拟地球顶部缩放级别的左上角平铺地址为“0”,右上角为“1”,左下角为“2”,右下角为“3”。下一层的每个图块都是通过首先引用包含它的顶层图块,然后引用它相对于该图块的地址来寻址的。因此,第二个缩放级别的左上角平铺为“00”,右下角平铺为“33”。有关详细信息,请访问虚拟地球网站:http://msdn.microsoft.com/en-us/library/bb545006.aspx

使用谷歌地图

这个 Google Maps API 包括支持将可选切片集用作套印格式或备用基础地图。下面是一个例子 GTileLayerOverlay

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<!DOCTYPE html
  PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Google/MapServer Tile Example</title>
<script src="http://maps.google.com/maps?file=api&v=2&key=[YOUR KEY HERE]"
        type="text/javascript"></script>
<script type="text/javascript">

function load() {
  if (GBrowserIsCompatible()) {
    var urlTemplate = 'http://localhost/cgi-bin/mapserv?';
        urlTemplate += 'map=/var/map.map&';
        urlTemplate += 'layers=layer1 layer2&';
        urlTemplate += 'mode=tile&';
        urlTemplate += 'tilemode=gmap&';
        urlTemplate += 'tile={X}+{Y}+{Z}';
    var myLayer = new GTileLayer(null,0,18,{
                                 tileUrlTemplate:urlTemplate,
                                 isPng:true,
                                 opacity:1.0 });
    var map = new GMap2(document.getElementById("map"));
    map.addControl(new GLargeMapControl());
    map.addControl(new GMapTypeControl());
    map.setCenter(new GLatLng(35.35, -80.55), 15);
    map.addOverlay(new GTileLayerOverlay(myLayer));
  }
}

</script>
</head>
<body onload="load()" onunload="GUnload()">
  <div id="map" style="width: 500px; height: 500px"></div>
</body>
</html>

请注意tileurltemplate的格式:一个有效的URL,带有x、y和z替换标记,Google地图将替换为平铺坐标和动态缩放级别,以便从您的服务器检索平铺。

您还可以将MapServer平铺层用作备用基础映射:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<!DOCTYPE html
  PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Google/MapServer Tile Example</title>
<script src="http://maps.google.com/maps?file=api&v=2&key=[YOUR KEY HERE]"
        type="text/javascript"></script>
<script type="text/javascript">

function load() {
  if (GBrowserIsCompatible()) {
    var urlTemplate = 'http://localhost/cgi-bin/mapserv?';
        urlTemplate += 'map=/var/map.map&';
        urlTemplate += 'layers=layer1 layer2&';
        urlTemplate += 'mode=tile&';
        urlTemplate += 'tilemode=gmap&';
        urlTemplate += 'tile={X}+{Y}+{Z}';
    var myLayer = new GTileLayer(null,0,18,{
                                 tileUrlTemplate:urlTemplate,
                                 isPng:true,
                                 opacity:0.3 });
    var map = new GMap2(document.getElementById("map"));
    map.addControl(new GLargeMapControl());
    map.addControl(new GMapTypeControl());
    map.setCenter(new GLatLng(35.35, -80.55), 15);
    var myMapType = new GMapType([myLayer], new GMercatorProjection(18), 'MapServer');
    map.addMapType(myMapType);
  }
}

</script>
</head>
<body onload="load()" onunload="GUnload()">
  <div id="map" style="width: 500px; height: 500px"></div>
</body>
</html>

与上一个示例相比,唯一的变化是我们不创建gtilelayerOverlay,而是创建一个gmapype,并使用addmapType(),而不是addOverlay()。

使用虚拟地球

这个 Virtual Earth API 还包括支持将备选图块集用作覆盖图或备选基础图。下面是一个例子:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
  <title>Virtual Earth Example</title>
  <script type="text/javascript" src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.1"></script>
  <script type="text/javascript">

    var map = null;

    function OnLoadMap () {
      map = new VEMap("myMap");
      map.LoadMap();

      var url = "http://localhost/cgi-bin/mapserv?";
      url += "map=/var/map.map&";
      url += "mode=tile&";
      url += "layers=layer1 layer2&";
      url += "tilemode=ve&";
      url += "tile=%4";

      var tileSourceSpec = new VETileSourceSpecification( "myLayer", url );
      tileSourceSpec.Opacity = 0.3;
      map.AddTileLayer(tileSourceSpec, true);
    }

  </script>
</head>
<body onload="OnLoadMap();">
  <div id="myMap" style="position:relative; width:500px; height:500px;"></div>
</body>
</html>