if (nodeuis[node.id]) { deleteNodeUI(node); }
}
}
+
+ /** Return WayUI properties */
+ public function wayUIProperties(way:Way):Object {
+ if (wayuis[way.id]) {
+ return { centroid_x: wayuis[way.id].centroid_x,
+ centroid_y: wayuis[way.id].centroid_y,
+ patharea: wayuis[way.id].patharea,
+ pathlength: wayuis[way.id].pathlength };
+ } else {
+ return {};
+ }
+ }
/** Make a UI object representing a node. */
public function createNodeUI(node:Node,rotation:Number=0,layer:int=NO_LAYER,stateClasses:Object=null):NodeUI {
performAction(new ReverseNodesAction(this, nodes));
}
+
+ /** Is a point within this way?
+ * From http://as3.miguelmoraleda.com/2009/10/28/point-in-polygon-with-actionscript-3punto-dentro-de-un-poligono-con-actionscript-3/
+ */
+
+ public function pointWithin(lon:Number,lat:Number):Boolean {
+ if (!isArea()) return false;
+
+ var counter:uint = 0;
+ var p1x:Number = nodes[0].lon;
+ var p1y:Number = nodes[0].lat;
+ var p2x:Number, p2y:Number;
+
+ for (var i:uint = 1; i <= length; i++) {
+ p2x = nodes[i % length].lon;
+ p2y = nodes[i % length].lat;
+ if (lat > Math.min(p1y, p2y)) {
+ if (lat <= Math.max(p1y, p2y)) {
+ if (lon <= Math.max(p1x, p2x)) {
+ if (p1y != p2y) {
+ var xinters:Number = (lat - p1y) * (p2x - p1x) / (p2y - p1y) + p1x;
+ if (p1x == p2x || lon <= xinters) counter++;
+ }
+ }
+ }
+ }
+ p1x = p2x;
+ p1y = p2y;
+ }
+ if (counter % 2 == 0) { return false; }
+ else { return true; }
+ }
+
/**
* Finds the 1st way segment which intersects the projected
* coordinate and adds the node to that segment. If snap is
override public function processKeyboardEvent(event:KeyboardEvent):ControllerState {
if (event.keyCode==74) return mergeWays(); // 'J'
+ if (event.keyCode==75) return createMultipolygon();
var cs:ControllerState = sharedKeyboardEvents(event);
return cs ? cs : this;
}
}
return false;
}
+
+ /** Create multipolygon from selection, or add to existing multipolygon. */
+
+ public function createMultipolygon():ControllerState {
+ var entity:Entity;
+ var relation:Relation;
+ var outer:Way;
+ var inner:Way;
+ var inners:Array=[];
+
+ // If there's an existing outer in the selection, use that
+ for each (entity in selection) {
+ if (!entity is Way) continue;
+ var r:Array=entity.findParentRelationsOfType('multipolygon','outer');
+ if (r.length) { outer=Way(entity); relation=r[0]; }
+ }
+
+ // Otherwise, find the way with the biggest area
+ var largest:Number=0;
+ if (!outer) {
+ for each (entity in selection) {
+ if (!entity is Way) continue;
+ if (!Way(entity).isArea()) continue;
+ var props:Object=layer.wayUIProperties(entity as Way);
+ if (props.patharea>largest) { outer=Way(entity); }
+ }
+ }
+
+ // If we still don't have an outer, then squawk
+ if (!outer) {
+ controller.dispatchEvent(new AttentionEvent(AttentionEvent.ALERT, null, "No areas selected"));
+ return this;
+ }
+
+ // Identify the inners
+ for each (entity in selection) {
+ if (entity==outer) continue;
+ if (!entity is Way) continue;
+ if (!Way(entity).isArea()) continue;
+ var node:Node=Way(entity).getFirstNode();
+ if (outer.pointWithin(node.lon,node.lat)) inners.push(entity);
+ }
+ if (inners.length==0) {
+ controller.dispatchEvent(new AttentionEvent(AttentionEvent.ALERT, null, "Couldn't identify inner areas"));
+ return this;
+ }
+
+ // If relation exists, add any inners that aren't currently present
+ if (relation) {
+ var action:CompositeUndoableAction = new CompositeUndoableAction("Add to multipolygon");
+ for each (inner in inners) {
+ if (!relation.hasMemberInRole(inner,'inner'))
+ relation.appendMember(new RelationMember(inner,'inner'),action.push);
+ }
+ MainUndoStack.getGlobalStack().addAction(action);
+
+ // Otherwise, create whole new relation
+ } else {
+ var memberlist:Array=[new RelationMember(outer,'outer')];
+ for each (inner in inners)
+ memberlist.push(new RelationMember(inner,'inner'));
+ relation = entity.connection.createRelation( { type: 'multipolygon' }, memberlist, MainUndoStack.getGlobalStack().addAction);
+ }
+
+ return new SelectedWay(outer);
+ }
override public function enterState():void {
selection=initSelection.concat();