2张图教你认识世界人口分布

下面图中,蓝色区域生活着世界上大概5%的人口,红色区域同样生活着5%的人。
蓝色区域主要是高山、极地和沙漠等不适合人类居住的区域,这包括整个大洋洲、北美的加拿大以及北欧部分地区。
红色区域为世界上人口最稠密的地图,包括孟加拉国和印度的三个地区:比哈尔邦,恰尔肯德邦和西孟加拉邦。这里的人口越3.9亿。

下面这张图,同样是将世界5%的人口进行极化分布制图,其中蓝色部分约占地球面积的72%。而地图上的17个红点则同样生活着约5%的人口。

 

gis Leave a comment

ArcGIS for Server 10.3.X 新型紧凑型缓存的解读和应用 zz

原文地址:http://mp.weixin.qq.com/s?__biz=MzA4NjI0ODMyNA==&mid=400860148&idx=1&sn=ea65c230cc2fdcca1fb983dea0d1d453&scene=5&srcid=1127QN8qFNaaGaQ77sAGJkMp#rd
早在2010年年底,牛魔王在其博客空间(http://blog.csdn.net/warrenwyf/article/details/6069711 ) 中对ArcGIS 10中推出的紧凑型缓存格式进行了详细的解读。紧随着的4年时间里,ArcGIS for Server本身经历了10、10.1.X和10.2.X各版本的逐级更替,特别是软件架构发生了显著的变化。然而,就紧凑型缓存本身而言,牛魔王中王的解读一直都是适用的。衷心地向我们的大牛致敬!

直到2014年年底ArcGIS 10.3正式发布,Esri才推出了新的紧凑型缓存格式以增强用户的访问体验。新的缓存格式下,关键的差别在于Esri将缓存的索引信息.bundlx包含在了缓存的切片文件.bundle中。

接下来,我们就简单解读一下这一新型的紧凑型缓存格式。俗语说,万变不离其宗。既然缓存文件夹下仅包含了bundle文件,可以想见,切片的索引,切片的偏移和切片的图片流都必然包含在这一文件中。根据经验,缓存本身遵循的是16进制的形式。依照这一思路,利用UltraEdit打开bundle文件并以16进制格式进行查看。

为了便于分析,我们先创建一个在L00级只包含一个切片的缓存服务,并在UltraEdit中以16进制格式查看L00级下的R0000C0000.bundle文件。

通过对这一文件中信息存储规律的分析,可初步得出如下结论: 1) 文件中包含大量04 00 00 00 00 00 00 00的16进制字节组,共计16893组;
2) 文件中仅包含一个PNG24的文件头字节组89504E47,即第一行第一列的切片,bundle文件中唯一的一张图片。图片流紧随(1)中所提到的字节组之后,但偏移4个字节;
3) (2)中所述的4字节偏移量的数值恰等于图片流的长度;
4) 文件第5行的起始4个字节44 00 02 00按照低位到高位换算出的数值等于131140,这一值与(2)中所述的PNG文件头位置恰恰吻合。

综上分析: 1)起始4行是bundle的文件头信息,可忽略;
2)bundle的文件头之后记录了16384张切片的切片位置,仅4字节,从低位到高位,后4字节可忽略;
3)位置信息之后,对于切片的记录,先以4字节记录切片的长度,而后紧跟图片流信息。到此,bundle结束。

下一步呢,我们将选择一个狭长的矩形面要素发布服务并切图,以分析行列切片在bundle文件中的具体存储规律。

通过对bundle文件和对应的松散缓存在L02级别上的对比,可推断: 1)bundle中索引的存储是按行依次存储,即第1行的1至128,第2行的1至128,以此类推,直至最后一张切片即第128行128列;
2)bundle中图片流的存储仅包含非空切片。此外,通过对这一更复杂的地图缓存的分析,再次论证了前面的推论。

既然上述的分析完毕,接下来就要对上述的分析进行一番验证啦。这里呢,我会利用ArcGIS Runtime SDK for Android实现抽象理论的实践工作。本次验证的核心在于,通过对TiledServiceLayer进行扩展,按照上面的存储推论覆写getTile(intmLevel, int mColumn, int mRow)方法。

第一步,根据参数中的比例级别、列号和行号定位到Bundle文件。 1 String level = Integer.toString(mLevel);
2 int levelLength = level.length();
3 if(levelLength == 1){
4 level = “0” + level; 5 } 6 level = “L” + level; 7
8 int rowGroup = 128(mRow/128); 9 String row =Integer.toHexString(rowGroup);
10 int rowLength = row.length();
11 if(rowLength < 4){
12 for(int i=0; i<4-rowLength; i++){
13 row = “0” + row;
14 }
15 }
16 row = “R” + row;
17
18 int columnGroup = 128
(mColumn/128);
19 String column = Integer.toHexString(columnGroup);
20 int columnLength = column.length();
21 if(columnLength < 4) {
22 for(int i=0; i<4-columnLength; i++){
23 column = “0” + column;
24 }
25 }
26 column = “C” + column;
27
28 String bundleName = String.format(“%s/%s/%s%s”,compactTileLoc, level, row, column) + “.bundle”;

第二步,读取bundle文件,根据前面分析中所推断出的切片的起始位置和切片的长度获取对应的切片并返回。 1 int index = 128(mRow – rowGroup) +(mColumn-columnGroup); 2
3 RandomAccessFile isBundle = newRandomAccessFile(bundleFileName, “r”); 4 isBundle.skipBytes(64 + 8
index); 5
6 //获取位置索引并计算切片位置偏移量 7 byte[] indexBytes = new byte[4]; 8 isBundle. Read(indexBytes, 0, 4);
9 long offset = (long)(indexBytes[0]&0xff)+(long)(indexBytes[1]&0xff)256 + (long)(indexBytes[2]&0xff)65536 10 + (long)(indexBytes[3]&0xff)16777216;
11
12 //获取切片长度索引并计算切片长度
13 long startOffset = offset – 4;
14 isBundle.seek(startOffset);
15 byte[] lengthBytes = new byte[4];
16 isBundle.read(lengthBytes, 0, 4);
17 int length = (int)(lengthBytes[0] & 0xff) + (int)(lengthBytes[1]& 0xff)
256 + (int)(lengthBytes[2] & 0xff) * 65536
18 + (int)(lengthBytes[3] &0xff) * 16777216;
19
20 //根据切片位置和切片长度获取切片
21 ByteArrayOutputStream bos = new ByteArrayOutputStream();
22
23 byte[] tileBytes = new byte[length];
24 int bytesRead = 0;
25 if(length > 0){
26 bytesRead = isBundle.read(tileBytes, 0, tileBytes.length);
27 if(bytesRead > 0){
28 bos.write(tileBytes, 0,bytesRead);
29 }
30 }
31
32 tile = bos.toByteArray();

呵呵,成功实现。直接奉上Android端的显示效果吧。

Tips

关于紧凑型切片,唠唠叨叨的我还是忍不住要嘱咐几句: 1)新型的紧凑型切片无法被直接用于先前版本的ArcGIS for Server;
2)新型的紧凑型切片可通过导出切片即export tiles获取先前格式的缓存;
3)老版本的紧凑型切片可直接在新版本的ArcGIS for Server中复用,但可通过升级存储格式即UpgradeStorage Format更新为新型紧凑型切片格式。

ArcGIS Leave a comment

Esri 矢量底图介绍(Beta)

今年早些时候,Esri公布了在ArcGIS平台中引入矢量底图的计划并展示了预览版。随着ArcGIS Online在11月的更新,web map先已经支持矢量瓦片图层。作为更新的一部分,Esri已经提供了几种矢量地图,用户可以在webmap中使用。
几年以来,Esri一直提供图片格式的底图供用户使用,非常多用户在使用这些底图,但基于图片的底图有一些限制,例如用户无法自定义样式,对高分辨率设备支持不好等。因此Esri引入矢量切片的底图来解决这些问题。
矢量底图以矢量切片的方式提供,格式为pbf(MapBox定义),用户在客户端渲染数据。用户可以通过ArcGIS Pro 1.2来生成矢量切片。
随着ArcGIS Pro 1.2在2016年的发布,用户可以使用自己的数据生成矢量切片并托管到ArcGIS Server 10.4 或ArcGIS Online上。矢量底图目前只支持浏览器的渲染,将来会支持桌面的移动端设备,用户可以自定义样式来渲染矢量切片。

已经上线的矢量底图

目前已经上线的矢量底图使用同一个瓦片服务,但提供了8种样式,可以通过ArcGIS Online的Esri Vector Basemaps (Beta) 组来访问。 链接为:http://www.arcgis.com/home/group.html?id=30de8da907d240a0bccd5ad3ff25ef4a
矢量底图在Webmap中,既可以作为底图,也可以作为普通图层加载。
image

自定义矢量底图

用户可以自定义矢量底图的样式,通过编辑已经存在的矢量切片图层的样式文件,并重新发布的方式可以创建一个新的矢量切片图层。

重要提示

目前矢量底图处于Beta阶段,数据和样式文件的格式都有可能发生变化,因此用户创建的样式文件可能需要随之更新,请在项目中慎用。另外,和已经存在的底图一样,矢量底图对所有ArcGIS用户是免费使用的。

ArcGIS Leave a comment

高德位置纠偏服务

众所周知,国内地图都是经过偏移的数据,那么想要把用户自己的数据添加上去,必须通过偏移才可以。
目前高德提供了位置纠偏服务,但隐藏的比较深,在主页面上没有提供,在论坛中提供了相关API。
相关网址:http://lbsbbs.amap.com/forum.php?mod=viewthread&tid=724&highlight=%E5%9D%90%E6%A0%87%E8%BD%AC%E6%8D%A2

一.适用对象: 苦苦纠结于如何将GPS、mapbar、baidu坐标转换为高德坐标系的开发者们。

二.转换方法:

  1. 首先当然还是需要人手一个的百宝key。注意:权限君升级权限系统后,调用坐标转换接口的童鞋们需要重新申请。注意:绑定服务需选择web服务API:
2.      调用坐标转换接口,接口请求攻略如下:
1)  服务协议为GET请求
3)  请求参数:
名称
含义
规则说明
是否必须
key
用户唯一标识
官网申请,用户唯一标识
必填
locations
坐标点
经度和纬度用”,”分割,经度在前,纬度在后,经纬度小数点后不得超过6位。多个坐标点间用”;”进行分隔
必填
coordsys
原坐标系
可选值:gps;mapbar;baidu
请求坐标加密,返回加密结果。
必填
output
返回数据类型
可选值:json(默认),xml
可选
URL示例:
3.      通过简单的http请求,即可以愉快地完成坐标转换的任务。
gis Leave a comment

iOS中给WebView写入cookie

在混合模式的开发过程中,用户在NativeApp中进行了登陆,但打开WebApp的时候还需要登陆,这就会造成较差的用户体验。
如果WebApp支持使用从Cookie验证的话,可以通过在NativeApp往WebView写入cookie的方式来解决该问题。

代码如下:

NSMutableDictionary *cookieProperties =         [NSMutableDictionary dictionary];
[cookieProperties setObject:@"testCookie" forKey:NSHTTPCookieName];
[cookieProperties setObject:@"someValue123456" forKey:NSHTTPCookieValue];
[cookieProperties setObject:@"www.example.com" forKey:NSHTTPCookieDomain];
[cookieProperties setObject:@"www.example.com" forKey:NSHTTPCookieOriginURL];
[cookieProperties setObject:@"/" forKey:NSHTTPCookiePath];
[cookieProperties setObject:@"0" forKey:NSHTTPCookieVersion];

// set expiration to one month from now or any NSDate of your choosing
// this makes the cookie sessionless and it will persist across web sessions and app launches
/// if you want the cookie to be destroyed when your app exits, don't set this
[cookieProperties setObject:[[NSDate date] dateByAddingTimeInterval:2629743] forKey:NSHTTPCookieExpires];

NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:cookieProperties];
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
iOS Leave a comment

ArcGIS开发权威指南 上架

《ArcGIS开发权威指南》内容提要

随着Web GIS 2.0时代的到来,单个研发技术的实施已经不能满足当前GIS项目的基本需求。如今用户既需要专业人士进行业务管理,又要求整个企业进行协作分享,而且还需要将信息通过网络或者移动端进行发布,这无疑需要多源技术的共同结合才能完成。那么从事GIS行业的开发者就需要了解GIS多源的开发技术。《ArcGIS开发权威指南》主要介绍ArcGIS平台及相关产品的开发模式,包括桌面端开发、Web端开发、移动端开发、数据库开发、脚本开发等主流的ArcGIS开发技术。

《ArcGIS开发权威指南》要求用户具有ArcGIS for Desktop、ArcGIS for Server、ArcSDE等ArcGIS产品相关基础,同时要求具有C#、Java、Python、JavaScript、PL/SQL等编程基础。《ArcGIS开发权威指南》适合ArcGIS开发工程师、GIS项目经理、GIS系统建设者,以及即将步入社会的相关专业学生阅读。

购买地址: 亚马逊

 

ArcGIS Leave a comment

Esri与开源

Esri与开源

随着主流的开发平台逐渐开源化,加上GitHub的兴起,开源深入了各个领域,Esri也不例外,积极的拥抱开源。
目前,Esri产品不仅支持开源产品(Linux,PostgreSQL,Python等),还开源了许多产品。
Esri开源代码主要通过github来进行发布,主页面为http://esri.github.io/

在Esri开源的产品中既有App开发框架,也有web前端功能类库,还有服务器端产品,基本上覆盖了Web开发,移动端开发和服务器端开发。使用Esri开源的产品,可以大大加快用户业务系统的开发,降低系统开发难度。 目前主要的开源产品包括:

  • FlexViewer
  • Esri Geoportal Server
  • ArcGIS Editor for OpenStreetMap
  • Terraformer
  • Esri Leaflet
  • Koop
  • Esri Geometry API for Java
  • 其他

FlexViewer

  • 项目地址:https://github.com/Esri/arcgis-viewer-flex
  • 项目截图:
    image
  • 项目介绍:FlexViewer可以说是目前为止Esri最成功的一款开源产品。FlexViewer从2009年开源至今,已经有成千上万个网站在使用。
    Flex Viewer是可以高效开发基于WEB的地理信息应用系统的一种完全免费的应用程序框架。业务人员使用该框架可以无需任何额外的编程就能够通过简单配置的方法快速搭建起一个基于ArcGIS Server的、以地图为中心的富客户端(RIA)应用的原型。该框架中还自带了大量的能够满足各种地图应用需要的Widget,如Identify、GeoRSS、DataExtract、BookMark、NetworkAnalyst、MapSwitcher等地图交互和分析等工具。同时,如果需要增加新的Widget,则开发人员只需在自定义的Widget中实现框架要求的接口,然后再将该Widget配置到框架中的Config.xml文件中,就能在无需修改框架代码的情况下轻松地完成独立Widget与框架的无缝集成。

Esri Geoportal Server

  • 项目地址:https://github.com/Esri/geoportal-server
  • 项目截图:
  • 项目介绍:Geoportal Server主要用于展示和使用各项空间资源,包括数据集、栅格数据以及网络服务。它能够帮助用户管理和发布各项空间资源的元数据以便于检索和展示资源。
    Geoportal server可支撑基于标准的数据交换和元数据展示应用。 使用Geoportal server可以提高企业或组织内地理空间活动的效率和效果,能够促进地理信息资源的共享,提高地理信息资源的查找效率并充分利用这些资源。

ArcGIS Editor for OpenStreetMap

项目地址:https://github.com/Esri/arcgis-osm-editor
* 项目截图:
image
* 项目介绍
ArcGIS Editor for OpenStreetMap是一个基于c#开发的在ArcMap中读取OpenStreetMap数据的插件。使用这个插件的功能如下:
1. 从OSM网站下载数据并存储到File Geodatabase中 2. 创建planet文件(.osm) 3. 编辑OSM数据 4. 将编辑后的数据更新到OSM网站 5. 从OSM数据创建网络数据集

Terraformer

  • 项目地址:https://github.com/Esri/Terraformer
  • 项目介绍:Terraformer是基于javascript的地理工具包,主要包括下面几个模块:
    1. Terraformer Core,主要用来处理GeoJSON
    2. WKT Parser,用来将WKT格式的数据转换成GeoJSON
    3. ArcGIS Geometry Parser,用来将ArcGIS Geometry格式数据转换成GeoJSON
    4. GeoStore,使用GeoJSON格式存储和查询空间数据的框架,支持空间索引

该项目既可以在浏览器中使用,又可以在node.js中使用

Esri Leaflet

项目地址:https://github.com/Esri/esri-leaflet
项目截图:
image
项目介绍:
Esri Leaflet是著名开源地图类库Leaflet的插件,主要实现在Leaflet中加载基础地图、要素服务的功能。同时还支持加载Esri的切片地图服务、动态地图服务和影像服务。
Esri Leaflet的目标不是替换掉 ArcGIS API for JavaScript,而是为Leaflet用户提供更方便调用Esri服务的方式。

Koop

项目地址:https://github.com/koopjs/koop

项目架构:
image
项目介绍:
Koop是一个基于Javascript的开源ETL工具。Koop支持将不同来源的数据转换成GeoJSON服务或者ArcGIS 要素服务。方便将来源不同的数据集成到Esri的产品体系中。
Koop是一个服务器端产品,运行在node.js中。

Esri Geometry API for Java

项目地址:https://github.com/Esri/geometry-api-java
项目介绍:Esri Geometry API for Java主要用来为第三方软件集成空间数据处理能力,例如Hadoop用户可以使用该类库在MapReduce环境中进行空间数据处理。该类库同样也可以用于Hive UDF中。当然,所有使用java开发的项目都可以集成该类库来进行空间数据的处理。
Esri Geometry API for Java提供的主要功能包括:

  1. 可以通过API直接创建Geometry,或者从JSON,WKT,Shape格式导入Geometry
  2. 提供了空间操作,例如叠加、相交、裁剪、缓冲分析等
  3. 提供了空间拓扑判定功能,例如相等、包含等

其他

除了上面的开源产品,Esri还开源了非常多的产品,主要包括:

更多的开源产品可以到主页面查看http://esri.github.io/

ArcGIS Leave a comment

QGIS python开发手册–使用栅格图层

使用栅格图层

图层详细信息

栅格图层一般包含一个或多个波段,即单波段栅格图层或多波段栅格图层。一般来说彩色图形包含红、蓝、绿三个波段。单波段图层一般用来表示连续变量(如高程)或离散变量(如土地利用)。在有些情况下,栅格图层包含一个调色板,栅格值对应的颜色会存储在调色板中,下面代码获取栅格图层的基本信息,例如长度、宽度、范围波段数、元数据等等。

    rlayer.width(), rlayer.height()
    (812, 301)
    rlayer.extent()
    &lt;qgis._core.QgsRectangle object at 0x000000000F8A2048&gt;
    rlayer.extent().toString()
    u'12.095833,48.552777 : 18.863888,51.056944'
    rlayer.rasterType()
    2  # 0 = GrayOrUndefined (single band), 1 = Palette (single band), 2 = Multiband
    rlayer.bandCount()
    3
    rlayer.metadata()
    u'&lt;p class="glossy"&gt;Driver:&lt;/p&gt;...'
    rlayer.hasPyramids()
    False

渲染器

当栅格图层加载后,QGIS会根据栅格类型使用一个默认的渲染器。渲染器可以在图层的属性中修改,也可以使用程序修改.下面代码查询当前使用的渲染器:

    &gt;&gt;&gt; rlayer.renderer()
    &lt;qgis._core.QgsSingleBandPseudoColorRenderer object at 0x7f471c1da8a0&gt;
    &gt;&gt;&gt; rlayer.renderer().type()
    u'singlebandpseudocolor'

使用QgsRasterLayer对象的setRenderer()方法可以给图层设置渲染器,可选的渲染器包括:
* QgsMultiBandColorRenderer * QgsPalettedRasterRenderer * QgsSingleBandColorDataRenderer * QgsSingleBandGrayRenderer * QgsSingleBandPseudoColorRenderer 这些渲染器全部继承于QgsRasterRenderer。

单波段栅格图层既可以以灰度图的方式显示,也可以通过色带映射的方式以彩色方式显示。多波段栅格图层,一般把波段映射成RGB颜色值进行显示。当然多波段栅格图层也可以使用灰度或者色带的方式显示其中的一个波段。

下面的小节会展开介绍如何查询和修改栅格图层的显示风格。

单波段栅格图层

下面的例子使用一个从绿色到黄色的色带(对应栅格值0-255)来渲染单波段栅格图层,首先创建一个QgsRasterShader对象,并配置他的shader函数:

&gt;&gt; fcn = QgsColorRampShader()
&gt;&gt;&gt; fcn.setColorRampType(QgsColorRampShader.INTERPOLATED)
&gt;&gt; lst = [ QgsColorRampShader.ColorRampItem(0, QColor(0,255,0)), \
QgsColorRampShader.ColorRampItem(255, QColor(255,255,0)) ]
&gt;&gt;&gt; fcn.setColorRampItemList(lst)
&gt;&gt;&gt; shader = QgsRasterShader()
&gt;&gt;&gt; shader.setRasterShaderFunction(fcn)

shader函数完成像素值和颜色值的映射,映射方式有三种:
* 线性:使用线性插值的方式获得像素的颜色值
* 离散:像素值大于或等于某一个阈值对应的颜色值,类似与ArcGIS中的分类渲染
* 精确:不进行插值,只有设置的色带中有对应的值才显示,类似于ArcGIS中的唯一值渲染
第二步,给栅格图层设置渲染器:

&gt;&gt;&gt; renderer = QgsSingleBandPseudoColorRenderer(layer.dataProvider(), 1, shader)
&gt;&gt;&gt; layer.setRenderer(renderer)

代码中的数字1为波段号。

多波段栅格图层

默认情况下,QGIS的多波段栅格图层使用RGB模式来生成彩色图像,有些情况下,如果用户想重置这个设置,可以使用下面的代码,代码重设了波段对应RGB的顺序,把波段1设为G,把波段2设为R:

rlayer.renderer().setGreenBand(1)
rlayer.renderer().setRedBand(2)

刷新图层

当用户修改了图层的符号设置并且需要立即显示的话,需要立即刷新图层,代码如下:

if hasattr(layer, "setCacheImage"):
      layer.setCacheImage(None)
layer.triggerRepaint()

前两行代码确保图层的缓存图片被删除。该方法在QGIS1.4以后有效,为了兼容QGIS的所有版本,请在使用前检查该函数是否存在。
triggerRepaint()方法用来强制地图刷新。
需要注意的是,对于WMS服务,只使用这个方法无效,还需要重新加载数据,刷新才会起作用,代码如下:

layer.dataProvider().reloadData()
layer.triggerRepaint()

在有些情况下,用户修改完图层的符号设置后,需要更新Layer List显示的图例,通过下面代码可以实现:

iface.legendInterface().refreshLayerSymbology(layer)

查询值

查询栅格图层中特定位置的值,使用identify()方法即可,代码如下:

ident = rlayer.dataProvider().identify(QgsPoint(15.30, 40.98), \
  QgsRaster.IdentifyFormatValue)
if ident.isValid():
  print ident.results()

result方法的返回结果是一个字段对象,包含每个波段对应的值:

{1: 17, 2: 220}

 

python Leave a comment

QGIS Python开发手册-加载图层

加载图层

在QGIS中,图层主要分为矢量图层和栅格图层,另外还支持自定义图层,本文不予讨论。

矢量图层

加载矢量图层,需要知道图层的数据源标识、名称和数据源类型(provider),加载代码如下:

layer = QgsVectorLayer(data_source, layer_name, provider_name)
if not layer.isValid():
      print "Layer failed to load!"

根据数据源类型的不同,数据源标识也不同。图层名称用于在图层列表Widget里显示。需要注意的是在加载图层后要判断是否加载成功,可以通过layer的isValid()方法进行判断。
在QGIS中快速打开并显示图层的方式是使用QgisInterface的addVectorLayer方法,代码如下:

 layer = iface.addVectorLayer("/path/to/shapefile/file.shp",     "layer_name_you_like", "ogr")
if not layer:
      print "Layer failed to load!"

该方法创建一个图层,静将图层假入到地图对象中,其返回一个图层对象。如果图层对象为None,则图层加载失败。
下面介绍加载不同数据源的图层:
* OGR–数据源标识为指向文件的路径

 vlayer = QgsVectorLayer("/path/to/shapefile/file.shp", "layer_name_you_like", "ogr")   

* PostGIS数据库–数据源标识是数据库连接字符串,可以通过QgsDataSourceURI类来生成,需要注意的是QGIS编译的时候选择了支持Postgres,否则不支持PostGIS。代码如下:

     uri = QgsDataSourceURI()
    # set host name, port, database name, username and password
    uri.setConnection("localhost", "5432", "dbname", "johny", "xxx")
    # set database schema, table name, geometry column and optionally
    # subset (WHERE clause)
    uri.setDataSource("public", "roads", "the_geom", "cityid = 2643")

    vlayer = QgsVectorLayer(uri.uri(), "layer_name_you_like", "postgres")

* CSV或其他平面数据文件–用分号作为分隔符,并且x字段存储x坐标,y字段存储y坐标,使用上述规则打开文件,则相关代码如下:

      uri = "/some/path/file.csv?delimiter=%s&xField=%s&yField=%s" % (";", "x", "y")
    vlayer = QgsVectorLayer(uri, "layer_name_you_like", "delimitedtext")

需要注意的是,从QGIS1.7开始,该类型的数据源标识为URL,因此路径要包含file://前缀。另外,使用该数据源还可以加载WKT格式的数据,并且允许定义参考系,相关代码如下:

    uri = "file:///some/path/file.csv?delimiter=%s&crs=epsg:4723&wktField=%s" % (";", "shape")

* GPX–gpx数据源可以读取从gpx文件里读取tracks, routes and waypoints 。使用gpx数据源的时候需要在路径中指定上述三种类型中的一种,代码如下:

     uri = "path/to/gpx/file.gpx?type=track"
    vlayer = QgsVectorLayer(uri, "layer_name_you_like", "gpx")

* SpatiaLite数据库–从QGIS1.1开始支持,类似于PostGIS数据库

    uri = QgsDataSourceURI()
    uri.setDatabase('/home/martin/test-2.3.sqlite')
    schema = ''
    table = 'Towns'
    geom_column = 'Geometry'
    uri.setDataSource(schema, table, geom_column)

    display_name = 'Towns'
    vlayer = QgsVectorLayer(uri.uri(), display_name, 'spatialite')

* MySQL,几何对象为WKB类型,通过OGR读取–数据源标识为数据库连接字符串,代码如下:

    uri = "MySQL:dbname,host=localhost,port=3306,user=root,password=xxx|layername=my_table"
    vlayer = QgsVectorLayer( uri, "my_table", "ogr" )

* WFS连接–数据源标识为URI,代码如下:

    uri = "http://localhost:8080/geoserver/wfs?srsname=EPSG:        23030&typename=union&version=1.0.0&request=GetFeature&service=WFS",
    vlayer = QgsVectorLayer("my_wfs_layer", "WFS")
uri也可以通过urilib创建:

    params = {
        'service': 'WFS',
     'version': '1.0.0',
    'request': 'GetFeature',
    'typename': 'union',
    'srsname': "EPSG:23030"
    }
    uri = 'http://localhost:8080/geoserver/wfs?' +      urllib.unquote(urllib.urlencode(params))

栅格图层

在QGIS中,使用GDAL来读取栅格图层,因此支持非常多种栅格格式。如果打开某些栅格文件有问题,请检查GDAL是否支持这种格式。
加载栅格图层,只需要指定栅格文件的路径和名称即可,代码如下:

    fileName = "/path/to/raster/file.tif"
    fileInfo = QFileInfo(fileName)
    baseName = fileInfo.baseName()
    rlayer = QgsRasterLayer(fileName, baseName)
    if not rlayer.isValid():
         print "Layer failed to load!"

和矢量图层类似,使用QgisInterface的addRasterLayer方法可以快速加载和显示栅格图层,代码如下:

    iface.addRasterLayer("/path/to/raster/file.tif", "layer_name_you_like")

上面的代码会创建一个栅格图层,并将该图层添加到地图对象中。
栅格图层还可以从WCS服务中创建,代码如下:

    urlWithParams = 'url=http://wms.jpl.nasa.gov/wms.cgi&layers=global_mosaic&styles=pseudo&format=image/jpeg&crs=EPSG:4326'
    rlayer = QgsRasterLayer(urlWithParams, 'some layer name', 'wms')
    if not rlayer.isValid():
          print "Layer failed to load!"

同样的,栅格图层还可以从WMS服务创建,代码如下:

    urlWithParams = 'url=http://wms.jpl.nasa.gov/wms.cgi&layers=global_mosaic&styles=pseudo&format=image/jpeg&crs=EPSG:4326'
    rlayer = QgsRasterLayer(urlWithParams, 'some layer name', 'wms')
    if not rlayer.isValid():
          print "Layer failed to load!"

图层加入到地图中

图层加载完成后,如果想进行显示,需要加载到地图中。代码如下:

    QgsMapLayerRegistry.instance().addMapLayer(layer)

当程序退出的时候,图层会自动析构,如果想手动删除,可以使用下面的代码:

    QgsMapLayerRegistry.instance().removeMapLayer(layer_id) 

用户可以通过图层的id来获取地图中图层,下面的方法列出地图对象中的所有图层:

    QgsMapLayerRegistry.instance().mapLayers()
python Leave a comment

QGIS python开发手册-加载工程文件

加载工程文件

在QGIS中加载工程文件需要使用QgsProject实例的read()方法,该方法需要传入QFileInfo对象。QFileInfo对象指定了QGIS工程文件的路径,下面的代码加载QGIS的工程文件到当前应用程序中:

# If you are not inside a QGIS console you first need to import
# qgis and PyQt4 classes you will use in this script as shown below:
from qgis.core import QgsProject
from PyQt4.QtCore import QFileInfo
# Get the project instance
project = QgsProject.instance()
# Print the current project file name (might be empty in case no projects have been loaded)
print project.fileName
u'/home/user/projects/my_qgis_project.qgs'
# Load another project
project.read(QFileInfo('/home/user/projects/my_other_qgis_project.qgs'))
print project.fileName
u'/home/user/projects/my_other_qgis_project.qgs'

在应用程序中,如果修改了工程文件,例如增加、删除图层,可以使用QgsProject实例的write()方法保存工程文件,write()方法可以传入QFileInfo对象,将工程文件另存到其他目录中。如下面代码:

# Save the project to the same
project.write()
# ... or to a new file
project.write(QFileInfo('/home/user/projects/my_new_qgis_project.qgs'))

read()和write()方法都会返回布尔类型的结果,用于判断读写是否成功。
需要注意的是,如果自定义程序是一个独立应用的话,为了能够同步的加载地图画布(canvas),需要首先实例化QgsLayerTreeMapCanvasBridge对象,代码如下:

bridge = QgsLayerTreeMapCanvasBridge( \
     QgsProject.instance().layerTreeRoot(), canvas)
# Now you can safely load your project and see it in the canvas
project.read(QFileInfo('/home/user/projects/my_other_qgis_project.qgs'))
python Leave a comment