add todo
[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.VectorLayer;
6         import flash.net.*;
7         import flash.events.*;
8
9         /* still to do:
10         - don't join to GPS track when you click on it
11         - light-blue colour
12         - empty layer on reload
13         - cope with tracks with timestamps */
14
15         public class TrackLoader {
16
17                 private var left:Number=0;
18                 private var right:Number=0;
19                 private var top:Number=0;
20                 private var bottom:Number=0;
21                 private var page:uint=0;
22                 private var _layer:VectorLayer;
23
24                 private var map:Map;
25                 private var apiBaseURL:String;
26
27                 private static const STYLESHEET:String="wireframe.css";
28                 
29                 public function TrackLoader(map:Map, url:String) {
30                         this.map=map;
31                         apiBaseURL=url;
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 vector layer
44                         }
45
46                         var loader:URLLoader = new URLLoader();
47                         loader.load(new URLRequest(apiBaseURL+"trackpoints?bbox="+left+","+bottom+","+right+","+top+"&page="+page));
48                         loader.addEventListener(Event.COMPLETE, parseGPX);
49                 }
50
51                 public function parseGPX(event:Event):void {
52                         var xmlnsPattern:RegExp = new RegExp("xmlns[^\"]*\"[^\"]*\"", "gi");
53                         var xsiPattern:RegExp = new RegExp("xsi[^\"]*\"[^\"]*\"", "gi");
54                         var raw:String = String(event.target.data).replace(xmlnsPattern, "").replace(xsiPattern, "");
55                         var file:XML=new XML(raw);
56
57                         for each (var trk:XML in file.child("trk")) {
58                                 for each (var trkseg:XML in trk.child("trkseg")) {
59                                         var nodestring:Array=[];
60                                         var lat:Number=NaN, lastlat:Number=NaN;
61                                         var lon:Number=NaN, lastlon:Number=NaN;
62                                         for each (var trkpt:XML in trkseg.child("trkpt")) {
63                                                 lat=trkpt.@lat;
64                                                 lon=trkpt.@lon;
65                                                 if (lastlat && nodestring.length>0 && greatCircle(lat,lon,lastlat,lastlon)>30) {
66                                                         layer.createWay({}, nodestring);
67                                                         nodestring=[];
68                                                 }
69                                                 nodestring.push(layer.createNode({}, lat, lon));
70                                                 lastlat=lat; lastlon=lon;
71                                         }
72                                         if (nodestring.length>0) { layer.createWay({}, nodestring); }
73                                 }
74                         }
75                         layer.paint.updateEntityUIs(layer.getObjectsByBbox(left,right,top,bottom), false, false);
76                 }
77
78                 
79                 private function get layer():VectorLayer {
80                         if (!_layer) {
81                                 var n:String='GPS tracks';
82                                 _layer=new VectorLayer(n,map,STYLESHEET);
83                                 map.addVectorLayer(_layer);
84                         }
85                         return _layer;
86                 }
87                 
88                 private function greatCircle(lat1:Number,lon1:Number,lat2:Number,lon2:Number):Number {
89                         var dlat:Number=(lat2-lat1)*Math.PI/180;
90                         var dlon:Number=(lon2-lon1)*Math.PI/180;
91                         var a:Number=Math.pow(Math.sin(dlat / 2),2) + 
92                                      Math.cos(lat1*Math.PI/180) * 
93                                      Math.cos(lat2*Math.PI/180) * 
94                                      Math.pow(Math.sin(dlon / 2),2);
95                         a=Math.atan2(Math.sqrt(a),Math.sqrt(1-a));
96                         return a*3958.75*1609;
97                 }
98                 
99         }
100 }