- 浏览: 21494 次
最新评论
用JavaFX访问ArcGIS Server的REST服务(2)
- 博客分类:
- 技术杂绘
用JavaFX访问ArcGIS Server的REST服务(2)
2010年12月22日
上一篇文章介绍了ArcGIS Server地图服务JSON格式的元数据内容,下面介绍一下怎么用这些JSON数据构造出ArcGISTiledMapServiceLayer(类名与ArcGIS for JavaScript API保持一致)。
这个类有一个成员变量url,在init{}代码块发送一个请求,请求的地址是地图服务的rest地址加上"?f=json"参数: init{ def http:HttpRequest = HttpRequest{ method:HttpRequest.GET; location:"{url}?f=json"; onInput:function(is:InputStream){ jsonHandler.parse(is); is.close(); loaded = true; } } http.start(); } 这段代码很好理解,构造一个HTTP的GET请求,然后通过start()方法发送这个请求。收到响应以后调用onInput函数,响应的内容就是地图服务的JSON格式的元数据。
值得一提的是"jsonHandler.parse(is); "这行代码。由于JavaFX 中全是对象,所以没办法用Flex或JavaScript中的[]和.符号来访问JSON结构的数据。JavaFX开发包提供给我们的是javafx.data.pull.PullParser对象,随便google一下,就可以找到一些JavaFX解析JSON的例子代码,比如: def parser = PullParser { documentType: PullParser.JSON; input: is; onEvent: parseEventCallback; }; parser.parse(); is.close(); def parseEventCallback = function(event: Event) { if (event.type == PullParser.START_VALUE) { if (event.name == "Rating" and event.level == 2) { result.rating = Rating {} } else if (event.name == "Category" and event.level == 3) { category = Category {} } } else if (event.type == PullParser.END_VALUE) { if (event.name == "id" and event.level == 2) { result.id = event.text; } else if (event.name == "Title" and event.level == 2) { result.title = event.text; } //…更多else if } } 所有的解析工作都在onEvent事件处理函数里完成。看完这个例子让人有点绝望,这种"直白"的解析方式处理一层的结构或者是没有同名变量的JSON是没有问题的,一旦JSON格式比较复杂,比如层次解析起来就会有极大的麻烦。的JSON,spatialReference对象出现了多次,用这种if/else 秉承不行就换的原则,推荐使用一个开源工具--JFXtras(http://code.google.com/p/jfxtras),最新版本是0.7rc2,建议下载JFXtras-0.6.zip版本,可以学习一下其中的源码。
def jsonHandler:JSONHandler = JSONHandler{ rootClass:"com.wj.ags.data.ServiceResponseAdapter" ; onDone:function(obj,isSequence){ _adapter = obj as ServiceResponseAdapter; } }; 这个jsonHandler就是文章开始的那段代码中用来解析JSON的工具。我们只需要指定一个rootClass,解析过程中会自动把JSON中的值赋给rootClass的成员变量,在回调函数onDone中将得到一个rootClass的实例。这样我们的工作就简单多了,只需要按照JSON的结构声明若干类,比如我定义了一个com.wj.ags.data.ServiceResponseAdapter类来保存地图服务的描述信息(一件很happy的事情就是在rootClass中还可以嵌套使用自定义类,这样不管JSON有多少层,数据多么复杂,也能顺利解析完): public class ServiceResponseAdapter{ public var serviceDescription:String; public var description:String; public var mapName:String; public var copyrightText:String; public var layers:LayerInfo[]; public var spatialReference:SpatialReference; public var singleFusedMapCache:Boolean; public var tileInfo:TileInfo; public var initialExtent:Extent; public var fullExtent:Extent; public var units:String; public var supportedImageFormatTypes:String; public var capabilities:String; }
这是一个描述切片的经典示意图,我们实现在客户端访问切片的地图服务,最核心的一个功能就是根据地图显示范围计算切片的级别、行列号范围等信息。通过解析JSON已经构造出TileInfo的一个实例,它包含以下信息: public class TileInfo { public var dpi:Integer; public var format:String; public var compressionQuality:Integer; public var cols:Integer; public var rows:Integer; public var lods:LOD[]; public var origin:MapPoint; public var spatialReference:SpatialReference; LOD[]数组描述的是每个级别的切片信息,它的类结构如下: public class LOD extends Comparable{ public var level:Integer; public var resolution:Number; public var scale:Number; public var startCol:Integer; public var endCol:Integer; public var startRow:Integer; public var endRow:Integer; 每个LOD中都有startCol,endCol,startRow,endRow信息,这是一个控制信息,在计算切片的行列号时可以约束在这个范围内。这样可以避免请求空白的区域,减少客户端请求的数量是性能优化的一个重要方面!它们的计算方法如下:
lod.startCol = Math.round((fullExt.xmin - origin.x)/lod.resolution/tileWidth - 0.5);
lod.endCol = Math.round((fullExt.xmax - origin.x)/lod.resolution/tileWidth - 0.5) - 1
lod.startRow = Math.round((origin.y - fullExt.ymax)/lod.resolution/tileWidth - 0.5);
lod.endRow = Math.round((origin.y - fullExt.ymin)/lod.resolution/tileWidth - 0.5);
切片的行列号从原点开始计算,向右为X正方向,向下为Y正方向;而地图的extent的Y轴正方向是向上的。所以startRow的计算方法和startCol略微有些差别。奇怪的是我计算出来的每个级别的endCol总是比Service Directory里显示大1,所以人为地把这个值减去1,使其与Service Directory的描述一致。
最后介绍ArcGISTiledMapServiceLayer最核心的两个个方法:1、根据地图当前显示范围计算切片的级别和起止行列号;2、根据级别和起止行列号获取图片。
在计算切片级别和行列号的时候,地图窗口的大小是固定的,而用户指定的地图的extent值是"不准确"的。切片服务显示的本质就是按照行列号把图片排列在屏幕上,然后用地图窗口去截一块显示给用户。因此,地图的extent是和地图窗口大小绑定的。
//根据lods中的比例尺级别选择一个适合显示当前范围的级别,前提是lods已经按照scale排序 var _min:Number = -1; for(_lod in lods){ var _difference:Number = 0; if(ext.width>ext.height){ _difference= Math.abs(ext.height - (this.height*_lod.resolution)); }else{ _difference= Math.abs(ext.width - (ext.width*_lod.resolution)); } if(_min地图显示的extent。接下来要计算该级别下的起止行列号。 var _startCol:Integer = Math.round((map.extent.xmin - tileInfo.origin.x)/tileInfo.lods[_chooseLevel].res olution/tileInfo.cols - 0.5); if(_startCol tileInfo.lods[_chooseLevel].endCol) _endCol = tileInfo.lods[_chooseLevel].endCol; if(_endCol tileInfo.lods[_chooseLevel].endRow) _endRow = tileInfo.lods[_chooseLevel].endRow; if(_endRow < 0)_endRow = 0;
发表评论
-
一个智能的 Web 界面测试系统
2012-01-20 02:42 618一个智能的 Web 界面测试系统 2011年01月05日 ... -
Flash builder 4.5支持Android平台之初体验
2012-01-20 02:42 661Flash builder 4.5支持Android平台之初体 ... -
Gis分析 POI空间聚合研究Demo实现
2012-01-20 02:42 2060Gis分析 POI空间聚合研究Demo实现 2010年06月 ... -
主流地图API比较
2012-01-20 02:42 483主流地图API比较 2010年0 ... -
2011-10-26
2012-01-19 10:33 6262011-10-26 2011年10月26日 ... -
服装厂岗位说明书
2012-01-19 10:33 1058服装厂岗位说明书 2011年05月25日 服装厂岗位说明 ... -
Grub4dos典型菜单文件示范解读[转贴]
2012-01-17 03:06 803Grub4dos典型菜单文件示范解读[转贴] 2011年07 ... -
java线程安全总结
2012-01-17 03:06 600java线程安全总结 2010年 ... -
ITV常见故障错误代码(中兴平台)
2012-01-17 03:06 1208ITV常见故障错误代码(中 ... -
电脑关机时显示该内存不能为REED的解决办法
2012-01-17 03:06 2575电脑关机时显示该内存不能为REED的解决办法 2010年12 ... -
43543254325432
2012-01-17 03:06 76943543254325432 2011年06月23日 ... -
如何用vb获取指定网页的验证码啊?(可以用webbrowser)
2012-01-16 01:39 1944如何用vb获取指定网页的验证码啊?(可以用webbrowser ... -
VB代码VB小程序: 捕获 WebBrowser控件的鼠标和键盘事件
2012-01-16 01:39 1090VB代码VB小程序: 捕获 Web ... -
我是用自己所谓的“爱”在控制自己最亲爱的孩子――JULY27
2012-01-16 01:39 689我是用自己所谓的“爱”在控制自己最亲爱的孩子――JULY27 ... -
如何培养小学生写日记的兴趣
2012-01-16 01:39 604如何培养小学生写日记 ... -
2011-12-21
2012-01-16 01:39 5882011-12-21 2011年12月21日 ... -
eclipse远程调试
2012-01-11 01:17 679eclipse远程调试 2011年09月01日 在极端 ... -
JavaScript 调用CMD命令
2012-01-11 01:17 1610JavaScript 调用CMD命令 2011年09月01日 ... -
struts2 标签错误
2012-01-11 01:16 582struts2 标签错误 2011年09月01日 htm ... -
javascript函数,对象入门
2012-01-11 01:16 560javascript函数,对象入门 2011年09月01日 ...
相关推荐
javafx-rest-archetype.zip,javafx基本原型提供了一个maven原型,用于生成基本javafx rest客户机服务器启动程序
Building GUI Applications With JavaFX来自javafx官方网站
javaFX实现的图书馆后台管理系统,有数据库增删改查,基于sqlserver数据库.zip
javafx
jAVAfx的增删改查demo文件,支持多选框,支持内容表格内编辑
javafx2-demo
基于JAVAFX的微信客户端和服务器,并整合了Jfoenix框架,使用idea为开发工具,MySQL为数据库,本人自己的课题,包含系统源代码和答辩ppt
JavaFX2开发教程 学习的好资料、适合刚刚接触的朋友哇
Everest - 使用JavaFX构建的一个漂亮且轻量级的REST客户端
javafx-sdk-17.0.2-lts-windows-x64
In Pro JavaFX 2: A Definitive Guide to Rich Clients with Java Technology, Jim Weaver, Weiqi Gao, Stephen Chin, Dean Iverson, and Johan Vos show you how you can use the JavaFX platform to create rich-...
JavaFX API文档。Sun公司已于2008年12月05日发布了JavaFX技术的正式版,它使您能利用 JavaFX 编程语言开发互联网应用程序(RIA)。该产品于2007年5月在JavaOne大会上首次对外公布。JavaFX技术主要应用于创建Rich ...
JavaFx做界面VLC做视频处理,请看源码
Javafx2 系统托盘实现
有需要使用java开发客户端的,可使用该项目,该项目使用javafx实现用web技术开发客户端,该例子仅供参考学习使用(注:由于javafx已经更新本人并没有去了解新版本的javafx的使用,这个例子只举有参考作用,如果发现...
JavaFX2 API chm文件
JavaFX 8 Introduction by Example - 2nd Edition 介绍了Javafx基础知识、Layout、控件、画图以及在链接Arduino、草莓派等嵌入式设备,是一本很好的Javafx入门书
将_Adobe_Flex_和_JavaFX_与_JavaServer_Faces_2.0_结合使用.pdf
JavaFX2_编程语言
JavaFx2-api.chw虽然用的人少了,但是是个好东西