PageRenderTime 39ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/com/google/maps/extras/arcgislink/ArcGISUtil.as

http://gmaps-utility-library-flash.googlecode.com/
ActionScript | 430 lines | 275 code | 34 blank | 121 comment | 91 complexity | be83d3ba2faffd5fcad91e30e872bed5 MD5 | raw file
  1. /*
  2. * ArcGIS for Google Maps Flash API
  3. *
  4. * License http://www.apache.org/licenses/LICENSE-2.0
  5. */ /**
  6. * @author nianwei at gmail dot com
  7. */
  8. package com.google.maps.extras.arcgislink {
  9. import com.google.maps.*;
  10. import com.google.maps.extras.arcgislink.json.*;
  11. import com.google.maps.interfaces.IOverlay;
  12. import com.google.maps.overlays.*;
  13. import flash.events.*;
  14. import flash.geom.Point;
  15. import flash.net.*;
  16. import flash.utils.*;
  17. // import mx.rpc.events.*;
  18. // import mx.rpc.http.*;
  19. /**
  20. * Utility tools
  21. */
  22. public class ArcGISUtil {
  23. public function ArcGISUtil() {
  24. }
  25. /**
  26. * Helper method to convert an {@link ArcGISEnvelope} object to <code>GLatLngBounds</code>
  27. * @param {Envelope} extent
  28. * @return {GLatLngBounds} gLatLngBounds
  29. */
  30. internal static function fromEnvelopeToLatLngBounds( /*Envelope*/ extent:*):LatLngBounds {
  31. var sr:SpatialReference=SpatialReferences.getSpatialReference(extent.spatialReference.wkid);
  32. sr=sr || SpatialReferences.WGS84;
  33. var sw:Array=sr.reverse([extent.xmin, extent.ymin]);
  34. var ne:Array=sr.reverse([extent.xmax, extent.ymax]);
  35. return new LatLngBounds(new LatLng(sw[1], sw[0]), new LatLng(ne[1], ne[0]));
  36. }
  37. internal static function fromLatLngBoundsToEnvelope(gLatLngBounds:LatLngBounds, spatialReference:SpatialReference=null):* {
  38. spatialReference=spatialReference || SpatialReferences.WGS84;
  39. var sw:Array=spatialReference.forward([gLatLngBounds.getSouthWest().lng(), gLatLngBounds.getSouthWest().lat()]);
  40. var ne:Array=spatialReference.forward([gLatLngBounds.getNorthEast().lng(), gLatLngBounds.getNorthEast().lat()]);
  41. return {xmin: sw[0], ymin: sw[1], xmax: ne[0], ymax: ne[1], spatialReference: {wkid: spatialReference.wkid}};
  42. }
  43. internal static function fromLatLngToPoint(gLatLng:LatLng, sr:SpatialReference=null):* {
  44. sr=sr || SpatialReferences.WGS84;
  45. var p:Array=sr.forward([gLatLng.lng(), gLatLng.lat()]);
  46. return {x: p[0], y: p[1], spatialReference: {wkid: sr.wkid}};
  47. }
  48. internal static function fromPointToLatLng(point:*, opt_sr:*=null):LatLng {
  49. var srid:*=point.spatialReference || opt_sr;
  50. var sr:SpatialReference=srid ? SpatialReferences.getSpatialReference(srid.wkid) : SpatialReferences.WGS84;
  51. sr=sr || SpatialReferences.WGS84;
  52. if (isNaN(point.x) || isNaN(point.y)) {
  53. return null;
  54. }
  55. var p:Array=sr.reverse([point.x, point.y]);
  56. return new LatLng(p[1], p[0]);
  57. }
  58. /**
  59. * Add a ArcGIS Server resource to map. if it is cached, it will be added as a map type, if dynamic, it will be added as overlay.
  60. * @param map
  61. * @param url
  62. * @param opt_callback
  63. *
  64. */
  65. public static function addArcGISMap(map:Map, url:String, opt_callback:Function=null):void {
  66. var service:MapService=new MapService(url);
  67. service.addEventListener(ServiceEvent.LOAD, function(evt:Event):void {
  68. if (service.singleFusedMapCache) {
  69. var tile:ArcGISTileLayer=new ArcGISTileLayer(service);
  70. var type:ArcGISMapType=new ArcGISMapType([tile], new ArcGISMapTypeOptions({name: tile.getName().replace(/ /g, '\n')}));
  71. map.addMapType(type);
  72. if (opt_callback != null) {
  73. opt_callback.call(null, type);
  74. }
  75. } else {
  76. var ov:ArcGISMapOverlay=new ArcGISMapOverlay(service);
  77. map.addOverlay(ov);
  78. if (opt_callback != null) {
  79. opt_callback.call(null, ov);
  80. }
  81. }
  82. });
  83. }
  84. /**
  85. * Enable wheel zoom as alternative to Map.enableScrollWheelZoom because the later passed zoom=0 to Projection.
  86. */
  87. internal static function enableScrollWheelZoom(map:com.google.maps.Map):void {
  88. map.getDisplayObject().addEventListener(MouseEvent.MOUSE_WHEEL, function(evt:MouseEvent):void {
  89. var p:flash.geom.Point=new flash.geom.Point(evt.localX, evt.localY);
  90. var latlng:LatLng;
  91. var c:flash.geom.Point=new flash.geom.Point(map.width / 2, map.height / 2);
  92. var z:Number=map.getZoom();
  93. if (evt.delta > 0) {
  94. z=Math.min(z + 1, map.getMaxZoomLevel());
  95. latlng=map.fromViewportToLatLng(new flash.geom.Point((p.x + c.x) / 2, (p.y + c.y) / 2));
  96. } else {
  97. z=Math.max(z - 1, map.getMinZoomLevel());
  98. latlng=map.fromViewportToLatLng(new flash.geom.Point(c.x * 2 - p.x, c.y * 2 - p.y));
  99. }
  100. map.setCenter(latlng, z);
  101. });
  102. }
  103. internal static var ArcGISConfig:*={maxPolyPoints: 3000, style: {icon: null, strokeStyle: {thickness: 3, color: 0xffff00, alpha: 0.5, pixelHinting: true}, fillStyle: {color: 0xFFFF00, alpha: 0.5}
  104. }};
  105. /**
  106. * Convert a {@link ArcGISFeature} or {@link ArcGISIdentifyResult} or {@link ArcGISFindResult} to core Google Maps API
  107. * overlays such as {@link ArcGISGMarker},
  108. * {@link ArcGISGPolyline}, or {@link ArcGISGPolygon}s.
  109. * Note ArcGIS Geometry may have multiple parts, but the coresponding GOverlay
  110. * does not support multi-parts, so the result is an array.
  111. * <ul><li><code>feature</code>: an object returned by ArcGIS Server with at least <code>geometry</code> property of type {@link ArcGISGeometry}.
  112. * if it contains a name-value pair "attributes" property, it will be attached to the result overlays.
  113. * <li><code>opt_sr</code>: optional {@link ArcGISSpatialReference}. Can be object literal.
  114. * <li><code>opt_agsStyle</code> {@link ArcGISStyleOptions}. default is {@link ArcGISConfig}.style.
  115. * <li><code>opt_displayName</code> optional field name used for title of feature.
  116. * @param {Feature} feature
  117. * @param {ArcGISSpatialReference} opt_sr
  118. * @param {overlayOptions} opt_agsStyle
  119. * @param {String} opt_displayName
  120. * @return {GOverlay[]}
  121. */
  122. internal static function fromGeometryToOverlays(geom:*, opt_sr:SpatialReference=null, overlayOptions:OverlayOptions=null, title:String=''):Array {
  123. var ovs:Array=[];
  124. var sr:SpatialReference=null;
  125. var ov:IOverlay=null;
  126. overlayOptions=overlayOptions || new OverlayOptions();
  127. if (opt_sr) {
  128. sr=opt_sr;
  129. } else {
  130. sr=SpatialReferences.getSpatialReference(geom.spatialReference.wkid);
  131. }
  132. if (sr === null) {
  133. return ovs;
  134. }
  135. var x:String, i:int, ic:int, j:int, jc:int, parts:Array, part:Array, lnglat:Array, glatlngs:Array;
  136. if (geom.x) {
  137. //point
  138. lnglat=sr.reverse([geom.x, geom.y]);
  139. if (!overlayOptions.marker) {
  140. overlayOptions.marker=new MarkerOptions({tooltip: title});
  141. } else if (!overlayOptions.marker.tooltip) {
  142. overlayOptions.marker.tooltip=title;
  143. }
  144. ov=new Marker(new LatLng(lnglat[1], lnglat[0]), overlayOptions.marker);
  145. ovs.push(ov);
  146. } else {
  147. //mulpt, line and poly
  148. parts=geom.points || geom.paths || geom.rings;
  149. if (!parts) {
  150. return ovs;
  151. }
  152. for (i=0, ic=parts.length; i < ic; i++) {
  153. part=parts[i];
  154. if (geom.points) {
  155. // multipoint
  156. lnglat=sr.reverse(part);
  157. ov=new Marker(new LatLng(lnglat[1], lnglat[0]), overlayOptions.marker);
  158. ovs.push(ov);
  159. } else {
  160. if (part.length > ArcGISConfig.maxPolyPoints) {
  161. // TODO: do a simple point reduction
  162. continue;
  163. }
  164. glatlngs=[];
  165. for (j=0, jc=part.length; j < jc; j++) {
  166. lnglat=sr.reverse(part[j]);
  167. glatlngs.push(new LatLng(lnglat[1], lnglat[0]));
  168. }
  169. if (geom.paths) {
  170. ov=new Polyline(glatlngs, overlayOptions.polyline); //new PolylineOptions({strokeStyle: style.strokeStyle}));
  171. ovs.push(ov);
  172. } else if (geom.rings) {
  173. overlayOptions.polygon=overlayOptions.polygon || new PolygonOptions();
  174. overlayOptions.polygon.tooltip=title;
  175. if (ov == null) {
  176. ov=new Polygon(glatlngs, overlayOptions.polygon); //new PolygonOptions({strokeStyle: style.strokeStyle, fillStyle: style.fillStyle, tooltip: title})); //, style.outlineColor, style.outlineWeight, style.outlineOpacity, style.fillColor, style.fillOpacity);
  177. ovs.push(ov);
  178. } else {
  179. (ov as Polygon).setPolyline(i, glatlngs);
  180. }
  181. }
  182. }
  183. }
  184. }
  185. return ovs;
  186. }
  187. internal static function fromOverlaysToGeometry(ovs:Array, opt_sr:SpatialReference=null):* {
  188. var sr:SpatialReference=null;
  189. if (opt_sr) {
  190. sr=opt_sr;
  191. } else {
  192. sr=SpatialReferences.WGS84;
  193. }
  194. var ov:*;
  195. if (!ovs || ovs.length == 0)
  196. return null;
  197. ov=ovs[0];
  198. var x:String, i:int, ic:int, j:int, jc:int, parts:Array, part:Array, ll:LatLng, lnglat:Array;
  199. if (ovs.length == 1 && (ov is LatLng || ov is Marker)) {
  200. ll=(ov is LatLng ? ov as LatLng : (ov as Marker).getLatLng());
  201. lnglat=sr.forward([ll.lng(), ll.lat()]);
  202. return {x: lnglat[0], y: lnglat[1], spatialReference: {wkid: sr.wkid}};
  203. }
  204. parts=[];
  205. if (ov is LatLng) {
  206. for (i=0; i < ovs.length; i++) {
  207. ll=ovs[i] as LatLng;
  208. parts.push(sr.forward([ll.lng(), ll.lat()]));
  209. }
  210. return {points: parts, spatialReference: {wkid: sr.wkid}};
  211. } else if (ov is Marker) {
  212. for (i=0; i < ovs.length; i++) {
  213. ll=(ovs[i] as Marker).getLatLng();
  214. parts.push(sr.forward([ll.lng(), ll.lat()]));
  215. }
  216. return {points: parts, spatialReference: {wkid: sr.wkid}};
  217. } else if (ov is Polyline || ov is Polygon) {
  218. for (i=0; i < ovs.length; i++) {
  219. part=[];
  220. //var line:Polyline = ovs[i] as Polyline;
  221. ov=ovs[i];
  222. for (j=0; j < ov.getVertexCount(); j++) {
  223. ll=ov.getVertex(j);
  224. part.push(sr.forward([ll.lng(), ll.lat()]));
  225. }
  226. parts.push(part);
  227. }
  228. if (ov is Polyline) {
  229. return {paths: parts, spatialReference: {wkid: sr.wkid}};
  230. } else {
  231. return {rings: parts, spatialReference: {wkid: sr.wkid}};
  232. }
  233. }
  234. }
  235. internal static function restRequest(url:String, params:Object, thisObj:IEventDispatcher, sucessFn:Function, failFn:Function=null):void {
  236. var full:String=url + (url.indexOf('?') === -1 ? '?' : '&');
  237. /*
  238. var service:HTTPService=new HTTPService();
  239. service.url=url;
  240. service.addEventListener(FaultEvent.FAULT, function(evt:FaultEvent):void {
  241. var err:ServiceError=new ServiceError({code: -1, message: evt.toString(), details: []});
  242. if (thisObj != null) {
  243. thisObj.dispatchEvent(new ServiceEvent(ServiceEvent.ERROR, err));
  244. }
  245. if (failFn != null) {
  246. failFn(thisObj, err);
  247. }
  248. });
  249. service.addEventListener(ResultEvent.RESULT, function(evt:ResultEvent):void {
  250. var jsons:String=evt.result as String;
  251. var d:JSONDecoder=new JSONDecoder(jsons, false); // false strict to allow NAN in geocode results
  252. var json:Object=d.getValue();
  253. if (json.error) {
  254. var err:ServiceError=new ServiceError(json.error);
  255. thisObj.dispatchEvent(new ServiceEvent(ServiceEvent.ERROR, err));
  256. if (failFn != null) {
  257. failFn.call(thisObj, err);
  258. }
  259. } else if (sucessFn != null) {
  260. sucessFn.call(thisObj, json);
  261. }
  262. });
  263. service.send(params);
  264. */
  265. var variables:URLVariables=new URLVariables();
  266. if (params) {
  267. for (var x:String in params) {
  268. if (params.hasOwnProperty(x)) {
  269. //full+=(x + '=' + escape(params[x]) + '&');
  270. variables[x]=params[x];
  271. }
  272. }
  273. }
  274. var loader:URLLoader=new URLLoader();
  275. var request:URLRequest=new URLRequest(full);
  276. request.method=URLRequestMethod.GET; //.POST;
  277. request.data=variables;
  278. loader.addEventListener(Event.COMPLETE, function(evt:Event):void {
  279. var jsons:String=evt.target.data as String;
  280. var d:JSONDecoder=new JSONDecoder(jsons, false); // false strict to allow NAN in geocode results
  281. var json:Object=d.getValue();
  282. if (json.error) {
  283. var err:ServiceError=new ServiceError(json.error);
  284. thisObj.dispatchEvent(new ServiceEvent(ServiceEvent.ERROR, err));
  285. if (failFn != null) {
  286. failFn.call(thisObj, err);
  287. }
  288. } else if (sucessFn != null) {
  289. sucessFn.call(thisObj, json);
  290. }
  291. });
  292. loader.addEventListener(IOErrorEvent.IO_ERROR, function(evt:IOErrorEvent):void {
  293. var err:ServiceError=new ServiceError({code: -1, message: evt.toString(), details: []});
  294. if (thisObj != null) {
  295. thisObj.dispatchEvent(new ServiceEvent(ServiceEvent.ERROR, err));
  296. }
  297. if (failFn != null) {
  298. failFn(thisObj, err);
  299. }
  300. });
  301. loader.load(request);
  302. }
  303. /**
  304. * Extract the substring from full string, between start string and end string
  305. * @param {Object} full
  306. * @param {Object} start
  307. * @param {Object} end
  308. */
  309. internal static function extractString(full:String, start:String, end:String):String {
  310. var i:int=(start === '') ? 0 : full.indexOf(start);
  311. var e:int=end === '' ? full.length : full.indexOf(end, i + start.length);
  312. return full.substring(i + start.length, e);
  313. }
  314. internal static function augmentObject(src:*, dest:*, force:Boolean=false):Object {
  315. if (src && dest) {
  316. var p:String;
  317. // used to count/check if it is a dyna class
  318. // with properties that can be looped with for.. in
  319. // In AS3, for..in can not be used to loop properties of a class instance except those
  320. // dynamic added. That makes converting parameter classes into REST request harder.
  321. var i:int=0;
  322. for (p in src) {
  323. i++;
  324. if (src.hasOwnProperty(p)) {
  325. if (force || !(p in dest) || (p in dest && !dest[p])) {
  326. dest[p]=src[p];
  327. }
  328. }
  329. }
  330. if (i == 0) {
  331. var varList:XMLList=flash.utils.describeType(src)..variable;
  332. for (i=0; i < varList.length(); i++) {
  333. p=varList[i].@name;
  334. if (src[p]) {
  335. dest[p]=src[p];
  336. }
  337. }
  338. }
  339. }
  340. return dest;
  341. }
  342. internal static function isString(o:*):Boolean {
  343. return o && o is String;
  344. }
  345. internal static function isArray(o:*):Boolean {
  346. return o && o is Array;
  347. }
  348. public static function getAttributeValue(attrs:*, name:String):* {
  349. if (attrs[name])
  350. return attrs[name];
  351. for (var x:String in attrs) {
  352. if (x.toUpperCase() == name.toUpperCase()) {
  353. return attrs[x];
  354. }
  355. }
  356. return null;
  357. }
  358. internal static function fromGeometryToJSON(geom:Object, opt_includeSR:Boolean=false):String {
  359. /*function fromPointsToJSON(pts) {
  360. var arr = [];
  361. for (var i = 0, c = pts.length; i < c; i++) {
  362. arr.push('[' + pts[i][0] + ',' + pts[i][1] + ']');
  363. }
  364. return '[' + arr.join(',') + ']';
  365. }
  366. function fromLinesToJSON(lines) {
  367. var arr = [];
  368. for (var i = 0, c = lines.length; i < c; i++) {
  369. arr.push(fromPointsToJSON(lines[i]));
  370. }
  371. return '[' + arr.join(',') + ']';
  372. }
  373. var json = '{';
  374. if (geom.x) {
  375. json += 'x:' + geom.x + ',y:' + geom.y;
  376. } else if (geom.xmin) {
  377. json += 'xmin:' + geom.xmin + ',ymin:' + geom.ymin + ',xmax:' + geom.xmax + ',ymax:' + geom.ymax;
  378. } else if (geom.points) {
  379. json += 'points:' + fromPointsToJSON(geom.points);
  380. } else if (geom.paths) {
  381. json += 'paths:' + fromLinesToJSON(geom.paths);
  382. } else if (geom.rings) {
  383. json += 'rings:' + fromLinesToJSON(geom.rings);
  384. }
  385. if (opt_includeSR && geom.spatialReference) {
  386. json += ',spatialReference:{wkid:' + geom.spatialReference.wkid + '}';
  387. }
  388. json += '}';
  389. return json;
  390. */
  391. var e:JSONEncoder=new JSONEncoder(geom);
  392. return e.getString();
  393. }
  394. }
  395. }