ArcGIS API for Flex主要构建于ArcGIS Server REST API之上,客户端的功能比较有限,很多高级功能都通过Geometry Service 和 Geoprocessing Service实现。但是,有时候一些简单的功能,比如获取Polygon的中心点,在这个点上弹出一个自定义的窗口之类的,如果都通过服务来交互,可能用户体验就会变差。所以,你可以自己编写一些代码,在客户端实现这些功能。
这是我写的从一个Polygon获取中心点坐标的代码:
/**
* Author:Wu Yongfeng
* MSN/Email:warrenwyf@gmail.com
*/
package wuyf
{
import com.esri.ags.geometry.Extent;
import com.esri.ags.geometry.MapPoint;
import com.esri.ags.geometry.Polygon;
public class GeometryUtil
{
/**
* 获取多边形的重心
* @param polygon 多边形
* @return 重心点
*
*/
static public function getGravityCenter(polygon polygon):MapPoint
{
var ext:Extent = polygon.extent;
var p0:MapPoint = new MapPoint(ext.xmin, ext.ymin);
var momentX:Number = 0;
var momentY:Number = 0;
var weight:Number = 0;
for (var i:int=0; i<polygon.rings.length; i++ )
{
var pts:Array = polygon.rings as Array;
for ( var j:int=0; j<pts.length; j++ )
{
var p1:MapPoint = polygon.getPoint(i, j);
var p2:MapPoint;
if( j==pts.length-1 )
{
p2 = polygon.getPoint(i, 0);
}
else
{
p2 = polygon.getPoint(i, j+1);
}
var dWeight:Number = (p1.x-p0.x)*(p2.y-p1.y)
- (p1.x-p0.x)*(p0.y-p1.y)/2
- (p2.x-p0.x)*(p2.y-p0.y)/2
- (p1.x-p2.x)*(p2.y-p1.y)/2;
weight += dWeight;
var pTmp:MapPoint = new MapPoint((p1.x+p2.x)/2, (p1.y+p2.y)/2);
var gravityX:Number = p0.x + (pTmp.x-p0.x)*2/3;
var gravityY:Number = p0.y + (pTmp.y-p0.y)*2/3;
momentX += gravityX*dWeight;
momentY += gravityY*dWeight;
}
}
return new MapPoint(momentX/weight, momentY/weight);
}
}
}
看看效果:
2008年12月29日星期一
GIS Portal Toolkit 管理员的一些工作流程
【环境】GPT9.3,服务器Win2003 SP2,客户端WinXP SP3
1.从互联网搜索并保存元数据
通过GPT的CSW Client工具可以在ArcMap或者ArcGIS Explorer中对CSW(Catalog Service for the Web)进行查询,从而获得元数据信息。
以ArcGIS Explorer为例(照说明文档安装CSW Client并在ArcGIS Explorer添加工具):
比如我想搜索北京的服务,输入beijing,通过默认的http://www.geodata.gov/aimscsw/csw2.0入口搜索到若干结果如下:
选择“china”那项,点击View Metadata按钮,查看这个服务的详细信息。从元数据详细信息可以看到,这个服务来自http://sms.webmap.cn(测绘科学数据共享网)。
点击Download Metadata按钮将元数据下载到本地。
2.将元数据发布到GPT
通过GPT的Publish Client将元数据发布到GPT服务器:
打开ArcCatalog(照说明文档安装Publish Client并在ArcCatalog中添加工具),找到刚才下载的元数据文件。点击工具栏的Publish Metadata按钮。
在弹出的对话框中,按照GPT的配置填入相关信息,完成后点击Publish按钮,如果成功,将会弹出成功信息的对话框。
3.审核元数据并标记为公开
管理员可以查看元数据并进行审核,如果没有问题,可以将此元数据编辑为公开状态,使之可以被GPT用户搜索到。
在浏览器中输入http://SERVER_IP:8080/GPT9/,使用GPT的管理员帐号登录,进入Administration选项卡。在这可以看到刚才发布的china元数据,状态是Posted
勾选中这个元数据,在下拉框中选择“Set as Approved”,点击Excute Action按钮。
这个时候,用户已经可以通过GPT对这些元数据进行搜索了。还记得那个数据不负责任的描述“ddd”么?在首页搜索一下已经可以搜索到了。
1.从互联网搜索并保存元数据
通过GPT的CSW Client工具可以在ArcMap或者ArcGIS Explorer中对CSW(Catalog Service for the Web)进行查询,从而获得元数据信息。
以ArcGIS Explorer为例(照说明文档安装CSW Client并在ArcGIS Explorer添加工具):
比如我想搜索北京的服务,输入beijing,通过默认的http://www.geodata.gov/aimscsw/csw2.0入口搜索到若干结果如下:
选择“china”那项,点击View Metadata按钮,查看这个服务的详细信息。从元数据详细信息可以看到,这个服务来自http://sms.webmap.cn(测绘科学数据共享网)。
点击Download Metadata按钮将元数据下载到本地。
2.将元数据发布到GPT
通过GPT的Publish Client将元数据发布到GPT服务器:
打开ArcCatalog(照说明文档安装Publish Client并在ArcCatalog中添加工具),找到刚才下载的元数据文件。点击工具栏的Publish Metadata按钮。
在弹出的对话框中,按照GPT的配置填入相关信息,完成后点击Publish按钮,如果成功,将会弹出成功信息的对话框。
3.审核元数据并标记为公开
管理员可以查看元数据并进行审核,如果没有问题,可以将此元数据编辑为公开状态,使之可以被GPT用户搜索到。
在浏览器中输入http://SERVER_IP:8080/GPT9/,使用GPT的管理员帐号登录,进入Administration选项卡。在这可以看到刚才发布的china元数据,状态是Posted
勾选中这个元数据,在下拉框中选择“Set as Approved”,点击Excute Action按钮。
这个时候,用户已经可以通过GPT对这些元数据进行搜索了。还记得那个数据不负责任的描述“ddd”么?在首页搜索一下已经可以搜索到了。
GIS Portal Toolkit (GPT) 在线案例
http://portal.gsa.state.al.us/
http://www.geostor.arkansas.gov/
http://www.conservationmaps.org/
http://www.geonorge.no/Portal/ptk
http://gos2.geodata.gov/wps/portal/gos
http://gisserver.nic.in/nsdiportal/
http://www.inspire-geoportal.eu/
http://www.gis.ms.gov/Portal/ptk
http://gis.bpa.gov/Portal/
http://www.gov.ns.ca/geonova/
http://gisdata.virginia.gov/Portal/
http://www.geostor.arkansas.gov/
http://www.conservationmaps.org/
http://www.geonorge.no/Portal/ptk
http://gos2.geodata.gov/wps/portal/gos
http://gisserver.nic.in/nsdiportal/
http://www.inspire-geoportal.eu/
http://www.gis.ms.gov/Portal/ptk
http://gis.bpa.gov/Portal/
http://www.gov.ns.ca/geonova/
http://gisdata.virginia.gov/Portal/
2008年12月25日星期四
GIS Portal Toolkit (GPT) 9.3 安装配置 - 7.其余Tomcat配置
复制$CATALINA_BASE/webapps/GPT9/WEB-INF/lib/ojdbc5.jar到$CATALINA_BASE/common/lib下
复制安装盘的Other/JNDI Configuration/GPT9.xml到$CATALINA_BASE/conf/Catalina/localhost目录下
编辑GPT9.xml文件,找安装文档进行参数配置。
安装文档上还有一些其他配置,可能是apache版本或者操作系统的缘故,并没有找到。
复制安装盘的Other/JNDI Configuration/GPT9.xml到$CATALINA_BASE/conf/Catalina/localhost目录下
编辑GPT9.xml文件,找安装文档进行参数配置。
安装文档上还有一些其他配置,可能是apache版本或者操作系统的缘故,并没有找到。
GIS Portal Toolkit (GPT) 9.3 安装配置 - 6.配置MapViewer
首先,打开安装盘Database Scripts/Map Viewer目录,执行数据库对应的sql脚本。注意,登录数据库的时候采用前面配置数据库环节新建的gpt93用户,以下是Oracle上的命令:
sqlplus
gpt93
gpt93pwd
@.../MVS_Personalization_Oracle.sql;
下面就开始正式安装MapViewer Application:
打开安装盘的Web Applications/Map Viewer目录,将mvs_viewer.war部署到tomcat上。
打开$CATALINA_BASE/webapps/mvs_viewer/WEB-INF,编辑config.properties文件,详细参数见安装文档。
sqlplus
gpt93
gpt93pwd
@.../MVS_Personalization_Oracle.sql;
下面就开始正式安装MapViewer Application:
打开安装盘的Web Applications/Map Viewer目录,将mvs_viewer.war部署到tomcat上。
打开$CATALINA_BASE/webapps/mvs_viewer/WEB-INF,编辑config.properties文件,详细参数见安装文档。
GIS Portal Toolkit (GPT) 9.3 安装配置 - 5.部署并配置GPT9和servlet Application
首先部署GPT9.war(安装盘Web Applications/GPT9下)。建议使用Tomcat manager来部署,确保你的$CATALINA_BASE/conf/tomcat.users.xml中设置了manager用户,用这个用户来登录http://localhost:8080/manager/html后选择GPT9.war部署到服务器。
下面进行GPT9的配置,首先进入$CATALINA_BASE/GPT9/WEB‐INF/classes/gp/config目录。开始编辑gpt.xml文件。200多行的参数配置……自己看吧。
完成以后部署servlet.war(安装盘Web Applications/Servlet下)。进入$CATALINA_BASE/servlet/WEB‐INF目录,编辑web.xml文件。这里只有几个参数需要修改,见安装文档。
下面进行GPT9的配置,首先进入$CATALINA_BASE/GPT9/WEB‐INF/classes/gp/config目录。开始编辑gpt.xml文件。200多行的参数配置……自己看吧。
完成以后部署servlet.war(安装盘Web Applications/Servlet下)。进入$CATALINA_BASE/servlet/WEB‐INF目录,编辑web.xml文件。这里只有几个参数需要修改,见安装文档。
2008年12月24日星期三
GIS Portal Toolkit (GPT) 9.3 安装配置 - 3.配置数据库
GPT9.3支持Oracle、SQL Server和PostgreSQL,我这里使用的是Oracle 10g sp4。
首先,新建GPT的表空间和用户:
通过sqlplus进入SQL命令行
执行:
create tablespace GPT93 datafile '/opt/oracle/app/oracle/oradata/GPT93.dbf' size 500M AUTOEXTEND ON;
create user gpt93 identified by gpt93pwd default tablespace GPT93 temporary tablespace temp;
commit;
quit;
然后,运行一下几个sql脚本来创建schema:
通过sqlplus进入SQL命令行
我这里使用的是Oracle,脚本位于安装盘的“Database Scripts/Oracle”目录下
首先执行grants_oracle.sql:
@grants_oracle.sql sys syspwd gpt93 sde;
然后执行schema_oracle.sql:
@schema_oracle.sql gpt93 gpt93pwd;
再然后,用sde用户登录,并执行一下命令:
sdetable -o register -t gpt_admin -C none -i 5151 -s machineName -u gpt93 -p gpt93pwd
下面要配置数据库支持XML列
详细查看:http://webhelp.esri.com/arcgisdesktop/9.3/index.cfm?TopicName=Configuring_a_database_to_support_XML_columns
最后可以使用AcrCatalog来测试上述的配置是否正确:
新建一个Spatial Database Connection,server:服务器ip,service:5151,username:gpt93,password:gpt93pwd
首先,新建GPT的表空间和用户:
通过sqlplus进入SQL命令行
执行:
create tablespace GPT93 datafile '/opt/oracle/app/oracle/oradata/GPT93.dbf' size 500M AUTOEXTEND ON;
create user gpt93 identified by gpt93pwd default tablespace GPT93 temporary tablespace temp;
commit;
quit;
然后,运行一下几个sql脚本来创建schema:
通过sqlplus进入SQL命令行
我这里使用的是Oracle,脚本位于安装盘的“Database Scripts/Oracle”目录下
首先执行grants_oracle.sql:
@grants_oracle.sql sys syspwd gpt93 sde;
然后执行schema_oracle.sql:
@schema_oracle.sql gpt93 gpt93pwd;
再然后,用sde用户登录,并执行一下命令:
sdetable -o register -t gpt_admin -C none -i 5151 -s machineName -u gpt93 -p gpt93pwd
下面要配置数据库支持XML列
详细查看:http://webhelp.esri.com/arcgisdesktop/9.3/index.cfm?TopicName=Configuring_a_database_to_support_XML_columns
最后可以使用AcrCatalog来测试上述的配置是否正确:
新建一个Spatial Database Connection,server:服务器ip,service:5151,username:gpt93,password:gpt93pwd
2008年12月23日星期二
扩展 ArcGIS Server 在移动平台/互联网应用的可达性
其姊妹篇《扩展 ArcGIS Server 在移动平台/互联网应用的可达性补遗 —— 使用WFS-T》
【环境】ArcGIS Server 9.3
在ArcGIS Server 9.3中焕然一新的ArcGIS MobileSDK让ArcGIS Server的魅力延伸到了WindowsMobile平台上,填补了ArcGIS企业级移动平台应用的空白;稍后推出的ArcGIS API forFlex/JS又在让ArcGIS在WebGIS领域浓妆重彩,带来良好的用户体验。无疑,在ArcGIS ServerADF提供完善功能的同时,这些不同平台、快速开发、体验良好的SDK和API扩展了ArcGIS的应用领域,深合以正合以奇胜的兵法之道。
然而,这几支奇兵初次露面,未免有些青涩。ArcGIS Mobile SDK与WindowsMobile和.Net的死死绑定限制了它的应用范围,市场份额远大于WindowsMobile的 Symbian+iPhone+RIM被华丽地无视了;而在互联网应用上,ArcGIS API forFlex构建与REST之上,也使得空间数据的提交被忽视,这在后Web2.0时代几乎是不可被容忍的。本文讨论的主要目标就是另辟蹊径,在这些缺 憾之处加以弥补,延伸ArcGIS Server的触角,使之尽量可以扩展到各个平台、各个应用的死角。
本文主要涉及两方面内容,一方面是数据的获得,一方面是数据的提交。事实上关于数据的获得我前面的一些文章已经有所阐述,这里就简而言之;而在数据提交上,本文将从REST出发,详细叙述通过REST和Geoprocessing构建“万能”的数据提交方法。
首先看一下数据的获得,对于ArcGISServer强大的服务发布功能,获得数据相当容易。比如我比较喜欢kml服务,你需要在(移动)客户端或者其他 地方需要处理的无非就是一个kmz(zip)的解压缩问题,这几乎在所有的平台上都有解决方案。当然,ArcGIS还提供很多的服务种类,你大可以选择自 己喜欢的类型。
下面是一个Android的应用,地图采用了Google Map组件,底图是Google卫星影像图,再次基础上叠加ArcGIS Server发布的kml服务,关于如何从ArcGIS Server获得kmz并进行解析,详细可查看我的另外一篇文章:http://wu-yongfeng.blogspot.com/2008/10/androidkml.html。
对于数据的提交,我们最好需要一种不受SDK限制,不受防火墙限制的方法。好在ArcGISServer的核心就是服务,充分地利用这些服务是我们发挥想 象的空间。这里,我的方法是REST+GeoprocessingService。下面,让我还是在Android平台上先走一遍这个技术流程:
首先,编写一个python脚本,实现根据参数保存Feature到FeatureClass的功能:
import string, os, sys, locale, arcgisscripting
gp = arcgisscripting.create()
def createPoint(point, x, y):
try:
point.x = x
point.y = y
return point
except:
raise Exception, "Create point error."
try:
if len(sys.argv) < 2:
raise Exception, "No enough parameters."
outputFC = sys.argv[1]
inputString = sys.argv[2]
outDesc = gp.describe(outputFC)
shapefield = outDesc.ShapeFieldName
rows = gp.insertcursor(outputFC)
pnt = gp.createobject("point")
values = inputString.replace("\n", "").split(",")
row = rows.newrow()
pnt = createPoint(pnt, values[0], values[1])
row.SetValue(shapefield, pnt)
row.SetValue("CaseDetail", values[2])
rows.insertrow(row)
del rows
del row
except Exception, ErrorDesc:
if ErrorDesc[0] != "":
gp.AddError(str(ErrorDesc))
新建一个Toolbox,添加这个脚本并命名为AddTrafficCase,给脚本附上两个参数:需要保存的FeatureClass和传入的字符串 (包含坐标信息和某字段的属性值)。这个时候你可以先测试一下功能是否正常。在需要发布成Geoprocessing服务的Toolbox中的新建一个 Model,加入这个AddTrafficCase脚本,并定义Model的输入参数(字符串)和保存到的FeatureClass,如图:
当模型构建完成后,你可以将其发布成一个Geoprocessing服务。简单起见,我这个模型是没有返回值、仅提交一个点数据的服务,当然,你可以做很多扩展,万变不离其宗了。
让我们打开这个GP服务REST地址,检查它的功能是否正常:
下面我在Android的Map组件上开发一个小Demo,可以点击选择当前的坐标,再输入一些字符串作为信息一起提交到ArcGIS Server上来。
比如在Android平台,通过输入一些文本信息,通过如下的REST URL可以提交用户输入的信息:
String detail = editTextCaseDetail.getText().toString();
String strURL ="http://192.168.200.157/ArcGIS/rest/services/GPService/FeatureService/GPServer/AddTrafficCase/submitJob?String="+x+","+y+","+detail;
try
{
URL url = new URL(strURL);
HttpURLConnection uc = (HttpURLConnection)url.openConnection();
uc.connect();
uc.getInputStream();
}
catch(Exception e){}
点击确定提交以后,刷新Map以后,我们可以看到地图上多了一个事件点,点击这个事件点,出现提示信息——刚才在文本框中输入的“arcgis”:
下面让我们在ArcGIS API for Flex中再走一下这个流程,其实本质是一致的:
var parms : Object = new Object();
parms.String = x+","+y+",这是Flex保存的";
var geoprocessTask : Geoprocessor = new Geoprocessor();
geoprocessTask.url = "http://192.168.200.157/ArcGIS/rest/services/GPService/FeatureService/GPServer/AddTrafficCase";
geoprocessTask.submitJob( parms );
提交完成后查看一下结果:
从这两个例子可以看到,通过ArcGIS Server的REST和GeoprocessingService的组合,可以在任何满足联网条件的平台和应用上获取和提交数据,而不局限于 ArcGIS提供的SDK和API。也就是说,不管是移动平台、富因特网应用或是其他互联网应用都可以采用这种“万能”的方法进行空间数据的交互。在移动 领域,除了Android,移动市场份额最大的Symbian也已经选择了开源,可以看到以后在移动平台上进行开发绝非难事,通过本文你或许也可以感觉 到,ArcGISServer完全可以在这些地方大展身手。我们不用为ArcGISServer目前提供的仅有几个SDK和API而耿耿于怀,相信 LINING的这句断语:一切皆有可能!
【环境】ArcGIS Server 9.3
在ArcGIS Server 9.3中焕然一新的ArcGIS MobileSDK让ArcGIS Server的魅力延伸到了WindowsMobile平台上,填补了ArcGIS企业级移动平台应用的空白;稍后推出的ArcGIS API forFlex/JS又在让ArcGIS在WebGIS领域浓妆重彩,带来良好的用户体验。无疑,在ArcGIS ServerADF提供完善功能的同时,这些不同平台、快速开发、体验良好的SDK和API扩展了ArcGIS的应用领域,深合以正合以奇胜的兵法之道。
然而,这几支奇兵初次露面,未免有些青涩。ArcGIS Mobile SDK与WindowsMobile和.Net的死死绑定限制了它的应用范围,市场份额远大于WindowsMobile的 Symbian+iPhone+RIM被华丽地无视了;而在互联网应用上,ArcGIS API forFlex构建与REST之上,也使得空间数据的提交被忽视,这在后Web2.0时代几乎是不可被容忍的。本文讨论的主要目标就是另辟蹊径,在这些缺 憾之处加以弥补,延伸ArcGIS Server的触角,使之尽量可以扩展到各个平台、各个应用的死角。
本文主要涉及两方面内容,一方面是数据的获得,一方面是数据的提交。事实上关于数据的获得我前面的一些文章已经有所阐述,这里就简而言之;而在数据提交上,本文将从REST出发,详细叙述通过REST和Geoprocessing构建“万能”的数据提交方法。
首先看一下数据的获得,对于ArcGISServer强大的服务发布功能,获得数据相当容易。比如我比较喜欢kml服务,你需要在(移动)客户端或者其他 地方需要处理的无非就是一个kmz(zip)的解压缩问题,这几乎在所有的平台上都有解决方案。当然,ArcGIS还提供很多的服务种类,你大可以选择自 己喜欢的类型。
下面是一个Android的应用,地图采用了Google Map组件,底图是Google卫星影像图,再次基础上叠加ArcGIS Server发布的kml服务,关于如何从ArcGIS Server获得kmz并进行解析,详细可查看我的另外一篇文章:http://wu-yongfeng.blogspot.com/2008/10/androidkml.html。
对于数据的提交,我们最好需要一种不受SDK限制,不受防火墙限制的方法。好在ArcGISServer的核心就是服务,充分地利用这些服务是我们发挥想 象的空间。这里,我的方法是REST+GeoprocessingService。下面,让我还是在Android平台上先走一遍这个技术流程:
首先,编写一个python脚本,实现根据参数保存Feature到FeatureClass的功能:
import string, os, sys, locale, arcgisscripting
gp = arcgisscripting.create()
def createPoint(point, x, y):
try:
point.x = x
point.y = y
return point
except:
raise Exception, "Create point error."
try:
if len(sys.argv) < 2:
raise Exception, "No enough parameters."
outputFC = sys.argv[1]
inputString = sys.argv[2]
outDesc = gp.describe(outputFC)
shapefield = outDesc.ShapeFieldName
rows = gp.insertcursor(outputFC)
pnt = gp.createobject("point")
values = inputString.replace("\n", "").split(",")
row = rows.newrow()
pnt = createPoint(pnt, values[0], values[1])
row.SetValue(shapefield, pnt)
row.SetValue("CaseDetail", values[2])
rows.insertrow(row)
del rows
del row
except Exception, ErrorDesc:
if ErrorDesc[0] != "":
gp.AddError(str(ErrorDesc))
新建一个Toolbox,添加这个脚本并命名为AddTrafficCase,给脚本附上两个参数:需要保存的FeatureClass和传入的字符串 (包含坐标信息和某字段的属性值)。这个时候你可以先测试一下功能是否正常。在需要发布成Geoprocessing服务的Toolbox中的新建一个 Model,加入这个AddTrafficCase脚本,并定义Model的输入参数(字符串)和保存到的FeatureClass,如图:
当模型构建完成后,你可以将其发布成一个Geoprocessing服务。简单起见,我这个模型是没有返回值、仅提交一个点数据的服务,当然,你可以做很多扩展,万变不离其宗了。
让我们打开这个GP服务REST地址,检查它的功能是否正常:
下面我在Android的Map组件上开发一个小Demo,可以点击选择当前的坐标,再输入一些字符串作为信息一起提交到ArcGIS Server上来。
比如在Android平台,通过输入一些文本信息,通过如下的REST URL可以提交用户输入的信息:
String detail = editTextCaseDetail.getText().toString();
String strURL ="http://192.168.200.157/ArcGIS/rest/services/GPService/FeatureService/GPServer/AddTrafficCase/submitJob?String="+x+","+y+","+detail;
try
{
URL url = new URL(strURL);
HttpURLConnection uc = (HttpURLConnection)url.openConnection();
uc.connect();
uc.getInputStream();
}
catch(Exception e){}
点击确定提交以后,刷新Map以后,我们可以看到地图上多了一个事件点,点击这个事件点,出现提示信息——刚才在文本框中输入的“arcgis”:
下面让我们在ArcGIS API for Flex中再走一下这个流程,其实本质是一致的:
var parms : Object = new Object();
parms.String = x+","+y+",这是Flex保存的";
var geoprocessTask : Geoprocessor = new Geoprocessor();
geoprocessTask.url = "http://192.168.200.157/ArcGIS/rest/services/GPService/FeatureService/GPServer/AddTrafficCase";
geoprocessTask.submitJob( parms );
提交完成后查看一下结果:
从这两个例子可以看到,通过ArcGIS Server的REST和GeoprocessingService的组合,可以在任何满足联网条件的平台和应用上获取和提交数据,而不局限于 ArcGIS提供的SDK和API。也就是说,不管是移动平台、富因特网应用或是其他互联网应用都可以采用这种“万能”的方法进行空间数据的交互。在移动 领域,除了Android,移动市场份额最大的Symbian也已经选择了开源,可以看到以后在移动平台上进行开发绝非难事,通过本文你或许也可以感觉 到,ArcGISServer完全可以在这些地方大展身手。我们不用为ArcGISServer目前提供的仅有几个SDK和API而耿耿于怀,相信 LINING的这句断语:一切皆有可能!
2008年12月22日星期一
GIS Portal Toolkit (GPT) 9.3 安装配置 - 2.选择验证机制
GPT提供两种验证机制:
它们之间的区别见下表
简单验证意味着GPT只有一个用户:管理员。使用这种验证机制不需要再安装其它任何软件,但是GPT和其它应用之间使用单点登录将不可能实现。一般来说,这种验证机制仅在测试的时候使用,在部署真实应用的时候通常应使用LDAP。
下面叙述下如何配置LDAP,以Apache Directory Server(ApacheDS)为例。
首先,安装ApacheDS,建议另外再安装管理客户端JXplorer(SLES10默认仅支持JXplorer 3.0)。在Linux上ApacheDS安装完以后其配置文件在/var/lib/apacheds.../conf目录下,启动通过命令/opt/apacheds.../apacheds start default命令。JXplorer默认的端口为10389,DN为:“uid=admin,ou=system”,密码为“secret”,连接成功会出现如下界面:
在此基础上,我们需要新建一个GPT的管理员帐号。注意,这里的教程是基于ApacheDS的,其余情况需要详细查看ESRI的文档。注意,在点击“Add”以后出现的面板中,sn输入“gptadmin”,其余根据情况填写,一般需要填写“mail”“uid”“userPassword”,uid可以设为“gptadmin”。
新建一个group,命名为gpt_administrators,其中uniqueMember可填刚刚新建的gptadmin用户的DN:“cn=gptadmin,ou=users,ou=system”。重复这个过程,在新建2个组“gpt_publishers”和“gpt_registeredUsers”。
注意,以上过程是基于新建一个LDAP服务器,如果使用已经已有的LDAP服务器,那么配置过程将有所不同,更加详细的信息可以参考安装文档。
- 简单验证
- LDAP验证
它们之间的区别见下表
简单验证意味着GPT只有一个用户:管理员。使用这种验证机制不需要再安装其它任何软件,但是GPT和其它应用之间使用单点登录将不可能实现。一般来说,这种验证机制仅在测试的时候使用,在部署真实应用的时候通常应使用LDAP。
下面叙述下如何配置LDAP,以Apache Directory Server(ApacheDS)为例。
首先,安装ApacheDS,建议另外再安装管理客户端JXplorer(SLES10默认仅支持JXplorer 3.0)。在Linux上ApacheDS安装完以后其配置文件在/var/lib/apacheds.../conf目录下,启动通过命令/opt/apacheds.../apacheds start default命令。JXplorer默认的端口为10389,DN为:“uid=admin,ou=system”,密码为“secret”,连接成功会出现如下界面:
在此基础上,我们需要新建一个GPT的管理员帐号。注意,这里的教程是基于ApacheDS的,其余情况需要详细查看ESRI的文档。注意,在点击“Add”以后出现的面板中,sn输入“gptadmin”,其余根据情况填写,一般需要填写“mail”“uid”“userPassword”,uid可以设为“gptadmin”。
新建一个group,命名为gpt_administrators,其中uniqueMember可填刚刚新建的gptadmin用户的DN:“cn=gptadmin,ou=users,ou=system”。重复这个过程,在新建2个组“gpt_publishers”和“gpt_registeredUsers”。
注意,以上过程是基于新建一个LDAP服务器,如果使用已经已有的LDAP服务器,那么配置过程将有所不同,更加详细的信息可以参考安装文档。
2008年12月15日星期一
GIS Portal Toolkit (GPT) 9.3 安装配置 - 1.环境需求
【本教程环境】SuSE Linux Enterprise Server 10(目前不能安装MetadataServer,建议Windows)
【操作系统】
GIS Portal Toolkit(以下简称GPT)9.3在Windows 2003 SP2 Server 和 Windows XP SP2 Professional上进行了测试,不过应该支持以下操作系统:
• Red Hat Enterprise Linux AS/ES 4.0 Update 2
• SUSE Linux Enterprise Server 10
• Sun Solaris 9, 10 (SPARC)
• Windows 2000 SP4 Server
• Windows 2003 SP2 Server
• Windows Vista SP1 Ultimate, Enterprise, Business
• Windows XP SP2 Professional Edition
【数据库】
• Oracle 9i 9.2.0.7
• Oracle 10g 10.2.0.2
• Microsoft SQL Server 2000 SP4
• Microsoft SQL Server 2005 SP2
• PostgreSQL
【JAVA】
需要JDK 1.5,文档说1.5.0_06 和1.5.0_14 都可以,估计在这两个平台上进行了测试。不能用JDK1.6!
【ESRI相关软件】
• ArcGIS Server 9.3 Standard Enterprise – Java Edition
• ArcGIS Desktop 9.3 (可选, 不过建议安装)
• ArcSDE 9.3
另外,还需要一下内容:
a. 一个ArcGIS Server Map Service, 你需要知道它的REST地址
b. 一个ArcGIS Server Locator Service. 如果你不想创建这样一个服务,你可以使用这个在线服务:http://sampleserver1.arcgisonline.com/ArcGIS /rest/services/Locator/ESRI_Geocode_USA/GeocodeServer
注意: 如果在需要安装GPT 9.3的机器上装有ArcIMS,你首先需要卸载ArcIMS,并确认\webapps下不再有“servlet”目录。
【Web服务器和Servlet引擎】
• Apache 2.0.58 或 IIS
• Tomcat 5.5.17 或5.5.26,不能使用Tomcat 6.0.
【目录服务器】
• Apache Directory Server
• Sun OpenDS
【操作系统】
GIS Portal Toolkit(以下简称GPT)9.3在Windows 2003 SP2 Server 和 Windows XP SP2 Professional上进行了测试,不过应该支持以下操作系统:
• Red Hat Enterprise Linux AS/ES 4.0 Update 2
• SUSE Linux Enterprise Server 10
• Sun Solaris 9, 10 (SPARC)
• Windows 2000 SP4 Server
• Windows 2003 SP2 Server
• Windows Vista SP1 Ultimate, Enterprise, Business
• Windows XP SP2 Professional Edition
【数据库】
• Oracle 9i 9.2.0.7
• Oracle 10g 10.2.0.2
• Microsoft SQL Server 2000 SP4
• Microsoft SQL Server 2005 SP2
• PostgreSQL
【JAVA】
需要JDK 1.5,文档说1.5.0_06 和1.5.0_14 都可以,估计在这两个平台上进行了测试。不能用JDK1.6!
【ESRI相关软件】
• ArcGIS Server 9.3 Standard Enterprise – Java Edition
• ArcGIS Desktop 9.3 (可选, 不过建议安装)
• ArcSDE 9.3
另外,还需要一下内容:
a. 一个ArcGIS Server Map Service, 你需要知道它的REST地址
b. 一个ArcGIS Server Locator Service. 如果你不想创建这样一个服务,你可以使用这个在线服务:http://sampleserver1.arcgisonline.com/ArcGIS /rest/services/Locator/ESRI_Geocode_USA/GeocodeServer
注意: 如果在需要安装GPT 9.3的机器上装有ArcIMS,你首先需要卸载ArcIMS,并确认\webapps下不再有“servlet”目录。
【Web服务器和Servlet引擎】
• Apache 2.0.58 或 IIS
• Tomcat 5.5.17 或5.5.26,不能使用Tomcat 6.0.
【目录服务器】
• Apache Directory Server
• Sun OpenDS
2008年12月11日星期四
使用 FlashDevelop 开发 ArcGIS Flex 应用
【环境】Windows XP SP3,FlashDevelop 3.0.0 Beta9,Flex SDK 3.2,ArcGIS Flex API 1.0
如果你对基于Eclipse的Flex Builder的编译和操作不甚满意,常常为它的无端崩溃而心怀不满,更或者,你不倾向于使用收费的Flex Builder(标准版300多美刀),那么,或许你可以尝试一下这个主题的主角——一款开源的Flex IDE:FlashDevelop。FlashDevelop使用MIT许可分发,拥有和Visual Studio风格类似的界面和操作,还拥有插件机制来扩展功能——总而言之,它可以成为FlexBuilder之外开发Flex应用的又一选择。
我们可以从 http://www.flashdevelop.org 获取FlashDevelop的安装文件和文档。当你安装Flex Builder的时候,或许你不用操心任何其它组件,包括Flex SDK和Flash Player Debug版本等等都内置在其中。但是安装FlashDevelop之前,你需要做些额外的准备:
1. 从 http://www.adobe.com/products/flex/flexdownloads/ 下载Flex SDK,解压到某个目录
2. 从 http://www.adobe.com/support/flashplayer/downloads.html 下载Flash Player Debug版本,我用的是:Download the Windows Flash Player 9 Projector content debugger (EXE, 3.64 MB)
3. 从 http://www.java.com/zh_CN/download/manual.jsp#win 下载并安装JRE 1.6
好了,现在你可以从 http://www.flashdevelop.org/community/viewforum.php?f=11 选择一个FlashDevelop版本下载并安装,马上我们就可以开始使用这个IDE了。
……
此处等待若干秒
好了,FlashDevelop安装完成,运行它,再进行最后一点配置:
1. 打开 Tools->Program Settings,选择 AS3Context 选项卡
2. 编辑 Flex SDK Location到你刚才下载并解压缩的Flex SDK目录
在进入Flex开发之前,再唠叨一点关于插件的内容。默认的FlashDevelop没有可视化的组件拖拽,如果需要,可以从http://www.flashdevelop.org/wikidocs/index.php?title=3rd_Party_Plugins获取Flex Design View插件并安装,安装过程可以参考http://www.flashdevelop.org/community/viewtopic.php?f=4&t=3727,安装这个插件以后你就可以在打开一个mxml文件以后选择Design视图进行可视化设计了。
另外,还有一个必不可少的插件FDB,用于AS3代码调试。这个插件可以在这个地址下载:http://orange.zero.jp/zbn39616.pine/download/download.html,把dll文件拷入FlashDevelop的plugin目录即可。安装完FDB后打开Tools->Program Settings->FdbPlugin,将DebugFlashPlayerPath设为上面下载的debug版本的Flash Player所在的位置。
好,现在让我们开始ArcGIS Flex API的开发。
首先新建一个Flex项目
然后,将ArcGIS API for Flex的swc库文件添加到项目
很遗憾,目前的FlashDevelop对外部库的智能感应做的还不好,所以在使用mxml进行编程的时候,需要你写比较多的手工代码。如图,我们添加了一个最简单的一个ArcGIS Flex例子,在一个Application中添加一个Map对象,Map中放置一个ArcGISTiledMapLayer,用以显示切片地图。值得注意的是,在Application标签中,对com.esri.ags.*和com.esri.ags.layers.*这两个命名空间的声明。
目前由于FlashDevelop对mxml支持的有限,建议将功能代码分离到AS代码中去,比如上面的例子可以把大部分代码放到Scripti标签中去,如此你可以充分利用FlashDevelop强大的AS功能。
最后说一下程序的调试,调试程序的前提是安装了FDB插件,并且正确设置了debug版本Flash Player的路径。在Debug菜单有切换断点、单步调试等菜单项,当然,每次都从菜单操作是很麻烦的,你可以打开Tools->Program Settings->FdbPlugin设置各个操作的快捷键。注意,不要和Flash Develop内置的快捷键冲突。
好,剩下的事情就和Visual Studio调试差不多了,看一下效果:
如果你对基于Eclipse的Flex Builder的编译和操作不甚满意,常常为它的无端崩溃而心怀不满,更或者,你不倾向于使用收费的Flex Builder(标准版300多美刀),那么,或许你可以尝试一下这个主题的主角——一款开源的Flex IDE:FlashDevelop。FlashDevelop使用MIT许可分发,拥有和Visual Studio风格类似的界面和操作,还拥有插件机制来扩展功能——总而言之,它可以成为FlexBuilder之外开发Flex应用的又一选择。
我们可以从 http://www.flashdevelop.org 获取FlashDevelop的安装文件和文档。当你安装Flex Builder的时候,或许你不用操心任何其它组件,包括Flex SDK和Flash Player Debug版本等等都内置在其中。但是安装FlashDevelop之前,你需要做些额外的准备:
1. 从 http://www.adobe.com/products/flex/flexdownloads/ 下载Flex SDK,解压到某个目录
2. 从 http://www.adobe.com/support/flashplayer/downloads.html 下载Flash Player Debug版本,我用的是:Download the Windows Flash Player 9 Projector content debugger (EXE, 3.64 MB)
3. 从 http://www.java.com/zh_CN/download/manual.jsp#win 下载并安装JRE 1.6
好了,现在你可以从 http://www.flashdevelop.org/community/viewforum.php?f=11 选择一个FlashDevelop版本下载并安装,马上我们就可以开始使用这个IDE了。
……
此处等待若干秒
好了,FlashDevelop安装完成,运行它,再进行最后一点配置:
1. 打开 Tools->Program Settings,选择 AS3Context 选项卡
2. 编辑 Flex SDK Location到你刚才下载并解压缩的Flex SDK目录
在进入Flex开发之前,再唠叨一点关于插件的内容。默认的FlashDevelop没有可视化的组件拖拽,如果需要,可以从http://www.flashdevelop.org/wikidocs/index.php?title=3rd_Party_Plugins获取Flex Design View插件并安装,安装过程可以参考http://www.flashdevelop.org/community/viewtopic.php?f=4&t=3727,安装这个插件以后你就可以在打开一个mxml文件以后选择Design视图进行可视化设计了。
另外,还有一个必不可少的插件FDB,用于AS3代码调试。这个插件可以在这个地址下载:http://orange.zero.jp/zbn39616.pine/download/download.html,把dll文件拷入FlashDevelop的plugin目录即可。安装完FDB后打开Tools->Program Settings->FdbPlugin,将DebugFlashPlayerPath设为上面下载的debug版本的Flash Player所在的位置。
好,现在让我们开始ArcGIS Flex API的开发。
首先新建一个Flex项目
然后,将ArcGIS API for Flex的swc库文件添加到项目
很遗憾,目前的FlashDevelop对外部库的智能感应做的还不好,所以在使用mxml进行编程的时候,需要你写比较多的手工代码。如图,我们添加了一个最简单的一个ArcGIS Flex例子,在一个Application中添加一个Map对象,Map中放置一个ArcGISTiledMapLayer,用以显示切片地图。值得注意的是,在Application标签中,对com.esri.ags.*和com.esri.ags.layers.*这两个命名空间的声明。
目前由于FlashDevelop对mxml支持的有限,建议将功能代码分离到AS代码中去,比如上面的例子可以把大部分代码放到Scripti标签中去,如此你可以充分利用FlashDevelop强大的AS功能。
最后说一下程序的调试,调试程序的前提是安装了FDB插件,并且正确设置了debug版本Flash Player的路径。在Debug菜单有切换断点、单步调试等菜单项,当然,每次都从菜单操作是很麻烦的,你可以打开Tools->Program Settings->FdbPlugin设置各个操作的快捷键。注意,不要和Flash Develop内置的快捷键冲突。
好,剩下的事情就和Visual Studio调试差不多了,看一下效果:
2008年12月9日星期二
总结 ArcGIS Mobile 9.3 图层可编辑的条件
1. 数据源必须是 SDE
2. 数据必须包含 GlobalIDs
3. 不可含有 M and Z 值
4. 没有使用FeatureClass的 area或length字段进行渲染
5. 编辑多边形的第一部分必须按顺时针方向走,逆时针方向会形成洞从而引发一个异常。
2. 数据必须包含 GlobalIDs
3. 不可含有 M and Z 值
4. 没有使用FeatureClass的 area或length字段进行渲染
5. 编辑多边形的第一部分必须按顺时针方向走,逆时针方向会形成洞从而引发一个异常。
2008年12月5日星期五
ArcGIS Server Java 9.3 REST API的中文查询问题的解决方案
【2009.2.18补注】这个问题在SP1 for Linux中修复,SP1 for Windows下问题更加严重,如果打了SP1 for Windows,还想使用REST服务,就必须使用Linux或者没有打SP1补丁的Windows的ArcGIS Server的$arcgis/java/web_output/rest替换现有的目录(同时,还需要手动修改/WEB-INF/classes下的配置文件server.properties)。
目前在ArcGIS Server 9.3 Java中使用中文进行REST查询时是有问题的,这是ArcGIS Server for Java集成的tomcat的问题,我的同事曾经给出一个解决方案:
1、ArcGIS Server Java 9.3可以把services和rest单独导出成war包,部署到其他的web服务器上,从而可以避免内置tomcat的性能瓶颈。进入Manager-->services-->Configure Services Handler-->Export页面,把rest服务导出成rest.war,保存到本地;
2、把保存下来的rest.拷贝到任何一个其他版本的tomcat 的webapps目录下(ArcGIS Server内置的tomcat是5.5.9版本,我们测试用的是apache-tomcat-6.0.10)
3、启动tomcat6.0.10,在浏览器中输入http://localhost:8080/rest,进入service directory页面。
4、选中服务的图层进行查询,输入中文进行查询,看是否可以得到正确的结果。
有人反映这个方案不能解决问题,可能和tomcat的版本有关,我研究了一下,给出两种解决方案:
方案1:
从客户端入手。
中文不能查询的根本原因在于编码,当我们在使用REST API进行查询的时候,请求的URL一般是这样:“http://wuyfsles:8399/arcgis/rest/services/BeijingTraffic/MapServer/find?searchText=事故&contains=true&searchFields=&sr=&layers=0&returnGeometry=true”,其中的中文无法被服务器识别。因此,你可以在发送前对“事故”这个中文关键词进行URL编码,应该是“%CA%C2%B9%CA”,你在浏览器中输入“http://wuyfsles:8399/arcgis/rest/services/BeijingTraffic/MapServer /find?searchText=%CA%C2%B9%CA&contains=true&searchFields=&sr=& layers=0&returnGeometry=true”的时候,是不是可以看到结果了?
方案2:
从服务器端入手,还是着手解决编码问题。
既然tomcat有问题,我们就在tomcat身上开刀。以Linux为例,分别打开“/arcgis/java/manager/service/tomcat/managerappserver/conf/server.xml”和“/arcgis/java/manager/service/tomcat/managerserver/conf/server.xml”,找到“Connector”元素,如图添加属性URIEncoding="UTF-8"。保存退出,重启tomcat和ArcGIS Server。
在浏览器中试一下中文查询,问题已经解决,如图:
再在Flex中进行Find Task查询,也能查到正确结果,如图:
目前在ArcGIS Server 9.3 Java中使用中文进行REST查询时是有问题的,这是ArcGIS Server for Java集成的tomcat的问题,我的同事曾经给出一个解决方案:
1、ArcGIS Server Java 9.3可以把services和rest单独导出成war包,部署到其他的web服务器上,从而可以避免内置tomcat的性能瓶颈。进入Manager-->services-->Configure Services Handler-->Export页面,把rest服务导出成rest.war,保存到本地;
2、把保存下来的rest.拷贝到任何一个其他版本的tomcat 的webapps目录下(ArcGIS Server内置的tomcat是5.5.9版本,我们测试用的是apache-tomcat-6.0.10)
3、启动tomcat6.0.10,在浏览器中输入http://localhost:8080/rest,进入service directory页面。
4、选中服务的图层进行查询,输入中文进行查询,看是否可以得到正确的结果。
有人反映这个方案不能解决问题,可能和tomcat的版本有关,我研究了一下,给出两种解决方案:
方案1:
从客户端入手。
中文不能查询的根本原因在于编码,当我们在使用REST API进行查询的时候,请求的URL一般是这样:“http://wuyfsles:8399/arcgis/rest/services/BeijingTraffic/MapServer/find?searchText=事故&contains=true&searchFields=&sr=&layers=0&returnGeometry=true”,其中的中文无法被服务器识别。因此,你可以在发送前对“事故”这个中文关键词进行URL编码,应该是“%CA%C2%B9%CA”,你在浏览器中输入“http://wuyfsles:8399/arcgis/rest/services/BeijingTraffic/MapServer /find?searchText=%CA%C2%B9%CA&contains=true&searchFields=&sr=& layers=0&returnGeometry=true”的时候,是不是可以看到结果了?
方案2:
从服务器端入手,还是着手解决编码问题。
既然tomcat有问题,我们就在tomcat身上开刀。以Linux为例,分别打开“/arcgis/java/manager/service/tomcat/managerappserver/conf/server.xml”和“/arcgis/java/manager/service/tomcat/managerserver/conf/server.xml”,找到“Connector”元素,如图添加属性URIEncoding="UTF-8"。保存退出,重启tomcat和ArcGIS Server。
在浏览器中试一下中文查询,问题已经解决,如图:
再在Flex中进行Find Task查询,也能查到正确结果,如图:
2008年12月1日星期一
Google Map中国地图搜索的请求方式
与MapABC、Mapbar等国内地图“API”提供商不同,Google Map在对坐标的控制上比较宽松,不像国内地图厂家对坐标进行加密。而且,Google Map的地图搜索请求不仅仅支持html输出,而且还支持json和kml等输出,这无疑给程序整合带来便利。
目前,Google Map中国地图的搜索可以通过如下的URL请求完成:
http://ditu.google.cn/maps?output=kml&hl=zh-CN&q=东方新天地+餐厅&near=王府井&start=10
简单的解释一下:output对应输出格式,目前至少支持html、json和kml;q对应请求的搜索对象,多个关键字用“+”连接;near对应周边搜索;start对应多页搜索结果的起始值,默认一页10个结果,那么如果查看第二页那就是start=10,第三页就是20……
目前,Google Map中国地图的搜索可以通过如下的URL请求完成:
http://ditu.google.cn/maps?output=kml&hl=zh-CN&q=东方新天地+餐厅&near=王府井&start=10
简单的解释一下:output对应输出格式,目前至少支持html、json和kml;q对应请求的搜索对象,多个关键字用“+”连接;near对应周边搜索;start对应多页搜索结果的起始值,默认一页10个结果,那么如果查看第二页那就是start=10,第三页就是20……
2008年11月26日星期三
Windows Mobile程序获取google map切片时候需要注意的问题
如果始终提示403错误,可能需要检查一下HttpWebRequest的UserAgent的属性,可以随便设置一个,比如“Microsoft Internet Explorer”欺骗一下。
2008年11月20日星期四
Google地图中国切片地址变化
url已经从MapABC切换到了google.cn,切片数据应该是没变,只不过访问方式变成了如下格式:
http://mt0.google.cn/mt?v=cn1.5&hl=zh-CN&x=1686&y=775&z=11
可用的mt0~mt3,z值定义和Google Earth类似,和原先MapABC的定义相反,现在的z=17-zoom。
http://mt0.google.cn/mt?v=cn1.5&hl=zh-CN&x=1686&y=775&z=11
可用的mt0~mt3,z值定义和Google Earth类似,和原先MapABC的定义相反,现在的z=17-zoom。
2008年11月13日星期四
ArcGIS Mobile 9.3 SP1的更新
1. ArcGIS Mobile Application支持smartphone版本,包括Windows Mobile 5.0 SmartPhone和Windows Mobile 6.0/6.1 Standard。
2. 修正了存储二进制块到Blob字段的bug。
3. 完善对PostgreSQL的支持,9.3原版本不支持数据提交。
4. 修正了GpsDisplay的问题
2. 修正了存储二进制块到Blob字段的bug。
3. 完善对PostgreSQL的支持,9.3原版本不支持数据提交。
4. 修正了GpsDisplay的问题
2008年11月11日星期二
2008年11月10日星期一
Qt Creator 技术预览版
ArcGIS Mobile 9.3 的数据安全
很多人想必会关心在移动端的数据安全问题。ArcGIS Mobile中在移动端主要有两种数据:Basemap和Cache。Basemap一般会随安装包部署到移动设备上,Cache则会在用户访问的时候生成(也可事先部署)。
关于Cache数据,你可以很放心,Cache的bin文件不能通过ArcGIS Mobile之外的任何工具访问,也就是说,你的业务数据可以保证是保密的。但Basemap则不同,我们首先要理解Basemap的作用,它是底图,不提供业务操作;但是它是矢量的,包含了几何信息和属性信息。因此,它的数据被当作一种特殊的数据集来处理,通过ArcGIS Desktop可以打开Basemap的数据,同时还可以导出其它格式,也就是说,Basemap是可以被第三方获取并解析的。
因此,对于要生成Basemap的数据,事先需要对数据源进行一定的处理,删除敏感信息和不必要的属性字段。
关于Cache数据,你可以很放心,Cache的bin文件不能通过ArcGIS Mobile之外的任何工具访问,也就是说,你的业务数据可以保证是保密的。但Basemap则不同,我们首先要理解Basemap的作用,它是底图,不提供业务操作;但是它是矢量的,包含了几何信息和属性信息。因此,它的数据被当作一种特殊的数据集来处理,通过ArcGIS Desktop可以打开Basemap的数据,同时还可以导出其它格式,也就是说,Basemap是可以被第三方获取并解析的。
因此,对于要生成Basemap的数据,事先需要对数据源进行一定的处理,删除敏感信息和不必要的属性字段。
2008年11月6日星期四
2008年10月29日星期三
Android解析KML
KML服务有两种,一种是纯文本的XML,一种是将一个纯文本的XML文件和其他资源(如图标)进行zip压缩后形成的KMZ,本质是zip。使用Android解析KML服务需要根据情况首先判断是否需要解压缩,然后再解析XML文本。
Android Java中包含了zip压缩解压缩工具库,可以从“java.util.zip”包中进行调用。我们看一下一个KMZ如何被解压缩:
URL url = new URL(strUrl);
HttpURLConnection uc = (HttpURLConnection) url.openConnection();
InputStream isKxml = null;
ZipInputStream zipIs = new ZipInputStream(uc.getInputStream());
ZipEntry zipEntry = null;
while ((zipEntry = zipIs.getNextEntry()) != null)
{
String zipEntryName = zipEntry.getName();
if (zipEntryName.endsWith("kml"))
{
ByteArrayOutputStream os = new ByteArrayOutputStream();
byte[] b = new byte[512];
int readedByteSize = 0;
while ((readedByteSize = zipIs.read(b)) > 0)
{
os.write(b, 0, readedByteSize);
}
os.flush();
os.close();
isKxml = new ByteArrayInputStream(os.toByteArray());
}
else if (zipEntryName.endsWith("png"))
{
ByteArrayOutputStream os = new ByteArrayOutputStream();
byte[] b = new byte[512];
int readedByteSize = 0;
while ((readedByteSize = zipIs.read(b)) > 0)
{
os.write(b, 0, readedByteSize);
}
os.flush();
os.close();
InputStream isBitmap = new ByteArrayInputStream(os
.toByteArray());
Bitmap bitmap = BitmapFactory.decodeStream(isBitmap);
kml.addBitmap(zipEntryName, bitmap);
isBitmap.close();
}
}
zipIs.close();
Reader reader = new InputStreamReader(isKxml);
parseKxml(kml, reader);//解析KML文本的方法
isKxml.close();
reader.close();
好了,解压缩完成后,重点就在解析KML文本上了。鉴于移动终端的KML内容不应该很大,因此在这里使用了XmlDocument方法解析,下面看一下方法:
private static void parseKxml(Kml kml, Reader reader) throws Exception
{
KXmlParser kXmlParser = new KXmlParser();
kXmlParser.setInput(reader);
Document doc = new Document();
doc.parse(kXmlParser);
if (doc == null) return;
Element eRoot = doc.getRootElement();
……(处理XML Element)
}
Android Java中包含了zip压缩解压缩工具库,可以从“java.util.zip”包中进行调用。我们看一下一个KMZ如何被解压缩:
URL url = new URL(strUrl);
HttpURLConnection uc = (HttpURLConnection) url.openConnection();
InputStream isKxml = null;
ZipInputStream zipIs = new ZipInputStream(uc.getInputStream());
ZipEntry zipEntry = null;
while ((zipEntry = zipIs.getNextEntry()) != null)
{
String zipEntryName = zipEntry.getName();
if (zipEntryName.endsWith("kml"))
{
ByteArrayOutputStream os = new ByteArrayOutputStream();
byte[] b = new byte[512];
int readedByteSize = 0;
while ((readedByteSize = zipIs.read(b)) > 0)
{
os.write(b, 0, readedByteSize);
}
os.flush();
os.close();
isKxml = new ByteArrayInputStream(os.toByteArray());
}
else if (zipEntryName.endsWith("png"))
{
ByteArrayOutputStream os = new ByteArrayOutputStream();
byte[] b = new byte[512];
int readedByteSize = 0;
while ((readedByteSize = zipIs.read(b)) > 0)
{
os.write(b, 0, readedByteSize);
}
os.flush();
os.close();
InputStream isBitmap = new ByteArrayInputStream(os
.toByteArray());
Bitmap bitmap = BitmapFactory.decodeStream(isBitmap);
kml.addBitmap(zipEntryName, bitmap);
isBitmap.close();
}
}
zipIs.close();
Reader reader = new InputStreamReader(isKxml);
parseKxml(kml, reader);//解析KML文本的方法
isKxml.close();
reader.close();
好了,解压缩完成后,重点就在解析KML文本上了。鉴于移动终端的KML内容不应该很大,因此在这里使用了XmlDocument方法解析,下面看一下方法:
private static void parseKxml(Kml kml, Reader reader) throws Exception
{
KXmlParser kXmlParser = new KXmlParser();
kXmlParser.setInput(reader);
Document doc = new Document();
doc.parse(kXmlParser);
if (doc == null) return;
Element eRoot = doc.getRootElement();
……(处理XML Element)
}
2008年10月24日星期五
2008年10月16日星期四
ArcGIS API for Flex入门 - 7.API学习路线
如果我的这一系列文章不对你的胃口,或者你更喜欢官方一点的学习文档,我这里整理了一些在线资源和建议的学习路线,供你参考:)
首先,你是否了解Flex,如果你还不了解Flex和它的开发环境,那么可以到这里看看:
Flex 入门
Flex 语言参考
如果你对Flex已经有了一定了解,并准备开始使用ArcGIS API for Flex,那么首先推荐看一个ESRI的在线视频教你如何配置开发环境,工欲善其事必先利其器嘛。
《Creating an application using the ArcGIS API for Flex》
当你对Flex的MXML和ActionScript语言都有所了解,同时已经配置好ArcGIS API for Flex并且可以创建Flex应用以后,案例驱动是最好的学习方法,下面是ArcGIS API for Flex的在线Sample及其源代码。
ArcGIS API for Flex 在线Sample
在开发过程中,对ArcGIS API for Flex有任何疑问,最好的解决办法是查看API参考:
ArcGIS Flex API参考
最后,说点和ArcGIS API for Flex无关的话题,那就是Flex在WebGIS中的作用。使用Flex最大的好处是无需对原来的GIS系统和网站进行重新设计和架构,只需适时嵌入Flex应用即可达到非常好的效果。在这里,再附上一个Flex 3D Map的演示,看了这个演示你会对Flex如何促进WebGIS应用的表现能力有更为直观的了解:
http://thunderhead.esri.com/readonlyurl/HeatMap3D.html
上一节
【结束】
首先,你是否了解Flex,如果你还不了解Flex和它的开发环境,那么可以到这里看看:
Flex 入门
Flex 语言参考
如果你对Flex已经有了一定了解,并准备开始使用ArcGIS API for Flex,那么首先推荐看一个ESRI的在线视频教你如何配置开发环境,工欲善其事必先利其器嘛。
《Creating an application using the ArcGIS API for Flex》
当你对Flex的MXML和ActionScript语言都有所了解,同时已经配置好ArcGIS API for Flex并且可以创建Flex应用以后,案例驱动是最好的学习方法,下面是ArcGIS API for Flex的在线Sample及其源代码。
ArcGIS API for Flex 在线Sample
在开发过程中,对ArcGIS API for Flex有任何疑问,最好的解决办法是查看API参考:
ArcGIS Flex API参考
最后,说点和ArcGIS API for Flex无关的话题,那就是Flex在WebGIS中的作用。使用Flex最大的好处是无需对原来的GIS系统和网站进行重新设计和架构,只需适时嵌入Flex应用即可达到非常好的效果。在这里,再附上一个Flex 3D Map的演示,看了这个演示你会对Flex如何促进WebGIS应用的表现能力有更为直观的了解:
http://thunderhead.esri.com/readonlyurl/HeatMap3D.html
上一节
【结束】
ArcGIS API for Flex入门 - 6.有多少Task可以重来
上一小节我们了解了Flex API中的Task用法,你可以把Task想象成一条命令,当你把命令发送到服务器的时候,服务器会执行并返回给你结果——当然,前提是要服务器提供这个服务。上一节的例子是IdentifyTask,其它的Task大抵也可以触类旁通。可是,API的Task包的命名因为不同Task的功能不同而并不很一致,有些Task的名称并不是以Task结尾,同时,并不是所有的Task都可以execute。所以,我们在这一小节重点讨论一下各种Task的作用和用法。
1.FindTask
这是一个很简洁的Task,它的功能主要是通过关键字来搜索要素的某些字段,如果符合则返回查找到的要素。你可以参考Sample的“FindTask.mxml”,下面是对Task定义的一些代码:
我们似乎已经可以摸到Task的一般套路,先生成一个参数对象,对这个Task需要完成的任务进行一些设定,然后将Task与这些参数联系起来,最后执行等待服务器返回处理结果。这个FindTask就是这样,简洁明了。
2.GeometryService
这是对几何对象进行处理的一个Task,可是它是以Service结尾,这代表它并不简单地给你execute一下的,它提供了处理多种任务的能力。比如缓冲(buffer)、量测(lengths)等等。让我们打开Sample的“BufferSample.mxml”看看,这是一个缓冲的例子。
我们可以看到,处理的过程和其它Task也没什么区别,只不过没有了execute(有你也不知道到底执行什么命令),取代它的是明确的任务名称,比如要进行缓冲,那就是用buffer方法:
myGeometryService.buffer( bufferParameters );
好,那么随之而来的一个问题就是执行完了怎么办,怎么区分不同命令返回的结果?事实上,你只要监听不同的时间好了,比如你执行buffer命令,那么你就监听BUFFER_COMPLETE事件(mxml中:bufferComplete="..."),好了,只要你的方法监听到这个事件,你就可以在buffer完成后进行后续的处理了。
3.Geoprocessor
这是GP服务对应的Task。GP服务很灵活,因此你在设置Geoprocessor任务参数(Object对象)的时候,需要给予更多的注意。在用法上它并没有很多新意,具体可以参考一下Sample的“GeoprocessorMessageInABottle.mxml”。
4.IdentifyTask
识别要素,老朋友了,具体参考上一节。
5.Locator
从地址获得要素或者从要素获得地址的Task。让我们打开Sample的“LocatorTask.mxml”看一下,下面是执行命令的代码:
locateTask.addressToLocations(addy, null, new AsyncResponder(onResult, onFault));
Locator主要提供两个命令:addressToLocations()和locationToAddress()。它的参数也是Object对象,因此提供了灵活的参数设置和更多出错的机会。
6.QueryTask
查询要素。FindTask是搜索某些字段文本的命令,而QueryTask则提供了文本查询和空间查询的能力。sample中的“QueryTaskOnMap.mxml”是一个文本查询的例子。让我们对它进行一些修改以进行空间查询:
执行查询的命令是queryTask.execute( query, new AsyncResponder( onResult, onFault ));
让我们在它之前加上:
query.geometry = map.extent;
query.spatialRelationship = Query.SPATIAL_REL_INTERSECTS;
上面的map是Map组件的id(自己添加),同时,把query原先定义的text属性删除。让我们运行以后再点击查询,拖动一下地图,是不是看到只有原先视口中的要素被高亮了出来?这就是空间查询的结果,因为上面执行的查询是以当前地图范围为过滤条件的。
上一节 下一节
1.FindTask
这是一个很简洁的Task,它的功能主要是通过关键字来搜索要素的某些字段,如果符合则返回查找到的要素。你可以参考Sample的“FindTask.mxml”,下面是对Task定义的一些代码:
我们似乎已经可以摸到Task的一般套路,先生成一个参数对象,对这个Task需要完成的任务进行一些设定,然后将Task与这些参数联系起来,最后执行等待服务器返回处理结果。这个FindTask就是这样,简洁明了。
2.GeometryService
这是对几何对象进行处理的一个Task,可是它是以Service结尾,这代表它并不简单地给你execute一下的,它提供了处理多种任务的能力。比如缓冲(buffer)、量测(lengths)等等。让我们打开Sample的“BufferSample.mxml”看看,这是一个缓冲的例子。
我们可以看到,处理的过程和其它Task也没什么区别,只不过没有了execute(有你也不知道到底执行什么命令),取代它的是明确的任务名称,比如要进行缓冲,那就是用buffer方法:
myGeometryService.buffer( bufferParameters );
好,那么随之而来的一个问题就是执行完了怎么办,怎么区分不同命令返回的结果?事实上,你只要监听不同的时间好了,比如你执行buffer命令,那么你就监听BUFFER_COMPLETE事件(mxml中:bufferComplete="..."),好了,只要你的方法监听到这个事件,你就可以在buffer完成后进行后续的处理了。
3.Geoprocessor
这是GP服务对应的Task。GP服务很灵活,因此你在设置Geoprocessor任务参数(Object对象)的时候,需要给予更多的注意。在用法上它并没有很多新意,具体可以参考一下Sample的“GeoprocessorMessageInABottle.mxml”。
4.IdentifyTask
识别要素,老朋友了,具体参考上一节。
5.Locator
从地址获得要素或者从要素获得地址的Task。让我们打开Sample的“LocatorTask.mxml”看一下,下面是执行命令的代码:
locateTask.addressToLocations(addy, null, new AsyncResponder(onResult, onFault));
Locator主要提供两个命令:addressToLocations()和locationToAddress()。它的参数也是Object对象,因此提供了灵活的参数设置和更多出错的机会。
6.QueryTask
查询要素。FindTask是搜索某些字段文本的命令,而QueryTask则提供了文本查询和空间查询的能力。sample中的“QueryTaskOnMap.mxml”是一个文本查询的例子。让我们对它进行一些修改以进行空间查询:
执行查询的命令是queryTask.execute( query, new AsyncResponder( onResult, onFault ));
让我们在它之前加上:
query.geometry = map.extent;
query.spatialRelationship = Query.SPATIAL_REL_INTERSECTS;
上面的map是Map组件的id(自己添加),同时,把query原先定义的text属性删除。让我们运行以后再点击查询,拖动一下地图,是不是看到只有原先视口中的要素被高亮了出来?这就是空间查询的结果,因为上面执行的查询是以当前地图范围为过滤条件的。
上一节 下一节
2008年10月15日星期三
ArcGIS API for Flex入门 - 5.任务Task
Task是ArcGIS Server的重要组成部分,一个Task可以执行某些特定的任务,比如Identify、Query等等。在这个小节,我们通过IdentifyTask来认识Task的使用方法。
IdentifyTask是一个可以识别要素的任务,让我们打开Sample的“IdentifySample.mxml”,看一下其中核心的代码。
我们首先注意一下在Flex Application中添加了这样一个IdentifyTask的标签:
我们设想的功能大概是这样的:先在地图上画一个多边形,然后识别多边形内的所有要素,最后在图上标注出来。让我们看一下这个功能在Flex中是如何通过Task执行完成的:
首先是绘图,我首先需要在地图上画一个多边形,在ArcGIS API for Flex中有一个提供绘图的工具条com.esri.ags.toolbars.Draw,通过它我们可以很轻松地实现绘图功能:
如上所示,IdentifySample在Draw对象上添加一个事件监听器,当绘图完成时,执行drawEndHandler()方法,在这个方法中,我们将继续绘图以后的工作。
在已经绘制了一个多边形以后,我们就需要执行IdentifyTask来进行要素识别了。先看一下代码:
private function drawEndHandler(event:DrawEvent):void
{
var geometry : Geometry = event.geometry;
var identifyParams : IdentifyParameters = new IdentifyParameters();
identifyParams.returnGeometry = true;
identifyParams.tolerance = 3;
identifyParams.width = 600;
identifyParams.height = 550;
identifyParams.geometry = geometry;
switch (layerOption.value)
{
case "top":
identifyParams.layerOption = IdentifyParameters.LAYER_OPTION_TOP;
break;
case "visible":
identifyParams.layerOption = IdentifyParameters.LAYER_OPTION_VISIBLE;
break;
case "all":
identifyParams.layerOption = IdentifyParameters.LAYER_OPTION_ALL;
break;
}
identifyParams.mapExtent = map.extent;
identifyTask.execute( identifyParams );
}
在DrawEvent对象中,我们可以获取刚才绘图的Geometry对象,这个Geometry对象用于Identify的参数设置中,如果你做过ArcEngine开发,你可以对比一下SpatialFilter。好,再设置了一下需要搜索的图层和范围以后,你就可以执行这个IdentifyTask了,看到execute是不是很兴奋?
然后呢?我们回头看看这个IdentifyTask的定义,其中注册了当Task完成时候执行的方法:identifyCompleteHandler()。
private function identifyCompleteHandler(event:IdentifyEvent):void
{
for each (var result:IdentifyResult in event.identifyResults)
{
myGraphicsLayer.add(result.feature);
}
}
看明白了么?这个方法就是在GraphicLayer上把这个Task的结果画出来。
通过这个流程,你应该明白了Task的作用和用法了吧。
上一节 下一节
IdentifyTask是一个可以识别要素的任务,让我们打开Sample的“IdentifySample.mxml”,看一下其中核心的代码。
我们首先注意一下在Flex Application中添加了这样一个IdentifyTask的标签:
我们设想的功能大概是这样的:先在地图上画一个多边形,然后识别多边形内的所有要素,最后在图上标注出来。让我们看一下这个功能在Flex中是如何通过Task执行完成的:
首先是绘图,我首先需要在地图上画一个多边形,在ArcGIS API for Flex中有一个提供绘图的工具条com.esri.ags.toolbars.Draw,通过它我们可以很轻松地实现绘图功能:
如上所示,IdentifySample在Draw对象上添加一个事件监听器,当绘图完成时,执行drawEndHandler()方法,在这个方法中,我们将继续绘图以后的工作。
在已经绘制了一个多边形以后,我们就需要执行IdentifyTask来进行要素识别了。先看一下代码:
private function drawEndHandler(event:DrawEvent):void
{
var geometry : Geometry = event.geometry;
var identifyParams : IdentifyParameters = new IdentifyParameters();
identifyParams.returnGeometry = true;
identifyParams.tolerance = 3;
identifyParams.width = 600;
identifyParams.height = 550;
identifyParams.geometry = geometry;
switch (layerOption.value)
{
case "top":
identifyParams.layerOption = IdentifyParameters.LAYER_OPTION_TOP;
break;
case "visible":
identifyParams.layerOption = IdentifyParameters.LAYER_OPTION_VISIBLE;
break;
case "all":
identifyParams.layerOption = IdentifyParameters.LAYER_OPTION_ALL;
break;
}
identifyParams.mapExtent = map.extent;
identifyTask.execute( identifyParams );
}
在DrawEvent对象中,我们可以获取刚才绘图的Geometry对象,这个Geometry对象用于Identify的参数设置中,如果你做过ArcEngine开发,你可以对比一下SpatialFilter。好,再设置了一下需要搜索的图层和范围以后,你就可以执行这个IdentifyTask了,看到execute是不是很兴奋?
然后呢?我们回头看看这个IdentifyTask的定义,其中注册了当Task完成时候执行的方法:identifyCompleteHandler()。
private function identifyCompleteHandler(event:IdentifyEvent):void
{
for each (var result:IdentifyResult in event.identifyResults)
{
myGraphicsLayer.add(result.feature);
}
}
看明白了么?这个方法就是在GraphicLayer上把这个Task的结果画出来。
通过这个流程,你应该明白了Task的作用和用法了吧。
上一节 下一节
ArcGIS API for Flex入门 - 4.事件Event
前面讨论的主要是怎么样去操作Map,设定各种数据啊,通知它更新数据源啊等等。目前,你已经可以通过ArcGIS API for Flex渲染各种漂亮的地图了。下面,我们应当来想想怎么来做更多的事情了。
比如在你的Flex Application中,你希望在用户在点击Map的时候,获取到用户点击的坐标,然后到数据库去查找附近是不是有好吃的餐馆之类的。这个时候你应该想到我们应该要处理Map的事件了。
这里插播一句,ArcGIS API for Flex最重要的就是Map组件,你完全可以把Map组件等同于其他原生的Flex组件来使用。——所以,如果你很熟悉Flex,那么本小节下面的内容你可以跳过了。
好,我们打开Sample的“EventBasics.mxml”,在onApplicationCreationComplete()方法(它监听了Application的创建完成事件)中,其中添加了Map组件的鼠标click事件监听器:
myMap.addEventListener(MouseEvent.CLICK, logMouseEvent);
其中的logMouseEvent在下面进行了定义:
public function logMouseEvent(event:MouseEvent):void
{
log.text = "* MouseEvent: " + event.type + "\n" + log.text;
}
每当用户在Map上进行点击时,Map就会自动分发MouseEvent.CLICK事件,而监听Click事件的logMouseEvent()方法就会被执行。运行一个这个“EventBasics.mxml”,试着在地图上点击几下,有没有看到右面的文本变化?
当然,ArcGIS 的Map组件提供了许多的Event,涵盖地图操作、图层操作、查询操作、绘图操作等等,你可以在此基础上实现任何你想实现的功能。
上一节 下一节
比如在你的Flex Application中,你希望在用户在点击Map的时候,获取到用户点击的坐标,然后到数据库去查找附近是不是有好吃的餐馆之类的。这个时候你应该想到我们应该要处理Map的事件了。
这里插播一句,ArcGIS API for Flex最重要的就是Map组件,你完全可以把Map组件等同于其他原生的Flex组件来使用。——所以,如果你很熟悉Flex,那么本小节下面的内容你可以跳过了。
好,我们打开Sample的“EventBasics.mxml”,在onApplicationCreationComplete()方法(它监听了Application的创建完成事件)中,其中添加了Map组件的鼠标click事件监听器:
myMap.addEventListener(MouseEvent.CLICK, logMouseEvent);
其中的logMouseEvent在下面进行了定义:
public function logMouseEvent(event:MouseEvent):void
{
log.text = "* MouseEvent: " + event.type + "\n" + log.text;
}
每当用户在Map上进行点击时,Map就会自动分发MouseEvent.CLICK事件,而监听Click事件的logMouseEvent()方法就会被执行。运行一个这个“EventBasics.mxml”,试着在地图上点击几下,有没有看到右面的文本变化?
当然,ArcGIS 的Map组件提供了许多的Event,涵盖地图操作、图层操作、查询操作、绘图操作等等,你可以在此基础上实现任何你想实现的功能。
上一节 下一节
ArcGIS API for Flex入门 - 3.数据的绑定
在这一小节里,我们主要讨论数据绑定的问题。事实上这是属于Flex的范畴,如果你对Flex语言很熟悉,那你完全可以跳过这一节。
在前面的小节,我们已经学会了如何在Flex Application中加入一个Map组件,并且在Map组件中添加了一个ArcGISTiledMapServiceLayer图层,当然,ArcGIS Flex不仅支持切片图层,还有ArcGISDynamicMapServiceLayer、ArcGISMapServiceLayer、ArcGISImageServiceLayer、ArcIMSMapServiceLayer,这些类型的图层都可以顾名思义,熟悉ArcGIS Server的你肯定不陌生。
这时,如果你想要实现这样的功能:点击一个按钮(或者选中下拉框的一个选项),当前的Map中的地图就自动地切换——就像Google Map一样,你可以选择卫星图或者切片地图。当然,你可以这样做:在每个按钮的Click事件中,获得需要更新的图层URL,然后通知Map:换图层了!没有任何问题,但是,在Flex有更加“面对对象”的方法:数据绑定。
我是一个很懒的人,所以我经常引用的代码就是ArcGIS API for Flex自带的Sample(后面我说的Sample就是Flex API的例子,我就不重复说明了,这样的简称应该没有诸如RTFM之类的难懂吧)。这次也不例外,让我们打开Sample中的agol.mxml。
我们注意,在Map元素的属性中,有一个url定义,当然这就是地图服务的地址。然而这个地址并不是一个通常的字符串,在其中嵌入了一段“{servicePicker.selectedItem.toString()}”。这个servicePicker是什么呢,往下看几行,我们可以看到,在这个Flex Application中的ComboBox的id是servicePicker,这个ComboBox就是供你来选择地图服务的。顺便提一下,Flex背后站着的其实是Flash,因此id在Flex中有着非常重要的作用。
好,我们看看这段代码到底是什么意思。Flex组件默认监听了名为propertyChange的事件,当自身的数据改变的时候,它就会分发这一事件,这时,使用花括号括起来的对象就会接受到对应的事件并更新自身的数据。“{servicePicker}”监听的是id为servicePicker的下拉框的组件,当我们在下拉框选择了某个地图服务的时候,“{servicePicker.selectedItem.toString()}”就会根据这个下拉框的选择项生成一个字符串,再把字符串拼接到Map的url属性中去。Map就会根据新的url获取数据并进行渲染。这就是一种“面对对象”的数据处理方式。
上一节 下一节
在前面的小节,我们已经学会了如何在Flex Application中加入一个Map组件,并且在Map组件中添加了一个ArcGISTiledMapServiceLayer图层,当然,ArcGIS Flex不仅支持切片图层,还有ArcGISDynamicMapServiceLayer、ArcGISMapServiceLayer、ArcGISImageServiceLayer、ArcIMSMapServiceLayer,这些类型的图层都可以顾名思义,熟悉ArcGIS Server的你肯定不陌生。
这时,如果你想要实现这样的功能:点击一个按钮(或者选中下拉框的一个选项),当前的Map中的地图就自动地切换——就像Google Map一样,你可以选择卫星图或者切片地图。当然,你可以这样做:在每个按钮的Click事件中,获得需要更新的图层URL,然后通知Map:换图层了!没有任何问题,但是,在Flex有更加“面对对象”的方法:数据绑定。
我是一个很懒的人,所以我经常引用的代码就是ArcGIS API for Flex自带的Sample(后面我说的Sample就是Flex API的例子,我就不重复说明了,这样的简称应该没有诸如RTFM之类的难懂吧)。这次也不例外,让我们打开Sample中的agol.mxml。
我们注意,在Map元素的属性中,有一个url定义,当然这就是地图服务的地址。然而这个地址并不是一个通常的字符串,在其中嵌入了一段“{servicePicker.selectedItem.toString()}”。这个servicePicker是什么呢,往下看几行,我们可以看到,在这个Flex Application中的ComboBox的id是servicePicker,这个ComboBox就是供你来选择地图服务的。顺便提一下,Flex背后站着的其实是Flash,因此id在Flex中有着非常重要的作用。
好,我们看看这段代码到底是什么意思。Flex组件默认监听了名为propertyChange的事件,当自身的数据改变的时候,它就会分发这一事件,这时,使用花括号括起来的对象就会接受到对应的事件并更新自身的数据。“{servicePicker}”监听的是id为servicePicker的下拉框的组件,当我们在下拉框选择了某个地图服务的时候,“{servicePicker.selectedItem.toString()}”就会根据这个下拉框的选择项生成一个字符串,再把字符串拼接到Map的url属性中去。Map就会根据新的url获取数据并进行渲染。这就是一种“面对对象”的数据处理方式。
上一节 下一节
2008年10月13日星期一
ArcGIS API for Flex入门 - 2.配置开发环境和HelloWorld
如何配置Flex开发环境,参考前作:《ArcGIS API for Flex 配置使用》。
在这篇叙述如何进行开发环境配置的文档中,最后测试环境时使用了Flex API的一个Sample。我们来看一下那个Sample的具体内容(“Tutorial_Map.mxml”)。
在“mx:application”元素(顾名思义,这就定义了一个Flex应用)中首先定义了mx和esri,它们分别是Flex和ArcGIS的命名空间,通过命名空间就可以引用到相应的内容,比如“esri:Map”对应的就是API中的com.esri.ags.Map这个类。
事实上,mxml文件会首先被编译成ActionScript,通过mxml定义和通过ActionScript定义在效果上是等效的。比如在mxml中添加标签:
esri:Map
等同于as脚本:
import com.esri.ags.Map;
var map:Map= new Map();
继续来看这个Sample,在定义了Map以后,又往其中添加了2个元素:extent和ArcGISTiledMapServiceLayer。也就是在新建了一个Map以后,设定了当前的可视范围,然后再添加了一个切片图层。做完这几步简单的工作以后,Map就可以渲染出一幅漂亮的地图了。我们可以看到,使用ArcGIS API for Flex来开发是一件非常简单的事情。
好,下面我们试着用ActionScript来替换xml标签来做相同的事情:
运行它,你可以看到,效果和原来的Sample是完全一样的。
上一节 下一节
在这篇叙述如何进行开发环境配置的文档中,最后测试环境时使用了Flex API的一个Sample。我们来看一下那个Sample的具体内容(“Tutorial_Map.mxml”)。
在“mx:application”元素(顾名思义,这就定义了一个Flex应用)中首先定义了mx和esri,它们分别是Flex和ArcGIS的命名空间,通过命名空间就可以引用到相应的内容,比如“esri:Map”对应的就是API中的com.esri.ags.Map这个类。
事实上,mxml文件会首先被编译成ActionScript,通过mxml定义和通过ActionScript定义在效果上是等效的。比如在mxml中添加标签:
esri:Map
等同于as脚本:
import com.esri.ags.Map;
var map:Map= new Map();
继续来看这个Sample,在定义了Map以后,又往其中添加了2个元素:extent和ArcGISTiledMapServiceLayer。也就是在新建了一个Map以后,设定了当前的可视范围,然后再添加了一个切片图层。做完这几步简单的工作以后,Map就可以渲染出一幅漂亮的地图了。我们可以看到,使用ArcGIS API for Flex来开发是一件非常简单的事情。
好,下面我们试着用ActionScript来替换xml标签来做相同的事情:
运行它,你可以看到,效果和原来的Sample是完全一样的。
上一节 下一节
ArcGIS API for Flex入门 - 1.概述
【环境】ArcGIS Server 9.3,ArcGIS API for Flex 1.0 beta,Adobe Flex Builder 3
ArcGIS最新推出了Flex API,主要面向基于ArcGIS Server 的RIA开发。RIA近来越来越火热,Flex/Flash在RIA领域又是绝对的翘楚,ArcGIS在这个时候推出Flex API实在是太理所当然了。
如果你还不太了解Flex,那么你可能会知道Adobe公司的Flash。作为现在主要浏览器均支持的一个必备插件,Flash占据了Web浏览98%的市场份额。Flash可以整合图片、音频、视频、矢量图画、动画等各种资源,并提供良好的交互,因此在浏览器上可以提供给用户非常良好的体验。这就是Flash流行的原因。
Flex则是Adobe最近推出的SDK,旨在帮助程序员进行Flash开发。要知道,Flash里面的影片剪辑、时间线等等概念都是为动画美工所熟知的,但是和程序员的思维实在是大相径庭。因此,Adobe推出了这个可以使用xml、ActionScript(在Flash中同样存在)进行编程的工具——Flex。当然,Flex可以做的事情,Flash都可以做。Flex就像是一个作坊,在作坊里工作你就可以顺利生产出Flash(*.swf)来——况且,这个工作并不复杂。
在Flex和Flash中主要的开发语言是ActionScript(以下简称as),这是一种语法结构和JavaScript很像的脚本语言,也是对Flash进行控制的根本方法。其实,Flex只需要as就可以工作了,其提供的mxml(xml)只不过为了方便开发人员进行布局和快速开发的一个工具。mxml文件最终都会编译成as脚本,并在Flash中执行。
ArcGIS API for Flex(以下简称Flex API)能帮助你做什么呢?事实上这个API是以Flex组件库的形式存在的。当你在你的Flex项目中添加了Flex API,你可以像开发桌面程序一样拖动一个Flex控件到你的应用中,做些简单的设置就可以进行GIS操作:浏览、查询……你可以想象一下你正在使用ArcEngine进行开发……
我以前有写Flex API概述《ArcGIS API for Flex概览》,这里就不再赘述了。
下一节
ArcGIS最新推出了Flex API,主要面向基于ArcGIS Server 的RIA开发。RIA近来越来越火热,Flex/Flash在RIA领域又是绝对的翘楚,ArcGIS在这个时候推出Flex API实在是太理所当然了。
如果你还不太了解Flex,那么你可能会知道Adobe公司的Flash。作为现在主要浏览器均支持的一个必备插件,Flash占据了Web浏览98%的市场份额。Flash可以整合图片、音频、视频、矢量图画、动画等各种资源,并提供良好的交互,因此在浏览器上可以提供给用户非常良好的体验。这就是Flash流行的原因。
Flex则是Adobe最近推出的SDK,旨在帮助程序员进行Flash开发。要知道,Flash里面的影片剪辑、时间线等等概念都是为动画美工所熟知的,但是和程序员的思维实在是大相径庭。因此,Adobe推出了这个可以使用xml、ActionScript(在Flash中同样存在)进行编程的工具——Flex。当然,Flex可以做的事情,Flash都可以做。Flex就像是一个作坊,在作坊里工作你就可以顺利生产出Flash(*.swf)来——况且,这个工作并不复杂。
在Flex和Flash中主要的开发语言是ActionScript(以下简称as),这是一种语法结构和JavaScript很像的脚本语言,也是对Flash进行控制的根本方法。其实,Flex只需要as就可以工作了,其提供的mxml(xml)只不过为了方便开发人员进行布局和快速开发的一个工具。mxml文件最终都会编译成as脚本,并在Flash中执行。
ArcGIS API for Flex(以下简称Flex API)能帮助你做什么呢?事实上这个API是以Flex组件库的形式存在的。当你在你的Flex项目中添加了Flex API,你可以像开发桌面程序一样拖动一个Flex控件到你的应用中,做些简单的设置就可以进行GIS操作:浏览、查询……你可以想象一下你正在使用ArcEngine进行开发……
我以前有写Flex API概述《ArcGIS API for Flex概览》,这里就不再赘述了。
下一节
2008年10月12日星期日
Open API
其实大家都希望开放自己的API以后,吸引开发人员在自己的平台上做点事情。吹得美妙无比,内心都险恶得要死巴不得天底下别的API都死绝了,大家都用我的吧。Open API是一个比云更ws的概念,它的口号就是:我的是我的,你的还是我的。小子,我这里有全套工具,来给我打工吧!好,你就瞎忙活去吧。
你要用它的API在它那里实现了什么功能,恭喜你,你已经正式成为了它的免费兼职实习生;你要用它的API在你自己那里使用了什么功能,给它打了广告不说,啥时候你的流量大了,对不起,从今天开始限制访问量,非付费用户每天限制IP500个,不够?交钱啊。这叫什么,消费陷阱啊。
所以啊,云啊雾啊开放啥的都是虚的,数据才是根本。有了数据你才有发言权,你才有资本去做云啊雾的,然后对大家招招手说:hey come on,给你露几个接口,用去吧。ok,到时候你也会说:Open API好,云实在是好。
你要用它的API在它那里实现了什么功能,恭喜你,你已经正式成为了它的免费兼职实习生;你要用它的API在你自己那里使用了什么功能,给它打了广告不说,啥时候你的流量大了,对不起,从今天开始限制访问量,非付费用户每天限制IP500个,不够?交钱啊。这叫什么,消费陷阱啊。
所以啊,云啊雾啊开放啥的都是虚的,数据才是根本。有了数据你才有发言权,你才有资本去做云啊雾的,然后对大家招招手说:hey come on,给你露几个接口,用去吧。ok,到时候你也会说:Open API好,云实在是好。
2008年9月28日星期日
Android SDK 1.0 移除了原先0.9中包含的KXML2库
如果原先使用KXML2来解析KML文档的,需要手动添加这个库。
最新版KXML2可以从这里下:
http://sourceforge.net/project/showfiles.php?group_id=9157
最新版KXML2可以从这里下:
http://sourceforge.net/project/showfiles.php?group_id=9157
2008年9月19日星期五
Android开发简明教程-4.Activity跳转与传值
一个Android应用程序很少会只有一个Activity对象,如何在多个Activity之间进行跳转,而且能够互相传值是一个很基本的要求。
在前面创建的MyApp中,我们通过点击按钮可以更新当前界面上的文本内容。现在我们想换种方式,在点击按钮后,显示一个新的屏幕,在这个屏幕上输入一段话,然后再返回到原先的界面显示刚才输入的那句话。
首先我们新建这个新屏幕的布局文件input.xml,并添加一个文本输入框和一个按钮(注意,xml元素的命名不要和其他布局文件中的定义重名,因为所有的资源都在R中进行索引,比如id,如果重名了在使用R.id.*的时候就会有问题了)。这个布局文件对应的是一个Activity,因此我们再新建一个Input类(继承自Activity)用于显示这个布局并响应事件。
然后,还有一个重要的工作,那就是在清单文件AndroidManifest.xml中告诉程序,我定义了一个新的Activity,你可以去调用它。
我们希望在以前的那个主界面上点击按钮以后可以跳转到文本输入界面,所以我们需要对按钮的onClick事件进行定义:
在这段代码里出现了一些新东西。首先是Intent,它是Android一个很重要的类.Intent直译是“意图”,什么是意图呢?比如你想从这个Activity跳转到另外一个Activity,这就是一个意图。它不但可以连接多个Activity,还可以在它们之间传递数据。在这里,我们就是用Intent从MyApp对象跳转到了Input对象。
再看紧跟着的startActivityForResult()方法,顾名思义,它可以从一个定义好的Intent对象启动一个新的Activity,并且,这个Activity会返回执行的结果,这些内容下面马上就会提到。
好,这里我们已经可以调出新Activity了,我们看一下执行的结果:
你马上可以想到,现在需要对新的Activity(Input)进行处理了。我们在点击“确定”按钮的时候,需要获得上面EditText对象中的文本,然后返回到前一个Activity(MyApp)中去。看我们的按钮事件处理:
这里的关键是SharedPreferences对象,这是在多个Activity(同一包中)共享数据的方式,本质上它就是一个可以在包的范围内进行数据共享的文件。
我们通过一个标签“Text”获得了和文本相关的那个SharedPreferences对象(“Text”仅仅是自己定义的一个标签),然后给它赋予一个“text”对象值为当前文本框中输入的文本。设置完成以后,设置当前Activity的执行结果为RESULT_OK,再关闭当前的Activity,剩下的事情就可以回到MyApp这个主界面中去执行了。
其实剩下的事情也很简单,在MyApp这个Activity中,我们需要重写一个函数,onActivityResult()。因为我们启动Input这个Activity的时候使用的是startActivityForResult()方法,这个方法会使Input执行完以后返回给MyApp一个结果,MyApp接收到返回结果的时候会触发onActivityResult事件,对于结果的处理就在onActivityResult()中进行。同样,我们通过“Text”这个标签获得SharedPreferences对象,再把字符串从“text”对象中取出来并显示到当前屏幕上。
另外说明一下,requestCode是用来标识请求对象,我们刚才在启动Activity的时候使用的是“startActivityForResult(intent, 0)”,这里的0就是requestCode,当然,你可以设置成任何你喜欢的值。
我们看一下执行结果:
对于Activity我们先了解到这里,下面我们看一些其它的内容。
在前面创建的MyApp中,我们通过点击按钮可以更新当前界面上的文本内容。现在我们想换种方式,在点击按钮后,显示一个新的屏幕,在这个屏幕上输入一段话,然后再返回到原先的界面显示刚才输入的那句话。
首先我们新建这个新屏幕的布局文件input.xml,并添加一个文本输入框和一个按钮(注意,xml元素的命名不要和其他布局文件中的定义重名,因为所有的资源都在R中进行索引,比如id,如果重名了在使用R.id.*的时候就会有问题了)。这个布局文件对应的是一个Activity,因此我们再新建一个Input类(继承自Activity)用于显示这个布局并响应事件。
然后,还有一个重要的工作,那就是在清单文件AndroidManifest.xml中告诉程序,我定义了一个新的Activity,你可以去调用它。
我们希望在以前的那个主界面上点击按钮以后可以跳转到文本输入界面,所以我们需要对按钮的onClick事件进行定义:
在这段代码里出现了一些新东西。首先是Intent,它是Android一个很重要的类.Intent直译是“意图”,什么是意图呢?比如你想从这个Activity跳转到另外一个Activity,这就是一个意图。它不但可以连接多个Activity,还可以在它们之间传递数据。在这里,我们就是用Intent从MyApp对象跳转到了Input对象。
再看紧跟着的startActivityForResult()方法,顾名思义,它可以从一个定义好的Intent对象启动一个新的Activity,并且,这个Activity会返回执行的结果,这些内容下面马上就会提到。
好,这里我们已经可以调出新Activity了,我们看一下执行的结果:
你马上可以想到,现在需要对新的Activity(Input)进行处理了。我们在点击“确定”按钮的时候,需要获得上面EditText对象中的文本,然后返回到前一个Activity(MyApp)中去。看我们的按钮事件处理:
这里的关键是SharedPreferences对象,这是在多个Activity(同一包中)共享数据的方式,本质上它就是一个可以在包的范围内进行数据共享的文件。
我们通过一个标签“Text”获得了和文本相关的那个SharedPreferences对象(“Text”仅仅是自己定义的一个标签),然后给它赋予一个“text”对象值为当前文本框中输入的文本。设置完成以后,设置当前Activity的执行结果为RESULT_OK,再关闭当前的Activity,剩下的事情就可以回到MyApp这个主界面中去执行了。
其实剩下的事情也很简单,在MyApp这个Activity中,我们需要重写一个函数,onActivityResult()。因为我们启动Input这个Activity的时候使用的是startActivityForResult()方法,这个方法会使Input执行完以后返回给MyApp一个结果,MyApp接收到返回结果的时候会触发onActivityResult事件,对于结果的处理就在onActivityResult()中进行。同样,我们通过“Text”这个标签获得SharedPreferences对象,再把字符串从“text”对象中取出来并显示到当前屏幕上。
另外说明一下,requestCode是用来标识请求对象,我们刚才在启动Activity的时候使用的是“startActivityForResult(intent, 0)”,这里的0就是requestCode,当然,你可以设置成任何你喜欢的值。
我们看一下执行结果:
对于Activity我们先了解到这里,下面我们看一些其它的内容。
订阅:
博文 (Atom)