add undo for creating stuff
[potlatch2.git] / net / systemeD / potlatch2 / tools / Circularise.as
index 2e6150b..c02999d 100644 (file)
@@ -14,41 +14,51 @@ package net.systemeD.potlatch2.tools {
                        var b:Node=way.getNode(way.length-1);
                        if (a!=b) { return; }
 
-                       // Find centre-point
-                       // ** should be refactored to be within Way.as, so we can share with WayUI.as
-                       var patharea:Number=0;
-                       var cx:Number=0; var lx:Number=b.lon;
-                       var cy:Number=0; var ly:Number=b.latp;
-                       var i:uint,j:uint,n:Node;
-                       for (i=0; i<way.length; i++) {
-                               n=way.getNode(i);
-                               var sc:Number = (lx*n.latp-n.lon*ly);
-                               cx += (lx+n.lon )*sc;
-                               cy += (ly+n.latp)*sc;
-                               patharea += sc;
-                               lx=n.lon; ly=n.latp;
-                       }
-                       patharea/=2;
-                       cx/=patharea*6;
-                       cy/=patharea*6;
+            new Circularise(way, map).run();
+        }
+        
+        private var way:Way;
+        private var map:Map;
+        
+        // centre
+        private var cx:Number=0;
+        private var cy:Number=0;
+        
+        // distance to centre
+               private var d:Number=0;
+        
+        // our undoable
+        private var action:CompositeUndoableAction = new CompositeUndoableAction("Circularise");
 
-                       // Average distance to centre
-                       var d:Number=0; var angles:Array=[];
-                       for (i=0; i<way.length; i++) {
-                               d+=Math.sqrt(Math.pow(way.getNode(i).lon -cx,2)+
-                                                        Math.pow(way.getNode(i).latp-cy,2));
-                       }
-                       d=d/way.length;
-                       
+        // recording the node lats lons so we're not relying on instant update
+        private var lats:Array = [];
+               private var lons:Array = [];
 
-                       var action:CompositeUndoableAction = new CompositeUndoableAction("Circularise");
+        function Circularise(way:Way, map:Map) {
+            this.way = way;
+            this.map = map;
+        }
+        
+        private function run():void {
+            calculateCentre();
+            calculateCentreDistance();
 
+            var i:uint;
+            var j:uint;
+            var n:Node;
+            
                        // Move each node
                        for (i=0; i<way.length-1; i++) {
                                n=way.getNode(i);
                                var c:Number=Math.sqrt(Math.pow(n.lon-cx,2)+Math.pow(n.latp-cy,2));
-                               n.setLonLatp(cx+(n.lon -cx)/c*d,
-                                            cy+(n.latp-cy)/c*d, action.push);
+                               var lat:Number = cy+(n.latp-cy)/c*d;
+                               var lon:Number = cx+(n.lon -cx)/c*d;
+                               n.setLonLatp(lon, lat, action.push);
+                               
+                               // record the lat lons we're using as the node won't update
+                               // till later
+                               lats.push(lat);
+                               lons.push(lon);
                        }
 
                        // Insert extra nodes to make circle
@@ -56,19 +66,17 @@ package net.systemeD.potlatch2.tools {
                        i=0;
                        var clockwise:Boolean=way.clockwise;
                        var diff:Number, ang:Number;
-                       while (i<way.length-1) {
-                               j=(i+1) % way.length;
-                               var a1:Number=Math.atan2(way.getNode(i).lon-cx,way.getNode(i).latp-cy)*(180/Math.PI);
-                               var a2:Number=Math.atan2(way.getNode(j).lon-cx,way.getNode(j).latp-cy)*(180/Math.PI);
+                       while (i<lons.length) {
+                               j=(i+1) % lons.length;
+                               var a1:Number=Math.atan2(lons[i]-cx, lats[i]-cy)*(180/Math.PI);
+                               var a2:Number=Math.atan2(lons[j]-cx, lats[j]-cy)*(180/Math.PI);
 
                                if (clockwise) {
                                        if (a2>a1) { a2=a2-360; }
                                        diff=a1-a2;
                                        if (diff>20) {
                                                for (ang=a1-20; ang>a2+10; ang-=20) {
-                                                       way.insertNode(j,map.connection.createNode({},
-                                                               map.latp2lat(cy+Math.cos(ang*Math.PI/180)*d),
-                                                               cx+Math.sin(ang*Math.PI/180)*d));
+                                                   insertNode(ang, i+1);
                                                        j++; i++;
                                                }
                                        }
@@ -77,9 +85,7 @@ package net.systemeD.potlatch2.tools {
                                        diff=a2-a1;
                                        if (diff>20) {
                                                for (ang=a1+20; ang<a2-10; ang+=20) {
-                                                       way.insertNode(j,map.connection.createNode({},
-                                                               map.latp2lat(cy+Math.cos(ang*Math.PI/180)*d),
-                                                               cx+Math.sin(ang*Math.PI/180)*d));
+                                                   insertNode(ang, i+1);
                                                        j++; i++;
                                                }
                                        }
@@ -89,5 +95,45 @@ package net.systemeD.potlatch2.tools {
 
                        MainUndoStack.getGlobalStack().addAction(action);
                }
+
+        private function calculateCentre():void {
+                       // Find centre-point
+                       // ** should be refactored to be within Way.as, so we can share with WayUI.as
+                       var b:Node=way.getNode(way.length-1);
+                       var patharea:Number=0;
+                       var lx:Number=b.lon;
+                       var ly:Number=b.latp;
+                       var i:uint, n:Node;
+                       for (i=0; i<way.length; i++) {
+                               n=way.getNode(i);
+                               var sc:Number = (lx*n.latp-n.lon*ly);
+                               cx += (lx+n.lon )*sc;
+                               cy += (ly+n.latp)*sc;
+                               patharea += sc;
+                               lx=n.lon; ly=n.latp;
+                       }
+                       patharea/=2;
+                       cx/=patharea*6;
+                       cy/=patharea*6;
+        }
+
+        private function calculateCentreDistance():void {
+                       // Average distance to centre
+                       // (first + last are the same node, don't use twice)
+                       for (var i:uint = 0; i < way.length - 1; i++) {
+                               d+=Math.sqrt(Math.pow(way.getNode(i).lon -cx,2)+
+                                                        Math.pow(way.getNode(i).latp-cy,2));
+                       }
+                       d /= way.length - 1;
+           }
+
+               private function insertNode(ang:Number, index:int):void {
+                       var lat:Number = cy+Math.cos(ang*Math.PI/180)*d;
+                       var lon:Number = cx+Math.sin(ang*Math.PI/180)*d;
+                       lats.splice(index, 0, lat);
+                       lons.splice(index, 0, lon);
+                       var newNode:Node = map.connection.createNode({}, map.latp2lat(lat), lon, action.push);
+                       way.insertNode(index, newNode, action.push);
+               }
        }
 }