举例来说

作者

温可维尔萨洛维奇

联系

在VIKOO.CL

最后更新

2005-12-12

备注

从7.4.0版本开始,PHP 7可以通过MapServer的 SWIG API . 我们鼓励MapServer用户使用SWIG API通过MapScript连接到PHP 7。本文档仅涵盖对遗留MapScript的支持;有关php7mapscript的最新示例,请参见 MS4W wiki 因为用户已经在那里贡献了PHP 7 mapscript脚本。

介绍

本文件旨在逐步解释 PHP映射脚本API 每一个都有实际的例子。它被假定为 MAP 和mapserver,并熟悉 PHP (scripting)HTML (markup) 语言。此文档最初是为MapServer v4.0创建的,但示例仍然适用于较新的版本。

我们开始吧…。

你好,好心的读者。我是图特,谢谢你下载我。对不起,我只是一本技术手册,所以我不能回答任何问题。维修人员,一个英俊,非常好和懒惰的家伙,根据我从屏幕的另一边看到的,也许可以回答你的问题。我现在在这里告诉您关于mapscript在其php化身中的情况。在我目前的年龄,我对初学者比高级用户更有用,尽管我希望有一天我会足够老,能够对高级mapscript程序员有用。

希望我活得够久…叹息。

但我的个人问题已经够多了,让我自己开始吧。我的职责是让您熟悉mapscript,尤其是php mapscript。当我结束时,您应该了解mapscript是什么,并且能够编写应用程序来显示和导航,即通过Web浏览器缩放和平移形状文件。

以下是您在陪同我完成余下的旅程之前必须肯定回答的问题(我为我的维护者缺乏文学品味而道歉)。

你有没有在某个地方跑步…

  • 一个能够将PHP作为CGI运行的Web服务器(Apache会这样做)?

  • PHP语言配置为CGI,4.1.2版或更高版本?我建议从4.3开始。

  • php mapscript,4.0版还是更高版本? php mapscript安装

你能。。。

  • 编码php或愿意 learn how to 是吗?

  • 写作和理解 HTML 文件?(请注意,javascript是一个加号)

  • 告诉别人到底什么是 shapefile [或 PostGIS 表?

此文档的大纲

  • 以独立于语言的方式概述mapscript

  • 一个微不足道的例子

  • 一个简单的例子

  • 结论

如果您想跳过某些部分,也可以直接通过位于顶部的目录转到每个部分。

MapScript概述

好吧,现在我终于到了我喜欢的地方。本概述旨在清除初学者在第一次面对mapscript时遇到的一些常见误解,并对mapscript的内部结构进行概述。现在,请看下面的图表(我再次为维护人员缺乏图形设计的品味而道歉)。

../../_images/phpmapscript-byexample-map.png

一切都始于网络上的一切。浏览器通过HTTP请求特定的URL。请求到达Web服务器,服务器依次传递文件或执行程序,然后将其输出返回浏览器。是的,我知道你知道,但是我被告知要尽可能完整,我会尽力的。

在mapscript的情况下,服务器执行一个特定的脚本,其中包含标准语言功能,也就是说,在没有mapscript的情况下,在该语言中具有的相同功能,加上对几乎所有mapserver c api的访问,mapserver api支持的完整性级别随您选择的语言而有所不同,但我认为它我的职责是告诉你几乎所有可用的mapscript风格都是可用的。这个API现在通过mapscript模块在脚本语言中公开,它允许您对空间数据执行许多类似于地理信息系统的操作,包括对形状文件的读写访问、数据的重投影以及许多其他操作。有关API的更多信息,请单击上面的链接。对于其他口味,您可以查看自己的文档,您会发现没有太大的区别。

运行mapscript应用程序不需要mapserver的cgi版本,就像运行cgi不需要特定的mapscript模块一样。CGI版本有许多现成的特性,mapscript只是一个API,所以对于mapscript,您必须从头开始,或者使用一些可用的示例。把CGI想象成一个直接用C语言编写的mapscript应用程序,可以直接访问mapserver c api。有时候开箱即用的功能有一些限制,这些限制可以被mapscript超越,但不能嵌入到CGI中。换句话说,CGI是不可脚本化的,但是您可以用mapscript来编程所有的CGI以及更多的CGI。这似乎是一个奇怪的事情要澄清,但是一个常见的误解,只要检查一下 list archives 如果你不愿意相信我。

与MAPServer本身一样,MAPScript只能使用 Mapfile 进行配置,但与CGI不同,它还包括动态创建地图或修改现有地图的可能性,以及将此信息与其他非地理信息系统数据源(如用户输入、非空间和空间数据)混合(这是MAPScript具有灵活性的关键)。数据库、文本文件等,您可以使用语言提供的每个模块。这种方法的威力是巨大的,最具限制性的是你的想象力。一如既往,灵活性伴随着价格、性能。通常使用脚本语言而不是C语言要慢一些,但现在这不应该是一个大问题。您仍然可以直接在C语言中编程(虽然您可能希望检查 mapserver-dev list )如果你愿意的话。

mapscript可以处理的输入和输出格式与构建mapserver/mapscript时配置的格式完全相同。但要记住的最重要的一点是,基本上,您将地理数据和相关的用户输入(例如单击地图图像)输入到mapscript,从而获得一个或多个文件,通常是标准图像文件,如png或jpeg。因此,您可以在任何服务器端脚本化Web应用程序、DHTML、Java小程序、CSS、HTML模板、会话中应用您所看到的任何东西。

我们的第一个申请

在第一个示例中,我将告诉您如何使用映射文件在网页上显示形状文件。

Mapfile

这是 Mapfile :

 1    NAME "Europe in purple"
 2    SIZE 400 400
 3    STATUS ON
 4    SYMBOLSET "/var/www/html/maps/symbols/symbols.sym"
 5    EXTENT -5696501 1923039 5696501 11022882
 6    UNITS METERS
 7    SHAPEPATH "/var/www/html/maps/data"
 8
 9    WEB
10        IMAGEPATH "/var/www/html/maps/tmp/"
11        IMAGEURL "/tmp/"
12    END
13
14    LAYER
15        NAME "Europe"
16        TYPE POLYGON
17        STATUS ON
18        DATA "europe.shp"
19        CLASS
20            STYLE
21                COLOR 110 50 100
22                OUTLINECOLOR 200 200 200
23                SYMBOL 0
24            END
25        END
26    END
27
28    END

这里我展示了一个单层的地图,其中europe.shp、europe.shx和europe.dbf文件必须位于名为data的子目录中。符号位于符号子目录中。所有这些位置都是相对于 Mapfile 所在的位置的,但我想这比对不起更安全。Web部分用于定义保存图像的位置和可用的URL。

用mapscript显示地图

要显示地图,将使用以下mapscript对象和方法:

  • MAPOBJ对象

  • ImageObj对象

MAPOBJ方法:

  • 构造器方法:mapobj ms_new mapobj(string map_file_name[,string new_map_path])

  • 绘制方法:imageobj draw()。

ImageObj方法:

  • saveWebImage方法:string saveWebImage()。

代码如下:

 1    <?php
 2
 3    dl('php_mapscript.so');
 4
 5    $map_path="/var/www/html/ms/map_files/";
 6
 7    $map = ms_newMapObj($map_path."europe.map");
 8    $image=$map->draw();
 9    $image_url=$image->saveWebImage();
10
11    ?>
12
13     <HTML>
14      <HEAD>
15          <TITLE>Example 1: Displaying a map</TITLE>
16      </HEAD>
17      <BODY>
18          <IMG SRC=<?php echo $image_url; ?> >
19      </BODY>
20     </HTML>

我将通过本文档其余部分呈现的代码将遵循以下规则:

  • 每个非空行都有编号

此代码将呈现与shapefile europe对应的图像,并将其显示在HTML页上。

代码解释

  • 在第2行中,它加载了mapscript扩展名(如果您的php.ini文件配置为自动加载,则可能不需要它)。

  • 第3行声明一个保存映射文件绝对路径的变量。

  • 第4行使用构造函数创建mapobj对象的实例。如您所见,构造函数接收映射文件的位置作为其唯一必需的参数,映射文件接收到europe.map名称。

  • 然后调用映射对象的draw方法来渲染由映射文件(第5行)定义的图像。结果(imageobj)保存在$image变量中。

  • 第6行调用savewebimage方法来生成图像文件,它返回一个字符串,该字符串表示mapfile中定义的URL(在本例中为/tmp/filename.png)。

  • 其余的行是纯HTML,第13行除外,它定义图像的源URL将是存储在$image_url中的值。

您应该在系统上测试应用程序,以检查它是否真正工作,并在继续进行更复杂的示例之前解决特定配置中可能出现的问题。

产量

输出(使用欧洲形状文件)应如下所示:

../../_images/phpmapscript-byexample-map.png

缩放与平移

现在我将告诉您如何向代码添加缩放和平移功能。

下面是新方法和调用的对象的列表。

新对象:

  • 彭波托基

  • 雷克托布杰

调用的新方法和成员:

  • 映射对象的zoompoint方法:void zoompoint(int nzoomfactor、pointobj opixelpos、int nimagewidth、int nimageheight、rectobj ogeorefext)。

  • map对象的setextent方法:$map->setextent(double minx,double miny,double maxx,double maxy);。

  • 地图对象的范围、宽度和高度成员。

  • rectobj和pointobj的构造函数:$point=ms_newpointobj();$rect=ms_newrectobj();

  • 点对象的setxy方法:$point->setxy(double x_coord,double y_coord);

  • 矩形对象的setextent方法:$rect->setextent(double minx,double miny,double maxx,double maxy);

.map文件与上一个示例中显示的文件保持相同。

php/mapscript代码

在这里我介绍了新的代码。

  1    <?php
  2
  3    dl('php_mapscript.so');
  4
  5    // Default values and configuration
  6
  7    $val_zsize=3;
  8    $check_pan="CHECKED";
  9    $map_path="/var/www/html/ms/map_files/";
 10    $map_file="europe.map";
 11
 12    $map = ms_newMapObj($map_path.$map_file);
 13
 14
 15    if ( isset($_POST["mapa_x"]) && isset($_POST["mapa_y"])
 16          && !isset($_POST["full"]) ) {
 17
 18          $extent_to_set = explode(" ",$_POST["extent"]);
 19
 20          $map->setextent($extent_to_set[0],$extent_to_set[1],
 21                          $extent_to_set[2],$extent_to_set[3]);
 22
 23          $my_point = ms_newpointObj();
 24          $my_point->setXY($_POST["mapa_x"],$_POST["mapa_y"]);
 25
 26          $my_extent = ms_newrectObj();
 27
 28          $my_extent->setextent($extent_to_set[0],$extent_to_set[1],
 29                                  $extent_to_set[2],$extent_to_set[3]);
 30
 31          $zoom_factor = $_POST["zoom"]*$_POST["zsize"];
 32          if ($zoom_factor == 0) {
 33                  $zoom_factor = 1;
 34                  $check_pan = "CHECKED";
 35                  $check_zout = "";
 36                  $check_zin = "";
 37          } else if ($zoom_factor < 0) {
 38                  $check_pan = "";
 39                  $check_zout = "CHECKED";
 40                  $check_zin = "";
 41          } else {
 42                  $check_pan = "";
 43                  $check_zout = "";
 44                  $check_zin = "CHECKED";
 45          }
 46
 47          $val_zsize = abs($zoom_factor);
 48
 49          $map->zoompoint($zoom_factor,$my_point,$map->width,$map->height,
 50                          $my_extent);
 51
 52     }
 53
 54
 55     $image=$map->draw();
 56     $image_url=$image->saveWebImage();
 57
 58     $extent_to_html = $map->extent->minx." ".$map->extent->miny." "
 59                  .$map->extent->maxx." ".$map->extent->maxy;
 60
 61     ?>
 62     <HTML>
 63     <HEAD>
 64     <TITLE>Map 2</TITLE>
 65     </HEAD>
 66     <BODY>
 67     <CENTER>
 68     <FORM METHOD=POST ACTION=<?php echo $HTTP_SERVER_VARS['PHP_SELF']?>>
 69     <TABLE>
 70     <TR>
 71          <TD>
 72                  <INPUT TYPE=IMAGE NAME="mapa" SRC="<?php echo $image_url?>">
 73          </TD>
 74     </TR>
 75     <TR>
 76          <TD>
 77                  Pan
 78          </TD>
 79          <TD>
 80                  <INPUT TYPE=RADIO NAME="zoom" VALUE=0 <?php echo $check_pan?>>
 81          </TD>
 82     </TR>
 83     <TR>
 84          <TD>
 85                  Zoom In
 86          </TD>
 87          <TD>
 88                  <INPUT TYPE=RADIO NAME="zoom" VALUE=1 <?php echo $check_zin?>>
 89          </TD>
 90     </TR>
 91     <TR>
 92          <TD>
 93                  Zoom Out
 94          </TD>
 95          <TD>
 96                  <INPUT TYPE=RADIO NAME="zoom" VALUE=-1 <?php echo $check_zout?>>
 97          </TD>
 98     </TR>
 99     <TR>
100          <TD>
101                  Zoom Size
102          </TD>
103          <TD>
104                  <INPUT TYPE=TEXT NAME="zsize" VALUE="<?php echo $val_zsize?>"
105                  SIZE=2>
106          </TD>
107     </TR>
108     <TR>
109          <TD>
110                  Full Extent
111          </TD>
112          <TD>
113                  <INPUT TYPE=SUBMIT NAME="full" VALUE="Go"
114                  SIZE=2>
115          </TD>
116     </TABLE>
117     <INPUT TYPE=HIDDEN NAME="extent" VALUE="<?php echo $extent_to_html?>">
118     </FORM>
119     </CENTER>
120     </BODY>
121     </HMTL>

此代码将缩小、放大、平移和完全还原上一示例中显示的图像。

看起来比实际情况复杂得多,很多行是HTML代码,剩下的大部分PHP代码只是处理表单等。

你应该先试试看它是怎么工作的。通过复制和粘贴代码,在您自己的服务器中进行尝试。

现在是时候让你玩一下了,看看你浏览器中的源代码,看看它是如何变化的。

完成?,现在让我们从HTML部分开始解释。

代码解释-HTML

第49行声明一个表单,第53行声明mapscript生成的图像是该表单的一部分,因此当您单击它时,单击的X和Y坐标(以像素为单位)将与其他数据一起发送,以供PHP代码处理。

如果您熟悉HTML和PHP,那么除了第98行之外,其余的HTML代码应该很容易理解,这将在适当的时候得到解释。

代码解释-php

现在看看PHP代码,它几乎是示例1中使用的相同代码,加上第9行到第37行。这些线是干什么的?

第9行检查表单中的相关变量是否已设置。mapa_x'和'mapa_y'表示单击图像的x和y坐标,“full”表示单击“full extent”按钮。

第一次显示页面时,if语句之间的代码没有执行,但其余的代码执行。第40行和第41行将“$extent”设置为“html”变量,并将映射文件中定义的范围值用空格分隔;该值将放入第98行的html变量“extent”。

现在看第11行和第12行。我们在if语句中,这意味着表单至少已经提交了一次。我们获取存储在代码前一次执行中的范围(“extent”html变量),并将映射的范围设置为最后一个范围。这允许缩放或平移上一个范围,而不是映射文件中设置的范围。

从最后一段中,您可以推断出所有默认值都设置在映射文件中,并且必须以某种方式存储通过mapscript更改并希望保留在代码中的任何内容。在这种情况下,它是通过表单中的隐藏变量完成的。对于更高级的应用程序,可以使用会话变量或数据库。

现在,您应该能够看到“完全扩展”按钮的工作原理。如果您检查第10行,它会说如果您没有按下按钮,跳过if语句中的代码,那么范围将重置为映射文件的值。您还应该看到它不一定是完整的范围(如果映射文件中的范围不是完整的范围)。

第14行和第15行声明一个新的点对象,并用用户单击的值初始化它。您不应该忘记这些值是以像素为单位的,而不是以地理坐标为单位的。

第16行到第18行创建一个新的矩形对象,并使用上一个图像的范围对其进行设置,就像在第12行中一样。事实上,这也会起作用:$my_extent=$map->extent;。

要进行所有的缩放和平移,第35行调用了zoompoint函数,但首先必须准备好它接收到的参数。您可以确定用户单击的点,以及图像的范围(分别是my-point和$my-extent),但现在您必须确定缩放系数。这就是19到33行所做的。如果您想知道为什么单选按钮的值为0、-1和1,用于平移、放大和缩小,那么现在您将知道原因了。

缩放系数为1表示缩放点操作为平移,负值表示缩小,正值表示放大。因此,通过将接收到的单选按钮值(HTML变量“zoom”)乘以用户输入的缩放大小,就可以计算出缩放系数。如果该值为0,则表示用户选择了平移操作,因此“$zoom_factor”设置为1,否则乘法的结果是需要接收的缩放因子zoompoint。其他行用于保留用户下次单击的按钮。第34行试图保留用户输入的缩放大小值(它不会一直这样做,何时以及为什么该行失败?这是你要知道的)。

最后,第34行使用获得的缩放因子调用zoom point方法,即根据像素坐标构建的点(我坚持这个问题,因为zoom point几乎是接收像素坐标的唯一方法,对于其他方法,您必须自己将像素转换为地理参考坐标),i的高度和宽度法师,和范围。

调用zoompoint后,图像的范围将根据所执行的操作(或者,更好地说,缩放系数)进行相应的更改。然后绘制图像并保存当前范围(缩放后),以便在下一次迭代中使用。

结论

好吧,我该去给电池充电了。所以我会用最后的能量来分享最后的话。我在这里介绍的例子非常基本,但是你现在应该能够设计出改进它们的方法,并使之适合你的需要。请记住,您可以从通常可以通过PHP读取的任何源代码预处理、存储、读取、写入数据,以及MapServer可以处理的所有GIS数据源。您甚至可以使用PHP处理一些地理信息系统数据,前提是需要(SQL源就是一个很好的例子)。您还可以使用混合方法,其中一些脚本准备数据,然后通过到MapServer的CGI接口显示这些数据,或者基于GPS的输入动态创建数据,等等。这种可能性太多,无法完全枚举。正如我已经说过的,你的想象力是极限。本文档的下一个版本将包括包含多个层、具有不同数据源(不只是形状文件)和创建动态层和类的示例。如果你有更好的主意,或者想先在这里看看其他的东西,请给我的维修人员写张便条。

同时,如果您需要更大的示例,您可以参考原始的“GMAP演示”(您可以下载源代码 hereMapTools site (对于较旧的maplab,是基于phpmapscript构建的变色龙应用程序)。再见,谢谢你读到这里。