fix circularise undo action (still doesn't undo adding the nodes)
[potlatch2.git] / net / systemeD / potlatch2 / tools / Circularise.as
1 package net.systemeD.potlatch2.tools {
2         import net.systemeD.halcyon.Map;
3         import net.systemeD.halcyon.connection.CompositeUndoableAction;
4         import net.systemeD.halcyon.connection.Way;
5         import net.systemeD.halcyon.connection.Node;
6         import net.systemeD.halcyon.connection.MainUndoStack;
7
8         public class Circularise {
9
10                 public static function circularise(way:Way,map:Map):void {
11                         if (way.length<4) { return; }
12
13                         var a:Node=way.getNode(0);
14                         var b:Node=way.getNode(way.length-1);
15                         if (a!=b) { return; }
16
17                         // Find centre-point
18                         // ** should be refactored to be within Way.as, so we can share with WayUI.as
19                         var patharea:Number=0;
20                         var cx:Number=0; var lx:Number=b.lon;
21                         var cy:Number=0; var ly:Number=b.latp;
22                         var i:uint,j:uint,n:Node;
23                         for (i=0; i<way.length; i++) {
24                                 n=way.getNode(i);
25                                 var sc:Number = (lx*n.latp-n.lon*ly);
26                                 cx += (lx+n.lon )*sc;
27                                 cy += (ly+n.latp)*sc;
28                                 patharea += sc;
29                                 lx=n.lon; ly=n.latp;
30                         }
31                         patharea/=2;
32                         cx/=patharea*6;
33                         cy/=patharea*6;
34
35                         // Average distance to centre
36                         var d:Number=0; var angles:Array=[];
37                         for (i=0; i<way.length; i++) {
38                                 d+=Math.sqrt(Math.pow(way.getNode(i).lon -cx,2)+
39                                                          Math.pow(way.getNode(i).latp-cy,2));
40                         }
41                         d=d/way.length;
42                         
43
44                         var action:CompositeUndoableAction = new CompositeUndoableAction("Circularise");
45
46                         // Move each node
47                         for (i=0; i<way.length-1; i++) {
48                                 n=way.getNode(i);
49                                 var c:Number=Math.sqrt(Math.pow(n.lon-cx,2)+Math.pow(n.latp-cy,2));
50                                 n.setLonLatp(cx+(n.lon -cx)/c*d,
51                                              cy+(n.latp-cy)/c*d, action.push);
52                         }
53
54                         // Insert extra nodes to make circle
55                         // clockwise: angles decrease, wrapping round from -170 to 170
56                         i=0;
57                         var clockwise:Boolean=way.clockwise;
58                         var diff:Number, ang:Number;
59                         while (i<way.length-1) {
60                                 j=(i+1) % way.length;
61                                 var a1:Number=Math.atan2(way.getNode(i).lon-cx,way.getNode(i).latp-cy)*(180/Math.PI);
62                                 var a2:Number=Math.atan2(way.getNode(j).lon-cx,way.getNode(j).latp-cy)*(180/Math.PI);
63
64                                 if (clockwise) {
65                                         if (a2>a1) { a2=a2-360; }
66                                         diff=a1-a2;
67                                         if (diff>20) {
68                                                 for (ang=a1-20; ang>a2+10; ang-=20) {
69                                                         way.insertNode(j,map.connection.createNode({},
70                                                                 map.latp2lat(cy+Math.cos(ang*Math.PI/180)*d),
71                                                                 cx+Math.sin(ang*Math.PI/180)*d));
72                                                         j++; i++;
73                                                 }
74                                         }
75                                 } else {
76                                         if (a1>a2) { a1=a1-360; }
77                                         diff=a2-a1;
78                                         if (diff>20) {
79                                                 for (ang=a1+20; ang<a2-10; ang+=20) {
80                                                         way.insertNode(j,map.connection.createNode({},
81                                                                 map.latp2lat(cy+Math.cos(ang*Math.PI/180)*d),
82                                                                 cx+Math.sin(ang*Math.PI/180)*d));
83                                                         j++; i++;
84                                                 }
85                                         }
86                                 }
87                                 i++;
88                         }
89
90                         MainUndoStack.getGlobalStack().addAction(action);
91                 }
92         }
93 }