don't bother redrawing EntityUIs that are offscreen
authorRichard Fairhurst <richard@systemed.net>
Mon, 31 May 2010 18:35:38 +0000 (18:35 +0000)
committerRichard Fairhurst <richard@systemed.net>
Mon, 31 May 2010 18:35:38 +0000 (18:35 +0000)
13 files changed:
TODO.txt
net/systemeD/halcyon/Map.as
net/systemeD/halcyon/MapPaint.as
net/systemeD/halcyon/connection/Connection.as
net/systemeD/halcyon/connection/Entity.as
net/systemeD/halcyon/connection/Node.as
net/systemeD/halcyon/connection/Way.as
net/systemeD/halcyon/vectorlayers/VectorLayer.as
net/systemeD/potlatch2/VectorSourceDialog.mxml
net/systemeD/potlatch2/controller/SelectedParallelWay.as
net/systemeD/potlatch2/utils/GpxImporter.as
net/systemeD/potlatch2/utils/Importer.as
net/systemeD/potlatch2/utils/ShpImporter.as

index 6ba6946d88945c29c2517277c863c1ffbafbb55e..62afb09912bce9b83807eb06e1cea5ed3ca0282a 100644 (file)
--- a/TODO.txt
+++ b/TODO.txt
@@ -42,6 +42,7 @@ Potlatch 2: main outstanding issues
 
 == UI ==
 
+* Parallelise should use the distance from the way, not from the first click (needs someone good at maths to fix this)
 * Potlatch 1-style "floaty warnings"
 * Keyboard shortcuts
 * Mouse wheel zooming
@@ -65,6 +66,5 @@ Potlatch 2: main outstanding issues
 * Shields
 * More line decoration (cliffs etc.), and implied values for 'dashes' if not supplied
 * Complete MapCSS support
-* Don't redraw stuff that's offscreen
 * 'Light' version without vectorlayer support etc.
 * Infinite z-indexes
index b7bed890f43b519fd075f4f2c6db8eed8e7f906c..7de3dbaf0673c4b4e69bc3193db5b13a64b907c1 100755 (executable)
@@ -40,16 +40,6 @@ package net.systemeD.halcyon {
                public var bigedge_b:Number= 999999;                    //  |
                public var bigedge_t:Number=-999999;                    //  |
 
-               public var waycount:uint=0;                                             // ways:                number currently loaded
-               public var waysrequested:uint=0;                                //                              total number requested
-               public var waysreceived:uint=0;                                 //                              total number received
-               public var relcount:uint=0;                                             // relations:   number currently loaded
-               public var relsrequested:uint=0;                                //                              total number requested
-               public var relsreceived:uint=0;                                 //                              total number received
-               public var poicount:uint=0;                                             // POIs:                number currently loaded
-               public var whichrequested:uint=0;                               // whichways:   total number requested
-               public var whichreceived:uint=0;                                //                              total number received
-
                public var edge_l:Number;                                               // current bounding box
                public var edge_r:Number;                                               //  |
                public var edge_t:Number;                                               //  |
@@ -239,12 +229,13 @@ package net.systemeD.halcyon {
 
         private function newWayCreated(event:EntityEvent):void {
             var way:Way = event.entity as Way;
-                       if (!way.loaded) { return; }
+                       if (!way.loaded || !way.within(edge_l,edge_r,edge_t,edge_b)) { return; }
                        paint.createWayUI(way);
         }
 
         private function newPOICreated(event:EntityEvent):void {
             var node:Node = event.entity as Node;
+                       if (!node.within(edge_l,edge_r,edge_t,edge_b)) { return; }
                        var nodeui:NodeUI=paint.createNodeUI(node);
                        nodeui.redraw();
         }
@@ -287,6 +278,12 @@ package net.systemeD.halcyon {
                // ------------------------------------------------------------------------------------------
                // Redraw all items, zoom in and out
                
+               public function updateEntityUIs(redraw:Boolean,remove:Boolean):void {
+                       paint.updateEntityUIs(connection.getObjectsByBbox(edge_l, edge_r, edge_t, edge_b), redraw, remove);
+                       for each (var v:VectorLayer in vectorlayers) {
+                               v.paint.updateEntityUIs(v.getObjectsByBbox(edge_l, edge_r, edge_t, edge_b), redraw, remove);
+                       }
+               }
                public function redraw():void {
                        paint.redraw();
                        for each (var v:VectorLayer in vectorlayers) { v.paint.redraw(); }
@@ -312,8 +309,8 @@ package net.systemeD.halcyon {
                        scalefactor=MASTERSCALE/Math.pow(2,13-scale);
                        updateCoordsFromLatLon((edge_t+edge_b)/2,(edge_l+edge_r)/2);    // recentre
                        tileset.changeScale(scale);
+                       updateEntityUIs(true,true);
                        download();
-                       redraw();
                }
 
                private function reportPosition():void {
@@ -361,6 +358,7 @@ package net.systemeD.halcyon {
                public function mouseUpHandler(event:MouseEvent):void {
                        if (dragstate==DRAGGING) {
                                updateCoords(x,y);
+                               updateEntityUIs(false, false);
                                download();
                        }
                        dragstate=NOT_DRAGGING;
@@ -395,7 +393,6 @@ package net.systemeD.halcyon {
                public function keyUpHandler(event:KeyboardEvent):void {
                        if ( !event.ctrlKey ) return;
                        addDebug("pressed "+event.keyCode);
-                       if (event.keyCode==82) { redraw(); }                    // R - redraw
                        if (event.keyCode==73) { zoomIn(); }                    // I - zoom in
                        if (event.keyCode==79) { zoomOut(); }                   // O - zoom out
                        if (event.keyCode==76) { reportPosition(); }    // L - report lat/long
index 14dc97eb925f43e48e980ca8f1f1bbccea4b0add..68f0713c8c10e448b1c5ce9f55a1cf3249b77c9f 100644 (file)
@@ -67,22 +67,44 @@ package net.systemeD.halcyon {
                }
 */
 
+               public function updateEntityUIs(o:Object, redraw:Boolean, remove:Boolean):void {
+                       var way:Way, node:Node;
+
+                       for each (way in o.waysInside) {
+                               if (!wayuis[way.id]) { createWayUI(way); }
+                               else if (redraw) { wayuis[way.id].recalculate(); wayuis[way.id].redraw(); }
+                       }
+                       if (remove) {
+                               for each (way in o.waysOutside) { deleteWayUI(way); }
+                       }
+
+                       for each (node in o.poisInside) {
+                               if (!nodeuis[node.id]) { createNodeUI(node); }
+                               else if (redraw) { nodeuis[node.id].redraw(); }
+                       }
+                       if (remove) {
+                               for each (node in o.poisOutside) { deleteNodeUI(node); }
+                       }
+               }
+
                public function createWayUI(way:Way):WayUI {
-                       wayuis[way.id]=new WayUI(way,this,false);
+                       if (!wayuis[way.id]) { wayuis[way.id]=new WayUI(way,this,false); }
                        return wayuis[way.id];
                }
 
                public function createNodeUI(node:Node):NodeUI {
-                       nodeuis[node.id]=new NodeUI(node,this,0,false);
+                       if (!nodeuis[node.id]) { nodeuis[node.id]=new NodeUI(node,this,0,false); }
                        return nodeuis[node.id];
                }
 
                public function deleteWayUI(way:Way):void {
+                       if (!wayuis[way.id]) { return; }
                        wayuis[way.id].removeSprites();
                        delete wayuis[way.id];
                }
 
                public function deleteNodeUI(node:Node):void {
+                       if (!nodeuis[node.id]) { return; }
                        nodeuis[node.id].removeSprites();
                        delete nodeuis[node.id];
                }
index f448ad8108f452a5bbcbcf6335177ad4dfb56660..f9906226f8b256f43b245cd8f4ee5b66ad138407 100755 (executable)
@@ -262,13 +262,28 @@ package net.systemeD.halcyon.connection {
             return list;
         }
 
+               public function getObjectsByBbox(left:Number, right:Number, top:Number, bottom:Number):Object {
+                       var o:Object = { poisInside: [], poisOutside: [], waysInside: [], waysOutside: [] };
+                       for each (var way:Way in ways) {
+                               if (way.within(left,right,top,bottom)) { o.waysInside.push(way); }
+                                                                 else { o.waysOutside.push(way); }
+                       }
+                       for each (var node:Node in nodes) {
+                               if (!node.hasParentWays) {
+                                       if (node.within(left,right,top,bottom)) { o.poisInside.push(node); }
+                                                                          else { o.poisOutside.push(node); }
+                               }
+                       }
+                       return o;
+               }
+
         public function getActiveChangeset():Changeset {
             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) {
+                               if (!way.within(left,right,top,bottom) && !way.isDirty) {
                                        killWayWithNodes(way.id);
                                }
                        }
index 094911225a4f30d00c09a60a071ab15d4b5e1acd..1d5975d20e16d8f56618adac1c3bd0199e027fdb 100644 (file)
@@ -118,6 +118,10 @@ package net.systemeD.halcyon.connection {
                internal function isEmpty():Boolean {
                        return false;   // to be overridden
                }
+               
+               public function within(left:Number,right:Number,top:Number,bottom:Number):Boolean {
+                       return true;    // to be overridden
+               }
 
                public function removeFromParents(performAction:Function):void {
                        for (var o:Object in parents) {
index 027b618c1cf0945dafe28ef3068f28f24eb250b6..4982db07c260486d837e6f9596fc36ee32461f0d 100644 (file)
@@ -66,6 +66,11 @@ package net.systemeD.halcyon.connection {
                public override function remove(performAction:Function):void {
                        performAction(new DeleteNodeAction(this, setDeletedState));
                }
+
+               public override function within(left:Number,right:Number,top:Number,bottom:Number):Boolean {
+                       if (_lon<left || _lon>right || _lat<bottom || _lat>top) { return false; }
+                       return true;
+               }
                
                internal override function isEmpty():Boolean {
                        return deleted;
index 4b50303ee360734d255faeef5f72bf67490453bb..4f4c06c7f3d4b546f655923302360500d756d1d4 100644 (file)
@@ -43,7 +43,7 @@ package net.systemeD.halcyon.connection {
                        edge_t=Math.max(edge_t,node.lat);
                }
                
-               public function intersectsBbox(left:Number,right:Number,top:Number,bottom:Number):Boolean {
+               public override function within(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) ||
index 6cd22f3250fee80c877017f99960f9a3f55318ec..48f9a6898840941c8f592b1681871b188c2f6ac5 100644 (file)
@@ -37,6 +37,23 @@ package net.systemeD.halcyon.vectorlayers {
                        relations[negativeID]=relation; negativeID--;
             return relation;
                }
+
+               public function getObjectsByBbox(left:Number, right:Number, top:Number, bottom:Number):Object {
+                       // ** FIXME: this is just copied-and-pasted from Connection.as, which really isn't very
+                       // good practice. Is there a more elegant way of doing it?
+                       var o:Object = { poisInside: [], poisOutside: [], waysInside: [], waysOutside: [] };
+                       for each (var way:Way in ways) {
+                               if (way.within(left,right,top,bottom)) { o.waysInside.push(way); }
+                                                                 else { o.waysOutside.push(way); }
+                       }
+                       for each (var node:Node in nodes) {
+                               if (!node.hasParentWays) {
+                                       if (node.within(left,right,top,bottom)) { o.poisInside.push(node); }
+                                                                          else { o.poisOutside.push(node); }
+                               }
+                       }
+                       return o;
+               }
                
                public function pullThrough(entity:Entity,connection:Connection):Way {
                        var i:uint=0;
@@ -59,7 +76,7 @@ package net.systemeD.halcyon.vectorlayers {
                                        delete nodes[id];
                                }
                                paint.wayuis[oldWay.id].redraw();
-                               ways[oldWay.id]=null;
+                               delete ways[oldWay.id];
                                map.paint.createWayUI(newWay);
                        }
                        return newWay;
index 31c005d09191a2e205fb023ebc582ff00f225706..941a6aafd4ccfbfd8fd5daf286a9f5c1bba3819d 100644 (file)
@@ -25,7 +25,7 @@
         PopUpManager.removePopUp(this);
     }
 
-       private function loadFiles(url:String,filetype:String):void {
+       private function loadFiles(url:String,filetype:String,simplify:Boolean):void {
         PopUpManager.removePopUp(this);
                var theMap:Map = Globals.vars.root;
                var vectorlayer:CustomVectorLayer=new CustomVectorLayer(url,theMap,"potlatch.css");
                theMap.vectorbg.addChild(vectorlayer.paint);
 
                if (filetype=='gpx') {
-                       var gpx:GpxImporter=new GpxImporter(vectorlayer,vectorlayer.paint,[url]);
+                       var gpx:GpxImporter=new GpxImporter(vectorlayer, vectorlayer.paint, [url], simplify);
                } else {
                        var re:RegExp=/.shp$/i; url=url.replace(re,'');
                        var shp:ShpImporter=new ShpImporter(vectorlayer,
                                                            vectorlayer.paint,
-                                                           [url+".shp",url+".shx",url+".dbf"]);
+                                                           [url+".shp",url+".shx",url+".dbf"], simplify);
                }
        }
 
       Input the URL of a file to import.
     </mx:text>
   </mx:Text>
-  <mx:TextInput id="src" text="" />
+  <mx:TextInput width="100%" id="src" text="" />
   <mx:RadioButtonGroup id="filetype" />
-  <mx:RadioButton groupName="{filetype}" value="shp" id="shp" label="Shapefile" selected="true" />
-  <mx:RadioButton groupName="{filetype}" value="gpx" id="gpx" label="GPX" />
+  <mx:RadioButton width="100%" groupName="{filetype}" value="shp" id="shp" label="Shapefile" selected="true" />
+  <mx:RadioButton width="100%" groupName="{filetype}" value="gpx" id="gpx" label="GPX" />
+  <mx:CheckBox width="100%" label="Simplify paths" selected="true" id="simplify" />
   <mx:ControlBar>
     <mx:Spacer width="100%"/>
-    <mx:Button label="Load" click="loadFiles(src.text, shp.selected?'shp':'gpx');" enabled="{src.text == '' ? false : true}"/>
+    <mx:Button label="Load" click="loadFiles(src.text, shp.selected?'shp':'gpx', simplify.selected);" enabled="{src.text == '' ? false : true}"/>
   </mx:ControlBar>
 
 </mx:TitleWindow>
index 8a04bffe4d4a2dbc9afa1500de30ee0e9271cac3..c1a15cf8cfd1b442b2e303efd900183860c5d2a7 100644 (file)
@@ -38,6 +38,7 @@ package net.systemeD.potlatch2.controller {
                }
 
                override public function enterState():void {
+                       controller.map.paint.createWayUI(selectedWay);
                        startlon =controller.map.coord2lon(controller.map.mouseX);
                        startlatp=controller.map.coord2latp(controller.map.mouseY);
                        Globals.vars.root.addDebug("**** -> "+this);
index ce0983f0a24f752cbd7e4f3b015d36456388cff2..a125c30775408e89117b65f2f74175c6caea69de 100644 (file)
@@ -3,12 +3,13 @@ package net.systemeD.potlatch2.utils {
        import net.systemeD.halcyon.MapPaint;
        import net.systemeD.halcyon.Globals;
        import net.systemeD.halcyon.connection.Node;
+       import net.systemeD.halcyon.connection.Way;
+       import net.systemeD.potlatch2.tools.Simplify;
 
        public class GpxImporter extends Importer {
 
-               public function GpxImporter(container:*, paint:MapPaint, filenames:Array) {
-trace("started gpximporter");
-                       super(container,paint,filenames);
+               public function GpxImporter(container:*, paint:MapPaint, filenames:Array, simplify:Boolean=false) {
+                       super(container,paint,filenames,simplify);
                }
 
                override protected function doImport(): void {
@@ -21,19 +22,21 @@ trace("started gpximporter");
                                trace("trk");
                                for each (var trkseg:XML in trk.child("trkseg")) {
                                        trace("trkseg");
+                                       var way:Way;
                                        var nodestring:Array=[];
                                        for each (var trkpt:XML in trkseg.child("trkpt")) {
                                                nodestring.push(container.createNode({}, trkpt.@lat, trkpt.@lon));
                                                trace("adding point at "+trkpt.@lat+","+trkpt.@lon);
                                        }
                                        if (nodestring.length>0) {
-                                               paint.createWayUI(container.createWay({}, nodestring));
+                                               way=container.createWay({}, nodestring);
+                                               if (simplify) { Simplify.simplify(way, paint.map, false); }
                                        }
                                }
                        }
                        for each (var wpt:XML in file.child("wpt")) {
                                // ** could potentially get the children and add them as gpx:tags
-                               paint.createNodeUI(container.createNode({}, wpt.lat, wpt.lon));
+                               container.createNode({}, wpt.lat, wpt.lon);
                        }
                }
        }
index 46ee4c3a8bc06e5f01710fcd8463cd34788cd56f..1caca65334cfc3e7cb7b354edc606c5ce6567cb0 100644 (file)
@@ -18,14 +18,16 @@ package net.systemeD.potlatch2.utils {
                protected var filenames:Array;
                protected var filesloaded:uint=0;
                protected var callback:Function;
+               protected var simplify:Boolean;
 
-               public function Importer(container:*, paint:MapPaint, filenames:Array) {
+               public function Importer(container:*, paint:MapPaint, filenames:Array, simplify:Boolean) {
                        Globals.vars.root.addDebug("starting importer"); 
                        Globals.vars.root.addDebug("container is "+container);
                        Globals.vars.root.addDebug("paint is "+paint);
                        this.container = container;
                        this.paint = paint;
                        this.filenames=filenames;
+                       this.simplify=simplify;
 
                        var sp:uint=0;
                        for each (var fn:String in filenames) {
@@ -47,7 +49,10 @@ package net.systemeD.potlatch2.utils {
                        Globals.vars.root.addDebug("loaded file "+e.target.info['file']); 
                        files[e.target.info['file']]=e.target.data;
                        filesloaded++;
-                       if (filesloaded==filenames.length) { doImport(); }
+                       if (filesloaded==filenames.length) { 
+                               doImport();
+                               paint.updateEntityUIs(container.getObjectsByBbox(paint.map.edge_l, paint.map.edge_r, paint.map.edge_t, paint.map.edge_b), false, false);
+                       }
                }
                
                protected function doImport():void {
index b324a25b6b3ff1dc9a1b85a75e3aa7f1f78f5a0f..9fc32ca86503b3064fb9ae7caa2e27cc73b4af46 100644 (file)
@@ -5,11 +5,13 @@ package net.systemeD.potlatch2.utils {
        import net.systemeD.halcyon.MapPaint;
        import net.systemeD.halcyon.Globals;
        import net.systemeD.halcyon.connection.Node;
+       import net.systemeD.halcyon.connection.Way;
+       import net.systemeD.potlatch2.tools.Simplify;
 
        public class ShpImporter extends Importer {
 
-               public function ShpImporter(container:*, paint:MapPaint, filenames:Array) {
-                       super(container,paint,filenames);
+               public function ShpImporter(container:*, paint:MapPaint, filenames:Array, simplify:Boolean=false) {
+                       super(container,paint,filenames,simplify);
                }
 
                override protected function doImport(): void {
@@ -29,6 +31,7 @@ package net.systemeD.potlatch2.utils {
 
                                        // Do each ring in turn, then each point in the ring
                                        for (var j:int=0; j < polyArray[i].shape.rings.length; j++) {
+                                               var way:Way;
                                                var nodestring:Array=[];
                                                var points:Array = polyArray[i].shape.rings[j];
                                                if (points!=null) {
@@ -38,7 +41,8 @@ package net.systemeD.potlatch2.utils {
                                                        }
                                                }
                                                if (nodestring.length>0) {
-                                                       paint.createWayUI(container.createWay({}, nodestring));
+                                                       way=container.createWay({}, nodestring);
+                                                       if (simplify) { Simplify.simplify(way, paint.map, false); }
                                                }
                                        }
                                }