this should speed up redraw - need to add registerPOI support for vector background...
[potlatch2.git] / net / systemeD / halcyon / VectorLayer.as
1 package net.systemeD.halcyon {
2
3         import net.systemeD.halcyon.Map;
4         import net.systemeD.halcyon.MapPaint;
5         import net.systemeD.halcyon.connection.*;
6     import net.systemeD.halcyon.connection.actions.*;
7         import net.systemeD.halcyon.Globals;
8         import net.systemeD.halcyon.styleparser.RuleSet;
9
10         public class VectorLayer extends Object {
11
12                 public var map:Map;
13                 public var paint:MapPaint;                                              // sprites
14                 public var name:String;
15                 public var url:String;
16                 public var style:String='';
17
18                 public var ways:Object=new Object();                    // geodata
19                 public var nodes:Object=new Object();                   //  |
20                 public var relations:Object=new Object();               //  |
21         private var negativeID:Number = -1;
22
23                 public function VectorLayer(n:String,m:Map,s:String) {
24                         name=n;
25                         map=m;
26                         style=s;
27                         paint=new MapPaint(m,0,0);
28                         redrawFromCSS(style);
29                 }
30
31                 public function redrawFromCSS(style:String):void {
32                         paint.ruleset=new RuleSet(map.MINSCALE,map.MAXSCALE,paint.redraw);
33                         paint.ruleset.loadFromCSS(style);
34                 }
35                 
36                 public function createNode(tags:Object,lat:Number,lon:Number):Node {
37                         var node:Node = new Node(negativeID, 0, tags, true, lat, lon);
38                         nodes[negativeID]=node; negativeID--;
39                         return node;
40                 }
41                 public function createWay(tags:Object,nodes:Array):Way {
42                         var way:Way = new Way(negativeID, 0, tags, true, nodes.concat());
43                         ways[negativeID]=way; negativeID--;
44                         return way;
45                 }
46                 public function createRelation(tags:Object,members:Array):Relation {
47             var relation:Relation = new Relation(negativeID, 0, tags, true, members.concat());
48                         relations[negativeID]=relation; negativeID--;
49             return relation;
50                 }
51
52                 public function getObjectsByBbox(left:Number, right:Number, top:Number, bottom:Number):Object {
53                         // ** FIXME: this is just copied-and-pasted from Connection.as, which really isn't very
54                         // good practice. Is there a more elegant way of doing it?
55                         var o:Object = { poisInside: [], poisOutside: [], waysInside: [], waysOutside: [] };
56                         for each (var way:Way in ways) {
57                                 if (way.within(left,right,top,bottom)) { o.waysInside.push(way); }
58                                                                   else { o.waysOutside.push(way); }
59                         }
60                         // ** FIXME: this needs to do POIs, not nodes (i.e. we need registerPOI for vector layers too)
61                         for each (var poi:Node in nodes) {
62                                 if (poi.within(left,right,top,bottom)) { o.poisInside.push(poi); }
63                                                                    else { o.poisOutside.push(poi); }
64                         }
65                         return o;
66                 }
67                 
68                 public function pullThrough(entity:Entity,connection:Connection):Entity {
69                         var i:uint=0;
70                         var oldNode:Node, newNode:Node;
71                         if (entity is Way) {
72                                 // copy way through to main layer
73                                 // ** shouldn't do this if the nodes are already in the main layer
74                                 //    (or maybe we should just match on lat/long to avoid ways in background having nodes in foreground)
75                                 var oldWay:Way=Way(entity);
76                                 var newWay:Way=connection.createWay(oldWay.getTagsCopy(), [], MainUndoStack.getGlobalStack().addAction);
77                                 var nodemap:Object={};
78                                 for (i=0; i<oldWay.length; i++) {
79                                         oldNode = oldWay.getNode(i);
80                                         newNode = nodemap[oldNode.id] ? nodemap[oldNode.id] : connection.createNode(
81                                                 oldNode.getTagsCopy(), oldNode.lat, oldNode.lon, 
82                                                 MainUndoStack.getGlobalStack().addAction);
83                                         newWay.appendNode(newNode, MainUndoStack.getGlobalStack().addAction);
84                                         nodemap[oldNode.id]=newNode;
85                                 }
86                                 // delete this way
87                                 while (oldWay.length) { 
88                                         var id:Number=oldWay.getNode(0).id;
89                                         oldWay.removeNodeByIndex(0,MainUndoStack.getGlobalStack().addAction,false);
90                                         delete nodes[id];
91                                 }
92                                 paint.wayuis[oldWay.id].redraw();
93                                 delete ways[oldWay.id];
94                                 map.paint.createWayUI(newWay);
95                                 return newWay;
96
97                         } else if (entity is Node && !entity.hasParentWays) {
98                                 // copy node through to main layer
99                                 // ** should be properly undoable
100                                 oldNode=Node(entity)
101                                 var newPoiAction:CreatePOIAction = new CreatePOIAction(
102                                         oldNode.getTagsCopy(), oldNode.lat, oldNode.lon);
103                                 MainUndoStack.getGlobalStack().addAction(newPoiAction);
104                                 paint.deleteNodeUI(oldNode);
105                                 delete nodes[oldNode.id];
106                                 return newPoiAction.getNode();
107                         }
108                         return null;
109                 }
110                 
111                 public function blank():void {
112                         for each (var node:Node in nodes) { paint.deleteNodeUI(node); }
113                         for each (var way:Way in ways) { paint.deleteWayUI(way); }
114                         relations={}; nodes={}; ways={};
115                 }
116
117         }
118 }