posts - 41,  comments - 90,  trackbacks - 0
  2010年8月26日

Android老大哥安迪鲁宾近日在发布2.3姜饼系统和Nexus S的时候曾演示了最新版本的Google Maps 5.0手机地图,最大的变化就是采用了全3D地图。

在新版手机地图中,矢量图将替换原本的2D画面为用户呈现出全新的3D界面,用户可以自由的转动和缩放。此外用户还将会获得离线地图浏览功能,不用在浏览地图时保持在线状态。

Google现在在其官方手机频道又放出了一段用Nexus S运行新版Maps应用的全功能演示,这款软件将会随Nexus S上市,之后提供其他设备更新,但是对手机硬件有一定的要求,新款800MHz至1GHz处理器且配有专用图形核心的手机才能支持3D视图。



原文见驱动之家
http://news.mydrivers.com/1/181/181818.htm
posted @ 2010-12-12 21:54 天狼 阅读(591) | 评论 (1)编辑 收藏
天地图官方网站提供的二次开发文档和例子过于简单,很多关键信息没有给予说明,例如给出了WFS服务接口,却没有提供详细的开发文档。
不过这并不影响我们的使用,因为OGC WFS规范包含元数据查询命令,通过发送getCapabilities请求,我们可以得知服务器提供哪些WFS服务。

获取WFS服务器元数据
http://search.tianditu.com/wfs?request=getCapabilities
返回信息如下:
<WFS_Capabilities version="1.0.0" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengeospatial.net//wfs/1.0.0/WFS-capabilities.xsd">
<Service>
<Name>GeoGlobe WFS</Name>
<Title>GeoGlobe网络要素服务器</Title>
<Abstract>武大吉奥信息技术有限公司GeoGlobe网络要素服务器</Abstract>
<KeywordList/>
<OnlineResource>http://search.tianditu.com:80/wfs</OnlineResource>
</Service>
<Capability>
<Request>
<GetCapabilities>
<DCPType>
<HTTP>
<Get onlineResource="http://search.tianditu.com:80/wfs"/>
</HTTP>
</DCPType>
</GetCapabilities>
<GetFeature>
<ResultFormat>
<GML2/>
</ResultFormat>
<DCPType>
<HTTP>
<Get onlineResource="http://search.tianditu.com:80/wfs"/>
<Post onlineResource="http://search.tianditu.com:80/wfs"/>
</HTTP>
</DCPType>
</GetFeature>
<DescribeFeatureType>
<SchemaDescriptionLanguage>
<XMLSCHEMA/>
</SchemaDescriptionLanguage>
<DCPType>
<HTTP>
<Get onlineResource="http://search.tianditu.com:80/wfs"/>
</HTTP>
</DCPType>
</DescribeFeatureType>
</Request>
<VendorSpecificCapabilities/>
</Capability>
<FeatureTypeList>
<Operations>
<Query/>
</Operations>
<FeatureType>
<Name>DOMAIN_POI_NEW</Name>
<Title>DOMAIN_POI_NEW</Title>
<Abstract>DOMAIN_POI_NEW</Abstract>
<Keywords>DOMAIN_POI_NEW</Keywords>
<SRS>EPSG:4326</SRS>
<LatLongBoundingBox minx="-180.0" miny="-90.0" maxx="180.0" maxy="90.0"/>
</FeatureType>
<FeatureType>
<Name>iso19112:SI_Gazetteer</Name>
<Title>iso19112:SI_Gazetteer</Title>
<SRS>EPSG:4326</SRS>
<LatLongBoundingBox minx="-180.0" miny="-90.0" maxx="180.0" maxy="90.0"/>
</FeatureType>
</FeatureTypeList>
<ogc:Filter_Capabilities>
<ogc:Spatial_Capabilities>
<ogc:Spatial_Operators>
<ogc:BBOX/>
<ogc:Equals/>
<ogc:Disjoint/>
<ogc:Intersect/>
<ogc:Touches/>
<ogc:Crosses/>
<ogc:Within/>
<ogc:Contains/>
<ogc:Overlaps/>
<ogc:Beyond/>
</ogc:Spatial_Operators>
</ogc:Spatial_Capabilities>
<ogc:Scalar_Capabilities>
<ogc:Logical_Operators/>
<ogc:Comparison_Operators>
<ogc:Simple_Comparisons/>
<ogc:Like/>
<ogc:Between/>
</ogc:Comparison_Operators>
</ogc:Scalar_Capabilities>
</ogc:Filter_Capabilities>
</WFS_Capabilities>

返回信息包含了WFS服务器的开发单位(武大吉奥),WFS图层的名称(DOMAIN_POI_NEW和iso19112:SI_Gazetteer),支持的逻辑操作符和空间操作符。

继续测试
http://search.tianditu.com/wfs?request=GetFeature&version=1.0.0&typeName=DOMAIN_POI_NEW&BBOX=105.99,29.99,106,30
返回
<wfs:FeatureCollection xsi:schemaLocation="http://www.opengis.net/wfs WFS_Basic.xsd http://www.geostart.com.cn/geoglobe describe.xsd">
<gml:boundedBy>
<gml:Box>
<gml:coordinates>-180.0,-90.0 180.0,90.0</gml:coordinates>
</gml:Box>
</gml:boundedBy>
<gml:featureMember>
<DOMAIN_POI_NEW>
<OID>6764930</OID>
<Geometry>
<gml:Point srsName="-1">
<gml:coordinates>105.999183,29.995258</gml:coordinates>
</gml:Point>
</Geometry>
<DOMAINNAME>梅子村</DOMAINNAME>
<DOMAINCODE>1CHN50022400000130172</DOMAINCODE>
<NLEVEL>16</NLEVEL>
<X>105.999183</X>
<Y>29.995258</Y>
<COLDATE/>
<NAMETIME/>
<ENDTIME/>
<CLASSID/>
<STANDARDNAME>亚洲中国重庆市铜梁县梅子村</STANDARDNAME>
<TELEPHONE/>
<ADDRESS/>
<KIND>BB80</KIND>
<ZIPCODE/>
<ADMINCODE>500224</ADMINCODE>
<POI_ID>5000000130172</POI_ID>
<PID/>
<DATATYPE>chinapoi</DATATYPE>
<FENAME/>
<locationType>
<SI_LocationType>
<name>DOMAIN_POI_NEW</name>
</SI_LocationType>
</locationType>
</DOMAIN_POI_NEW>
</gml:featureMember>
</wfs:FeatureCollection>

分析返回的GML数据,可知DOMAIN_POI_NEW是地名图层,包含名称、代码、类别码等属性字段。

将图层改为iso19112:SI_Gazetteer,没有返回任何信息,google ISO19112,得到如下解释:
DIN EN ISO 19112-2005 地理信息.通过地理标识符的空间定位 标准号: DIN EN ISO 19112-2005 标准名称: 地理信息.通过地理标识符的空间定位

得到以上信息后,我们尝试使用Openlayers获取,即全国地名数据库。

通过URL(GET方式)访问“天地图”WFS服务,可以使用OpenLayers.Request.GET类,示例代码如下:
   //使用FEATUREID查询

   new OpenLayers.Request.GET( {
        url : "http://search.tianditu.com/wfs?request=GetFeature",
        params: {
            typeName: "DOMAIN_POI_NEW",
            FEATUREID: "DOMAIN_POI_NEW.6649356"
        },
        callback : handler
    });


   //使用BBOX查询

    new OpenLayers.Request.GET( {
        url : "http://search.tianditu.com/wfs?request=GetFeature",
        params: {
            typeName: "DOMAIN_POI_NEW",
            BBOX: "105.99,29.99,106,30"  //map.getExtent().toBBOX()
        },
        callback : handler
    });


说明:
url WFS服务器地址,必须加上?request=GetFeature
typeName 图层名称
FEATUREID WFS的图元ID,采用标准格式: [图层名].[OID编号]
BBOX 指定区域查询,注意不要设置过大,否则浏览器可能失去响应。

通过POST方式访问“天地图”WFS服务,可以使用OpenLayers.Request.POST类,示例代码如下:

    var xmlPara = "<?xml version='1.0' encoding='UTF-8'?>"
            + "<wfs:GetFeature maxFeatures='100' service='WFS' version='1.0.0' "
            + "xmlns:wfs='http://www.opengis.net/wfs' "
            + "xmlns:gml='http://www.opengis.net/gml' "
            + "xmlns:ogc='http://www.opengis.net/ogc' "
            + "xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' "
            + "xsi:schemaLocation='http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd'>"
            + "<wfs:Query typeName='iso19112:SI_Gazetteer' srsName='EPSG:4326'>"
            + "<ogc:Filter xmlns:ogc='http://www.opengis.net/ogc'>"
            + "<ogc:And><ogc:PropertyIsLike wildCard='*' singleChar='.' escape='!'>"
            + "<ogc:PropertyName>STANDARDNAME</ogc:PropertyName>"
            + "<ogc:Literal>*解放碑*</ogc:Literal>"
            + "</ogc:PropertyIsLike></ogc:And></ogc:Filter>"
            + "</wfs:Query></wfs:GetFeature>";
    
    var request = OpenLayers.Request.POST( {
        url : "http://search.tianditu.com/wfs?",
        data : xmlPara,
        callback : handler
    });
};

说明:

url WFS服务器地址

data WFS请求正文,返回的GML由回调函数handler处理

handler负责处理服务端返回的GML数据,也就是矢量化的地图数据,根据应用需求编写代码,获取feature的通用代码如下:
var g = new OpenLayers.Format.GML();
var features = g.read(req.responseText);
for ( var i = 0; i < features.length; ++i) {
   var feature = features[i];
   var geometry = feature.geometry;
   var attributes = feature.attributes;
}

定义过滤条件时请使用STANDARDNAME字段,不要使用DOMAINNAME字段,前者应该有索引支持,而后者没有,查询速度差别很大。

经过测试,typeName="DOMAIN_POI_NEW"和typeName="iso19112:SI_Gazetteer"都能返回结果。由于缺少官方文档说明,不知道这两个图层有何区别。

尝试使用OpenLayers.Protocol.WFS无法访问“天地图”WFS服务,服务器返回: 请求参数[REQUEST]的值为空或不正确。

提醒: 使用POST查询时,页面文件或代码文件务必保存为utf-8编码,如果使用gbk、gb2312编码,汉字地名会变成乱码,导致javascript代码错误。

posted @ 2010-12-10 16:22 天狼 阅读(5888) | 评论 (3)编辑 收藏
国家测绘局2010年10月21日正式发布中国公众版国家地理信息公共服务平台“天地图”,作为中国境内数据资源最全的地理信息服务网站,“天地图”将为公众提供权威、可信、统一的地理信息资源。

“天地图”公开开放了地图数据服务接口,第三方使用者可以直接通过互联网获取地图数据,无需授权认证,在公众服务信息公开方面可以说是一次非常大的进步。
“天地图”的在线服务数据近10TB以下是“天地图”提供的在线地理信息数据资源:

数据类型

数据源

级别

服务地址

线划地图

全球1:100万地理底图

2-10

http://tile0.tianditu.com/services/A0512_EMap

http://tile0.tianditu.com/services/AB0512_Anno

全国1:25万公开版数字地形图

11-12

http://tile0.tianditu.com/services/B0627_EMap1112

全国车载导航

13-18

http://tile0.tianditu.com/services/siwei0608

卫星影像

全球250米卫星影像 (MODIS)

2-7

http://tile0.tianditu.com/services/sbsm0210

全国15米卫星影像 (ETM)

8-10

全国2.5米卫星影像 (P5)

11-14

http://tile0.tianditu.com/services/e11

http://tile0.tianditu.com/services/e12
http://tile0.tianditu.com/services/e13
http://tile0.tianditu.com/services/eastdawnall

地级城市0.6米卫星影像

 (QuickBirdWorldView IWorldView II)

15-18

http://tile0.tianditu.com/services/sbsm1518

数字高程模型

全球90X90米数字高程模型

 

http://tile0.tianditu.com/services/J07098

地名地址

全球1:100万地名地址

 

http://search.tianditu.com/wfs

全国1:25万地名地址


全国车载导航地名地址


除地名地址数据使用OGC WFS协议发布外,其他数据全部采用基于OGC WMS-C协议的分级瓦片形式发布,工作原理类似于谷歌地图和OSM(OpenStreetMap)。

类似谷歌地图,“天地图”为互联网开发人员提供了二次开发API(武大吉奥开发的GeoGlobe二维地图API)。

通过分析GeoGlobe API代码,发现它源自Openlayers,大部分代码除了把Openlayers换成GeoSurf外,没有任何变化。不知道Openlayers项目组就此作何感想。
正因为如此,我们可以参考OpenLayers.Layer.TileCache和OpenLayers.Layer.XYZ类,编写一个专用于读取“天地图”的TDTLayer类,使Openlayers能够直接访问“天地图”的在线地图数据。

“天地图”采用256×256像素,png格式的地图瓦片文件,读取单个文件需要四个参数:T、X、Y、L
T=瓦片(Tile)名称,X=瓦片横向编码,Y=瓦片纵向编码,L=瓦片级别
这个是一个完整的请求示例:http://tile0.tianditu.com/DataServer?T=AB0512_Anno&X=50&Y=12&L=6

天地图”地理信息数据资源列表将地图瓦片分为16级(L=2-18),其中L=2级比例尺最小,对应全球地图。
L=2级只有8个瓦片文件,分别是

 X= 0 1 2 3 0 1 2 3
 Y= 0 0 0 0 1 1 1 1
L=3级有32个瓦片文件,分别是:
 X= 0-7
 Y= 0-3
L=4级有128个瓦片文件,分别是:
 X= 0-15
 Y= 0-7
其余各级以此类推,每级的瓦片文件数比前一级增加4倍,其中线划地图10级以上,卫星地图8级以上只提供中国境内的数据,没有覆盖全球。

查看
GeoGlobe API主代码GeoSurfJSAPI.js文件(相当于Openlayers.js,可以了解X(x_num)、Y(y_num)、L(level)的生成方法,伪代码如下:
level=getLevelForResolution(map.getResolution()); //计算瓦片级别
coef=TopTileSize.w/Math.pow(2,level); //中间系数
x_num=this.pyramid.topTileFromX<this.pyramid.topTileToX?Math.round((bounds.left-this.pyramid.topTileFromX)/coef):Math.round((this.pyramid.topTileFromX-bounds.right)/coef);
y_num=this.pyramid.topTileFromY<this.pyramid.topTileToY?Math.round((bounds.bottom-this.pyramid.topTileFromY)/coef):Math.round((this.pyramid.topTileFromY-bounds.top)/coef);
根据当前分辨率计算地图瓦片级别
function getLevelForResolution(res){
var ratio=map.getMaxResolution()/res;
if(ratio<1)return 0;
for(var level=0;ratio/2>=1;)
{level++;ratio/=2;}
return level;
}

经过简单测试,“天地图”和谷歌地图在数据上差别不大,二次开发方面借助于强大的Openlayers地图客户端引擎不会弱于Google Map API,唯独在速度上与谷歌地图存在较大差距,特别是地图放大到13级-18级时,延迟变得非常明显,有时甚至无法显示。
使用Firebug跟踪运行发现,大约1/3的地图瓦片请求超时,导致客户端读取失败。
“天地图”目前还处于测试阶段,希望相关单位继续改进和提升服务器端性能,快速稳定的响应大量客户端发出的并发请求。
测试中发现,“天地图”开放的地图数据服务接口从tile0.tianditu.com一直到tile7.tianditu.com。依次ping 这8个服务接口,tile1到tile7的响应速度相对较快。修改客户端js代码,将瓦片地图请求平均发送给tile0到tile7 八个服务接口,可以有效加快地图显示速度。“天地图”提供的GeoSurfJSAPI.js中已经包含相关代码,通过给Layer的mirrorUrl属性赋值,可以均衡读取指定的多个服务接口,代码如下:
                        var layer3 = new GeoSurf.Layer.GlobeTile("siwei0608", "http://tile6.tianditu.com/services/siwei0608", {
                                transitionEffect: "resize",
                                topLevel: 13,
                                bottomLevel: 18,
                                maxExtent: new GeoSurf.Bounds(100, 27, 110, 34),
                                mirrorUrls: [
                                    "http://tile1.tianditu.com/services/siwei0608",
                                    "http://tile2.tianditu.com/services/siwei0608",
                                    "http://tile3.tianditu.com/services/siwei0608",
                                    "http://tile4.tianditu.com/services/siwei0608",
                                    "http://tile5.tianditu.com/services/siwei0608",
                                    "http://tile6.tianditu.com/services/siwei0608"
                                ]
                            });

客户端使用上述读取策略后,即便放大到17-18级,整幅地图也能够完全显示,速度有明显的提升。


posted @ 2010-12-06 14:06 天狼 阅读(8566) | 评论 (5)编辑 收藏
发布WFS矢量地图

OGC WFS协议定义了地图客户端查询和传送矢量数据的方法,在查询、分析、动态绘图等实际应用中非常有用。MapServer支持OGC WFS 1.0.0和1.1.0规范。

重新定义一个Mapfile文件,命名为ext2.map,内容如下:
MAP

  NAME "vector"
    SHAPEPATH "I://cn_data"
    
    FONTSET fonts.txt
    IMAGECOLOR 255 255 255
    IMAGETYPE agg

    SIZE 800 600
    STATUS ON
    UNITS DD
    EXTENT 115.275 39.2204 117.475 40.9462
   
    OUTPUTFORMAT
        NAME agg
        DRIVER AGG/PNG
        IMAGEMODE RGB
        FORMATOPTION "INTERLACE=false"
        MIMETYPE "image/png"
    END

    PROJECTION
        "init=epsg:4326"
    END

    WEB
        METADATA
            "wms_title"                       "road wms"
            "wfs_title"                       "road wfs"
            "wms_onlineresource"              "http://192.98.151.23/cgi-bin/mapserv.exe?"  #mapserver服务器的url
            "wms_srs"                         "EPSG:4326"   #地图坐标系        
        END
    END

    LAYER
        NAME "road"
        METADATA
            "wms_title"                       "road"
            "wfs_title"                       "road"
            "wms_srs"                         "EPSG:4326"  #图层坐标系
            "gml_include_items"             "all"
            "gml_featureid"                 "id" #必须指定id
        END
        STATUS ON
        DATA "roa_4m.shp"
        TYPE line
        DUMP TRUE
        CLASS
            STYLE
                COLOR "#00FF00"
            END
        END
    END

END

该文件中有两组METADATA标签,是WFS(WMS) Server所需要的,分别是MAP的METADATA标签和LAYER的METADATA标签。
前者是针对整个地图的全局定义,后者是每个图层的元数据定义。

保存Mapfile文件,打开浏览器进行测试
http://192.98.151.23/cgi-bin/mapserv.exe?map=I:/cn_data/ext2.map&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetCapabilities
正常情况下,可以看到以下返回信息
<WFS_Capabilities version="1.0.0" updateSequence="0" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/WFS-capabilities.xsd">
<!--
 MapServer version 5.2.1 OUTPUT=GIF OUTPUT=PNG OUTPUT=JPEG OUTPUT=WBMP OUTPUT=PDF OUTPUT=SWF OUTPUT=SVG SUPPORTS=PROJ SUPPORTS=AGG SUPPORTS=FREETYPE SUPPORTS=ICONV SUPPORTS=FRIBIDI SUPPORTS=WMS_SERVER SUPPORTS=WMS_CLIENT SUPPORTS=WFS_SERVER SUPPORTS=WFS_CLIENT SUPPORTS=WCS_SERVER SUPPORTS=SOS_SERVER SUPPORTS=FASTCGI SUPPORTS=THREADS SUPPORTS=GEOS SUPPORTS=RGBA_PNG INPUT=JPEG INPUT=POSTGIS INPUT=ORACLESPATIAL INPUT=OGR INPUT=GDAL INPUT=SHAPEFILE
-->
<Service>
<Name>MapServer WFS</Name>
<Title>road wfs</Title>
<OnlineResource>
http://192.98.151.23/cgi-bin/mapserv.exe?map=I:/cn_data/ext2.map&
</OnlineResource>
</Service>
<Capability>
<Request>
<GetCapabilities>
<DCPType>
<HTTP>
<Get onlineResource="http://192.98.151.23/cgi-bin/mapserv.exe?map=I:/cn_data/ext2.map&"/>
</HTTP>
</DCPType>
<DCPType>
<HTTP>
<Post onlineResource="http://192.98.151.23/cgi-bin/mapserv.exe?map=I:/cn_data/ext2.map&"/>
</HTTP>
</DCPType>
</GetCapabilities>
<DescribeFeatureType>
<SchemaDescriptionLanguage>
<XMLSCHEMA/>
</SchemaDescriptionLanguage>
<DCPType>
<HTTP>
<Get onlineResource="http://192.98.151.23/cgi-bin/mapserv.exe?map=I:/cn_data/ext2.map&"/>
</HTTP>
</DCPType>
<DCPType>
<HTTP>
<Post onlineResource="http://192.98.151.23/cgi-bin/mapserv.exe?map=I:/cn_data/ext2.map&"/>
</HTTP>
</DCPType>
</DescribeFeatureType>
<GetFeature>
<ResultFormat>
<GML2/>
</ResultFormat>
<DCPType>
<HTTP>
<Get onlineResource="http://192.98.151.23/cgi-bin/mapserv.exe?map=I:/cn_data/ext2.map&"/>
</HTTP>
</DCPType>
<DCPType>
<HTTP>
<Post onlineResource="http://192.98.151.23/cgi-bin/mapserv.exe?map=I:/cn_data/ext2.map&"/>
</HTTP>
</DCPType>
</GetFeature>
</Request>
</Capability>
<FeatureTypeList>
<Operations>
<Query/>
</Operations>
<FeatureType>
<Name>road</Name>
<Title>road</Title>
<SRS>EPSG:4326</SRS>
<LatLongBoundingBox minx="80.3869" miny="18.2823" maxx="132.515" maxy="49.6272"/>
</FeatureType>
</FeatureTypeList>
<ogc:Filter_Capabilities>
<ogc:Spatial_Capabilities>
<ogc:Spatial_Operators>
<ogc:Equals/>
<ogc:Disjoint/>
<ogc:Touches/>
<ogc:Within/>
<ogc:Overlaps/>
<ogc:Crosses/>
<ogc:Intersect/>
<ogc:Contains/>
<ogc:DWithin/>
<ogc:BBOX/>
</ogc:Spatial_Operators>
</ogc:Spatial_Capabilities>
<ogc:Scalar_Capabilities>
<ogc:Logical_Operators/>
<ogc:Comparison_Operators>
<ogc:Simple_Comparisons/>
<ogc:Like/>
<ogc:Between/>
</ogc:Comparison_Operators>
</ogc:Scalar_Capabilities>
</ogc:Filter_Capabilities>
</WFS_Capabilities>

在OpenLayers中加载WFS图层

OpenLayers是一个功能强大的Web地图客户端引擎。

接下来,我们利用OpenLayers的OpenLayers.Protocol.WFS类,显示刚才发布的WFS图层,代码如下

       var protocol = OpenLayers.Protocol.WFS({
                    url: "http://192.98.151.23/cgi-bin/mapserv.exe?map=I:/cn_data/ext2.map&", //mapserver地图服务器的url,加上mapfi了文件的路径
                    featureType: "road", //layer的名称
                    srsName: "EPSG:4326", //layer的坐标系
                    geometryName: "msGeometry", //geometry字段的名称
                    featurePrefix: "ms"
                });

以下是全部javascript代码:
        window.onload = function() {
                var map = new OpenLayers.Map('mapdiv', {
                    projection: "EPSG:4326",
                    units: "degree"
                });
                
                var roads = new OpenLayers.Layer.WMS("road", "http://192.98.151.23/cgi-bin/mapserv.exe?map=I:/cn_data/ext2.map&", {
                    layers: 'road',
                    transparent: 'true',
                    format: 'image/png'
                }, {
                    isBaseLayer: false,
                    visibility: true,
                    buffer: 0
                });
                
                
                var empty = new OpenLayers.Layer("empty", {
                    isBaseLayer: true
                });
                
                var select = new OpenLayers.Layer.Vector("Selection", {
                    styleMap: new OpenLayers.Style(OpenLayers.Feature.Vector.style["select"]),
                    displayInLayerSwitcher: false
                });
                
                var hover = new OpenLayers.Layer.Vector("Hover", {
                    displayInLayerSwitcher: false
                });
                
                map.addLayers([roads, hover, select, empty]);
                
                var protocol = OpenLayers.Protocol.WFS({
                    url: "http://192.98.151.23/cgi-bin/mapserv.exe?map=I:/cn_data/ext2.map&",
                    featureType: "road",
                    srsName: "EPSG:4326",
                    geometryName: "msGeometry",
                    featurePrefix: "ms"
                });
                
                var control = new OpenLayers.Control.GetFeature({
                    protocol: protocol,
                    box: true,
                    hover: true,
                    multipleKey: "shiftKey",
                    toggleKey: "ctrlKey"
                });
                
                control.events.register("featureselected", this, function(e){
                    select.addFeatures([e.feature]);
                });
                control.events.register("featureunselected", this, function(e){
                    select.removeFeatures([e.feature]);
                });
                control.events.register("hoverfeature", this, function(e){
                    hover.addFeatures([e.feature]);
                });
                
                control.events.register("outfeature", this, function(e){
                    hover.removeFeatures([e.feature]);
                });
                
                map.addControl(control);
                control.activate();
                
                map.addControl(new OpenLayers.Control.LayerSwitcher());
                map.addControl(new OpenLayers.Control.MousePosition());
                
                if (!map.getCenter()) {
                    map.zoomToMaxExtent();
                }

            }

在浏览器中运行html页面,国道数据将以矢量方式传送到客户端,由openlayers动态绘制,鼠标移动到道路上或者选中道路,道路将实时改变颜色,在Web上实现与传统桌面GIS应用类似的体验效果。

posted @ 2010-12-01 15:00 天狼 阅读(2510) | 评论 (0)编辑 收藏
在今年的FOSS4G国际大会上,geoserver项目组发布了2.1beta1版本。
新版本增加了多项引人注目的功能,原文如下:

WMS Cascading

Something users have asked for since the addition of WMS support itself is cascading, the ability of GeoServer to proxy for another remote WMS server like MapServer or another GeoServer. This feature has many uses such as pulling in a remote base layer and overlaying local vector data onto it or securing a locally unsecured map server. Special thanks to the University of Perugia for sponsoring this feature.

Read more about WMS cascading.

Virtual Services

Anyone who has published a large number of layers or feature types with GeoServer has probably at some point been annoyed by the fact that every single layer is published by a single global service. WMS has the ability to group and nest layers but WFS and WCS have no such equivalent. Well now with virtual services one can create multiple service endpoints within a single physical geoserver instance.

Special thanks to Landgate for funding this work.

Read more about virtual services.

Layers from SQL

GeoServer has always been good at publishing a flat database table. But users often need to do more such as pre filter the data in a table, or join two tables together, or generate column values on the fly with a function. Before this feature the recommendation was to create a view. However views can be a maintenance burden and are at times problematic.

Now one can create a layer directly from an SQL query. And on top of that query definitions can be parameterized which allows one to create dynamic queries on the fly. These parameters can be restricted with regular expressions in order to prevent an SQL injection security hole.

Special thanks to Andrea for spending much of his personal time on this one. And also to OBIS who provided the funding for the parametric component of the work.

Read more about SQL layers.

WPS

With 2.1 and the arrival of WPS we welcome a new OGC service to the family. The Web Processing Service is an OGC service for performing geospatial analysis functions over the web. The specification is extensible in nature and allows for simple processes like buffering a geometry to more complex processes such as image processing.

Historically GeoServer has been focused primarily on data delivery without any tools for performing analysis of spatial data. WPS fills that gap making GeoServer a more compete solution for geospatial web services.

Thanks to Refractions Research for the initial contribution of the WPS module and to Andrea once again for taking personal time to bring WPS support to its current state.

Read more about WPS. Download the WPS extension now to try it out.

Unit of Measure

Support for units in SLD allows one to specify values in measurements other than pixels such as feet or meters. This adds a very powerful capability to SLD that in many cases alleviates the need for multiple scale dependent rendering rules. This has the upside of greatly simplifying complex SLD documents.

Special thanks to Milton Jonathan who did the initial GeoTools work to make unit of measure support possible and to Andrea for working with Milton to improve the initial patch. Note that this feature has also been backported to the stable 2.0.x branch. Thanks to SWECO and Malmö City of Sweden for sponsoring the backport.

Read more about UOM support.

DPI Scaling

By default GeoServer renders images at a resolution of 90 DPI. While this is acceptable for the standard screen it is not acceptable for print which requires a higher resolution. Now it is possible to supply a format option to a WMS request on the fly that controls the DPI setting.

Special thanks again to SWECO and to Malmö City of Sweden for sponsoring this work. Note also that this feature has also been backported to the stable 2.0.x branch.

Read more about DPI scaling.



posted @ 2010-12-01 10:42 天狼 阅读(1748) | 评论 (0)编辑 收藏
为MapServer添加瓦片缓存服务

国际上有两个比较流行的开源地图瓦片缓存服务器:geowebcache和tilecache。
geowebcache基于J2EE架构,具有完整的Web图形管理界面,支持多进程并发切图,可以随时查看切图进度和剩余时间,搭配geoserver非常合适。
titlecache采用python编写,CGI工作模式,非常小巧,2.11版本只有令人惊讶的68K!(这一点很像MapServer)。
titlecache采用SHELL或DOS命令行方式运行切图程序,实时输出切图进度信息。
mapserver选择titlecache作为地图切片缓存服务器,在ms4w_3.0beta10中包含了tilecache插件,由于beta版本存在问题,
我们在ms4w_2.3.1正式版中手工加入tilecache服务器,具体步骤如下:

1、从tilecache官方网站下载安装包tilecache-2.11.tar.gz,该安装包适用于所有操作系统,我们使用Windows XP。
2、解压安装包,将其中的tilecache-2.11目录整体复制到ms4w的apps目录下。
3、进入ms4w的http.d目录,新建一个名为httpd_tilecache.conf的文本文件,内容如下:
Alias /tilecache/ "/ms4w/apps/tilecache-2.11/"
<Directory "/ms4w/apps/tilecache-2.11/">
  AllowOverride None
  Options ExecCGI
  Order allow,deny
  Allow from all
</Directory>
addHandler cgi-script .cgi .py
4、进入ms4w/apps/tilecache-2.11目录,打开tilecache.cgi文件,修改第一行的python编译器路径,例如
#!E:\Python25\python.exe
5、打开该目录下的tilecache.cfg文件,修改cache标签,指定本地磁盘缓存目录,例如
[cache]
type=Disk
base=F:/tmp/tilecache
添加一个road标签,指定地图服务类型,服务地址,mapfile文件路径,图层名称,栅格格式,空间参考系统编码,例如
[road]
type=WMS
url=http://127.0.0.1/cgi-bin/mapserv.exe?map=I:/cn_data/c2.map&transparent=true&
layers=road
extension=png
srs=EPSG:4326
6、重新启动Apache
7、打开tilecache下的index.html文件,根据实际情况修改openlayers.js的路径,例如
<script src="/openlayers/OpenLayers.js"></script>
修改layer参数,例如
layer = new OpenLayers.Layer.WMS( "road", "tilecache.cgi?", {layers: 'road', format: 'image/png' } );

使用浏览器访问http://127.0.0.1/tilecache,Web页面上将显示经过tilecache处理的地图,客户端浏览过的地图切片文件被保存在tilecache.cfg文件指定的临时目录下,这里是F:/tmp/tilecache目录,如果其中包含客户端正在请求的地图,这些地图将不再通过MapServer动态生成,而是直接从缓存目录读取静态图片文件。对于大用户量、高并发的地图访问,瓦片缓存机制可以非常有效的提高客户端读取、显示地图的速度。

通过执行tilecache_seed.py脚本,可以手动生成地图切片,下面的命令给road图层发布0到6级的地图切片文件。
python "F:\ms4w\apps\tilecache-2.11\tilecache_seed.py" road 0 6
等待执行完毕,进入缓存目录可以找到刚才发布的地图切片文件。


posted @ 2010-11-26 15:45 天狼 阅读(3265) | 评论 (5)编辑 收藏
连接Oracle Spatial

前面的测试中我们使用shape文件作为地图数据源,下面我们将从Oracle Spatial空间数据库读取地理数据。

mapserver提供两种方式连接oracle空间数据库,native oracle spatial和ogr。安装包提供了支持native oracle spatial的二进制文件,ogr方式需要自行编译源代码。借用以往项目的Oracle 10.2.0.3数据库,MapServer采用ms4w_2.3.1已编译包,地图服务器安装Oracle10.2客户端,进行本地网络配置,测试连接正常。

关闭Apache MS4W Web Server服务,进入\ms4w\Apache\cgi-bin\ignored-libmap\oracle11g目录,将libmap.dll复制粘贴到\ms4w\Apache\cgi-bin目录,替换原有文件,启动Apache MS4W Web Server服务。

新建一个Mapfile文件,LAYER部分如下
LAYER
    NAME "road"
    TYPE LINE
    CONNECTION "geouser/123456@geodb" #数据库连接字符串
    CONNECTIONTYPE oraclespatial      #连接类型为oracle spatial
    DATA "GEOLOC FROM NAV_ROAD1 USING SRID 4326"  #此处GEOLOC为GEOMETRY字段名,NAV_ROAD1为表名
    PROJECTION
       "init=epsg:4326" #必须指定SRS编码
    END
    DUMP TRUE
    CLASS
        STYLE
            COLOR 0 128 128
        END
    END
END

DATA标签使用如下格式
"[geom_column]
FROM
[table]| [(SELECT [...]
FROM [table]|[Spatial Operator]
[WHERE condition] )]
[USING [UNIQUE column]| [SRID #srid]| [FUNCTION]| [VERSION #version]
]"
注意:不要在FROM之前加入属性字段名,属性字段可添加在FROM后的子查询中,如下所示



GEOLOC FROM (SELECT MI_PRINX AS OID, NAME AS ONAME, COLOR AS COLOR, GEOLOC AS GEOLOC FROM NAV_ROAD1) USING SRID 4326



LABEL或STYLE用到的属性字段必须包含在SELECT子查询中。







修改openlayers客户端代码



var ms_layer = new OpenLayers.Layer.WMS(



                "Test Map",
                "/cgi-bin/mapserv.exe",
                {   
                    layers: 'road',
                    map: 'I:/cn_data/c2.map',
                    format: 'png'
                },
                {
                    reproject: false,
                    'numZoomLevels': 20,
                    gutter: 15,
                    buffer: 0
                }
            );

打开浏览器,查看效果。

为图层添加标注(Label)


在地图上标注文字,必然涉及到字体,MapServer采用与操作系统无关的设计,不能自动获知当前操作系统下安装了哪些字体,必须手工创建字体集FONTSET文件。
该文件的格式非常简单,每行配置一个字体,左边是字体名(可自由命名),右边是字体文件的路径(请使用绝对路径),如下所示:
arial   C:\WINDOWS\Fonts\arial.ttf
sans    C:\WINDOWS\Fonts\SIMSUN.TTC
将以上内容保存为文本文件,文件名和扩展名不限,例如保存为fonts.txt

在Mapfile的Map标签下添加一行
FONTSET fonts.txt #指明字体集文件,可以包含路径

在Mapfile的Layer标签中添加一行
LABELITEM "NAME"  #指明标注所用的字段名

在Layer下的CLASS标签中添加以下内容
LABEL
    COLOR  0 0 0
    OUTLINECOLOR 255 255 255
    FONT "sans"  #此处sans对应宋体SIMSUN.TTC
    TYPE truetype
    SIZE 6
    POSITION AUTO
    PARTIALS FALSE
    ENCODING GBK #此处为文字编码,如果不设置该值,中文将不能正确显示。对于中文Windows系统,操作系统的默认编码为GBK。
END

注意:ms4w_3.0beta11属于开发版本,支持shape文件数据源配置label标签,不支持oracle spatial数据源配置label标签。
为了读取oracle空间表中的属性生成标签,我们换用ms4w_2.3.1正式版,系统工作正常。

使用动态样式(STYLE)

实际应用中对地图的渲染有很多要求,MapServer支持动态设置STYLE,修改Mapfile文件LAYER的STYLE,例如:
STYLE
    COLOR [COLOR]
END
每条道路的颜色由道路表的属性字段COLOR决定,与之类似,可以从数据库取值填充SYMBOL,SIZE,ANGLE等标签。
提示:MapServer的颜色码可以使用[r] [g] [b]十进制格式,也可以使用Web开发中常用的RRGGBB十六进制格式,例如:#FF0000


posted @ 2010-11-26 12:16 天狼 阅读(2793) | 评论 (1)编辑 收藏
MapServer简介
    在开源WebGIS领域,MapServer的历史和名气都超过GeoServer(20世纪90年代中期,由明尼苏达大学研制),很早就被列入OSGeo项目组。
与GeoServer不同,MapServer用C语言编写,采用传统的CGI架构,融合了Pro4j、GDAL等开源项目。对比J2EE架构的GeoServer,MapServer显得非常精巧,5.6版本的核心部分只有33KB,源代码只有2.2M,包括Apache、Php、Pro4j、GDAL、MapScript在内的完整安装包也只有35M。

安装过程
    和Java一样,C具有良好的跨平台特性,MapServer支持Windows、Linux、Mac OS X等操作系统。

    官方网站对Unix和Windows平台下的源代码安装步骤给出了详细说明。根据说明下载需要的第三方库,然后在Shell命令行模式下编译源代码,对于缺少Unix Shell或DOS操作经验的用户, 这是一件比较头疼的事情。好在MapServer已经考虑到不习惯命令行操作的Windows用户,给出了Windows下的已编译安装包ms4w,目前最新版本是3.0beta11。
   
    ms4w的安装过程很简单,下载ms4w,解压缩到硬盘任意目录(目录名最好不要包含中文字符),打开命令提示符窗口,切换到ms4w所在目录,键入apache-install即可。(提示:如果机器上安装有Apache或IIS,运行apache-install之前,请将它们关闭。ms4w安装后不会和原有的Apache冲突。)

看到如下信息,说明安装成功。
Installing the Apache MS4W Web Server service
The Apache MS4W Web Server service is successfully installed.
Testing httpd.conf....
Errors reported here must be corrected before the service
can be started.
The Apache MS4W Web Server service is starting.
The Apache MS4W Web Server service was started successfully.

安装完成后,使用浏览器访问 http://127.0.0.1/cgi-bin/mapserv.exe,MapServer返回如下提示信息
No query information to decode. QUERY_STRING is set, but empty.

发布地图数据
    类似于Arcgis Server和GeoServer,MapServer采用零代码编写的配置文件方式管理地图发布,配置文件被称为Mapfile,后缀名为map。

    Mapfile有三种编写方式:
    1、参考官方文档Mapfile章节,手工编写
    这种方式要求开发人员对Mapfile的编写规则非常熟悉,否则很容易出错。
    2、类似Arcgis Server和GeoServer提供的Web图形化配置界面,MapServer有一个对应的开源项目MapLab,提供基于Web的图形化配置界面
    不过个人感觉,MapLab的易用性远逊于Arcgis Server和GeoServer。
    3、使用开源桌面平台QGIS,自动生成Mapfile文件
    对于新手,推荐使用第三种方式。

以下是测试用的Mapfile文件,MapServer对Mapfile文件的存放位置没有特殊要求,可以存放在不同的计算机上。

# Mapfile文件必须以MAP开头
MAP
# Map的名字 test
NAME test
STATUS ON
# 地图大小
SIZE 800 600
# Projection definition
# Projections are not currenlty supported. If desired, add your own # projection information based on Mapserver documentation.
# Map的坐标系
PROJECTION "init=epsg:4326"
END

# Map的全图范围
EXTENT 75 15 140 55
# Map的坐标单位 DD表示经纬度
UNITS DD
# Map的背景颜色 白色
IMAGECOLOR 255 255 255
# 生成的图片类型,常用gif或png
IMAGETYPE gif
# shp文件的路径,请使用绝对路径
SHAPEPATH "I://cn_data"
#
# Start of web interface definition. Only the TEMPLATE parameter # must be specified to display a map. See Mapserver documentation
# MapServer内置了地图客户端功能,此处是Web客户端相关设置。
# 由于我们使用Openlayers作为地图客户端,MapServer做为地图服务器,此处不做设置
WEB
# HEADER
# TEMPLATE
# FOOTER
# 最小、最大比例尺等级
MINSCALE 1
MAXSCALE 13
# 设置IMAGEPATH,默认路径如下,请使用绝对路径
IMAGEPATH 'I:/ms4w/Apache/htdocs/tmp'
# 设置IMAGEURL,默认路径如下
IMAGEURL '/tmp/'
END
# 设置图层,一个Map下可以包含多个LAYER
LAYER NAME polyline  # 图层名称,MapServer使用该名称
TYPE LINE # 几何类型
STATUS ON
DATA "roa_4m" # shp文件名,不需要带扩展名,路径在前面的SHAPEPATH项中指定
CLASS NAME "roa_4m" # 类名
# TEMPLATE
COLOR 112 0 0 # 颜色
END
END
END # Map File

客户端测试
    接下来测试刚才建立的Mapfile,在浏览器地址栏中输入 http://127.0.0.1/cgi-bin/mapserv.exe?LAYERS=polyline&MAP=I:/ms4w/Apache/htdocs/my.map&FORMAT=gif&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&STYLES=&EXCEPTIONS=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A4326&BBOX=75,15,140,55&WIDTH=800&HEIGHT=600
大约0.5秒后(初次加载),浏览器显示出中国1:400万道路网,地图发布成功! 熟悉OGC标准的朋友可能已经发现,上面的URL是WMS地图请求。

直接通过CGI请求,得到的是一幅静态地图,为了实现地图的缩放、漫游,我们选用Openlayers地图客户端。 通过OpenLayers.Layer.WMS可以直接调用MapServer地图服务,测试代码如下:
var ms_layer = new OpenLayers.Layer.WMS(
   "polyline", //OpenLayers中的图层名
   "/cgi-bin/mapserv.exe", //MapServer地图服务器的路径
   { layers: 'polyline', //Mapfile中定义的图层名
     map: 'I:/cn_data/my.map', //Mapfile文件的绝对路径,注意必须使用'/'而不是'\',使用相对路径无法显示地图
     format: 'gif' },
   { reproject: false,
     'numZoomLevels': 20,
     gutter: 15,
     buffer: 0 }
);

滚动鼠标滚轮,地图的刷新速度保持在0.5秒以内。MapServer继承了C语言的特点,地图渲染效率很高。

写在最后
    MapServer提供两种工作方式,CGI方式(适用于CGI、AJAX、FLEX开发人员)和MapScript方式(适用于Php、Java、C#、Python开发人员)。以原生CGI方式效率最高,配合TileCache,可以快速生成大范围的地图瓦片数据。比较基于.Net和J2EE的商业或开源平台,MapServer更适合高负荷的大型互联网地图应用。

posted @ 2010-11-24 17:39 天狼 阅读(6692) | 评论 (5)编辑 收藏
OpenLayers.Layer.Google
#2493: Google layer instances with overridden methods may need to be modified, because some methods are now mixed in from OpenLayers.Layer.Google.v2. Affected API methods are
onMapResize,
getMapObjectBoundsFromOLBounds,
setMapObjectCenter,
dragPanMapObject,
getMapObjectLonLatFromMapObjectPixel,
getMapObjectPixelFromMapObjectLonLat,
getMapObjectZoomFromMapObjectBounds,
getMapObjectLonLatFromLonLat and getMapObjectPixelFromXY.
This means that when calling any of these methods on the prototype, the code needs to be changed to call it on OpenLayers.Layer.Google.v2 instead. You would e.g. have to change
OpenLayers.Layer.Google.prototype.onMapResize.apply(this, arguments);
to
OpenLayers.Layer.Google.v2.onMapResize.apply(this, arguments);
OpenLayers.Control.Panel
#2764: OpenLayers.Control.Panel does not change the active state of controls with a type of OpenLayers.Control.TYPE_BUTTON any more. If you want to retain the old behavior, create your panel with an overridden activateControl method like this:
var panel = new OpenLayers.Control.Panel({ activateControl: function(control) { OpenLayers.Control.Panel.prototype.activateControl.apply(this, arguments); if (control.active &amp;&amp; control.type == OpenLayers.Control.TYPE_TOOL) { for (var i=panel.controls.length-1; i&gt;=0; --i) { panel.controls[i].type == OpenLayers.Control.TYPE_BUTTON &amp;&amp; panel.controls[i].deactivate(); } } }
});
New Addins
InlineXhtml - adds support for WMS layers with SVG as image format, for SVG enabled browsers.
posted @ 2010-09-13 12:22 天狼 阅读(537) | 评论 (0)编辑 收藏
openlayers是一个纯javascript的web地图客户端框架,对开发平台的适应性非常强,可以很容易的嵌入静态http页面、asp页面、.net页面、jsp页面、j2ee页面。由于openlayers采用AJAX架构,当地图服务器与web客户端服务器不同时,WMS中的getFeatureInfo,以及所有WFS功能接口不能正常工作。原因是各种浏览器禁止跨域访问xml,解决的办法很简单,使用代理(Proxy)。

根据应用系统架构的不同,代理的实现方式有很多种,包括web服务器内置代理(如Apache)、cgi方式代理、php代理、jsp代理、aspx代理等。
openlayers官方提供了一个采用python编写的cgi代理,推荐在Apache2.2下使用。

openlayers官方代理安装步骤:
1、安装Python2.5,记住安装路径。
2、将openlayers官方提供的proxy.cgi复制到apache的cgi-bin目录下。
修改第一行Python25的安装路径,注意不要去掉最前面的#号。
修改allowedHosts中的geoserver/mapserver ip:geoserver/mapserver port部分。
3、打开conf目录下的httpd.conf文件,修改cgi部分,例如:
<Directory "C:/Program Files/Apache Software Foundation/Apache2.2/cgi-bin">
    AllowOverride None
    Options ExecCGI
    Order allow,deny
    Allow from all
</Directory>
AddHandler cgi-script .cgi .py
保存后重新启动Apache,在浏览器地址栏中填入http://apache ip/cgi-bin/proxy.cgi,测试代理是否工作正常。

以下是proxy.cgi的内容:
#!C:\Python25\python.exe
# -*- coding: utf-8 -*-

import urllib2
import cgi
import sys, os

# Designed to prevent Open Proxy type stuff.

allowedHosts = ['geoserver/mapserver ip:geoserver/mapserver port',
                                'www.openlayers.org',
                                'openlayers.org']

method = os.environ["REQUEST_METHOD"]

if method == "POST":
    qs = os.environ["QUERY_STRING"]
    d = cgi.parse_qs(qs)
    if d.has_key("url"):
        url = d["url"][0]
    else:
        url = "http://www.openlayers.org"
else:
    fs = cgi.FieldStorage()
    url = fs.getvalue('url', "http://www.openlayers.org")

try:
    host = url.split("/")[2]
    if allowedHosts and not host in allowedHosts:
        print "Status: 502 Bad Gateway"
        print "Content-Type: text/plain"
        print
        print "This proxy does not allow you to access that location (%s)." % (host,)
        print
        print os.environ
 
    elif url.startswith("http://") or url.startswith("https://"):
  
        if method == "POST":
            length = int(os.environ["CONTENT_LENGTH"])
            headers = {"Content-Type": os.environ["CONTENT_TYPE"]}
            body = sys.stdin.read(length)
            r = urllib2.Request(url, body, headers)
            y = urllib2.urlopen(r)
        else:
            y = urllib2.urlopen(url)
      
        # print content type header
        i = y.info()
        if i.has_key("Content-Type"):
            print "Content-Type: %s" % (i["Content-Type"])
        else:
            print "Content-Type: text/plain"
        print
      
        print y.read()
      
        y.close()
    else:
        print "Content-Type: text/plain"
        print
        print "Illegal request."

except Exception, E:
    print "Status: 500 Unexpected Error"
    print "Content-Type: text/plain"
    print
    print "Some unexpected error occurred. Error text was:", E

备注:部署在同一个机器、不同服务器上(相同ip,不同端口号)同样是跨域访问。例如地图服务器geoserver在tomcat,端口8080,应用系统在Apache或IIS,端口80),这种情况下只有IE6能够正常访问,条件是将ip地址加入可信站点列表,IE7、IE8、FF3.6都会禁止访问。


posted @ 2010-08-26 10:36 天狼 阅读(4107) | 评论 (0)编辑 收藏