HaxeMaps / Propojení s WMS službami

Cílem je ukázat jak vytvořit vrstvu a propojit ji s mapou, která získává data pomocí služby Web Map Service (WMS). Jelikož je WMS standardizována, objevuje se stále více portálů, které poskytují mapové podklady prostřednictvím WMS. U rastrových dat je princip defacto jednoduchý, klient zažádá o určitou oblast, specifikuje systém souřadnic a server vrátí rastrový obrázek. Nevýhodou je relativně nízká rychlost většiny volně dostupných služeb.

V této ukázce budeme pracovat s WMS daty poskytovanýmy serverem NASA.

1. Zdrojový kód

example05.hx

  1. import flash.display.Sprite;
  2. import flash.events.Event;
  3. import map.Canvas;
  4. import map.LngLat;
  5. import map.MapService;
  6. import com.Button;
  7. import com.ToolBar;
  8. import com.InfoBox;
  9.  
  10. class Example05 extends Sprite {
  11.  
  12.     var canvas:Canvas;
  13.     var toolbar:ToolBar;
  14.     var infobox:InfoBox;
  15.     var layer:map.TileLayer;
  16.  
  17.     static public function main()
  18.     {
  19.        flash.Lib.current.stage.scaleMode = flash.display.StageScaleMode.NO_SCALE;
  20.        var t:Example05 = new Example05();
  21.        flash.Lib.current.stage.addEventListener(Event.RESIZE, t.stageResized);
  22.        flash.Lib.current.stage.addChildAt(t,0);
  23.     }
  24.  
  25.  
  26.     function new()
  27.     {
  28.         super();
  29.    
  30.         toolbar = new ToolBar();
  31.         canvas = new Canvas();
  32.         infobox = new InfoBox();
  33.  
  34.         layer = new map.TileLayer(new OpenStreetMapService(7), 8);
  35.         layer.alpha = 0.15;
  36.  
  37.         toolbar.move(0, 0);
  38.         canvas.move(0, 0);
  39.         infobox.move(0, 30);
  40.         canvas.setCenter(new LngLat(15.5,49.5));
  41.         canvas.addLayer(new WMSLayer(null, infobox));
  42.         canvas.addLayer(layer);
  43.         stageResized(null);
  44.  
  45.         initToolbar();
  46.  
  47.         addChild(canvas);
  48.         addChild(toolbar);
  49.         addChild(infobox);
  50.  
  51.         canvas.initialize();
  52.         canvas.addEventListener(MapEvent.MAP_MOUSEMOVE, mouseMove);
  53.  
  54.     }
  55.  
  56.     public function stageResized(e:Event)
  57.     {
  58.         toolbar.setSize(flash.Lib.current.stage.stageWidth, 30);
  59.         infobox.setSize(300, flash.Lib.current.stage.stageHeight - 30);
  60.         canvas.setSize(flash.Lib.current.stage.stageWidth, flash.Lib.current.stage.stageHeight);
  61.     }
  62.  
  63.     function initToolbar()
  64.     {
  65.         var me = this;
  66.         toolbar.addButton(new ZoomOutButton(), "Zoom Out", function(b:CustomButton) { me.canvas.zoomOut(); });
  67.         toolbar.addButton(new ZoomInButton(), "Zoom In",  function(b:CustomButton) { me.canvas.zoomIn(); });
  68.         toolbar.addSeparator(30);
  69.         //pan buttons
  70.         toolbar.addButton(new UpButton(), "Move up",  function(b:CustomButton) { me.pan(1); });
  71.         toolbar.addButton(new DownButton(), "Move down",  function(b:CustomButton) { me.pan(2); });
  72.         toolbar.addButton(new LeftButton(), "Move left",  function(b:CustomButton) { me.pan(4); });
  73.         toolbar.addButton(new RightButton(), "Move right",  function(b:CustomButton) { me.pan(8); });
  74.         toolbar.addSeparator(30);
  75.         //show/hide layer
  76.         toolbar.addButton(new MaximizeButton(), "Show/hide tile layer",  function(b:CustomButton) {
  77.                           if (me.canvas.layerEnabled(me.layer))
  78.                               me.canvas.disableLayer(me.layer);
  79.                           else
  80.                               me.canvas.enableLayer(me.layer);
  81.                           });
  82.     }
  83.  
  84.     function pan(direction:Int)
  85.     {
  86.        var lt:LngLat = canvas.getLeftTopCorner();
  87.        var br:LngLat = canvas.getRightBottomCorner();
  88.        var p:LngLat  = canvas.getCenter();
  89.  
  90.        if (direction & 0x3 == 1) p.lat = lt.lat; //up
  91.        if (direction & 0x3 == 2) p.lat = br.lat; //down
  92.        if (direction & 0xC == 4) p.lng = lt.lng; //left
  93.        if (direction & 0xC == 8) p.lng = br.lng; //right
  94.  
  95.        canvas.panTo(p);
  96.     }
  97.  
  98.     function mouseMove(e:map.MapEvent)
  99.     {
  100.        toolbar.setText("longitude:" + LngLat.fmtCoordinate(e.point.lng) +
  101.                        " latitude:" + LngLat.fmtCoordinate(e.point.lat) +
  102.                        " zoom:" + canvas.getZoom());
  103.     }
  104.  
  105. }
  106.  

Jelikož WMS služby jsou kvůli online renderování relativně pomalé, není z hlediska výkonnosti vhodné volat službu při každém vyvolání metody updateContent. Tato metoda je totiž volána vždy, když potenciálně může dojít ke změně obsahu okna - tzn. při posuvu či změně rozlišení. Proto namísto přímého volání využijeme časovač. Žádost o obrázek vyšleme nejdříve sekundu od posledního volání metody updateContent s tím, že při každém zavolání začínáme počítat znovu od nuly. Tento mechanismus zaručí, že každé posunutí mapou nebude vést na zaslání žádosti na WMS server.

Při odesílání požadavku je nutné si zapamatovat pozici, na kterou musíme po vyřízení odpovědi obrázek umístit, neboť během vyřizování požadavku může dojít k posunu mapy. Jakmile obdržíme odpověď ze serveru, přidáme obrázek do vrstvy.

Při změně měřítka je nutné odstranit všechny obrázky, což je implementováno s využitím metody zoomChanged.

example05.hx

  1. import flash.net.URLRequest;
  2. import flash.net.URLVariables;
  3. import flash.geom.Point;
  4. import flash.utils.Timer;
  5. import flash.events.TimerEvent;
  6. import map.Layer;
  7.  
  8. class WMSLoader extends Loader
  9. {
  10.     public var offset:Point;
  11.     public var zoom:Int;
  12.     public var tf:flash.text.TextField;
  13. }
  14.  
  15. class WMSLayer extends Layer
  16. {
  17.     static var WMSURL:String = "http://wms.jpl.nasa.gov/wms.cgi";
  18.  
  19.     var ftimer:Timer;
  20.     var infobox:InfoBox;
  21.  
  22.     public function new(map_service:MapService = null, infobox:InfoBox)
  23.     {
  24.         super(map_service, false);
  25.  
  26.         this.infobox = infobox;
  27.         ftimer = new Timer(1000, 1);
  28.         ftimer.addEventListener(TimerEvent.TIMER_COMPLETE, loadImage);
  29.     }
  30.  
  31.     override function updateContent(forceUpdate:Bool=false)
  32.     {
  33.         if (ftimer.running)
  34.            ftimer.stop();
  35.         ftimer.start();
  36.     }
  37.  
  38.     override function zoomChanged(prevEnabled:Bool, newZoom:Int)
  39.     {
  40.         super.zoomChanged(prevEnabled, newZoom);
  41.  
  42.         //remove all images
  43.         while (numChildren > 0) removeChildAt(0);
  44.     }
  45.  
  46.     function loadImage(e:TimerEvent)
  47.     {
  48.         var loader : WMSLoader = new WMSLoader();
  49.         try
  50.         {
  51.             loader.offset = getOffset();
  52.             loader.zoom = this.zoom;
  53.             loader.tf = this.infobox.addItem("Loading, please wait ... " + getOffset());
  54.             loader.load(getWMSRequest("worldwind_dem"),  new flash.system.LoaderContext(true));
  55.             loader.contentLoaderInfo.addEventListener(flash.events.Event.COMPLETE, loaderComplete);
  56.             loader.contentLoaderInfo.addEventListener(flash.events.IOErrorEvent.IO_ERROR,
  57.                                                       function(evt) { trace("IO Error"); });
  58.  
  59.         }
  60.         catch (unknown : Dynamic)  
  61.         {
  62.             trace("load except:"+unknown);
  63.         }
  64.  
  65.     }
  66.  
  67.     function getWMSRequest(layers:String, styles:String = ""): URLRequest
  68.     {
  69.         var lt:LngLat = getLeftTopCorner();
  70.         var rb:LngLat = getRightBottomCorner();
  71.  
  72.         var request:URLRequest = new URLRequest(WMSURL);
  73.         request.method = flash.net.URLRequestMethod.GET;
  74.         request.data = new URLVariables();
  75.         request.data.Service = "WMS";
  76.         request.data.Request = "GetMap";
  77.         request.data.Version = "1.1.1";
  78.         request.data.Format = "image/png";
  79.         request.data.SRS = "EPSG:4326";
  80.         request.data.BBox = lt.lng+","+rb.lat+","+rb.lng+","+lt.lat;
  81.         request.data.Layers = layers;
  82.         request.data.Width = bbox.width;
  83.         request.data.Height = bbox.height;
  84.         request.data.styles = styles;
  85.  
  86.         return request;
  87.     }
  88.  
  89.     function loaderComplete(e:Event)
  90.     {
  91.  
  92.         if ((e.target == null) || (e.target.loader == null) || (e.target.loader.content == null))
  93.            return;
  94.  
  95.         var loader:WMSLoader = e.target.loader;
  96.  
  97.         loader.tf.text = "";
  98.  
  99.         if (loader.zoom != this.zoom) return;
  100.  
  101.         loader.tf.text = "Image loaded";
  102.  
  103.         //append image
  104.         loader.content.x = (-2*loader.offset.x - loader.content.width) / 2.0;
  105.         loader.content.y = (-2*loader.offset.y - loader.content.height) / 2.0;
  106.         this.addChild(loader.content);
  107.     }
  108. }
  109.  

2. Překlad a Html kód

Pro překlad platí informace uvedené v Ukázka použití. Pro vložení do Html stránky lze využít kód uvedený v tomto příkladu.

> haxe -swf output.swf -swf-version 9 -main Example05 -swf-header 800:600:25:ffffff -cp haxemaps

3. Výsledek

Aplikace načte výškovou mapu a zobrazí ji pod částečně průhlednou rastrovou mapou. Rastrovou mapu je možné skýt pomocí posledního tlačítka nástrojové lišty.

Pro správnou funkci je vyžadován Flash player
   


Deprecated: Function ereg() is deprecated in /home2/web/homes/vasicek/private/notes/web/data/map/examples.php on line 12

Zobrazeno: 782x Naposledy: 23.3.2024 05:54:17