Update trackloader to avoid using VectorLayer
[potlatch2.git] / net / systemeD / potlatch2 / utils / TrackLoader.as
1 package net.systemeD.potlatch2.utils {
2
3         import net.systemeD.halcyon.connection.*;
4         import net.systemeD.halcyon.Map;
5         import net.systemeD.halcyon.MapPaint;
6         import flash.net.*;
7         import flash.events.*;
8
9         /* still to do:
10         - empty layer on reload
11         - cope with tracks with timestamps */
12
13         public class TrackLoader {
14
15                 private var left:Number=0;
16                 private var right:Number=0;
17                 private var top:Number=0;
18                 private var bottom:Number=0;
19                 private var page:uint=0;
20
21                 private var map:Map;
22                 private var apiBaseURL:String;
23                 private var connection:Connection; /* to store the nodes/ways that are faked up for GPX tracks */
24
25                 private static const STYLESHEET:String="stylesheets/gpx.css";
26                 private static const LAYER:String="GPS tracks";
27                 
28                 public function TrackLoader(map:Map, url:String) {
29                         this.map=map;
30                         apiBaseURL=url;
31                         connection = new Connection(LAYER,apiBaseURL,null, null);
32                 }
33                 
34                 public function load(keep:Boolean=false):void {
35                         if (map.edge_l==left && map.edge_r==right && map.edge_t==top && map.edge_b==bottom) {
36                                 page++;
37                         } else {
38                                 left  =map.edge_l;
39                                 right =map.edge_r;
40                                 top   =map.edge_t;
41                                 bottom=map.edge_b;
42                                 page=0;
43                                 if (!keep) { } // ** TODO: blank the connection objects
44                         }
45
46             /* This isn't great - conceptially it would be nicer for the connection to do the request */
47                         var loader:URLLoader = new URLLoader();
48                         loader.load(new URLRequest(apiBaseURL+"trackpoints?bbox="+left+","+bottom+","+right+","+top+"&page="+page));
49                         loader.addEventListener(Event.COMPLETE, parseGPX);
50                 }
51
52                 public function parseGPX(event:Event):void {
53                         var file:XML = new XML(event.target.data);
54                         var action:CompositeUndoableAction = new CompositeUndoableAction("add track objects");
55                         for each (var ns:Namespace in file.namespaceDeclarations()) {
56                                 if (ns.uri.match(/^http:\/\/www\.topografix\.com\/GPX\/1\/[01]$/)) {
57                                         default xml namespace = ns;
58                                 }
59                         }
60
61                         for each (var trkseg:XML in file..trkseg) {
62                                 var nodestring:Array = [];
63                                 var lat:Number = NaN, lastlat:Number = NaN;
64                                 var lon:Number = NaN, lastlon:Number = NaN;
65                 for each (var trkpt:XML in trkseg.trkpt) {
66                                         lat = trkpt.@lat;
67                     lon = trkpt.@lon;
68                     if (lastlat && nodestring.length > 0 && greatCircle(lat, lon, lastlat, lastlon) > 30) {
69                         connection.createWay({}, nodestring, action.push);
70                         nodestring = [];
71                     }
72                     nodestring.push(connection.createNode({}, lat, lon, action.push));
73                     lastlat = lat; lastlon = lon;
74                                 }
75                 if (nodestring.length > 0) { connection.createWay({}, nodestring, action.push); trace("create way");}
76                         }
77
78             action.doAction(); /* just do it, don't add to undo stack */
79                         default xml namespace = new Namespace("");
80                         layer.updateEntityUIs(false, false);
81                 }
82
83                 private function get layer():MapPaint {
84             var mp:MapPaint = map.findLayer(LAYER);
85             if (!mp) {
86                 mp = map.addLayer(connection, STYLESHEET);
87             }
88             return mp;
89                 }
90                 
91                 private function greatCircle(lat1:Number,lon1:Number,lat2:Number,lon2:Number):Number {
92                         var dlat:Number=(lat2-lat1)*Math.PI/180;
93                         var dlon:Number=(lon2-lon1)*Math.PI/180;
94                         var a:Number=Math.pow(Math.sin(dlat / 2),2) + 
95                                      Math.cos(lat1*Math.PI/180) * 
96                                      Math.cos(lat2*Math.PI/180) * 
97                                      Math.pow(Math.sin(dlon / 2),2);
98                         a=Math.atan2(Math.sqrt(a),Math.sqrt(1-a));
99                         return a*3958.75*1609;
100                 }
101                 
102         }
103 }