1 package net.systemeD.halcyon.connection {
2 import flash.geom.Point;
4 public class Way extends Entity {
5 private var nodes:Array;
6 public static var entity_type:String = 'way';
8 public function Way(id:Number, version:uint, tags:Object, loaded:Boolean, nodes:Array) {
9 super(id, version, tags, loaded);
11 for each (var node:Node in nodes) { node.addParent(this); }
14 public function update(version:uint, tags:Object, loaded:Boolean, nodes:Array):void {
16 for each (node in this.nodes) { node.removeParent(this); }
17 updateEntityProperties(version,tags,loaded); this.nodes=nodes;
18 for each (node in nodes) { node.addParent(this); }
21 public function get length():uint {
25 public function getNode(index:uint):Node {
29 public function insertNode(index:uint, node:Node):void {
31 nodes.splice(index, 0, node);
33 dispatchEvent(new WayNodeEvent(Connection.WAY_NODE_ADDED, node, this, index));
36 public function appendNode(node:Node):uint {
40 dispatchEvent(new WayNodeEvent(Connection.WAY_NODE_ADDED, node, this, nodes.length - 1));
44 public function removeNode(index:uint):void {
45 var removed:Array=nodes.splice(index, 1);
46 removed[0].removeParent(this);
48 dispatchEvent(new WayNodeEvent(Connection.WAY_NODE_REMOVED, removed[0], this, index));
52 * Finds the 1st way segment which intersects the projected
53 * coordinate and adds the node to that segment. If snap is
54 * specified then the node is moved to exactly bisect the
57 public function insertNodeAtClosestPosition(newNode:Node, isSnap:Boolean):int {
58 var closestProportion:Number = 1;
59 var newIndex:uint = 0;
60 var nP:Point = new Point(newNode.lon, newNode.latp);
61 var snapped:Point = null;
63 for ( var i:uint; i < length - 1; i++ ) {
64 var node1:Node = getNode(i);
65 var node2:Node = getNode(i+1);
66 var p1:Point = new Point(node1.lon, node1.latp);
67 var p2:Point = new Point(node2.lon, node2.latp);
69 var directDist:Number = Point.distance(p1, p2);
70 var viaNewDist:Number = Point.distance(p1, nP) + Point.distance(nP, p2);
72 var proportion:Number = Math.abs(viaNewDist/directDist - 1);
73 if ( proportion < closestProportion ) {
75 closestProportion = proportion;
76 snapped = calculateSnappedPoint(p1, p2, nP);
82 newNode.latp = snapped.y;
83 newNode.lon = snapped.x;
85 insertNode(newIndex, newNode);
89 private function calculateSnappedPoint(p1:Point, p2:Point, nP:Point):Point {
90 var w:Number = p2.x - p1.x;
91 var h:Number = p2.y - p1.y;
92 var u:Number = ((nP.x-p1.x) * w + (nP.y-p1.y) * h) / (w*w + h*h);
93 return new Point(p1.x + u*w, p1.y+u*h);
96 public override function toString():String {
97 return "Way("+id+"@"+version+"): "+getTagList()+
98 " "+nodes.map(function(item:Node,index:int, arr:Array):String {return item.id.toString();}).join(",");
101 public function isArea():Boolean {
102 return (nodes[0].id==nodes[nodes.length-1].id && nodes.length>2);
105 public override function getType():String {