关闭

一步步DIY: OSM-Web服务器(五) GeoServer与矢量叠加图层

8012人阅读 评论(2) 收藏 举报
分类:
(-:<转载时请注明本文由goldenhawking在 CSDN blog 撰写http://write.blog.csdn.net/postedit/7964712

      只有栅格图层是没有意义的,我们需要矢量图层才能实现自己的功能。这里实现的功能是获取公司外派的外卖员的位置,并显示他们最后一次按动汇报器按钮的时刻,以便公司掌握这些员工的交通安全、买卖效率。员工ID 是唯一的工号,姓名、正在执行的送外卖对象的电话、地址。下面,我们来实现这个Web应用。

<0>、数据环境

         数据使用PostgreSQL 视图发布,该视图主要字段:

         1、id , 员工ID 

         2、s_tel, 员工电话

         3、t_tel , 外卖对象电话

         4、t_addr, 外卖对象位置

         5、d_starttm 任务开始时刻

         6、lat, 当前经度

         7、lon ,当前纬度

         8、GEO类型摩卡托坐标字段

CREATE TABLE express_status
(
  id character varying(16) NOT NULL,
  s_tel character varying(20),
  t_tel character varying(20),
  t_addr character varying(64),
  d_starttm timestamp with time zone,
  lat double precision NOT NULL DEFAULT 0,
  lon double precision NOT NULL DEFAULT 0,
  CONSTRAINT pk_id PRIMARY KEY (id )
)
WITH (
  OIDS=FALSE
);

CREATE OR REPLACE VIEW view_express_status AS
 SELECT express_status.id, express_status.s_tel, express_status.t_tel, express_status.t_addr, express_status.d_starttm, express_status.lat, 
express_status.lon, st_transform(st_setsrid(st_makepoint(express_status.lon, express_status.lat), 4326), 900913) AS geobj
   FROM express_status;      

           第八个字段,摩卡托投影的字段非常重要,使用 ST_Transform(ST_SetSRID(ST_MakePoint(lon,lat),4326),900913) 把经纬度的wgs84变为摩卡托的900913投影系,否则,在 OpenLayers 上就需要做很多的设置。

<1>、安装配置GeoSevrer

     下载GeoServer到本地,这里是2.1.4版本。下载后,解压到喜欢的地方待用。这里设置在 ~/bin/geoserver-2.1.4下。

     sudo nano /etc/environment

     设置 JAVA_HOME 环境变量到安装的JAVA虚拟机(JVM)路径,/usr/lib/jvm/default-java

           JAVA_HOME="/usr/lib/jvm/default-java"

     设置GEOSERVER_HOME 到安装路径

         GEOSERVER_HOME="/home/goldenhawking/bin/geoserver-2.1.4"

     直接运行 $(GEOSERVER_HOME)/bin/startup.sh 即可启动。stop终止,很方便的。

    测试,访问 127.0.0.1:8080/geoserver/web/出现起始页面即可。初始用户密码  admin   :   geoserver

<2> 创建新的数据服务

      1、 在 Web页面上首先创建一个workspace 叫 expresstatus ,uri也是 expresstatus

      2、创建 Stores,名字叫 storexpresstatus,工作空间是 expresstatus, 数据库连接写好后,会列出数据库里的表,选择我们的视图view_express_status,并publish

      3、系统调到创建图层的界面,主要注意的是,全球摩卡托的 bbox 为 正负20037508.342789,换算过去纬度为正负85

    测试地址http://192.168.1.100:8080/geoserver/expresstatus/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=expresstatus:view_express_status&maxFeatures=1,如果看到 下面的类似东西,就好啦:


<3> 为 OpenLays设置代理服务

     这张视图存储在PostgreSQL服务器上,但是位于另外一台机器。我们的GeoServer也位于另外一台机器,所以,首先要做的是突破 Ajax 默认拒绝异地XMLRequest的安全限制。根据OpenLayers 2.10 Beginner's Guide - E. Hazzard 书中所说,到http://trac.osgeo.org/openlayers/browser/trunk/openlayers/examples/proxy.cgi下载proxy.cgi,拷到自己的/usr/lib/cgi-bin下,别忘了把geoserver 所在的ip 追加到proxy.cgi准许访问网站中。

# Designed to prevent Open Proxy type stuff.
17	
18	allowedHosts = ['www.openlayers.org', 'openlayers.org', 
19	                'labs.metacarta.com', 'world.freemap.in', 
20	                'prototype.openmnnd.org', 'geo.openplans.org',
21	                'sigma.openplans.org', 'demo.opengeo.org',
22	                'www.openstreetmap.org', 'sample.azavea.com',
23	                'v2.suite.opengeo.org', 'v-swe.uni-muenster.de:8080', 
24	                'vmap0.tiles.osgeo.org', '192.168.1.100:8080']

在 OpenLayers 的 init里,写入

OpenLayers.ProxyHost = '/cgi-bin/proxy.cgi?url=';

这样,在下载时,Ajax即可访问与脚本所在位置不同的东东。

<4>  实现相关网页脚本

在前面章节的基础上,我们加入一个图层,并设置好单击的事件为在侧边的DIV上显示详细的信息。看看Init

        function init() {
            OpenLayers.ProxyHost = '/cgi-bin/proxy.cgi?url='
            map = new OpenLayers.Map("map", {
                controls: [
                    new OpenLayers.Control.Navigation(),
                    new OpenLayers.Control.PanZoomBar(),
                    new OpenLayers.Control.Permalink(),
                    new OpenLayers.Control.ScaleLine({ geodesic: true }),
                    new OpenLayers.Control.Permalink('permalink'),
                    //new OpenLayers.Control.KeyboardDefaults(),
                    new OpenLayers.Control.LayerSwitcher(),
                    new OpenLayers.Control.Attribution()],
                maxExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34, 20037508.34, 20037508.34),
                maxResolution: 156543.0339,
                numZoomLevels: 19,
                units: 'm',
                projection: new OpenLayers.Projection("EPSG:900913"),
                displayProjection: new OpenLayers.Projection("EPSG:4326")
            });

            // This is the layer that uses the locally stored tiles
            var newLayer = new OpenLayers.Layer.OSM("OSM Tiles", "/osm_tiles2/${z}/${x}/${y}.png", { numZoomLevels: 19, transitionEffect: "resize" });
            map.addLayer(newLayer);

            var vector_layer = new OpenLayers.Layer.Vector('Express Status', {
                projection: new OpenLayers.Projection('EPSG:900913'),
                protocol: new OpenLayers.Protocol.HTTP({
                url: 'http://192.168.1.100:8080/geoserver/expresstatus/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=expresstatus:view_express_status&maxFeatures=50',
                format: new OpenLayers.Format.GML({
                        extractAttributes:true
                    })
                }),
                strategies: [new OpenLayers.Strategy.Fixed()]
            });

            var vector_style = new OpenLayers.Style({
                'fillOpacity': .4,
                'strokeColor': '#aaee77',
                'strokeWidth': 3,
                'pointRadius': 8
            });
            var vector_style_select = new OpenLayers.Style({
                'fillOpacity': .9,
                'strokeColor': '#aaee77',
                'strokeWidth': 3,
                'pointRadius': 8
            });
            var vector_style_map = new OpenLayers.StyleMap({
                'default': vector_style,
                'select': vector_style_select
            });
            vector_layer.styleMap = vector_style_map;
            map.addLayer(vector_layer);
            map.addControl(new OpenLayers.Control.EditingToolbar(vector_layer));

            //Add a select feature control
            var select_feature_control = new OpenLayers.Control.SelectFeature(vector_layer);
            map.addControl(select_feature_control);
            select_feature_control.activate();

            //Activate the control
            map.addControl(new OpenLayers.Control.Graticule({ visible: false }));
            var mousepos = new OpenLayers.Control.MousePosition({ div: document.getElementById('mousepos_div') });
            map.addControl(mousepos);

            map.addControl(new OpenLayers.Control.OverviewMap());
            //map.addControl(new OpenLayers.Control.NavToolbar());

            map.layers[1].events.register('featureselected', this, OnFeatureSelected);
            map.layers[1].events.register('featureunselected', this, on_unselect_feature);
           
            var navigationT = new OpenLayers.Control.TouchNavigation({
                dragPanOptions: {
                    enableKinetic: true
                }
            });
            map.addControl(navigationT);
           
            if (!map.getCenter()) {
                var lonLat = new OpenLayers.LonLat(lon, lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
                map.setCenter(lonLat, zoom);

            }
        }

还有单击的事件,枚举所有的属性并显示

        function OnFeatureSelected(event) {
            var info_div = document.getElementById('nodelist');
            info_div.innerHTML = '';
            //Store the clusters
            evt_selected = event.feature.attributes;
            //Loop through the cluster features
             for (var atn in evt_selected) {
                 //Update the div with the info of the photos
                 info_div.innerHTML += "<p>"
                     + atn.toString()+":"+evt_selected[atn].toString()
                     + "</p>";
             }
        }
        function on_unselect_feature(event) {
            //Store a reference to the element
            var info_div = document.getElementById('nodelist');
            //Clear out the div
            info_div.innerHTML = 'Please Select a Point.';
        }

网页:


完整网页代码

<html>
<head>
	<meta http-equiv="CONTENT-TYPE" content="text/html; charset=utf-8">
    <title>OSM Local Tiles</title>
    <link rel="stylesheet" href="/openlayers/theme/default/style.css"
        type="text/css" />
    <script src="/openlayers/OpenLayers.js"></script>
    <script type="text/javascript">
        // Start position for the map (hardcoded here for simplicity)
        var lat = 31.27386;
        var lon = 121.48132;
        var zoom = 4;
        var evt_selected;
        var map; //complex object of type OpenLayers.Map
        //Initialise the 'map' object
        function init() {
            OpenLayers.ProxyHost = '/cgi-bin/proxy.cgi?url='
            map = new OpenLayers.Map("map", {
                controls: [
                    new OpenLayers.Control.Navigation(),
                    new OpenLayers.Control.PanZoomBar(),
                    new OpenLayers.Control.Permalink(),
                    new OpenLayers.Control.ScaleLine({ geodesic: true }),
                    new OpenLayers.Control.Permalink('permalink'),
                    //new OpenLayers.Control.KeyboardDefaults(),
                    new OpenLayers.Control.LayerSwitcher(),
                    new OpenLayers.Control.Attribution()],
                maxExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34, 20037508.34, 20037508.34),
                maxResolution: 156543.0339,
                numZoomLevels: 19,
                units: 'm',
                projection: new OpenLayers.Projection("EPSG:900913"),
                displayProjection: new OpenLayers.Projection("EPSG:4326")
            });

            // This is the layer that uses the locally stored tiles
            var newLayer = new OpenLayers.Layer.OSM("OSM Tiles", "/osm_tiles2/${z}/${x}/${y}.png", { numZoomLevels: 19, transitionEffect: "resize" });
            map.addLayer(newLayer);

            var vector_layer = new OpenLayers.Layer.Vector('Express Status', {
                projection: new OpenLayers.Projection('EPSG:900913'),
                protocol: new OpenLayers.Protocol.HTTP({
                url: 'http://192.168.1.100:8080/geoserver/expresstatus/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=expresstatus:view_express_status&maxFeatures=50',
                format: new OpenLayers.Format.GML({
                        extractAttributes:true
                    })
                }),
                strategies: [new OpenLayers.Strategy.Fixed()]
            });

            var vector_style = new OpenLayers.Style({
                'fillOpacity': .4,
                'strokeColor': '#aaee77',
                'strokeWidth': 3,
                'pointRadius': 8
            });
            var vector_style_select = new OpenLayers.Style({
                'fillOpacity': .9,
                'strokeColor': '#aaee77',
                'strokeWidth': 3,
                'pointRadius': 8
            });
            var vector_style_map = new OpenLayers.StyleMap({
                'default': vector_style,
                'select': vector_style_select
            });
            vector_layer.styleMap = vector_style_map;
            map.addLayer(vector_layer);
            map.addControl(new OpenLayers.Control.EditingToolbar(vector_layer));

            //Add a select feature control
            var select_feature_control = new OpenLayers.Control.SelectFeature(vector_layer);
            map.addControl(select_feature_control);
            select_feature_control.activate();

            //Activate the control
            map.addControl(new OpenLayers.Control.Graticule({ visible: false }));
            var mousepos = new OpenLayers.Control.MousePosition({ div: document.getElementById('mousepos_div') });
            map.addControl(mousepos);

            map.addControl(new OpenLayers.Control.OverviewMap());
            //map.addControl(new OpenLayers.Control.NavToolbar());

            map.layers[1].events.register('featureselected', this, OnFeatureSelected);
            map.layers[1].events.register('featureunselected', this, on_unselect_feature);
           
            var navigationT = new OpenLayers.Control.TouchNavigation({
                dragPanOptions: {
                    enableKinetic: true
                }
            });
            map.addControl(navigationT);
           
            if (!map.getCenter()) {
                var lonLat = new OpenLayers.LonLat(lon, lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
                map.setCenter(lonLat, zoom);

            }
        }

        function OnFeatureSelected(event) {
            var info_div = document.getElementById('nodelist');
            info_div.innerHTML = '';
            //Store the clusters
            evt_selected = event.feature.attributes;
            //Loop through the cluster features
             for (var atn in evt_selected) {
                 //Update the div with the info of the photos
                 info_div.innerHTML += "<p>"
                     + atn.toString()+":"+evt_selected[atn].toString()
                     + "</p>";
             }
        }
        function on_unselect_feature(event) {
            //Store a reference to the element
            var info_div = document.getElementById('nodelist');
            //Clear out the div
            info_div.innerHTML = 'Please Select a Point.';
        }

        function Button_Mark_onclick() {
            var lat = Text_lat.value;
            var lon = Text_lon.value;
            var lonLat = new OpenLayers.LonLat(lon, lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
            var current_zoom = map.zoom;
            map.setCenter(lonLat, current_zoom);
            var point = new OpenLayers.Geometry.Point(lon, lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
            var feature_point = new OpenLayers.Feature.Vector(point);
            map.layers[1].addFeatures([feature_point]);
        }

        function Button_Goto_onclick() {
            var lat = Text_lat.value;
            var lon = Text_lon.value;
            var lonLat = new OpenLayers.LonLat(lon, lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
            var current_zoom = map.zoom;
            map.setCenter(lonLat, current_zoom);
        }

        function Button_DMSMark_onclick() {
            var lat = parseFloat(Text_DMS_Lat_Deg.value.toString()) + parseFloat(Text_DMS_Lat_Min.value.toString()) / 60.0 + parseFloat(Text_DMS_Lat_Sec.value.toString()) / 3600.0;
            var lon = parseFloat(Text_DMS_Lon_deg.value.toString()) + parseFloat(Text_DMS_Lon_MIn.value.toString()) / 60.0 + parseFloat(Text_DMS_Lon_Sec.value.toString()) / 3600.0;
            Text_lat.value = lat;
            Text_lon.value = lon;
            var lonLat = new OpenLayers.LonLat(lon, lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
            var current_zoom = map.zoom;
            map.setCenter(lonLat, current_zoom);
            var point = new OpenLayers.Geometry.Point(lon, lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
            var feature_point = new OpenLayers.Feature.Vector(point);
            map.layers[1].addFeatures([feature_point]);
        }

        function Button_DMSGoto_onclick() {
            var lat = parseFloat(Text_DMS_Lat_Deg.value.toString()) + parseFloat(Text_DMS_Lat_Min.value.toString()) / 60.0 + parseFloat(Text_DMS_Lat_Sec.value.toString()) / 3600.0;
            var lon = parseFloat(Text_DMS_Lon_deg.value.toString()) + parseFloat(Text_DMS_Lon_MIn.value.toString()) / 60.0 + parseFloat(Text_DMS_Lon_Sec.value.toString()) / 3600.0;
            var lonLat = new OpenLayers.LonLat(lon, lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
            var current_zoom = map.zoom;
            map.setCenter(lonLat, current_zoom);
        }

    </script>

    <style type="text/css">
        .style1
        {
            width: 100%;
            height: 29px;
        }
        .style2
        {
            width: 100%;
            height: 90%;
        }

        #Text_DMS_Lat
        {
            width: 32px;
        }
        #Text_DMS_Lat_Deg
        {
            width: 32px;
        }
        #Text_DMS_Lat_min
        {
            width: 32px;
        }
        #Text_DMS_Lat_sec
        {
            width: 32px;
        }
        #Text_DMS_Lon_deg
        {
            width: 32px;
        }
        #Text_DMS_Lon_MIn
        {
            width: 32px;
        }
        #Text_DMS_Lon_Sec
        {
            width: 32px;
        }
    </style>

</head>
<!-- body.onload is called once the page is loaded (call the 'init' function) -->
<body onload="init();">
    <table class="style2">
        <tr>
            <td width="80%">
    <div style="width: 100%; height: 100%" id="map">
    </div>
            </td>
            <td width="20%">
                <div style="width: 100%; height: 100%" id="nodelist">
                </div>
            </td>
        </tr>
    </table>
    <!-- define a DIV into which the map will appear. Make it take up the whole window -->
    <div style="width: 100%; height: 5%" id="mousepos_div">
    </div>
    <table class="style1">
        <tr>
            <td>
                小数纬度:<input id="Text_lat" type="text" />经度:<input id="Text_lon" 
                    type="text" /><input id="Button_Mark" type="button" value="标记" 
                    onclick="return Button_Mark_onclick()" /><input 
                    id="Button_Goto" type="button" value="前往" 
                    onclick="return Button_Goto_onclick()" /></td>
            <td>
                 </td>
            <td>
                纬度 :<input id="Text_DMS_Lat_Deg" type="text" />度<input id="Text_DMS_Lat_Min" 
                    type="text" />分<input id="Text_DMS_Lat_Sec" type="text" />秒.经度:<input 
                    id="Text_DMS_Lon_deg" type="text" />度<input id="Text_DMS_Lon_MIn" 
                    type="text" />分<input id="Text_DMS_Lon_Sec" type="text" />秒</td>
            <td>
                <input id="Button_DMSMark" type="button" value="标记" onclick="return Button_DMSMark_onclick()" /><input id="Button_DMSGoto" type="button" value="前往" onclick="return Button_DMSGoto_onclick()" /></td>
            <td>
                 </td>
            <td>
                 </td>
            <td>
                 </td>
        </tr>
    </table>
</body>
</html>


下一篇,将开始介绍 基于native C++的 C/S 架构客户端的开发以及应用

4
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:307989次
    • 积分:4328
    • 等级:
    • 排名:第7309名
    • 原创:87篇
    • 转载:3篇
    • 译文:0篇
    • 评论:327条