Don't straighten ways if they diverge too much
authorRichard Fairhurst <richard@systemeD.net>
Sat, 6 Oct 2012 07:58:23 +0000 (08:58 +0100)
committerRichard Fairhurst <richard@systemeD.net>
Sat, 6 Oct 2012 07:58:23 +0000 (08:58 +0100)
net/systemeD/halcyon/connection/CompositeUndoableAction.as
net/systemeD/potlatch2/Toolbox.mxml
net/systemeD/potlatch2/tools/Straighten.as

index ffec7dc..cee31c0 100644 (file)
@@ -39,6 +39,13 @@ package net.systemeD.halcyon.connection {
             actions = [];
         }
 
+        /**
+        * Are there any actions set?
+        */
+        public function get empty():Boolean {
+            return actions.length==0;
+        }
+
         /**
         * Do all the actions on the list. Can be overridden by an specific implementation, usually to manage
         * the suspending and resuming of entities. If so, you'll want to call super.doAction from that implementation
index a5a59f3..6c3235b 100644 (file)
@@ -89,6 +89,7 @@
 
                import flash.events.Event;
                import flash.events.MouseEvent;
+               import net.systemeD.halcyon.AttentionEvent;
                import net.systemeD.halcyon.connection.*;
                import net.systemeD.halcyon.connection.actions.*;
                import net.systemeD.potlatch2.controller.*;
 
                public function doStraighten():void {
                        var undo:CompositeUndoableAction = new CompositeUndoableAction("Straighten objects");
+                       var success:Boolean=true;
                        for each (var way:Way in controller.state.selectedWays) {
-                               Straighten.straighten(way, controller.map, undo.push);
+                               success &&= Straighten.straighten(way, controller.map, undo.push);
                        }
-                       MainUndoStack.getGlobalStack().addAction(undo);
+                       if (!success) controller.dispatchEvent(new AttentionEvent(AttentionEvent.ALERT, null, "Too bendy to straighten"));
+                       if (!undo.empty) MainUndoStack.getGlobalStack().addAction(undo);
                }
 
                public function doCircularise():void {
index a5a6f8a..9d0f4f6 100644 (file)
@@ -13,31 +13,42 @@ package net.systemeD.potlatch2.tools {
                 * @param way Way to be straightened.
                 * @param map Map that it belongs to.
                 * @performAction Function that will be passed a CompositeUndoableAction parameter representing the transformation.
+                * @return True if ok (or closed/short way), false if the way was too bendy to straighten.
                 * */
-               public static function straighten(way:Way,map:Map,performAction:Function):void {
-                       if (way.length<3) { return; }
+               public static function straighten(way:Way,map:Map,performAction:Function):Boolean {
+                       if (way.length<3) { return true; }
 
                        var a:Node=way.getNode(0);
                        var b:Node=way.getNode(way.length-1);
-                       if (way.isArea()) { return; }
+                       if (way.isArea()) { return true; }
                        
-                       // ** could potentially do the 'too bendy?' check here as per Potlatch 1
+                       // Check way isn't too bendy
+                       var latfactor:Number=Math.cos(map.centre_lat/(180/Math.PI));
+                       var n:Node;
+                       for (var i:uint=1; i<way.length-1; i++) {
+                               n=way.getNode(i);
+                               var u:Number=Straighten.positionAlongWay(n,a,b);
+                               var x1:Number=a.lon +u*(b.lon -a.lon );
+                               var y1:Number=a.latp+u*(b.latp-a.latp);
+                               var t:Number=Math.sqrt(Math.pow(x1-n.lon,2) + Math.pow(y1-n.latp,2));
+                               t=111200*latfactor*t;
+                               if (t>50) { return false; }
+                       }
+
+                       // Not too bendy, so straighten
                        
                        var action:CompositeUndoableAction = new CompositeUndoableAction("Straighten");
                        
                        var todelete:Array=[];
-                       var n:Node;
                
-                       for (var i:uint=1; i<way.length-1; i++) {
+                       for (i=1; i<way.length-1; i++) {
                                n=way.getNode(i);
                                if (n.parentWays.length>1 || n.hasTags() ||
                                    n.lon<map.edge_l || n.lon>map.edge_r ||
                                    n.lat<map.edge_b || n.lat>map.edge_t) {
 
                                        // junction node, tagged, or off-screen - so retain and move
-                                       var u:Number=((n.lon -a.lon )*(b.lon -a.lon )+
-                                                     (n.latp-a.latp)*(b.latp-a.latp))/
-                                                    (Math.pow(b.lon-a.lon,2)+Math.pow(b.latp-a.latp,2));
+                                       u=Straighten.positionAlongWay(n,a,b);
                                        n.setLonLatp(a.lon +u*(b.lon -a.lon ),
                                                     a.latp+u*(b.latp-a.latp), action.push);
                                        
@@ -49,6 +60,13 @@ package net.systemeD.potlatch2.tools {
                        for each (n in todelete) { n.remove(action.push); }
                        
                        performAction(action);
+                       return true;
+               }
+
+               private static function positionAlongWay(n:Node, a:Node, b:Node):Number {
+                       return ((n.lon -a.lon )*(b.lon -a.lon )+
+                                   (n.latp-a.latp)*(b.latp-a.latp))/
+                                   (Math.pow(b.lon-a.lon,2)+Math.pow(b.latp-a.latp,2));
                }
        }
 }