Only add a new vector layer to the map once we know we have loaded
[potlatch2.git] / net / systemeD / potlatch2 / tools / Simplify.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 Simplify {
9
10                 private static const TOLERANCE:Number=0.00005;
11
12                 public static function simplify(way:Way, map:Map, keepOffscreen:Boolean):void {
13                         if (way.length<3 || way.isArea()) { return; }
14
15                         var action:CompositeUndoableAction = new CompositeUndoableAction("Simplify");
16                         
17                         var xa:Number, xb:Number;
18                         var ya:Number, yb:Number;
19                         var l:Number, d:Number, i:uint;
20                         var furthest:uint, furthdist:Number, float:Number;
21                         var n:Node;
22                         
23                         var tokeep:Object={};
24                         var stack:Array=[way.length-1];
25                         var anchor:uint=0;
26                         var todelete:Array=[];
27                 
28                         // Douglas-Peucker
29                         while (stack.length) {
30                                 float=stack[stack.length-1];
31                                 furthest=0; furthdist=0;
32                                 xa=way.getNode(anchor).lon ; xb=way.getNode(float).lon ;
33                                 ya=way.getNode(anchor).latp; yb=way.getNode(float).latp;
34                                 l=Math.sqrt((xb-xa)*(xb-xa)+(yb-ya)*(yb-ya));
35         
36                                 // find furthest-out point
37                                 for (i=anchor+1; i<float; i+=1) {
38                                         d=getDistance(xa,ya,xb,yb,l,way.getNode(i).lon,way.getNode(i).latp);
39                                         if (d>furthdist && d>TOLERANCE) { furthest=i; furthdist=d; }
40                                 }
41                         
42                                 if (furthest==0) {
43                                         anchor=stack.pop();
44                                         tokeep[way.getNode(float).id]=true;
45                                 } else {
46                                         stack.push(furthest);
47                                 }
48                         }
49                         
50                         // Delete unwanted nodes, unless they're tagged or junction nodes
51                         for (i=1; i<way.length; i++) {
52                                 n=way.getNode(i)
53                                 if (tokeep[n.id] || n.hasTags() || n.parentWays.length>1 ||
54                                     (keepOffscreen && (n.lon<map.edge_l || n.lon>map.edge_r || n.lat<map.edge_b || n.lat>map.edge_t )) ) {
55                                         // keep it
56                                 } else {
57                                         // delete it
58                                         todelete.push(n);
59                                 }
60                         }
61                         for each (n in todelete) { n.remove(action.push); }
62                         MainUndoStack.getGlobalStack().addAction(action);
63                 }
64                 
65                 private static function getDistance(ax:Number,ay:Number,bx:Number,by:Number,l:Number,cx:Number,cy:Number):Number {
66                         // l=length of line
67                         // r=proportion along AB line (0-1) of nearest point
68                         var r:Number=((cx-ax)*(bx-ax)+(cy-ay)*(by-ay))/(l*l);
69                         // now find the length from cx,cy to ax+r*(bx-ax),ay+r*(by-ay)
70                         var px:Number=(ax+r*(bx-ax)-cx);
71                         var py:Number=(ay+r*(by-ay)-cy);
72                         return Math.sqrt(px*px+py*py);
73                 }
74
75         }
76 }