purge ways when there are too many in memory
authorRichard Fairhurst <richard@systemed.net>
Thu, 6 May 2010 14:08:01 +0000 (14:08 +0000)
committerRichard Fairhurst <richard@systemed.net>
Thu, 6 May 2010 14:08:01 +0000 (14:08 +0000)
net/systemeD/halcyon/Map.as
net/systemeD/halcyon/connection/Connection.as
net/systemeD/halcyon/connection/Node.as
net/systemeD/halcyon/connection/Way.as

index 95d8e2485be7c715c8cd36c42c4386d3bd2392fe..b7bed890f43b519fd075f4f2c6db8eed8e7f906c 100755 (executable)
@@ -230,12 +230,13 @@ package net.systemeD.halcyon {
                                edge_b>=bigedge_b && edge_t<=bigedge_t) { return; }     // we have already loaded this area, so ignore
                        bigedge_l=edge_l; bigedge_r=edge_r;
                        bigedge_b=edge_b; bigedge_t=edge_t;
+                       if (connection.waycount>1000) {
+                               connection.purgeOutside(edge_l,edge_r,edge_t,edge_b);
+                       }
                        addDebug("Calling download with "+edge_l+"-"+edge_r+", "+edge_t+"-"+edge_b);
                        connection.loadBbox(edge_l,edge_r,edge_t,edge_b);
                }
 
-
-
         private function newWayCreated(event:EntityEvent):void {
             var way:Way = event.entity as Way;
                        if (!way.loaded) { return; }
index c7b9ab57842b2870c5a6ae11e4b55c657bf9fe89..f448ad8108f452a5bbcbcf6335177ad4dfb56660 100755 (executable)
@@ -87,22 +87,28 @@ package net.systemeD.halcyon.connection {
         private var relations:Object = {};
         private var pois:Array = [];
         private var changeset:Changeset = null;
+               public var nodecount:int=0;
+               public var waycount:int=0;
+               public var relationcount:int=0;
 
         protected function get nextNegative():Number {
             return negativeID--;
         }
 
         protected function setNode(node:Node, queue:Boolean):void {
+                       if (!nodes[node.id]) { nodecount++; }
             nodes[node.id] = node;
             if (node.loaded) { sendEvent(new EntityEvent(NEW_NODE, node),queue); }
         }
 
         protected function setWay(way:Way, queue:Boolean):void {
+                       if (!ways[way.id]) { waycount++; }
             ways[way.id] = way;
             if (way.loaded) { sendEvent(new EntityEvent(NEW_WAY, way),queue); }
         }
 
         protected function setRelation(relation:Relation, queue:Boolean):void {
+                       if (!relations[relation.id]) { relationcount++; }
             relations[relation.id] = relation;
             if (relation.loaded) { sendEvent(new EntityEvent(NEW_RELATION, relation),queue); }
         }
@@ -162,17 +168,60 @@ package net.systemeD.halcyon.connection {
             return relations[id];
         }
 
-               public function killNode(id:Number):void {
-                       delete nodes[id];
+               // Remove data from Connection
+               // These functions are used only internally to stop redundant data hanging around
+               // (either because it's been deleted on the server, or because we have panned away
+               //  and need to reduce memory usage)
+
+               protected function killNode(id:Number):void {
+                       if (!nodes[id]) return;
+            nodes[id].dispatchEvent(new EntityEvent(Connection.NODE_DELETED, nodes[id]));
+                       if (nodes[id].parentRelations.length>0) {
+                               nodes[id]=new Node(id,0,{},false,0,0);
+                       } else {
+                               delete nodes[id];
+                       }
+                       nodecount--;
                }
-               
-               public function killWay(id:Number):void {
-                       delete ways[id];
+
+               protected function killWay(id:Number):void {
+                       if (!ways[id]) return;
+            ways[id].dispatchEvent(new EntityEvent(Connection.WAY_DELETED, ways[id]));
+                       if (ways[id].parentRelations.length>0) {
+                               ways[id]=new Way(id,0,{},false,[]);
+                       } else {
+                               delete ways[id];
+                       }
+                       waycount--;
                }
-               
-               public function killRelation(id:Number):void {
-                       delete relations[id];
+
+               protected function killRelation(id:Number):void {
+                       if (!relations[id]) return;
+            relations[id].dispatchEvent(new EntityEvent(Connection.RELATION_DELETED, relations[id]));
+                       if (relations[id].parentRelations.length>0) {
+                               relations[id]=new Relation(id,0,{},false,[]);
+                       } else {
+                               delete relations[id];
+                       }
+                       relationcount--;
+               }
+
+               protected function killWayWithNodes(id:Number):void {
+                       var way:Way=ways[id];
+                       var node:Node;
+                       for (var i:uint=0; i<way.length; i++) {
+                               node=way.getNode(i);
+                               if (node.isDirty) { continue; }
+                               if (node.parentWays.length>1) {
+                                       node.removeParent(way);
+                               } else {
+                                       killNode(node.id);
+                               }
+                       }
+                       killWay(id);
                }
+               
+
 
         public function createNode(tags:Object, lat:Number, lon:Number, performCreate:Function):Node {
             var node:Node = new Node(nextNegative, 0, tags, true, lat, lon);
@@ -217,6 +266,15 @@ package net.systemeD.halcyon.connection {
             return changeset;
         }
         
+               public function purgeOutside(left:Number, right:Number, top:Number, bottom:Number):void {
+                       for each (var way:Way in ways) {
+                               if (!way.intersectsBbox(left,right,top,bottom) && !way.isDirty) {
+                                       killWayWithNodes(way.id);
+                               }
+                       }
+                       // ** should purge POIs and relations too
+               }
+
         // these are functions that the Connection implementation is expected to
         // provide. This class has some generic helpers for the implementation.
                public function loadBbox(left:Number, right:Number,
index 7050a22e6c852210482097a9974558a97b74d546..027b618c1cf0945dafe28ef3068f28f24eb250b6 100644 (file)
@@ -34,6 +34,9 @@ package net.systemeD.halcyon.connection {
             this._lat = lat;
             this._latproj = lat2latp(lat);
             this._lon = lon;
+                       for each (var way:Way in this.parentWays) {
+                               way.expandBbox(this);
+                       }
         }
         
         public function set lat(lat:Number):void {
index 810d03b58bbc503914aab0777387b7cc6edc46d1..6a1d14fe9372fad6af33e49f21533b89a8d519ca 100644 (file)
@@ -5,12 +5,17 @@ package net.systemeD.halcyon.connection {
 
     public class Way extends Entity {
         private var nodes:Array;
+               private var edge_l:Number;
+               private var edge_r:Number;
+               private var edge_t:Number;
+               private var edge_b:Number;
                public static var entity_type:String = 'way';
 
         public function Way(id:Number, version:uint, tags:Object, loaded:Boolean, nodes:Array) {
             super(id, version, tags, loaded);
             this.nodes = nodes;
                        for each (var node:Node in nodes) { node.addParent(this); }
+                       calculateBbox();
         }
 
                public function update(version:uint, tags:Object, loaded:Boolean, nodes:Array):void {
@@ -18,11 +23,33 @@ package net.systemeD.halcyon.connection {
                        for each (node in this.nodes) { node.removeParent(this); }
                        updateEntityProperties(version,tags,loaded); this.nodes=nodes;
                        for each (node in nodes) { node.addParent(this); }
+                       calculateBbox();
                }
                
         public function get length():uint {
             return nodes.length;
         }
+
+               private function calculateBbox():void {
+                       edge_l=999999; edge_r=-999999;
+                       edge_b=999999; edge_t=-999999;
+                       for each (var node:Node in nodes) { expandBbox(node); }
+               }
+
+               public function expandBbox(node:Node):void {
+                       edge_l=Math.min(edge_l,node.lon);
+                       edge_r=Math.max(edge_r,node.lon);
+                       edge_b=Math.min(edge_b,node.lat);
+                       edge_t=Math.max(edge_t,node.lat);
+               }
+               
+               public function intersectsBbox(left:Number,right:Number,top:Number,bottom:Number):Boolean {
+                       if ((edge_l<left   && edge_r<left  ) ||
+                           (edge_l>right  && edge_r>right ) ||
+                           (edge_b<bottom && edge_t<bottom) ||
+                           (edge_b>top    && edge_b>top   )) { return false; }
+                       return true;
+               }
         
         public function getNode(index:uint):Node {
             return nodes[index];