1 . 1 什么是 gis
地理信息系统 (GIS, Geographic Information System) 是一种基于计算机的工具,它可以对在地球上存在的东西和发生的事件进行成图和分析。 GIS 技术把地图这种独特的视觉化效果和地理分析功能与一般的数据库操作(例如查询和统计分析等)集成在一起。这种能力使 GIS 与其他信息系统相区别,从而使其在广泛的公众和个人企事业单位中解释事件、预测结果、规划战略等中具有实用价值。
GIS 由五个主要的元素所构成: 硬件、软件、数据、人员和方法。
GIS 就是用来存储有关世界的信息,这些信息是可以通过地 理关系连接在一起的所有主题层集合。这个简单却非常有力和通用的概念,对于解决许多真实世界的问题具有无价的作用,这些问题包括:跟 踪传输工具、记录计划的详细资料,模拟全球的大气循环等。
1 . 2 什么是 web gis
1 . 2 . 1 概念
随着 Internet 技术的不断发展和人们对地理信息系统 (GIS) 的需求,利用 Internet 在 Web 上发布和出版空间数据,为用户提供空间数据浏览、查询和分析的功能,已经成为 GIS 发展的必然趋势。于是,基于 Internet 技术的地理信息系统 --WebGIS 就应运而生。
WebGIS 是 Internet 技术应用于 GIS 开发的产物。 GIS 通过 WWW 功能得以扩展,真正成为一种大众使用的工具。从 WWW 的任意一个节点, Internet 用户可以浏览 WebGIS 站点中的空间数据、制作专题图,以及进行各种空间检索和空间分析,从而使 GIS 进入千家万户。
1 . 2 . 2WebGIS 的特点:
(1) 全球化的客户 / 服务器应用
全球范围内任意一个 WWW 节点的 Internet 用户都可以访问 WebGIS 服务器提供的各种 GIS 服务,甚至还可以进行全球范围内的 GIS 数据更新。
(2) 真正大众化的 GIS
由于 Internet 的爆炸性发展, Web 服务正在进入千家万户, WebGIS 给更多用户提供了使用 GIS 的机会。 WebGIS 可以使用通用浏览器进行浏览、查询,额外的插件 (plug-in) 、 ActiveX 控件和 Java Applet 通常都是免费的,降低了终端用户的经济和技术负担,很大程度上扩大了 GIS 的潜在用户范围。而以往的 GIS 由于成本高和技术难度大,往往成为少数专家拥有的专业工具,很难推广。
(3) 良好的可扩展性
WebGIS 很容易跟 Web 中的其他信息服务进行无缝集成,可以建立灵活多变的 GIS 应用。
(4) 跨平台特性
在 WebGIS 以前,尽管一些厂商为不同的操作系统 ( 如: Windows 、 UNIX 、 Macintosh) 分别提供了相应的 GIS 软件版本,但是没有一个 GIS 软件真正具有跨平台的特性。而基于 Java 的 WebGIS 可以做到 " 一次编程,到处运行 (write once, run anywhere)" ,把跨平台的特点发挥得淋漓尽致。
2 .开发控件的选择
目前影响较大的国外地理服务器有 Mapinfo MapXtreme 、 MapObject 、 Autodesk Map Guide 、 ArcIMS 、 Argcgisserver 以及国内的 Super Map 等。由于考虑到我们是采用 Java 语言开发基于 Web 方式的 Gis 应用,最终对比之后采用 Mapinfo 公司的 MapXtreme Java 作为开发控件进行地理应用的二次开发工具。
MapXtreme Java 是目前用于 Internet 或企业 Intranet 唯一的 100% 纯 Java 的地图服务器。 MapInfo MapXtreme Java 与 J2EE 兼容,为开发人员开发应用提供了无与伦比的灵活性。 MapXtreme Java 向应用开发商提供了一个高度可视化的、直观的组件,方便他们将地图功能集成到任何 Web 应用中。
MapXtreme Java 为 Internet 设计三种布署模式
瘦客户端 所有的地图生成 / 渲染是由服务器端完成的。客户只接收小于 20k 的 GIF 。在服务器端, MapXtreme 作为一个 Servlet 与 Web 服务器相连接,或者集成了 Web 服务器和应用服务器的功能。
中型客户端 Web 浏览器装载了一个 Java Applet ,但仍然从 MapXtreme 的 Servlet 中得到基于 GIF/JPEG 的地图图像。这种环境增加了灵活的用户交互,同时将从服务器下载的信息量降到最低。
胖客户端 装载了 applet 后, 地图以一系列矢量的形式传输到 applet 中。这样,除了可从任何远程数据库中获得的空间对象外,所有的地图功能都属于客户 applet 。这种环 境最适于更高带宽的内部网,所有的数据都能传输到每个客户端。要使用这种模式, MapXtreme 必须以命名用户方式注 册。 MapXtremeJava 以压缩了 10 倍的数据格式形成矢量流,便于网络传输,减少响应时间。
考虑到 IE 对 applet 的支持,客户端用户对 IE 的设置的反感,我们决定采用瘦客户端的部署模式。所有的地图生成全部由服务器来完成, web gis 应用中的客户端和普通 web 应用中的客户端一样。
3 . MapXtreme Java 的安装与使用
3 . 1 安装 MapXtreme Java
第一步:到网站 http://www.mapinfo.com.cn 下载开发控件 MapXtreme Java Edition 4.8.0 。
同时可以下载一些文档说明和 sample 地图供学习使用。
第二步:运行 install.exe 文件,跟普通的 windows 下安装软件一样安装。
安装成功后,开始菜单中会出现如下所示下拉菜单选项:
3 . 2 MapXtreme Java 工具的使用
3 . 2 . 1 MapXtreme Server
MapXtreme Server 是用于生成地图的 web 服务器,也即是地图服务器。
通过菜单栏中的“ Start MapXtreme Server ”启动地图服务器。
然后,我们可以打开 IE 在地址栏中输入 http://127.0.0.1:8080/ 进行访问。
我们可以看到左边的导航条中有很多有用的链接信息。主要包括对 tomcat 的管理、 API 文档的说明、地图应用的 sample 。可以根据自己的兴趣进行点击查看,进行学习。推荐先查看 Examples 中的 Servlet 部分,然后查看 Documentation 中的 MapXtreme Java API 以便有针对性的学习。
通过点击菜单目录中的“ Stop MapXtreme Server ”来关闭地图服务器。
3 . 2 . 2 MapXtreme Java Manager
通过点击菜单栏中的“ MapXtreme Java Manager - WebServer ”启动 MapXtreme Java Manager 。 注意:必须在地图服务器启动以后, MapXtreme Java Manager - WebServer 才能正常启动。
MapXtreme Java Manager 启动成功以后,会弹出如下的界面:
也可通过菜单目录的“ MapXtreme Java Manager - StandAlone ”在独立模式下启动 MapXtreme Java Manager 。后者的启动不依赖于地图服务器的启动与否。二者的区别在于后者启动方式下功能比前者少,不能与地图服务器进行交互。独立模式下启动界面如下图所示:
我们可以通过 MapXtreme Java Manager 客户端对指定格式( *.mdf 和 *.gst )的地图文件进行查看及编辑,功能十分强大。此客户端还具有 web 应用程序定制、创建用于命名地图和图层的上下文、管理 JDBC 连接等高级功能。
4 .构建自己的 web gis 应用
4 . 1 熟悉 MapJ API
MapJ 对象管理地图的状态。该对象维护地图中心和缩放、坐标系、距离单位和共同构成地图的图层。 MapJ 位于 MapXtreme 客户机 API 的最顶端。
打开 MapXtreme Java 的 API 文档,选择 com.mapinfo.mapj ,对类 MapJ 中的每个方法的使用我们都应该仔细阅读,因为在开发 web gis 的过程中我们将会用到。
其中,尤为关键的,我们需要了解如下几个方法:
MapJ 对象初始化: MapJ ()
加载地图: loadMapDefinition()
设置地图边界: setDeviceBounds()
设置地图中心: setCenter()
设置地图缩放比: setZoom()
4 . 2 熟悉 Javascript 中鼠标响应事件
我们在客户端浏览器中往往需要点击地图上的位置进行精确定位,或对地图进行放大、缩小、平移等操作,这时候就需要将客户端的请求提交到服务器端,与地图服务器进行交互。
为了实现客户端与服务器的交互,必须要能捕捉到用户的鼠标响应事件,获得鼠标指针的当前位置等信息。
其中,特别需要关注的鼠标响应事件有:
鼠标按下事件: onmousedown
鼠标松开事件: onmouseup
鼠标指针移动到元素上触发事件: OnMouseOver
此外,还可能需要用到 onclick 、 oncontextmenu 、 onmousewheel 等事件,根据自己开发的 web gis 应用的需要来选择使用。
4 . 3 开发一个完整的 web gis 应用
4 . 3 . 1 搭建开发环境
进行 web gis 开发的编程环境:
支持开发 web 应用的 Java IDE (如 MyEclipse 、 Jbuilder ),支持 servlet 的 web 应用服务器(如 tomcat 、 weblogic ),支持 javascript 的浏览器 ( 如 IE 6.0) ,标准格式的地图图片 (*.gst,*.mdf) 。
将安装目录中 MapXtreme- 4.8.0 /apache-tomcat-5.5/webapps/mapxtreme480 复制到自己的应用服务器发布目录下,或者仍沿用安装时 MapXtreme 默认安装的 tomcat 来部署地图服务器。
启动地图服务器,通过访问服务器地址 http://127.0.0.1:80/mapxtreme480/servlet/mapxtreme 来查看是否部署成功。若显示为一空白页面则表明已部署成功。
4 . 3 . 2 编写一个简单的 servlet
首先编写一个简单的 servlet ,后面我们将重写其 doGet 方法来生成地图。
将安装目录中 /MapXtreme- 4.8.0 /lib/common 中的文件和 /MapXtreme-4.8.0/lib/server 中的文件复制到自己的 web 应用中的 /WEB-INF/lib 目录下。
,然后启动 web 服务器,通过浏览器访问 servlet 看是否运行正常。
4 . 3 . 3 编写生成地图的服务端代码
这里所指的生成地图的服务端代码是指 web 服务器中 servlet 响应客户端请求生成图片信息的代码,具体讲就是指 servlet 中重写的 doGet( ) 方法中的代码。特别注意的是,这里所指的生成地图的代码是我们通过调用 MapJ 的 API 向地图服务器发送生成地图请求的代码;相对地图服务器而言,我们这里编写的又是地图服务的客户端代码;相当于 web 应用而言,我们这里编写的却又是服务端代码。
下面我们以一个实例来介绍如何调用 MapJ API 编写生成地图的服务端代码。
第一步:向地图服务器发送请求生成地图
// 输出图片的格式
private static String mimeType = "image/gif";
// mapxtremeservlet 地图服务器 url
private static String m_mxtURL = "http://localhost:80/mapxtreme480/servlet/mapxtreme";
// 实现 HttpServlet 的 doGet 方法
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
// 设置 ContentType
response.setContentType(mimeType);
// 返回响应的输出流
ServletOutputStream sos = response.getOutputStream();
// 创建 MapJ 对象
MapJ m_mapj = new MapJ();
try {
// 加载地图
String m_mapPath="E://gisapp//MapData//Others//China.mdf";
m_mapj.loadMapDefinition(m_mapPath);
// 设置地图大小
m_mapj.setDeviceBounds(new DoubleRect(0, 0, 800, 600));
request.getSession().setAttribute("worldMap", m_mapj);
// 创建图像请求器 ( 包装 mapj 对象 , 图片的色位 , 底色 , 格式信息 )
ImageRequestComposer irc = ImageRequestComposer.create(m_mapj, 256,
Color.white, mimeType);
// 创建 mxtj 的图像渲染器
MapXtremeImageRenderer renderer = new MapXtremeImageRenderer(
m_mxtURL);
// 用渲染器渲染请求器
renderer.render(irc);
// 渲染器输出图片流到输出流 , 客户端显示之
renderer.toStream(sos);
// 释放渲染器对象
renderer.dispose();
} catch (Exception e) {
System.out.println("Error");
e.printStackTrace();
}
}
第一步显示效果如下:
第二步:控制地图的显示 ( 响应客户端对地图放大、缩小、重定位、平移的请求 )
int xpoint=Integer.parseInt(request.getParameter("xpoint"));// 鼠标 left 坐标
int ypoint=Integer.parseInt(request.getParameter("ypoint"));// 鼠标 top 坐标
double zoomSize=Double.parseDouble(request.getParameter("zoomSize"));// 缩放比
// 返回响应的输出流
ServletOutputStream sos = response.getOutputStream();
// 获取地图对象
MapJ m_mapj = (MapJ)request.getSession().getAttribute("worldMap");
try {
// 设置地图大小
DoublePoint dpt= m_mapj.transformScreenToNumeric(new DoublePoint(xpoint,ypoint));
m_mapj.setCenter(dpt);
// 创建图像请求器 ( 包装 mapj 对象 , 图片的色位 , 底色 , 格式信息 )
ImageRequestComposer irc = ImageRequestComposer.create(m_mapj, 256,
Color.white, mimeType);
// 创建 mxtj 的图像渲染器
MapXtremeImageRenderer renderer = new MapXtremeImageRenderer(
m_mxtURL);
// 用渲染器渲染请求器
renderer.render(irc);
// 渲染器输出图片流到输出流 , 客户端显示之
renderer.toStream(sos);
// 释放渲染器对象
renderer.dispose();
} catch (Exception e) {
e.printStackTrace();
}
第二步,点击放大后可看到主要城市的图层信息,效果如下:
进一步放大后,能看到更多的图层信息,效果如下:
第三步:查询图层信息 ( 根据客户端点击的地图位置,展现不通的图层信息 )
PrintWriter out = response.getWriter();
HttpSession session = request.getSession();
String xmlInfo = "";
xmlInfo +="<LAYERS><CITY>";
try {
int xpoint=Integer.parseInt(request.getParameter("xpoint"));
int ypoint=Integer.parseInt(request.getParameter("ypoint"));
MapJ mainMap = (MapJ) session.getAttribute("worldMap");
FeatureLayer layer = (FeatureLayer) mainMap.getLayers().get("CHCTY_2K");
// 创建一个图原层
if (layer.isVisibleAtCurrentZoom()) {
ArrayList columns = new ArrayList();
columns.add("Place_Name");
columns.add("Latitude");
columns.add("Longitude");
DoubleRect rect = mainMap.transformScreenToNumeric(new DoubleRect(new DoublePoint(xpoint-100, ypoint-100), new DoublePoint(xpoint+100, ypoint+100)));
FeatureSet fs = layer.searchWithinRectangle(columns, rect, QueryParams.EMPTY_PARAMS);// 得到图元集
Feature f;
while ((f = fs.getNextFeature()) != null ) {
for (int i = 0; i < f.getAttributeCount(); i++) {
switch (i)
{
case 0:
xmlInfo +="<PLACENAME>"+f.getAttribute(i)+"</PLACENAME>";
break;
case 1:
xmlInfo +="<LATITUDE>"+f.getAttribute(i)+"</LATITUDE>";
break;
case 2:
xmlInfo +="<LONGITUDE>"+f.getAttribute(i)+"</LONGITUDE>";
break;
}
}
}
fs.dispose();
}
} catch (Exception ex) {
ex.printStackTrace();
}
xmlInfo +="</CITY></LAYERS>";
out.print(xmlInfo);
第三步,点击右键菜单,查看城市坐标图层信息:
查询出一定范围内的城市的坐标信息,示例效果如下:
4 . 3 . 4 控制页面与后台的交互
获取客户端鼠标点击位置 :
/**
* 获取地图的偏移量
*/
var xOffset=0;
var yOffset=0;
function getObjOffset() {
var obj=document.all( 'chinaMap' );
var xOff, yOff;
xOff = 0;
yOff = 0;
while ( null != obj) {
xOff += obj.offsetLeft;
yOff += obj.offsetTop;
obj = obj.offsetParent;
}
xOffset=xOff;
yOffset=yOff;
}
var xpoint=event.x- xOffset ;// 鼠标 x 坐标
vary point=event.y- yOffset ;// 鼠标 y 坐标
设置鼠标指针样式 :
element.style.cursor=”hand”;
element.style.cursor=”move”;
设置菜单位置 (若有右键操作时可设置):
menuDiv.style.left=event.x;
menuDiv.style.top=event.y;