From 4eb7ac03ffba11c1c46ae3742427a4dab47bf94c Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Sat, 21 May 2011 12:52:54 +0100 Subject: [PATCH 01/89] Refactoring in progress --- net/systemeD/halcyon/Map.as | 235 +++++------------- net/systemeD/halcyon/MapPaint.as | 110 +++++++- net/systemeD/halcyon/VectorLayer.as | 2 +- .../halcyon/connection/AMFConnection.as | 3 +- net/systemeD/halcyon/connection/Connection.as | 42 +--- .../halcyon/connection/OSMConnection.as | 3 +- net/systemeD/halcyon/connection/Trace.as | 4 +- .../connection/UndoableEntityAction.as | 6 +- .../halcyon/connection/XMLConnection.as | 3 +- net/systemeD/potlatch2/BugLayer.as | 2 +- .../potlatch2/RelationLoaderPanel.mxml | 4 +- .../potlatch2/RelationSelectPanel.mxml | 2 +- net/systemeD/potlatch2/TagViewer.mxml | 8 +- .../editors/TurnRestrictionEditor.mxml | 2 +- net/systemeD/potlatch2/mygpx/MyGpxDialog.mxml | 2 +- net/systemeD/potlatch2/save/OAuthPanel.mxml | 4 +- net/systemeD/potlatch2/save/SaveDialog.mxml | 2 +- net/systemeD/potlatch2/save/SaveManager.as | 4 +- .../potlatch2/utils/BikeShopLoader.as | 2 +- net/systemeD/potlatch2/utils/Importer.as | 2 +- net/systemeD/potlatch2/utils/TrackLoader.as | 2 +- 21 files changed, 201 insertions(+), 243 deletions(-) diff --git a/net/systemeD/halcyon/Map.as b/net/systemeD/halcyon/Map.as index ffc920a0..5024b23e 100644 --- a/net/systemeD/halcyon/Map.as +++ b/net/systemeD/halcyon/Map.as @@ -28,10 +28,8 @@ package net.systemeD.halcyon { /** don't zoom in past this */ public const MAXSCALE:uint=23; - /** sprite for ways and (POI/tagged) nodes in core layer */ - public var paint:MapPaint; - /** sprite for vector background layers */ - public var vectorbg:Sprite; + // Container for MapPaint objects + public var paintContainer:Sprite; /** map scale */ public var scale:uint=14; @@ -69,7 +67,7 @@ package net.systemeD.halcyon { /** How far the map can be dragged without actually triggering a pan. */ public const TOLERANCE:uint=7; // | - /** object containing HTML page parameters */ + /** object containing HTML page parameters: lat, lon, zoom, background_dim, background_sharpen, tileblocks */ public var initparams:Object; /** reference to backdrop sprite */ @@ -83,92 +81,44 @@ package net.systemeD.halcyon { /** show all objects, even if unstyled? */ public var showall:Boolean=true; - /** server connection */ - public var connection:Connection; - /** VectorLayer objects */ - public var vectorlayers:Object={}; - // ------------------------------------------------------------------------------------------ /** Map constructor function */ - public function Map(initparams:Object) { + public function Map() { + // Remove any existing sprites + while (numChildren) { removeChildAt(0); } + + // 900913 background + tileset=new TileSet(this); + addChild(tileset); - this.initparams=initparams; - connection = Connection.getConnection(initparams); - connection.addEventListener(Connection.NEW_WAY, newWayCreated); - connection.addEventListener(Connection.NEW_POI, newPOICreated); - connection.addEventListener(Connection.WAY_RENUMBERED, wayRenumbered); - connection.addEventListener(Connection.NODE_RENUMBERED, nodeRenumbered); - gotEnvironment(null); + // Container for all MapPaint objects + paintContainer = new Sprite(); + addChild(paintContainer); addEventListener(Event.ENTER_FRAME, everyFrame); scrollRect=new Rectangle(0,0,800,600); - } - public function gotEnvironment(r:Object):void { - var loader:Loader = new Loader(); - loader.contentLoaderInfo.addEventListener(Event.COMPLETE, gotFont); - loader.load(new URLRequest("FontLibrary.swf")); - } - - public function gotFont(r:Event):void { - var FontLibrary:Class = r.target.applicationDomain.getDefinition("FontLibrary") as Class; - Font.registerFont(FontLibrary.DejaVu); - - if (initparams['lat'] != null) { - // parameters sent from HTML - init(initparams['lat'], - initparams['lon'], - initparams['zoom']); - - } else { - // somewhere innocuous - init(53.09465,-2.56495,17); + if (ExternalInterface.available) { + ExternalInterface.addCallback("setPosition", function (lat:Number,lon:Number,zoom:uint):void { + updateCoordsFromLatLon(lat, lon); + changeScale(zoom); + }); } } // ------------------------------------------------------------------------------------------ /** Initialise map at a given lat/lon */ public function init(startlat:Number, startlon:Number, startscale:uint=0):void { - while (numChildren) { removeChildAt(0); } - - tileset=new TileSet(this); // 0 - 900913 background - if (initparams['tileblocks']) { // | option to block dodgy tile sources - tileset.blocks=initparams['tileblocks'];// | - } // | - addChild(tileset); // | - tileset.init(tileparams, false, - initparams['background_dim'] ==null ? true : initparams['background_dim'], - initparams['background_sharpen']==null ? false : initparams['background_sharpen']); - - vectorbg = new Sprite(); // 1 - vector background layers - addChild(vectorbg); // | - - paint = new MapPaint(this,-5,5); // 2 - core paint object - addChild(paint); // | - paint.isBackground=false; // | - - if (styleurl) { // if we've only just set up paint, then setStyle won't have created the RuleSet - paint.ruleset=new RuleSet(MINSCALE,MAXSCALE,redraw,redrawPOIs); - paint.ruleset.loadFromCSS(styleurl); - } if (startscale>0) { scale=startscale; this.dispatchEvent(new MapEvent(MapEvent.SCALE, {scale:scale})); } - scalefactor=MASTERSCALE/Math.pow(2,13-scale); baselon =startlon -(mapwidth /2)/scalefactor; basey =lat2latp(startlat)+(mapheight/2)/scalefactor; updateCoords(0,0); this.dispatchEvent(new Event(MapEvent.INITIALISED)); download(); - - if (ExternalInterface.available) { - ExternalInterface.addCallback("setPosition", function (lat:Number,lon:Number,zoom:uint):void { - updateCoordsFromLatLon(lat, lon); - changeScale(zoom); - }); - } } // ------------------------------------------------------------------------------------------ @@ -220,14 +170,14 @@ package net.systemeD.halcyon { private function moveMap(dx:Number,dy:Number):void { updateCoords(getX()+dx,getY()+dy); - updateEntityUIs(false, false); + updateAllEntityUIs(false, false); download(); } /** Recentre map at given lat/lon, updating the UI and downloading entities. */ public function moveMapFromLatLon(lat:Number,lon:Number):void { updateCoordsFromLatLon(lat,lon); - updateEntityUIs(false,false); + updateAllEntityUIs(false,false); download(); } @@ -278,80 +228,19 @@ package net.systemeD.halcyon { */ public function download():void { this.dispatchEvent(new MapEvent(MapEvent.DOWNLOAD, {minlon:edge_l, maxlon:edge_r, maxlat:edge_t, minlat:edge_b} )); - connection.loadBbox(edge_l,edge_r,edge_t,edge_b); - - // Do the same for vector layers - for each (var layer:VectorLayer in vectorlayers) { - layer.loadBbox(edge_l,edge_r,edge_t,edge_b); - } - } - - private function newWayCreated(event:EntityEvent):void { - var way:Way = event.entity as Way; - if (!way.loaded || !way.within(edge_l,edge_r,edge_t,edge_b)) { return; } - paint.createWayUI(way); - } - - private function newPOICreated(event:EntityEvent):void { - var node:Node = event.entity as Node; - if (!node.within(edge_l,edge_r,edge_t,edge_b)) { return; } - paint.createNodeUI(node); - } - - private function wayRenumbered(event:EntityRenumberedEvent):void { - var way:Way = event.entity as Way; - paint.renumberWayUI(way,event.oldID); - } - - private function nodeRenumbered(event:EntityRenumberedEvent):void { - var node:Node = event.entity as Node; - paint.renumberNodeUI(node,event.oldID); + for (var i:uint=0; i>>> REFACTOR: moved to MapPaint: + // public function setHighlight(entity:Entity, settings:Object):void { + // public function setHighlightOnNodes(way:Way, settings:Object):void { + // public function protectWay(way:Way):void { + // public function unprotectWay(way:Way):void { + // public function limitWayDrawing(way:Way,except:Number=NaN,only:Number=NaN):void { + // public function setPurgable(entities:Array, purgable:Boolean):void { - public function protectWay(way:Way):void { - if (paint.wayuis[way.id]) paint.wayuis[way.id].protectSprites(); - } - - public function unprotectWay(way:Way):void { - if (paint.wayuis[way.id]) paint.wayuis[way.id].unprotectSprites(); - } - - public function limitWayDrawing(way:Way,except:Number=NaN,only:Number=NaN):void { - if (!paint.wayuis[way.id]) return; - paint.wayuis[way.id].drawExcept=except; - paint.wayuis[way.id].drawOnly =only; - paint.wayuis[way.id].redraw(); - } - - /** Protect Entities and EntityUIs against purging. This prevents the currently selected items - from being purged even though they're off-screen. */ - - public function setPurgable(entities:Array, purgable:Boolean):void { - for each (var entity:Entity in entities) { - entity.locked=!purgable; - if ( entity is Way ) { - var way:Way=entity as Way; - if (paint.wayuis[way.id]) { paint.wayuis[way.id].purgable=purgable; } - for (var i:uint=0; i>>> REFACTOR: needs to do the equivalent of VectorLayer.blank() + } + } } - public function findVectorLayer(name:String):VectorLayer { - for each (var layer:VectorLayer in vectorlayers) { - if (layer.name==name) { return layer; } - } + public function findLayer(name:String):MapPaint { + for (var i:uint=0; iEach paint sprite has 4 child sprites (fill, casing, stroke, names). Each hit sprite has 2 child sprites (way hit tests, node hit tests).

*

Thus if layers range from -5 to +5, there will be 11 top level paint sprites followed by 11 top level hit sprites.

* - * @param map The map to be rendered. - * @param minlayer The lowest layer in that map that will be rendered. - * @param maxlayer The top layer in that map that will be rendered. + * @param map The Map this is attached to. (Required for finding out bounds and scale.) + * @param connection The Connection containing the data for this layer. + * @param minlayer The lowest OSM layer to display. + * @param maxlayer The highest OSM layer to display. * */ - public function MapPaint(map:Map,minlayer:int,maxlayer:int) { + public function MapPaint(map:Map,connection:Connection,minlayer:int,maxlayer:int) { mouseEnabled=false; this.map=map; + this.connection=connection; this.minlayer=minlayer; this.maxlayer=maxlayer; sublayerIndex[1]=0; var s:Sprite, l:int; + // Listen for changes on this Connection + connection.addEventListener(Connection.NEW_WAY, newWayCreatedListener); + connection.addEventListener(Connection.NEW_POI, newPOICreatedListener); + connection.addEventListener(Connection.WAY_RENUMBERED, wayRenumberedListener); + connection.addEventListener(Connection.NODE_RENUMBERED, nodeRenumberedListener); + // Add paint sprites for (l=minlayer; l<=maxlayer; l++) { // each layer (10 is +5, 0 is -5) s = getPaintSprite(); // | @@ -135,21 +147,18 @@ package net.systemeD.halcyon { } /** - * Update, and if necessary, create / remove UIs for the given objects. - * The object is effectively lists of objects split into inside/outside pairs, e.g. - * { waysInside: [], waysOutside: [] } where each is a array of entities either inside - * or outside this current view window. UIs for the entities on "inside" lists will be created if necessary. + * Update, and if necessary, create / remove UIs for the current viewport. * Flags control redrawing existing entities and removing UIs from entities no longer in view. * - * @param o The object containing all the relevant entites. * @param redraw If true, all UIs for entities on "inside" lists will be redrawn * @param remove If true, all UIs for entites on "outside" lists will be removed. The purgable flag on UIs can override this, for example for selected objects. * fixme? add smarter behaviour for way nodes - remove NodeUIs from way nodes off screen, create them for ones * that scroll onto screen (for highlights etc) */ - public function updateEntityUIs(o:Object, redraw:Boolean, remove:Boolean):void { + public function updateEntityUIs(redraw:Boolean, remove:Boolean):void { var way:Way, poi:Node, marker:Marker; + var o:Object = connection.getObjectsByBbox(map.edge_l,map.edge_r,map.edge_t,map.edge_b); for each (way in o.waysInside) { if (!wayuis[way.id]) { createWayUI(way); } @@ -326,6 +335,7 @@ package net.systemeD.halcyon { for each (var m:MarkerUI in markeruis) { m.invalidateStyleList(); m.redraw(); } } + // >>>> REFACTOR: remove this public function findSource():VectorLayer { var v:VectorLayer; for each (v in map.vectorlayers) { @@ -333,5 +343,79 @@ package net.systemeD.halcyon { } return null; } + + // ==================== Start of code moved from Map.as + + // Listeners for Connection events + + private function newWayCreatedListener(event:EntityEvent):void { + var way:Way = event.entity as Way; + if (!way.loaded || !way.within(map.edge_l, map.edge_r, map.edge_t, map.edge_b)) { return; } + createWayUI(way); + } + + private function newPOICreatedListener(event:EntityEvent):void { + var node:Node = event.entity as Node; + if (!node.within(map.edge_l, map.edge_r, map.edge_t, map.edge_b)) { return; } + createNodeUI(node); + } + + private function wayRenumberedListener(event:EntityRenumberedEvent):void { + var way:Way = event.entity as Way; + renumberWayUI(way,event.oldID); + } + + private function nodeRenumberedListener(event:EntityRenumberedEvent):void { + var node:Node = event.entity as Node; + renumberNodeUI(node,event.oldID); + } + + /** Visually mark an entity as highlighted. */ + public function setHighlight(entity:Entity, settings:Object):void { + if ( entity is Way && wayuis[entity.id] ) { wayuis[entity.id].setHighlight(settings); } + else if ( entity is Node && nodeuis[entity.id]) { nodeuis[entity.id].setHighlight(settings); } + } + + public function setHighlightOnNodes(way:Way, settings:Object):void { + if (wayuis[way.id]) wayuis[way.id].setHighlightOnNodes(settings); + } + + public function protectWay(way:Way):void { + if (wayuis[way.id]) wayuis[way.id].protectSprites(); + } + + public function unprotectWay(way:Way):void { + if (wayuis[way.id]) wayuis[way.id].unprotectSprites(); + } + + public function limitWayDrawing(way:Way,except:Number=NaN,only:Number=NaN):void { + if (!wayuis[way.id]) return; + wayuis[way.id].drawExcept=except; + wayuis[way.id].drawOnly =only; + wayuis[way.id].redraw(); + } + + /** Protect Entities and EntityUIs against purging. This prevents the currently selected items + from being purged even though they're off-screen. */ + + public function setPurgable(entities:Array, purgable:Boolean):void { + for each (var entity:Entity in entities) { + entity.locked=!purgable; + if ( entity is Way ) { + var way:Way=entity as Way; + if (wayuis[way.id]) { wayuis[way.id].purgable=purgable; } + for (var i:uint=0; ilayer.paint.updateEntityUIs(layer.getObjectsByBbox(...)...); + * e.g. layer.paint.updateEntityUIs(...); */ public function createNode(tags:Object,lat:Number,lon:Number):Node { var node:Node = new Node(negativeID, 0, tags, true, lat, lon); diff --git a/net/systemeD/halcyon/connection/AMFConnection.as b/net/systemeD/halcyon/connection/AMFConnection.as index 37d243d1..c47ec6d1 100644 --- a/net/systemeD/halcyon/connection/AMFConnection.as +++ b/net/systemeD/halcyon/connection/AMFConnection.as @@ -25,8 +25,9 @@ package net.systemeD.halcyon.connection { // ------------------------------------------------------------ // Constructor for new AMFConnection - public function AMFConnection() { + public function AMFConnection(name:String,api:String,policy:String,initparams:Object) { + super(name,api,policy,initparams); if (Connection.policyURL!='') Security.loadPolicyFile(Connection.policyURL); diff --git a/net/systemeD/halcyon/connection/Connection.as b/net/systemeD/halcyon/connection/Connection.as index 74514eb2..36933f9f 100644 --- a/net/systemeD/halcyon/connection/Connection.as +++ b/net/systemeD/halcyon/connection/Connection.as @@ -10,31 +10,19 @@ package net.systemeD.halcyon.connection { public class Connection extends EventDispatcher { - private static var connectionInstance:Connection = null; - - protected static var policyURL:String; - protected static var apiBaseURL:String; - protected static var params:Object; - - public static function getConnection(initparams:Object=null):Connection { - if ( connectionInstance == null ) { - - params = initparams == null ? new Object() : initparams; - policyURL = getParam("policy", "http://127.0.0.1:3000/api/crossdomain.xml"); - apiBaseURL = getParam("api", "http://127.0.0.1:3000/api/0.6/"); - var connectType:String = getParam("connection", "XML"); - - if ( connectType == "XML" ) - connectionInstance = new XMLConnection(); - else if ( connectType == "OSM" ) - connectionInstance = new OSMConnection(); - else - connectionInstance = new AMFConnection(); - } - return connectionInstance; - } + public var name:String; + protected var apiBaseURL:String; + protected var policyURL:String; + protected var params:Object; - public static function getParam(name:String, defaultValue:String):String { + public function Connection(cname:String,api:String,policy:String,initparams:Object={}) { + name=cname; + apiBaseURL=api; + policyURL=policy; + params=initparams; + } + + public function getParam(name:String, defaultValue:String):String { return params[name] == null ? defaultValue : params[name]; } @@ -42,13 +30,9 @@ package net.systemeD.halcyon.connection { return apiBaseURL; } - public static function get serverName():String { + public function get serverName():String { return getParam("serverName", "Localhost"); } - - public static function getConnectionInstance():Connection { - return connectionInstance; - } public function getEnvironment(responder:Responder):void {} diff --git a/net/systemeD/halcyon/connection/OSMConnection.as b/net/systemeD/halcyon/connection/OSMConnection.as index 18f12944..794e96db 100644 --- a/net/systemeD/halcyon/connection/OSMConnection.as +++ b/net/systemeD/halcyon/connection/OSMConnection.as @@ -44,8 +44,9 @@ package net.systemeD.halcyon.connection { private static const FILENAME:RegExp=/([\-\d\.]+)_([\-\d\.]+)_([\-\d\.]+)_([\-\d\.]+)\./i; - public function OSMConnection() { + public function OSMConnection(name:String,api:String,policy:String,initparams:Object) { + super(name,api,policy,initparams); if (Connection.policyURL!='') Security.loadPolicyFile(Connection.policyURL); diff --git a/net/systemeD/halcyon/connection/Trace.as b/net/systemeD/halcyon/connection/Trace.as index 5c4402fd..17bb5725 100644 --- a/net/systemeD/halcyon/connection/Trace.as +++ b/net/systemeD/halcyon/connection/Trace.as @@ -61,7 +61,7 @@ package net.systemeD.halcyon.connection { private function fetchFromServer():void { // todo - needs proper error handling - Connection.getConnectionInstance().fetchTrace(id, saveTraceData); + Connection.getConnection().fetchTrace(id, saveTraceData); dispatchEvent(new Event("loading_data")); } @@ -129,7 +129,7 @@ package net.systemeD.halcyon.connection { } default xml namespace = new Namespace(""); - layer.paint.updateEntityUIs(layer.getObjectsByBbox(map.edge_l,map.edge_r,map.edge_t,map.edge_b), true, false); + layer.paint.updateEntityUIs(true, false); } } } diff --git a/net/systemeD/halcyon/connection/UndoableEntityAction.as b/net/systemeD/halcyon/connection/UndoableEntityAction.as index b72c58b7..c8f5f32a 100644 --- a/net/systemeD/halcyon/connection/UndoableEntityAction.as +++ b/net/systemeD/halcyon/connection/UndoableEntityAction.as @@ -36,7 +36,7 @@ package net.systemeD.halcyon.connection { } if ( !connectionWasDirty ) { - Connection.getConnectionInstance().markDirty(); + Connection.getConnection().markDirty(); } } @@ -52,7 +52,7 @@ package net.systemeD.halcyon.connection { } if ( !connectionWasDirty ) { - Connection.getConnectionInstance().markClean(); + Connection.getConnection().markClean(); } } @@ -62,7 +62,7 @@ package net.systemeD.halcyon.connection { */ private function init():void { wasDirty = entity.isDirty; - connectionWasDirty = Connection.getConnectionInstance().isDirty; + connectionWasDirty = Connection.getConnection().isDirty; initialised = true; } diff --git a/net/systemeD/halcyon/connection/XMLConnection.as b/net/systemeD/halcyon/connection/XMLConnection.as index b77d59d3..3ce55059 100644 --- a/net/systemeD/halcyon/connection/XMLConnection.as +++ b/net/systemeD/halcyon/connection/XMLConnection.as @@ -16,8 +16,9 @@ package net.systemeD.halcyon.connection { */ public class XMLConnection extends XMLBaseConnection { - public function XMLConnection() { + public function XMLConnection(name:String,api:String,policy:String,initparams:Object) { + super(name,api,policy,initparams); if (Connection.policyURL!='') Security.loadPolicyFile(Connection.policyURL); var oauthPolicy:String = Connection.getParam("oauth_policy", ""); diff --git a/net/systemeD/potlatch2/BugLayer.as b/net/systemeD/potlatch2/BugLayer.as index 4a1c7ce1..df6681c6 100644 --- a/net/systemeD/potlatch2/BugLayer.as +++ b/net/systemeD/potlatch2/BugLayer.as @@ -97,7 +97,7 @@ package net.systemeD.potlatch2 { tags["status"] = status[int(feature.properties.status)]; var marker:Marker = createMarker(tags, lat, lon, Number(feature.id)); } - paint.updateEntityUIs(getObjectsByBbox(map.edge_l,map.edge_r,map.edge_t,map.edge_b), true, false); + paint.updateEntityUIs(true, false); } } diff --git a/net/systemeD/potlatch2/RelationLoaderPanel.mxml b/net/systemeD/potlatch2/RelationLoaderPanel.mxml index 53c9624e..39fb79fa 100644 --- a/net/systemeD/potlatch2/RelationLoaderPanel.mxml +++ b/net/systemeD/potlatch2/RelationLoaderPanel.mxml @@ -31,7 +31,7 @@ relid = Number(requestedID.text); PopUpManager.removePopUp(this); - var conn:Connection = Connection.getConnectionInstance(); + var conn:Connection = Connection.getConnection(); if (!relid) return; if (conn.getRelation(relid)) { relationLoaded(null); @@ -42,7 +42,7 @@ } private function relationLoaded(event:Event):void { - var conn:Connection = Connection.getConnectionInstance(); + var conn:Connection = Connection.getConnection(); var relation:Relation = conn.getRelation(relid); conn.removeEventListener(Connection.LOAD_COMPLETED, relationLoaded); if (!relation) return; diff --git a/net/systemeD/potlatch2/RelationSelectPanel.mxml b/net/systemeD/potlatch2/RelationSelectPanel.mxml index 6cd409ed..3c17eaff 100644 --- a/net/systemeD/potlatch2/RelationSelectPanel.mxml +++ b/net/systemeD/potlatch2/RelationSelectPanel.mxml @@ -32,7 +32,7 @@ PopUpManager.centerPopUp(this); var titles:Array = []; - conn = Connection.getConnectionInstance(); + conn = Connection.getConnection(); relationList = conn.getMatchingRelationIDs(t); if (relationList.length == 0) { warning.text = "No relations available"; diff --git a/net/systemeD/potlatch2/TagViewer.mxml b/net/systemeD/potlatch2/TagViewer.mxml index a6f961b2..582d9212 100644 --- a/net/systemeD/potlatch2/TagViewer.mxml +++ b/net/systemeD/potlatch2/TagViewer.mxml @@ -622,7 +622,7 @@ // but is at least robust for any kind of change. // Figuring out a better way is someone else's FIXME - var conn:Connection = Connection.getConnectionInstance(); + var conn:Connection = Connection.getConnection(); var rel:Relation = selectedEntity as Relation var action:CompositeUndoableAction = new CompositeUndoableAction("Rearrange relation members for "+rel); @@ -650,7 +650,7 @@ private function editRelation(id:Number):void { var panel:RelationEditorPanel = RelationEditorPanel( PopUpManager.createPopUp(Application(Application.application), RelationEditorPanel, true)); - panel.setRelation(Connection.getConnectionInstance().getRelation(id)); + panel.setRelation(Connection.getConnection().getRelation(id)); PopUpManager.centerPopUp(panel); } @@ -742,7 +742,7 @@ public function openEntityPage():void { if (selectedEntity != null && selectedEntity.id >= 0) { // This is slightly hard-coded, but not drastically. The ../s could be changed for string manipulation of the apiBase - var urlBase:String = Connection.getConnectionInstance().apiBase + '../../browse/' + var urlBase:String = Connection.getConnection().apiBase + '../../browse/' navigateToURL(new URLRequest(urlBase+selectedEntity.getType()+'/'+selectedEntity.id), "potlatch_browse"); } } @@ -752,7 +752,7 @@ } private function removeFromRelation(id:Number, index:int=-1):void { - var rel:Relation=Connection.getConnectionInstance().getRelation(id); + var rel:Relation=Connection.getConnection().getRelation(id); if (index>-1) { rel.removeMemberByIndex(index, MainUndoStack.getGlobalStack().addAction); } else if (selectedEntity is EntityCollection) { diff --git a/net/systemeD/potlatch2/mapfeatures/editors/TurnRestrictionEditor.mxml b/net/systemeD/potlatch2/mapfeatures/editors/TurnRestrictionEditor.mxml index c5ee5091..852c4b94 100644 --- a/net/systemeD/potlatch2/mapfeatures/editors/TurnRestrictionEditor.mxml +++ b/net/systemeD/potlatch2/mapfeatures/editors/TurnRestrictionEditor.mxml @@ -30,7 +30,7 @@ } public function addNewTurnRestriction():void { - var conn:Connection = Connection.getConnectionInstance(); + var conn:Connection = Connection.getConnection(); var relation:Relation = conn.createRelation( { type: 'restriction' }, [ new RelationMember(_entity, 'via') ], diff --git a/net/systemeD/potlatch2/mygpx/MyGpxDialog.mxml b/net/systemeD/potlatch2/mygpx/MyGpxDialog.mxml index 238815c7..3ca3c5c8 100644 --- a/net/systemeD/potlatch2/mygpx/MyGpxDialog.mxml +++ b/net/systemeD/potlatch2/mygpx/MyGpxDialog.mxml @@ -27,7 +27,7 @@ PopUpManager.centerPopUp(this); this.addEventListener(CloseEvent.CLOSE, myGpxDialog_close); - conn = Connection.getConnectionInstance(); + conn = Connection.getConnection(); map = Globals.vars.root; conn.addEventListener(Connection.TRACES_LOADED, onTracesLoaded); diff --git a/net/systemeD/potlatch2/save/OAuthPanel.mxml b/net/systemeD/potlatch2/save/OAuthPanel.mxml index bada911a..350df9be 100644 --- a/net/systemeD/potlatch2/save/OAuthPanel.mxml +++ b/net/systemeD/potlatch2/save/OAuthPanel.mxml @@ -105,7 +105,7 @@ } private function getRequestToken():void { - connection = Connection.getConnectionInstance(); + connection = Connection.getConnection(); var sig:IOAuthSignatureMethod = new OAuthSignatureMethod_HMAC_SHA1(); var consumer:OAuthConsumer = getConsumer(); @@ -192,7 +192,7 @@ PopUpManager.removePopUp(this); _accessToken = getResponseToken(URLLoader(event.target)); - Connection.getConnectionInstance().setAuthToken(_accessToken); + Connection.getConnection().setAuthToken(_accessToken); dispatchEvent(new Event(ACCESS_TOKEN_EVENT)); } diff --git a/net/systemeD/potlatch2/save/SaveDialog.mxml b/net/systemeD/potlatch2/save/SaveDialog.mxml index 9d121a26..ae3e60f6 100644 --- a/net/systemeD/potlatch2/save/SaveDialog.mxml +++ b/net/systemeD/potlatch2/save/SaveDialog.mxml @@ -83,7 +83,7 @@ import net.systemeD.halcyon.connection.*; import net.systemeD.halcyon.AttentionEvent; - private var conn:Connection = Connection.getConnectionInstance(); + private var conn:Connection = Connection.getConnection(); private var doSkip:Boolean = false; [Bindable] diff --git a/net/systemeD/potlatch2/save/SaveManager.as b/net/systemeD/potlatch2/save/SaveManager.as index 3e9cdaa8..e5cd2339 100644 --- a/net/systemeD/potlatch2/save/SaveManager.as +++ b/net/systemeD/potlatch2/save/SaveManager.as @@ -20,7 +20,7 @@ package net.systemeD.potlatch2.save { } private function save(callback:Function):void { - var conn:Connection = Connection.getConnectionInstance(); + var conn:Connection = Connection.getConnection(); if (conn.hasAccessToken()) { callback(); } else { @@ -51,7 +51,7 @@ package net.systemeD.potlatch2.save { PopUpManager.createPopUp(Application(Application.application), SaveDialog, true)); PopUpManager.centerPopUp(saveDialog); - if (Connection.getConnectionInstance().getActiveChangeset()) { + if (Connection.getConnection().getActiveChangeset()) { saveDialog.dontPrompt(); } } diff --git a/net/systemeD/potlatch2/utils/BikeShopLoader.as b/net/systemeD/potlatch2/utils/BikeShopLoader.as index 89e4d9f0..6be59e01 100644 --- a/net/systemeD/potlatch2/utils/BikeShopLoader.as +++ b/net/systemeD/potlatch2/utils/BikeShopLoader.as @@ -63,7 +63,7 @@ package net.systemeD.potlatch2.utils { var marker:Marker = layer.createMarker(tags, lat, lon); } default xml namespace = new Namespace(""); - layer.paint.updateEntityUIs(layer.getObjectsByBbox(map.edge_l,map.edge_r,map.edge_t,map.edge_b), true, false); + layer.paint.updateEntityUIs(true, false); } private function get layer():VectorLayer { diff --git a/net/systemeD/potlatch2/utils/Importer.as b/net/systemeD/potlatch2/utils/Importer.as index e4b61955..7e228423 100644 --- a/net/systemeD/potlatch2/utils/Importer.as +++ b/net/systemeD/potlatch2/utils/Importer.as @@ -50,7 +50,7 @@ package net.systemeD.potlatch2.utils { filesloaded++; if (filesloaded==filenames.length) { doImport(); - paint.updateEntityUIs(container.getObjectsByBbox(paint.map.edge_l, paint.map.edge_r, paint.map.edge_t, paint.map.edge_b), false, false); + paint.updateEntityUIs(false, false); if (callback!=null) { callback(true); } } } diff --git a/net/systemeD/potlatch2/utils/TrackLoader.as b/net/systemeD/potlatch2/utils/TrackLoader.as index d4bc6ece..812c5078 100644 --- a/net/systemeD/potlatch2/utils/TrackLoader.as +++ b/net/systemeD/potlatch2/utils/TrackLoader.as @@ -71,7 +71,7 @@ package net.systemeD.potlatch2.utils { } default xml namespace = new Namespace(""); - layer.paint.updateEntityUIs(layer.getObjectsByBbox(left,right,top,bottom), false, false); + layer.paint.updateEntityUIs(false, false); } private function get layer():VectorLayer { From a7d2cb95d6496c3ad91aef670b4190e11e6dd399 Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Sat, 21 May 2011 12:53:10 +0100 Subject: [PATCH 02/89] Refactoring in progress --- potlatch2.mxml | 69 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 25 deletions(-) diff --git a/potlatch2.mxml b/potlatch2.mxml index 368b7d38..94f364ce 100644 --- a/potlatch2.mxml +++ b/potlatch2.mxml @@ -7,7 +7,7 @@ horizontalScrollPolicy="off" verticalScrollPolicy="off" horizontalAlign="center" - addedToStage="initApp()" + addedToStage="startInit()" preloader="net.systemeD.potlatch2.Preloader"> @@ -125,14 +125,24 @@ include "version.as"; - private function initApp():void { - + private function startInit():void { /* For reasons that I don't yet understand, the en_US locale is the default and doesn't work at all. */ /* Change this to another locale (e.g. fr_FR) to see the differences. */ if (loaderInfo.parameters['locale']) { dispatchEvent(new LocaleEvent(LocaleEvent.LOAD_LOCALE,loaderInfo.parameters['locale'])); } + // Load font and don't do anything until that's done + var loader:Loader = new Loader(); + loader.contentLoaderInfo.addEventListener(Event.COMPLETE, continueInit); + loader.load(new URLRequest("FontLibrary.swf")); + } + + private function continueInit(r:Event):void { + // Set font + var FontLibrary:Class = r.target.applicationDomain.getDefinition("FontLibrary") as Class; + Font.registerFont(FontLibrary.DejaVu); + Globals.vars.map_area = map_area; Globals.vars.root = map_area.rawChildren; // set up global reference to root level var _root:IChildList = map_area.rawChildren; // convenient local shorthand @@ -165,17 +175,37 @@ // pass additional parameters to map var params:Object={}; var k:String; - for (k in this.loaderInfo.parameters) { - params[k]=this.loaderInfo.parameters[k]; - } - for (k in SharedObject.getLocal('user_state').data) { - params[k]=SharedObject.getLocal('user_state').data[k]; - } - params['tileblocks']=[new RegExp("google","i")]; // hard-coded block on Google tiles + for (k in this.loaderInfo.parameters) params[k]=this.loaderInfo.parameters[k]; + for (k in SharedObject.getLocal('user_state').data) params[k]=SharedObject.getLocal('user_state').data[k]; - // create map and Yahoo + // Create map theMap=new Map(params); + // Initialise 900913 background + // >>>> REFACTOR: something odd about accessing map.tileparams here... + map.tileset.blocks=[new RegExp("google","i")]; // hard-coded block on Google tiles + map.tileset.init(map.tileparams, false, + initparams['background_dim'] ==null ? true : initparams['background_dim'], + initparams['background_sharpen']==null ? false : initparams['background_sharpen']); + + // Add core data layer + // >>>> REFACTOR: shouldn't be hardcoded to XMLConnection + var conn:Connection = new XMLConnection("Main", initparams['api'], initparams['policy'], initparams); + conn.addEventListener(Connection.LOAD_STARTED, onDataStart); + conn.addEventListener(Connection.LOAD_COMPLETED, onDataComplete); + conn.addEventListener(Connection.SAVE_STARTED, onDataStart); + conn.addEventListener(Connection.SAVE_COMPLETED, onDataComplete); + conn.addEventListener(Connection.DATA_DIRTY, onDataDirty); + conn.addEventListener(Connection.DATA_CLEAN, onDataClean); + conn.addEventListener(MapEvent.ERROR, onMapError); + conn.addEventListener(AttentionEvent.ATTENTION, onAttention); + conn.addEventListener(AttentionEvent.ALERT, onAlert); + map.addLayer(conn,initparams['styleurl'],false); + + // Set start position of map + // >>>> REFACTOR: what happens if lat/lon/zoom not supplied? (Hurleston GPX case) + map.init(initparams['lat'], initparams['lon'], initparams['zoom']); + // Auto-load vector backgrounds from config // This could go spectacularly wrong if map.init completes before the event listener below is added theMap.addEventListener(MapEvent.INITIALISED, function(e:Event):void { VectorBackgrounds.instance().init(theMap); }); @@ -238,17 +268,6 @@ theController = new EditController(theMap, tagViewer, toolbox); theController.setActive(); - var conn:Connection = Connection.getConnectionInstance(); - conn.addEventListener(Connection.LOAD_STARTED, onDataStart); - conn.addEventListener(Connection.LOAD_COMPLETED, onDataComplete); - conn.addEventListener(Connection.SAVE_STARTED, onDataStart); - conn.addEventListener(Connection.SAVE_COMPLETED, onDataComplete); - conn.addEventListener(Connection.DATA_DIRTY, onDataDirty); - conn.addEventListener(Connection.DATA_CLEAN, onDataClean); - conn.addEventListener(MapEvent.ERROR, onMapError); - conn.addEventListener(AttentionEvent.ATTENTION, onAttention); - conn.addEventListener(AttentionEvent.ALERT, onAlert); - // set the access token from saved cookie var tokenObject:SharedObject = SharedObject.getLocal("access_token"); conn.setAccessToken(tokenObject.data["oauth_token"], tokenObject.data["oauth_token_secret"]); @@ -448,11 +467,11 @@ var createAction:CompositeUndoableAction = new CompositeUndoableAction("Create POI"); - var node:Node = Connection.getConnectionInstance().createNode({}, lat, lon, createAction.push); + var node:Node = Connection.getConnection().createNode({}, lat, lon, createAction.push); for each ( var tag:Object in tags ) { node.setTag(tag.k, tag.v, createAction.push); } - Connection.getConnectionInstance().registerPOI(node); + Connection.getConnection().registerPOI(node); MainUndoStack.getGlobalStack().addAction(createAction); theController.setState(new SelectedPOINode(node)); } @@ -463,7 +482,7 @@ } private function loadTrace(id:Number):void { - var conn:Connection = Connection.getConnectionInstance(); + var conn:Connection = Connection.getConnection(); conn.addEventListener(Connection.TRACES_LOADED, function (e:Event):void { for each (var trace:Trace in conn.getTraces()) { if (trace.id == id) { trace.addToMap(); } From b0cb5df99f9474d6b6c831c7e920a68a43b0a35c Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Sat, 21 May 2011 12:53:25 +0100 Subject: [PATCH 03/89] Refactoring notes --- REFACTOR.txt | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 REFACTOR.txt diff --git a/REFACTOR.txt b/REFACTOR.txt new file mode 100644 index 00000000..7746a868 --- /dev/null +++ b/REFACTOR.txt @@ -0,0 +1,31 @@ +== Potlatch 2 refactoring == + +Aims: +- to enable multiple Maps to be shown on-screen (e.g. for junction editor) +- to bring Connection and VectorLayer code together + +==== think what to do about controllers ==== + + +Map.as changes: +becomes a collection of MapPaint objects, all with the same lat/long/scale +(plus a backdrop sprite and a background imagery sprite) +√ move listeners to Connection to MapPaint (e.g. new way created in the Connection - MapPaint should know about it, not Map) +- refactor tileset/setbackground stuff? + +MapPaint.as changes: +- gains a reference to a Connection - i.e. the source data for this layer +- needs an 'interactive' flag +√ UpdateEntityUIs no longer needs a set of entities passing to it - it can read directly from the Connection +- consider whether it's better to have a backreference to Map or for Map to update edges/lat/long/scale etc. +- wayuis, nodeuis etc. should ideally be private +- removeLayer should blank + +VectorLayer.as changes: +- move into Connection + +Global changes: +- remove all references to getConnection etc. - there can now be more than one Connection +- remove all back-references to Map except where necessary for lat/long/scale +- Controllers are full of references to controller.map and to controller.connection +- move AttentionEvent stuff From ddaf955c530189094e76fb857fc14ae05c195ccb Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Sat, 21 May 2011 13:53:46 +0100 Subject: [PATCH 04/89] Work in progress --- REFACTOR.txt | 1 + net/systemeD/halcyon/Elastic.as | 8 +++-- net/systemeD/halcyon/Map.as | 31 ++++++++++--------- .../potlatch2/controller/ControllerState.as | 8 +++-- .../potlatch2/controller/DragSelection.as | 4 +-- .../potlatch2/controller/DragWayNode.as | 20 ++++++------ net/systemeD/potlatch2/controller/DrawWay.as | 28 ++++++++--------- .../potlatch2/controller/SelectedMarker.as | 8 ++--- .../potlatch2/controller/SelectedMultiple.as | 10 +++--- .../potlatch2/controller/SelectedPOINode.as | 8 ++--- .../controller/SelectedParallelWay.as | 2 +- .../potlatch2/controller/SelectedWay.as | 18 +++++------ .../potlatch2/controller/SelectedWayNode.as | 28 ++++++++--------- 13 files changed, 90 insertions(+), 84 deletions(-) diff --git a/REFACTOR.txt b/REFACTOR.txt index 7746a868..5334bde0 100644 --- a/REFACTOR.txt +++ b/REFACTOR.txt @@ -25,6 +25,7 @@ VectorLayer.as changes: - move into Connection Global changes: +- move lots of connection.map to connection.map.editableLayer - remove all references to getConnection etc. - there can now be more than one Connection - remove all back-references to Map except where necessary for lat/long/scale - Controllers are full of references to controller.map and to controller.connection diff --git a/net/systemeD/halcyon/Elastic.as b/net/systemeD/halcyon/Elastic.as index f0daa9d4..fdb521e3 100644 --- a/net/systemeD/halcyon/Elastic.as +++ b/net/systemeD/halcyon/Elastic.as @@ -17,14 +17,16 @@ package net.systemeD.halcyon { public var map:Map; // reference to parent map public var sprites:Array=new Array(); // instances in display list + private var editableLayer:MapPaint; private var _start:Point; private var _end:Point; /** Create and draw the elastic. */ public function Elastic(map:Map, start:Point, end:Point) { this.map = map; - this._start = start; - this._end = end; + editableLayer = map.editableLayer; + _start = start; + _end = end; redraw(); } @@ -62,7 +64,7 @@ package net.systemeD.halcyon { var stroke:Shape = new Shape(); stroke.graphics.lineStyle(1, 0xff0000, 1, false, "normal", CapsStyle.ROUND, JointStyle.ROUND); - var l:DisplayObject=map.paint.getPaintSpriteAt(map.paint.maxlayer); + var l:DisplayObject=editableLayer.getPaintSpriteAt(editableLayer.maxlayer); var o:DisplayObject=Sprite(l).getChildAt(3); // names layer (o as Sprite).addChild(stroke); sprites.push(stroke); diff --git a/net/systemeD/halcyon/Map.as b/net/systemeD/halcyon/Map.as index 5024b23e..d4001170 100644 --- a/net/systemeD/halcyon/Map.as +++ b/net/systemeD/halcyon/Map.as @@ -186,7 +186,6 @@ package net.systemeD.halcyon { if (lat> edge_t || lat < edge_b || lon < edge_l || lon > edge_r) { moveMapFromLatLon(lat, lon); } - } // Co-ordinate conversion functions @@ -228,20 +227,10 @@ package net.systemeD.halcyon { */ public function download():void { this.dispatchEvent(new MapEvent(MapEvent.DOWNLOAD, {minlon:edge_l, maxlon:edge_r, maxlat:edge_t, minlat:edge_b} )); - for (var i:uint=0; i>>> REFACTOR: moved to MapPaint: - // public function setHighlight(entity:Entity, settings:Object):void { - // public function setHighlightOnNodes(way:Way, settings:Object):void { - // public function protectWay(way:Way):void { - // public function unprotectWay(way:Way):void { - // public function limitWayDrawing(way:Way,except:Number=NaN,only:Number=NaN):void { - // public function setPurgable(entities:Array, purgable:Boolean):void { - - // Handle mouse events on ways/nodes private var mapController:MapController = null; @@ -270,11 +259,10 @@ package net.systemeD.halcyon { } public function removeLayerByName(name:String):void { - for (var i:uint=0; i>>> REFACTOR: needs to do the equivalent of VectorLayer.blank() - } } } @@ -283,6 +271,19 @@ package net.systemeD.halcyon { if (paintContainer.getChildAt(i).connection.name==name) return paintContainer.getChildAt(i); return null; } + + /* Find which layer is editable */ + public function get editableLayer():MapPaint { + var editableLayer:MapPaint; + for (var i:uint=0; i 0) { map.zoomIn(); diff --git a/net/systemeD/potlatch2/controller/DragSelection.as b/net/systemeD/potlatch2/controller/DragSelection.as index e17299a9..739180e5 100644 --- a/net/systemeD/potlatch2/controller/DragSelection.as +++ b/net/systemeD/potlatch2/controller/DragSelection.as @@ -95,14 +95,14 @@ package net.systemeD.potlatch2.controller { /** Highlight the dragged selection. */ override public function enterState():void { for each (var entity:Entity in selection) { - controller.map.setHighlight(entity, { selected: true }); + editableLayer.setHighlight(entity, { selected: true }); } } /** Un-highlight the dragged selection. */ override public function exitState(newState:ControllerState):void { for each (var entity:Entity in selection) { - controller.map.setHighlight(entity, { selected: false }); + editableLayer.setHighlight(entity, { selected: false }); } } /** "DragSelection" */ diff --git a/net/systemeD/potlatch2/controller/DragWayNode.as b/net/systemeD/potlatch2/controller/DragWayNode.as index 83421541..f53a7172 100644 --- a/net/systemeD/potlatch2/controller/DragWayNode.as +++ b/net/systemeD/potlatch2/controller/DragWayNode.as @@ -35,7 +35,7 @@ package net.systemeD.potlatch2.controller { private function addNode(selectedWay:Way,event:MouseEvent):int { // find which other ways are under the mouse var ways:Array=[]; var w:Way; - for each (var wayui:WayUI in controller.map.paint.wayuis) { + for each (var wayui:WayUI in editableLayer.wayuis) { w=wayui.hitTest(event.stageX, event.stageY); if (w && w!=selectedWay) { ways.push(w); } } @@ -115,17 +115,17 @@ package net.systemeD.potlatch2.controller { originalLat = draggingNode.lat; originalLon = draggingNode.lon; - controller.map.setHighlightOnNodes(parentWay, { selectedway: true } ); - controller.map.limitWayDrawing(parentWay, draggingIndex); - controller.map.setHighlight(draggingNode, { selected: true } ); - controller.map.protectWay(parentWay); - controller.map.limitWayDrawing(parentWay, NaN, draggingIndex); + editableLayer.setHighlightOnNodes(parentWay, { selectedway: true } ); + editableLayer.limitWayDrawing(parentWay, draggingIndex); + editableLayer.setHighlight(draggingNode, { selected: true } ); + editableLayer.protectWay(parentWay); + editableLayer.limitWayDrawing(parentWay, NaN, draggingIndex); } override public function exitState(newState:ControllerState):void { - controller.map.unprotectWay(parentWay); - controller.map.limitWayDrawing(parentWay); - controller.map.setHighlightOnNodes(parentWay, { selectedway: false } ); - controller.map.setHighlight(draggingNode, { selected: false } ); + editableLayer.unprotectWay(parentWay); + editableLayer.limitWayDrawing(parentWay); + editableLayer.setHighlightOnNodes(parentWay, { selectedway: false } ); + editableLayer.setHighlight(draggingNode, { selected: false } ); } override public function toString():String { return "DragWayNode"; diff --git a/net/systemeD/potlatch2/controller/DrawWay.as b/net/systemeD/potlatch2/controller/DrawWay.as index 71d98721..21aef75f 100644 --- a/net/systemeD/potlatch2/controller/DrawWay.as +++ b/net/systemeD/potlatch2/controller/DrawWay.as @@ -43,8 +43,8 @@ package net.systemeD.potlatch2.controller { controller.map.mouseUpHandler(); // in case you're still in the drag-tolerance zone, and mouse up over something. if ( entity == null || isBackground ) { // didn't hit anything: extend the way by one node. node = createAndAddNode(event, MainUndoStack.getGlobalStack().addAction); - controller.map.setHighlight(node, { selectedway: true }); - controller.map.setPurgable([node], false); + editableLayer.setHighlight(node, { selectedway: true }); + editableLayer.setPurgable([node], false); resetElastic(node); lastClick=node; controller.updateSelectionUIWithoutTagChange(); @@ -75,9 +75,9 @@ package net.systemeD.potlatch2.controller { // hit a node, add it to this way and carry on appendNode(entity as Node, MainUndoStack.getGlobalStack().addAction); if (focus is Way) { - controller.map.setHighlightOnNodes(focus as Way, { hoverway: false }); + editableLayer.setHighlightOnNodes(focus as Way, { hoverway: false }); } - controller.map.setHighlight(entity, { selectedway: true }); + editableLayer.setHighlight(entity, { selectedway: true }); resetElastic(entity as Node); lastClick=entity; if (Way(firstSelected).getNode(0)==Way(firstSelected).getLastNode()) { @@ -101,13 +101,13 @@ package net.systemeD.potlatch2.controller { node = createAndAddNode(event, jnct.push); Way(entity).insertNodeAtClosestPosition(node, true, jnct.push); MainUndoStack.getGlobalStack().addAction(jnct); - controller.map.setHighlight(node, { selectedway: true }); - controller.map.setPurgable([node], false); + editableLayer.setHighlight(node, { selectedway: true }); + editableLayer.setPurgable([node], false); } resetElastic(node); lastClick=node; - controller.map.setHighlightOnNodes(entity as Way, { hoverway: false }); - controller.map.setHighlightOnNodes(firstSelected as Way, { selectedway: true }); + editableLayer.setHighlightOnNodes(entity as Way, { hoverway: false }); + editableLayer.setHighlightOnNodes(firstSelected as Way, { selectedway: true }); } lastClickTime=new Date(); } else if ( event.type == MouseEvent.MOUSE_MOVE && elastic ) { @@ -121,7 +121,7 @@ package net.systemeD.potlatch2.controller { if (focus is Way && focus!=firstSelected) { // floating over another way, highlight its nodes hoverEntity=focus; - controller.map.setHighlightOnNodes(focus as Way, { hoverway: true }); + editableLayer.setHighlightOnNodes(focus as Way, { hoverway: true }); } // set cursor depending on whether we're floating over the start of this way, // another random node, a possible junction... @@ -136,7 +136,7 @@ package net.systemeD.potlatch2.controller { } else if ( event.type == MouseEvent.MOUSE_OUT && !isBackground ) { if (focus is Way && entity!=firstSelected) { hoverEntity=null; - controller.map.setHighlightOnNodes(focus as Way, { hoverway: false }); + editableLayer.setHighlightOnNodes(focus as Way, { hoverway: false }); // ** We could do with an optional way of calling WayUI.redraw to only do the nodes, which would be a // useful optimisation. } @@ -194,7 +194,7 @@ package net.systemeD.potlatch2.controller { protected function stopDrawing():ControllerState { if ( hoverEntity ) { - controller.map.setHighlightOnNodes(hoverEntity as Way, { hoverway: false }); + editableLayer.setHighlightOnNodes(hoverEntity as Way, { hoverway: false }); hoverEntity = null; } @@ -243,7 +243,7 @@ package net.systemeD.potlatch2.controller { } // Only actually delete the node if it has no other tags, and is not part of other ways (or part of this way twice) if (node.numParentWays==1 && Way(firstSelected).hasOnceOnly(node) && !node.hasInterestingTags()) { - controller.map.setPurgable([node], true); + editableLayer.setPurgable([node], true); controller.connection.unregisterPOI(node); node.remove(undo.push); } @@ -260,7 +260,7 @@ package net.systemeD.potlatch2.controller { performAction(undo); if(!node.isDeleted()) { // i.e. was junction with another way (or is now POI) - controller.map.setHighlight(node, {selectedway: false}); + editableLayer.setHighlight(node, {selectedway: false}); } return state; } @@ -309,7 +309,7 @@ package net.systemeD.potlatch2.controller { appendNode(nextNode as Node, MainUndoStack.getGlobalStack().addAction); resetElastic(nextNode as Node); lastClick=nextNode; - controller.map.setHighlight(nextNode, { selectedway: true }); + editableLayer.setHighlight(nextNode, { selectedway: true }); // recentre the map if the new lat/lon is offscreen controller.map.scrollIfNeeded(nextNode.lat,nextNode.lon); diff --git a/net/systemeD/potlatch2/controller/SelectedMarker.as b/net/systemeD/potlatch2/controller/SelectedMarker.as index a6164ee8..34e46e30 100644 --- a/net/systemeD/potlatch2/controller/SelectedMarker.as +++ b/net/systemeD/potlatch2/controller/SelectedMarker.as @@ -19,7 +19,7 @@ package net.systemeD.potlatch2.controller { return; clearSelection(this); - controller.map.setHighlight(marker, { selected: true }); + editableLayer.setHighlight(marker, { selected: true }); selection = [marker]; controller.updateSelectionUI(layer); initMarker = marker; @@ -27,7 +27,7 @@ package net.systemeD.potlatch2.controller { protected function clearSelection(newState:ControllerState):void { if ( selectCount ) { - controller.map.setHighlight(firstSelected, { selected: false }); + editableLayer.setHighlight(firstSelected, { selected: false }); selection = []; if (!newState.isSelectionState()) { controller.updateSelectionUI(); } } @@ -53,11 +53,11 @@ package net.systemeD.potlatch2.controller { override public function enterState():void { selectMarker(initMarker); - controller.map.setPurgable(selection,false); + editableLayer.setPurgable(selection,false); } override public function exitState(newState:ControllerState):void { - controller.map.setPurgable(selection,true); + editableLayer.setPurgable(selection,true); clearSelection(newState); } diff --git a/net/systemeD/potlatch2/controller/SelectedMultiple.as b/net/systemeD/potlatch2/controller/SelectedMultiple.as index b7c4f0bb..26015771 100644 --- a/net/systemeD/potlatch2/controller/SelectedMultiple.as +++ b/net/systemeD/potlatch2/controller/SelectedMultiple.as @@ -19,7 +19,7 @@ package net.systemeD.potlatch2.controller { if ( event.type == MouseEvent.MOUSE_DOWN && entity && event.ctrlKey ) { // modify selection - controller.map.setHighlight(entity, { selected: toggleSelection(entity) }); + editableLayer.setHighlight(entity, { selected: toggleSelection(entity) }); controller.updateSelectionUI(); if (selectCount>1) { return this; } @@ -110,16 +110,16 @@ package net.systemeD.potlatch2.controller { override public function enterState():void { selection=initSelection.concat(); for each (var entity:Entity in selection) { - controller.map.setHighlight(entity, { selected: true, hover: false }); + editableLayer.setHighlight(entity, { selected: true, hover: false }); } controller.updateSelectionUI(); - controller.map.setPurgable(selection,false); + editableLayer.setPurgable(selection,false); } override public function exitState(newState:ControllerState):void { - controller.map.setPurgable(selection,true); + editableLayer.setPurgable(selection,true); for each (var entity:Entity in selection) { - controller.map.setHighlight(entity, { selected: false, hover: false }); + editableLayer.setHighlight(entity, { selected: false, hover: false }); } selection = []; if (!newState.isSelectionState()) { controller.updateSelectionUI(); } diff --git a/net/systemeD/potlatch2/controller/SelectedPOINode.as b/net/systemeD/potlatch2/controller/SelectedPOINode.as index 178f2b00..278759db 100644 --- a/net/systemeD/potlatch2/controller/SelectedPOINode.as +++ b/net/systemeD/potlatch2/controller/SelectedPOINode.as @@ -16,7 +16,7 @@ package net.systemeD.potlatch2.controller { return; clearSelection(this); - controller.map.setHighlight(node, { selected: true }); + editableLayer.setHighlight(node, { selected: true }); selection = [node]; controller.updateSelectionUI(); initNode = node; @@ -24,7 +24,7 @@ package net.systemeD.potlatch2.controller { protected function clearSelection(newState:ControllerState):void { if ( selectCount ) { - controller.map.setHighlight(firstSelected, { selected: false }); + editableLayer.setHighlight(firstSelected, { selected: false }); selection = []; if (!newState.isSelectionState()) { controller.updateSelectionUI(); } } @@ -60,13 +60,13 @@ package net.systemeD.potlatch2.controller { override public function enterState():void { selectNode(initNode); - controller.map.setPurgable(selection,false); + editableLayer.setPurgable(selection,false); } override public function exitState(newState:ControllerState):void { if(firstSelected.hasTags()) { controller.clipboards['node']=firstSelected.getTagsCopy(); } - controller.map.setPurgable(selection,true); + editableLayer.setPurgable(selection,true); clearSelection(newState); } diff --git a/net/systemeD/potlatch2/controller/SelectedParallelWay.as b/net/systemeD/potlatch2/controller/SelectedParallelWay.as index 94ff8898..1324af13 100644 --- a/net/systemeD/potlatch2/controller/SelectedParallelWay.as +++ b/net/systemeD/potlatch2/controller/SelectedParallelWay.as @@ -76,7 +76,7 @@ package net.systemeD.potlatch2.controller { /** Creates the WayUI for the parallel way. */ override public function enterState():void { selection=[parallelise.parallelWay]; - controller.map.paint.createWayUI(firstSelected as Way); + editableLayer.createWayUI(firstSelected as Way); startlon =controller.map.coord2lon(controller.map.mouseX); startlatp=controller.map.coord2latp(controller.map.mouseY); } diff --git a/net/systemeD/potlatch2/controller/SelectedWay.as b/net/systemeD/potlatch2/controller/SelectedWay.as index b3aadd88..50f02ede 100644 --- a/net/systemeD/potlatch2/controller/SelectedWay.as +++ b/net/systemeD/potlatch2/controller/SelectedWay.as @@ -34,8 +34,8 @@ package net.systemeD.potlatch2.controller { /** Tidy up UI as we transition to a new state without the current selection. */ protected function clearSelection(newState:ControllerState):void { if ( selectCount ) { - controller.map.setHighlight(firstSelected, { selected: false, hover: false }); - controller.map.setHighlightOnNodes(firstSelected as Way, { selectedway: false }); + editableLayer.setHighlight(firstSelected, { selected: false, hover: false }); + editableLayer.setHighlightOnNodes(firstSelected as Way, { selectedway: false }); selection = []; if (!newState.isSelectionState()) { controller.updateSelectionUI(); } } @@ -70,7 +70,7 @@ package net.systemeD.potlatch2.controller { case 81: /* Q */ Quadrilateralise.quadrilateralise(firstSelected as Way, MainUndoStack.getGlobalStack().addAction); return this; case 82: /* R */ repeatTags(firstSelected); return this; case 86: /* V */ Way(firstSelected).reverseNodes(MainUndoStack.getGlobalStack().addAction); return this; - case 89: /* Y */ Simplify.simplify(firstSelected as Way, controller.map, true); return this; + case 89: /* Y */ Simplify.simplify(firstSelected as Way, controller.map, true); return this; case 191: /* / */ return cycleWays(); case Keyboard.BACKSPACE: case Keyboard.DELETE: if (event.shiftKey) { return deleteWay(); } break; @@ -87,7 +87,7 @@ package net.systemeD.potlatch2.controller { if (!wayList) { wayList=[initWay]; - for each (var wayui:WayUI in controller.map.paint.wayuis) { + for each (var wayui:WayUI in editableLayer.wayuis) { var w:Way=wayui.hitTest(clicked.x, clicked.y); if (w && w!=initWay) { wayList.push(w); } } @@ -100,7 +100,7 @@ package net.systemeD.potlatch2.controller { /** Perform deletion of currently selected way. */ public function deleteWay():ControllerState { - controller.map.setHighlightOnNodes(firstSelected as Way, {selectedway: false}); + editableLayer.setHighlightOnNodes(firstSelected as Way, {selectedway: false}); selectedWay.remove(MainUndoStack.getGlobalStack().addAction); return new NoSelection(); } @@ -109,13 +109,13 @@ package net.systemeD.potlatch2.controller { override public function enterState():void { if (firstSelected!=initWay) { clearSelection(this); - controller.map.setHighlight(initWay, { selected: true, hover: false }); - controller.map.setHighlightOnNodes(initWay, { selectedway: true }); + editableLayer.setHighlight(initWay, { selected: true, hover: false }); + editableLayer.setHighlightOnNodes(initWay, { selectedway: true }); selection = [initWay]; controller.updateSelectionUI(); initWay.addEventListener(Connection.WAY_REORDERED, updateSelectionUI, false, 0, true); } - controller.map.setPurgable(selection,false); + editableLayer.setPurgable(selection,false); } /** Officially leave the state, remembering the current way's tags for future repeats. */ // TODO: tweak this so that repeat tags aren't remembered if you only select a way in order to branch off it. (a la PL1) @@ -123,7 +123,7 @@ package net.systemeD.potlatch2.controller { if (firstSelected.hasTags()) { controller.clipboards['way']=firstSelected.getTagsCopy(); } - controller.map.setPurgable(selection,true); + editableLayer.setPurgable(selection,true); firstSelected.removeEventListener(Connection.WAY_REORDERED, updateSelectionUI); clearSelection(newState); } diff --git a/net/systemeD/potlatch2/controller/SelectedWayNode.as b/net/systemeD/potlatch2/controller/SelectedWayNode.as index 24e7d22b..5bb16b00 100644 --- a/net/systemeD/potlatch2/controller/SelectedWayNode.as +++ b/net/systemeD/potlatch2/controller/SelectedWayNode.as @@ -25,9 +25,9 @@ package net.systemeD.potlatch2.controller { return; clearSelection(this); - controller.map.setHighlight(way, { hover: false }); - controller.map.setHighlight(node, { selected: true }); - controller.map.setHighlightOnNodes(way, { selectedway: true }); + editableLayer.setHighlight(way, { hover: false }); + editableLayer.setHighlight(node, { selected: true }); + editableLayer.setHighlightOnNodes(way, { selectedway: true }); selection = [node]; parentWay = way; controller.updateSelectionUI(); selectedIndex = index; initIndex = index; @@ -35,9 +35,9 @@ package net.systemeD.potlatch2.controller { protected function clearSelection(newState:ControllerState):void { if ( selectCount ) { - controller.map.setHighlight(parentWay, { selected: false }); - controller.map.setHighlight(firstSelected, { selected: false }); - controller.map.setHighlightOnNodes(parentWay, { selectedway: false }); + editableLayer.setHighlight(parentWay, { selected: false }); + editableLayer.setHighlight(firstSelected, { selected: false }); + editableLayer.setHighlightOnNodes(parentWay, { selectedway: false }); selection = []; if (!newState.isSelectionState()) { controller.updateSelectionUI(); } } @@ -106,13 +106,13 @@ package net.systemeD.potlatch2.controller { override public function enterState():void { selectNode(parentWay,initIndex); - controller.map.setPurgable(selection,false); + editableLayer.setPurgable(selection,false); } override public function exitState(newState:ControllerState):void { if (firstSelected.hasTags()) { controller.clipboards['node']=firstSelected.getTagsCopy(); } - controller.map.setPurgable(selection,true); + editableLayer.setPurgable(selection,true); clearSelection(newState); } @@ -146,8 +146,8 @@ package net.systemeD.potlatch2.controller { if (parentWay.getLastNode() == n) { return this; } } - controller.map.setHighlightOnNodes(parentWay, { selectedway: false } ); - controller.map.setPurgable([parentWay],true); + editableLayer.setHighlightOnNodes(parentWay, { selectedway: false } ); + editableLayer.setPurgable([parentWay],true); MainUndoStack.getGlobalStack().addAction(new SplitWayAction(parentWay, ni)); return new SelectedWay(parentWay); @@ -162,7 +162,7 @@ package net.systemeD.potlatch2.controller { } public function deleteNode():ControllerState { - controller.map.setPurgable(selection,true); + editableLayer.setPurgable(selection,true); firstSelected.remove(MainUndoStack.getGlobalStack().addAction); return new SelectedWay(parentWay); } @@ -175,8 +175,8 @@ package net.systemeD.potlatch2.controller { /** Attempt to either merge the currently selected node with another very nearby node, or failing that, * attach it mid-way along a very nearby way. */ public function join():ControllerState { - var p:Point = new Point(controller.map.lon2coord(Node(firstSelected).lon), - controller.map.latp2coord(Node(firstSelected).latp)); + var p:Point = new Point(controller.map.lon2coord(Node(firstSelected).lon), + controller.map.latp2coord(Node(firstSelected).latp)); var q:Point = map.localToGlobal(p); // First, look for POI nodes in 20x20 pixel box around the current node @@ -193,7 +193,7 @@ package net.systemeD.potlatch2.controller { } var ways:Array=[]; var w:Way; - for each (var wayui:WayUI in controller.map.paint.wayuis) { + for each (var wayui:WayUI in editableLayer.wayuis) { w=wayui.hitTest(q.x, q.y); if (w && w!=selectedWay) { // hit a way, now let's see if we hit a specific node From dde8aae3a44f981b6b4a5b0a1e48992982673791 Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Sat, 21 May 2011 14:57:29 +0100 Subject: [PATCH 05/89] Give Entity a back-reference to the Connection it belongs to. (If we figure out another smart way of doing this we can replace the Entity getter.) --- net/systemeD/halcyon/Elastic.as | 2 +- net/systemeD/halcyon/VectorLayer.as | 8 ++++---- net/systemeD/halcyon/connection/AMFConnection.as | 14 +++++++------- net/systemeD/halcyon/connection/Changeset.as | 4 ++-- net/systemeD/halcyon/connection/Connection.as | 9 +++++---- net/systemeD/halcyon/connection/Entity.as | 9 ++++++++- .../halcyon/connection/EntityCollection.as | 5 ++++- net/systemeD/halcyon/connection/Marker.as | 4 ++-- net/systemeD/halcyon/connection/Node.as | 4 ++-- net/systemeD/halcyon/connection/Relation.as | 4 ++-- net/systemeD/halcyon/connection/Way.as | 4 ++-- .../halcyon/connection/XMLBaseConnection.as | 13 +++++++------ net/systemeD/halcyon/connection/XMLConnection.as | 2 +- 13 files changed, 47 insertions(+), 35 deletions(-) diff --git a/net/systemeD/halcyon/Elastic.as b/net/systemeD/halcyon/Elastic.as index fdb521e3..7daf83cd 100644 --- a/net/systemeD/halcyon/Elastic.as +++ b/net/systemeD/halcyon/Elastic.as @@ -25,7 +25,7 @@ package net.systemeD.halcyon { public function Elastic(map:Map, start:Point, end:Point) { this.map = map; editableLayer = map.editableLayer; - _start = start; + _start = start; _end = end; redraw(); } diff --git a/net/systemeD/halcyon/VectorLayer.as b/net/systemeD/halcyon/VectorLayer.as index dfb64490..644b39f4 100644 --- a/net/systemeD/halcyon/VectorLayer.as +++ b/net/systemeD/halcyon/VectorLayer.as @@ -52,7 +52,7 @@ package net.systemeD.halcyon { * e.g. layer.paint.updateEntityUIs(...); */ public function createNode(tags:Object,lat:Number,lon:Number):Node { - var node:Node = new Node(negativeID, 0, tags, true, lat, lon); + var node:Node = new Node(this, negativeID, 0, tags, true, lat, lon); nodes[negativeID]=node; negativeID--; return node; } @@ -62,7 +62,7 @@ package net.systemeD.halcyon { * @param nodes An array of Node objects */ public function createWay(tags:Object,nodes:Array):Way { - var way:Way = new Way(negativeID, 0, tags, true, nodes.concat()); + var way:Way = new Way(this, negativeID, 0, tags, true, nodes.concat()); ways[negativeID]=way; negativeID--; return way; } @@ -72,7 +72,7 @@ package net.systemeD.halcyon { * @param members An array of RelationMember objects */ public function createRelation(tags:Object,members:Array):Relation { - var relation:Relation = new Relation(negativeID, 0, tags, true, members.concat()); + var relation:Relation = new Relation(this, negativeID, 0, tags, true, members.concat()); relations[negativeID]=relation; negativeID--; return relation; } @@ -93,7 +93,7 @@ package net.systemeD.halcyon { } var marker:Marker = markers[id]; if (marker == null) { - marker = new Marker(id, 0, tags, true, lat, lon); + marker = new Marker(this, id, 0, tags, true, lat, lon); markers[id]=marker; } return marker; diff --git a/net/systemeD/halcyon/connection/AMFConnection.as b/net/systemeD/halcyon/connection/AMFConnection.as index c47ec6d1..3a21b004 100644 --- a/net/systemeD/halcyon/connection/AMFConnection.as +++ b/net/systemeD/halcyon/connection/AMFConnection.as @@ -107,7 +107,7 @@ package net.systemeD.halcyon.connection { var lat:Number = Number(p[2]); var lon:Number = Number(p[1]); var tags:Object = p[3]; - node = new Node(id, version, tags, true, lat, lon); + node = new Node(this, id, version, tags, true, lat, lon); setNode(node,true); } registerPOI(node); @@ -152,7 +152,7 @@ package net.systemeD.halcyon.connection { var node:Node = getNode(nodeID); if ( node == null ) { var nodeTags:Object = p[3]; - node = new Node(nodeID, nodeVersion, nodeTags, true, lat, lon); + node = new Node(this, nodeID, nodeVersion, nodeTags, true, lat, lon); } else if (!node.loaded) { node.update(nodeVersion, nodeTags, true, false, lat, lon); } @@ -161,7 +161,7 @@ package net.systemeD.halcyon.connection { } if (way==null) { - way = new Way(id, version, tags, true, nodes); + way = new Way(this, id, version, tags, true, nodes); } else { way.update(version, tags, true, true, nodes); } @@ -199,21 +199,21 @@ package net.systemeD.halcyon.connection { switch (type) { case 'Node': e=getNode(memid); - if (e==null) { e=new Node(memid,0,{},false,0,0); setNode(Node(e),true); } + if (e==null) { e=new Node(this, memid,0,{},false,0,0); setNode(Node(e),true); } break; case 'Way': e=getWay(memid); - if (e==null) { e=new Way(memid,0,{},false,[]); setWay(Way(e),true); } + if (e==null) { e=new Way(this, memid,0,{},false,[]); setWay(Way(e),true); } break; case 'Relation': e=getRelation(memid); - if (e==null) { e=new Relation(memid,0,{},false,[]); setRelation(Relation(e),true); } + if (e==null) { e=new Relation(this, memid,0,{},false,[]); setRelation(Relation(e),true); } break; } members.push(new RelationMember(e,role)); } if (relation==null) { - relation = new Relation(id, version, tags, true, members); + relation = new Relation(this, id, version, tags, true, members); } else { relation.update(version,tags,true,false,members); } diff --git a/net/systemeD/halcyon/connection/Changeset.as b/net/systemeD/halcyon/connection/Changeset.as index 096651d0..bb1a2bf1 100644 --- a/net/systemeD/halcyon/connection/Changeset.as +++ b/net/systemeD/halcyon/connection/Changeset.as @@ -3,8 +3,8 @@ package net.systemeD.halcyon.connection { public class Changeset extends Entity { public static var entity_type:String = 'changeset'; - public function Changeset(id:Number, tags:Object) { - super(id, 0, tags, true, NaN, ''); + public function Changeset(connection:Connection, id:Number, tags:Object) { + super(connection, id, 0, tags, true, NaN, ''); } public override function toString():String { diff --git a/net/systemeD/halcyon/connection/Connection.as b/net/systemeD/halcyon/connection/Connection.as index 36933f9f..dced4d3a 100644 --- a/net/systemeD/halcyon/connection/Connection.as +++ b/net/systemeD/halcyon/connection/Connection.as @@ -15,7 +15,8 @@ package net.systemeD.halcyon.connection { protected var policyURL:String; protected var params:Object; - public function Connection(cname:String,api:String,policy:String,initparams:Object={}) { + public function Connection(cname:String,api:String,policy:String,initparams:Object=null) { + initparams = (initparams!=null ? initparams:{}); name=cname; apiBaseURL=api; policyURL=policy; @@ -255,19 +256,19 @@ package net.systemeD.halcyon.connection { } public function createNode(tags:Object, lat:Number, lon:Number, performCreate:Function):Node { - var node:Node = new Node(nextNegative, 0, tags, true, lat, lon); + var node:Node = new Node(this, nextNegative, 0, tags, true, lat, lon); performCreate(new CreateEntityAction(node, setNode)); return node; } public function createWay(tags:Object, nodes:Array, performCreate:Function):Way { - var way:Way = new Way(nextNegative, 0, tags, true, nodes.concat()); + var way:Way = new Way(this, nextNegative, 0, tags, true, nodes.concat()); performCreate(new CreateEntityAction(way, setWay)); return way; } public function createRelation(tags:Object, members:Array, performCreate:Function):Relation { - var relation:Relation = new Relation(nextNegative, 0, tags, true, members.concat()); + var relation:Relation = new Relation(this, nextNegative, 0, tags, true, members.concat()); performCreate(new CreateEntityAction(relation, setRelation)); return relation; } diff --git a/net/systemeD/halcyon/connection/Entity.as b/net/systemeD/halcyon/connection/Entity.as index 6a24481f..fc297f8a 100644 --- a/net/systemeD/halcyon/connection/Entity.as +++ b/net/systemeD/halcyon/connection/Entity.as @@ -8,6 +8,7 @@ package net.systemeD.halcyon.connection { /** An Entity is an object stored in the map database, and therefore uploaded and downloaded. This includes Nodes, Ways, * Relations but also Changesets etc. */ public class Entity extends EventDispatcher { + private var _connection:Connection; private var _id:Number; private var _version:uint; private var _uid:Number; @@ -22,7 +23,8 @@ package net.systemeD.halcyon.connection { /** Have all its parents (ie, relations that contain this object as a member, ways that contain this node) been loaded into memory */ public var parentsLoaded:Boolean = true; - public function Entity(id:Number, version:uint, tags:Object, loaded:Boolean, uid:Number, timestamp:String) { + public function Entity(connection:Connection, id:Number, version:uint, tags:Object, loaded:Boolean, uid:Number, timestamp:String) { + this._connection = connection; this._id = id; this._version = version; this._uid = uid; @@ -62,6 +64,11 @@ package net.systemeD.halcyon.connection { return _timestamp; } + /** Connection to which this entity belongs. */ + public function get connection():Connection { + return _connection; + } + /** Set a bunch of properties in one hit. Implicitly makes entity not deleted. */ public function updateEntityProperties(version:uint, tags:Object, loaded:Boolean, parentsLoaded:Boolean, uid:Number, timestamp:String):void { _version=version; this.tags=tags; _loaded=loaded; this.parentsLoaded=parentsLoaded; _uid = uid; _timestamp = timestamp; diff --git a/net/systemeD/halcyon/connection/EntityCollection.as b/net/systemeD/halcyon/connection/EntityCollection.as index 6056cc6c..ad7f6b85 100644 --- a/net/systemeD/halcyon/connection/EntityCollection.as +++ b/net/systemeD/halcyon/connection/EntityCollection.as @@ -18,7 +18,10 @@ package net.systemeD.halcyon.connection { private var delayedEvents:Array = []; public function EntityCollection(entities:Array) { - super(-1, 0, {}, true, -1, ""); + var conn:Connection=entities[0].connection; + // ** FIXME: this really is a very nasty way of finding the connection + + super(conn, -1, 0, {}, true, -1, ""); _entities = entities; //To avoid firing on every contained entity, we wait some short time before firing the events diff --git a/net/systemeD/halcyon/connection/Marker.as b/net/systemeD/halcyon/connection/Marker.as index 0180bfb4..e39c5c9f 100644 --- a/net/systemeD/halcyon/connection/Marker.as +++ b/net/systemeD/halcyon/connection/Marker.as @@ -10,8 +10,8 @@ package net.systemeD.halcyon.connection { private var _latproj:Number; private var _lon:Number; - public function Marker(id:Number, version:uint, tags:Object, loaded:Boolean, lat:Number, lon:Number) { - super(id, version, tags, loaded, 0, null); + public function Marker(connection:Connection, id:Number, version:uint, tags:Object, loaded:Boolean, lat:Number, lon:Number) { + super(connection, id, version, tags, loaded, 0, null); this._lat = lat; this._latproj = lat2latp(lat); this._lon = lon; diff --git a/net/systemeD/halcyon/connection/Node.as b/net/systemeD/halcyon/connection/Node.as index e185d3f4..cd3d5269 100644 --- a/net/systemeD/halcyon/connection/Node.as +++ b/net/systemeD/halcyon/connection/Node.as @@ -7,8 +7,8 @@ package net.systemeD.halcyon.connection { private var _latproj:Number; private var _lon:Number; - public function Node(id:Number, version:uint, tags:Object, loaded:Boolean, lat:Number, lon:Number, uid:Number = NaN, timestamp:String = null) { - super(id, version, tags, loaded, uid, timestamp); + public function Node(connection:Connection, id:Number, version:uint, tags:Object, loaded:Boolean, lat:Number, lon:Number, uid:Number = NaN, timestamp:String = null) { + super(connection, id, version, tags, loaded, uid, timestamp); this._lat = lat; this._latproj = lat2latp(lat); this._lon = lon; diff --git a/net/systemeD/halcyon/connection/Relation.as b/net/systemeD/halcyon/connection/Relation.as index 795dd781..56808d41 100644 --- a/net/systemeD/halcyon/connection/Relation.as +++ b/net/systemeD/halcyon/connection/Relation.as @@ -6,8 +6,8 @@ package net.systemeD.halcyon.connection { private var members:Array; public static var entity_type:String = 'relation'; - public function Relation(id:Number, version:uint, tags:Object, loaded:Boolean, members:Array, uid:Number = NaN, timestamp:String = null) { - super(id, version, tags, loaded, uid, timestamp); + public function Relation(connection:Connection, id:Number, version:uint, tags:Object, loaded:Boolean, members:Array, uid:Number = NaN, timestamp:String = null) { + super(connection, id, version, tags, loaded, uid, timestamp); this.members = members; for each (var member:RelationMember in members) member.entity.addParent(this); diff --git a/net/systemeD/halcyon/connection/Way.as b/net/systemeD/halcyon/connection/Way.as index 87ed4e5d..8cefcf1a 100644 --- a/net/systemeD/halcyon/connection/Way.as +++ b/net/systemeD/halcyon/connection/Way.as @@ -11,8 +11,8 @@ package net.systemeD.halcyon.connection { private var edge_b:Number; public static var entity_type:String = 'way'; - public function Way(id:Number, version:uint, tags:Object, loaded:Boolean, nodes:Array, uid:Number = NaN, timestamp:String = null) { - super(id, version, tags, loaded, uid, timestamp); + public function Way(connection:Connection, id:Number, version:uint, tags:Object, loaded:Boolean, nodes:Array, uid:Number = NaN, timestamp:String = null) { + super(connection, id, version, tags, loaded, uid, timestamp); this.nodes = nodes; for each (var node:Node in nodes) { node.addParent(this); } calculateBbox(); diff --git a/net/systemeD/halcyon/connection/XMLBaseConnection.as b/net/systemeD/halcyon/connection/XMLBaseConnection.as index 7d083b5e..19e0032d 100644 --- a/net/systemeD/halcyon/connection/XMLBaseConnection.as +++ b/net/systemeD/halcyon/connection/XMLBaseConnection.as @@ -54,7 +54,7 @@ package net.systemeD.halcyon.connection { if ( type == "node" ) { member = getNode(memberID); if ( member == null ) { - member = new Node(memberID,0,{},false,0,0); + member = new Node(this,memberID,0,{},false,0,0); setNode(Node(member),true); } else if (member.isDeleted()) { member.setDeletedState(false); @@ -62,13 +62,13 @@ package net.systemeD.halcyon.connection { } else if ( type == "way" ) { member = getWay(memberID); if (member == null) { - member = new Way(memberID,0,{},false,[]); + member = new Way(this,memberID,0,{},false,[]); setWay(Way(member),true); } } else if ( type == "relation" ) { member = getRelation(memberID); if (member == null) { - member = new Relation(memberID,0,{},false,[]); + member = new Relation(this,memberID,0,{},false,[]); setRelation(Relation(member),true); } } @@ -78,7 +78,7 @@ package net.systemeD.halcyon.connection { } if ( rel == null ) - setRelation(new Relation(id, version, tags, true, members, uid, timestamp), false); + setRelation(new Relation(this, id, version, tags, true, members, uid, timestamp), false); else { rel.update(version, tags, true, false, members, uid, timestamp); sendEvent(new EntityEvent(NEW_RELATION, rel), false); @@ -89,7 +89,8 @@ package net.systemeD.halcyon.connection { for each(var nodeData:XML in map.node) { id = Number(nodeData.@id); node = getNode(id); - newNode = new Node(id, + newNode = new Node(this, + id, uint(nodeData.@version), parseTags(nodeData.tag), true, @@ -130,7 +131,7 @@ package net.systemeD.halcyon.connection { } tags = parseTags(data.tag); if ( way == null ) { - setWay(new Way(id, version, tags, true, nodes, uid, timestamp),false); + setWay(new Way(this, id, version, tags, true, nodes, uid, timestamp),false); } else { waycount++; way.update(version, tags, true, true, nodes, uid, timestamp); diff --git a/net/systemeD/halcyon/connection/XMLConnection.as b/net/systemeD/halcyon/connection/XMLConnection.as index 3ce55059..12c6c4a9 100644 --- a/net/systemeD/halcyon/connection/XMLConnection.as +++ b/net/systemeD/halcyon/connection/XMLConnection.as @@ -142,7 +142,7 @@ package net.systemeD.halcyon.connection { var id:Number = Number(URLLoader(event.target).data); // which means we now have a new changeset! - setActiveChangeset(new Changeset(id, lastUploadedChangesetTags)); + setActiveChangeset(new Changeset(this, id, lastUploadedChangesetTags)); } private function changesetCreateError(event:IOErrorEvent):void { From 43b2f3072cf641426ecd2d23c678dbf3e35d3719 Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Sat, 21 May 2011 16:33:52 +0100 Subject: [PATCH 06/89] More refactoring in progress --- REFACTOR.txt | 12 +++--- halcyon_viewer.as | 2 +- net/systemeD/halcyon/Map.as | 39 +++++++------------ net/systemeD/halcyon/MapPaint.as | 12 +++++- net/systemeD/halcyon/VectorLayer.as | 2 +- .../halcyon/connection/AMFConnection.as | 3 +- net/systemeD/halcyon/connection/Entity.as | 4 +- net/systemeD/halcyon/connection/Node.as | 3 -- .../halcyon/connection/OSMConnection.as | 7 ++-- net/systemeD/halcyon/connection/Trace.as | 6 ++- .../connection/UndoableEntityAction.as | 6 +-- .../halcyon/connection/XMLBaseConnection.as | 3 +- .../halcyon/connection/XMLConnection.as | 12 +++--- .../connection/actions/CreatePOIAction.as | 10 +++-- .../connection/actions/DeleteNodeAction.as | 2 +- .../connection/actions/DeleteWayAction.as | 2 +- .../connection/actions/SplitWayAction.as | 2 +- .../connection/actions/UnjoinNodeAction.as | 2 +- .../potlatch2/collections/Stylesheets.as | 3 +- .../potlatch2/controller/ControllerState.as | 2 +- net/systemeD/potlatch2/controller/DrawWay.as | 1 + .../potlatch2/controller/SelectedMultiple.as | 2 +- .../potlatch2/controller/SelectedWayNode.as | 4 +- net/systemeD/potlatch2/save/SaveDialog.mxml | 26 +++++++------ net/systemeD/potlatch2/save/SaveManager.as | 20 +++++----- net/systemeD/potlatch2/tools/Parallelise.as | 2 +- .../potlatch2/tools/Quadrilateralise.as | 2 +- potlatch2.mxml | 9 +++-- 28 files changed, 102 insertions(+), 98 deletions(-) diff --git a/REFACTOR.txt b/REFACTOR.txt index 5334bde0..a0747982 100644 --- a/REFACTOR.txt +++ b/REFACTOR.txt @@ -4,14 +4,10 @@ Aims: - to enable multiple Maps to be shown on-screen (e.g. for junction editor) - to bring Connection and VectorLayer code together -==== think what to do about controllers ==== - - Map.as changes: becomes a collection of MapPaint objects, all with the same lat/long/scale (plus a backdrop sprite and a background imagery sprite) √ move listeners to Connection to MapPaint (e.g. new way created in the Connection - MapPaint should know about it, not Map) -- refactor tileset/setbackground stuff? MapPaint.as changes: - gains a reference to a Connection - i.e. the source data for this layer @@ -29,4 +25,10 @@ Global changes: - remove all references to getConnection etc. - there can now be more than one Connection - remove all back-references to Map except where necessary for lat/long/scale - Controllers are full of references to controller.map and to controller.connection -- move AttentionEvent stuff +- getParam is broken - there needs to be a global equivalent (not in Connection) for stuff sent via flashvars - i.e. loaderInfo.parameters (but that's Flex-only) +- Look for Connection. - lots of static stuff which shouldn't be that any more + +Further refactoring probably needed: +- move AttentionEvent stuff (some may be commented out) +- Traces (e.g. in potlatch2.mxml) - seems a bit mixed up +- refactor tileset/setbackground stuff? diff --git a/halcyon_viewer.as b/halcyon_viewer.as index 3b01b9e9..cbf3c914 100644 --- a/halcyon_viewer.as +++ b/halcyon_viewer.as @@ -69,7 +69,7 @@ package { } private function onRefreshCSS(str:String):void { - theMap.setStyle(str); + theMap.editableLayer.setStyle(str); } private function onJumpTo(lat:Number,lon:Number):void { theMap.init(lat,lon); diff --git a/net/systemeD/halcyon/Map.as b/net/systemeD/halcyon/Map.as index d4001170..c0fdd699 100644 --- a/net/systemeD/halcyon/Map.as +++ b/net/systemeD/halcyon/Map.as @@ -76,8 +76,6 @@ package net.systemeD.halcyon { public var tileset:TileSet; /** background tile URL, name and scheme */ private var tileparams:Object={ url:'' }; - /** internal style URL */ - private var styleurl:String=''; /** show all objects, even if unstyled? */ public var showall:Boolean=true; @@ -228,7 +226,7 @@ package net.systemeD.halcyon { public function download():void { this.dispatchEvent(new MapEvent(MapEvent.DOWNLOAD, {minlon:edge_l, maxlon:edge_r, maxlat:edge_t, minlat:edge_b} )); for (var i:uint=0; i>>> REFACTOR: needs to do the equivalent of VectorLayer.blank() } @@ -268,18 +261,21 @@ package net.systemeD.halcyon { public function findLayer(name:String):MapPaint { for (var i:uint=0; i>>> REFACTOR: remove this public function findSource():VectorLayer { var v:VectorLayer; diff --git a/net/systemeD/halcyon/VectorLayer.as b/net/systemeD/halcyon/VectorLayer.as index 644b39f4..4631b0e4 100644 --- a/net/systemeD/halcyon/VectorLayer.as +++ b/net/systemeD/halcyon/VectorLayer.as @@ -170,7 +170,7 @@ package net.systemeD.halcyon { oldNode=Node(entity); unregisterPOI(oldNode); var newPoiAction:CreatePOIAction = new CreatePOIAction( - oldNode.getTagsCopy(), oldNode.lat, oldNode.lon); + this, oldNode.getTagsCopy(), oldNode.lat, oldNode.lon); MainUndoStack.getGlobalStack().addAction(newPoiAction); paint.deleteNodeUI(oldNode); delete nodes[oldNode.id]; diff --git a/net/systemeD/halcyon/connection/AMFConnection.as b/net/systemeD/halcyon/connection/AMFConnection.as index 3a21b004..d0152328 100644 --- a/net/systemeD/halcyon/connection/AMFConnection.as +++ b/net/systemeD/halcyon/connection/AMFConnection.as @@ -28,8 +28,7 @@ package net.systemeD.halcyon.connection { public function AMFConnection(name:String,api:String,policy:String,initparams:Object) { super(name,api,policy,initparams); - if (Connection.policyURL!='') - Security.loadPolicyFile(Connection.policyURL); + if (policyURL!='') Security.loadPolicyFile(policyURL); readConnection=new NetConnection(); readConnection.objectEncoding = flash.net.ObjectEncoding.AMF0; diff --git a/net/systemeD/halcyon/connection/Entity.as b/net/systemeD/halcyon/connection/Entity.as index fc297f8a..87512499 100644 --- a/net/systemeD/halcyon/connection/Entity.as +++ b/net/systemeD/halcyon/connection/Entity.as @@ -202,9 +202,9 @@ package net.systemeD.halcyon.connection { if (this is Node) { var n:Node = Node(this); if (isDeleted) { - Connection.getConnection().removeDupe(n); + connection.removeDupe(n); } else { - Connection.getConnection().addDupe(n); + connection.addDupe(n); } } } diff --git a/net/systemeD/halcyon/connection/Node.as b/net/systemeD/halcyon/connection/Node.as index cd3d5269..f3bc8d99 100644 --- a/net/systemeD/halcyon/connection/Node.as +++ b/net/systemeD/halcyon/connection/Node.as @@ -31,7 +31,6 @@ package net.systemeD.halcyon.connection { } private function setLatLonImmediate(lat:Number, lon:Number):void { - var connection:Connection = Connection.getConnection(); connection.removeDupe(this); this._lat = lat; this._latproj = lat2latp(lat); @@ -89,7 +88,6 @@ package net.systemeD.halcyon.connection { */ public function join(ways:Array, performAction:Function):void { if (this.isDupe() || ways.length > 0) { - var connection:Connection = Connection.getConnection(); var nodes:Array = connection.getNodesAtPosition(lat,lon); // filter the nodes array to remove any occurances of this. // Pass "this" as thisObject to get "this" into the callback function @@ -111,7 +109,6 @@ package net.systemeD.halcyon.connection { } public function isDupe():Boolean { - var connection:Connection = Connection.getConnection(); if (connection.getNode(this.id) == this // node could be part of a vector layer && connection.nodesAtPosition(lat, lon) > 1) { return true; diff --git a/net/systemeD/halcyon/connection/OSMConnection.as b/net/systemeD/halcyon/connection/OSMConnection.as index 794e96db..79774aa4 100644 --- a/net/systemeD/halcyon/connection/OSMConnection.as +++ b/net/systemeD/halcyon/connection/OSMConnection.as @@ -47,13 +47,12 @@ package net.systemeD.halcyon.connection { public function OSMConnection(name:String,api:String,policy:String,initparams:Object) { super(name,api,policy,initparams); - if (Connection.policyURL!='') - Security.loadPolicyFile(Connection.policyURL); + if (policyURL!='') Security.loadPolicyFile(policyURL); - tileResolution = Number(Connection.getParam("tile_resolution", "0.2")); + tileResolution = Number(getParam("tile_resolution", "0.2")); var o:Object = new Object(); - var files:String = Connection.getParam("files",""); + var files:String = getParam("files",""); if (files=="") { filemode=TILED; } else { diff --git a/net/systemeD/halcyon/connection/Trace.as b/net/systemeD/halcyon/connection/Trace.as index 17bb5725..4c7597e7 100644 --- a/net/systemeD/halcyon/connection/Trace.as +++ b/net/systemeD/halcyon/connection/Trace.as @@ -23,12 +23,14 @@ package net.systemeD.halcyon.connection { private var _filename:String; private var _traceData:String; private var map:Map; + private var _connection:Connection; private var _layer:VectorLayer; private var simplify:Boolean = false; private static const STYLESHEET:String="stylesheets/gpx.css"; - public function Trace() { + public function Trace(connection:Connection) { + _connection = connection; map = Globals.vars.root; } @@ -61,7 +63,7 @@ package net.systemeD.halcyon.connection { private function fetchFromServer():void { // todo - needs proper error handling - Connection.getConnection().fetchTrace(id, saveTraceData); + _connection.fetchTrace(id, saveTraceData); dispatchEvent(new Event("loading_data")); } diff --git a/net/systemeD/halcyon/connection/UndoableEntityAction.as b/net/systemeD/halcyon/connection/UndoableEntityAction.as index c8f5f32a..d6b784f8 100644 --- a/net/systemeD/halcyon/connection/UndoableEntityAction.as +++ b/net/systemeD/halcyon/connection/UndoableEntityAction.as @@ -36,7 +36,7 @@ package net.systemeD.halcyon.connection { } if ( !connectionWasDirty ) { - Connection.getConnection().markDirty(); + entity.connection.markDirty(); } } @@ -52,7 +52,7 @@ package net.systemeD.halcyon.connection { } if ( !connectionWasDirty ) { - Connection.getConnection().markClean(); + entity.connection.markClean(); } } @@ -62,7 +62,7 @@ package net.systemeD.halcyon.connection { */ private function init():void { wasDirty = entity.isDirty; - connectionWasDirty = Connection.getConnection().isDirty; + connectionWasDirty = entity.connection.isDirty; initialised = true; } diff --git a/net/systemeD/halcyon/connection/XMLBaseConnection.as b/net/systemeD/halcyon/connection/XMLBaseConnection.as index 19e0032d..65b9f258 100644 --- a/net/systemeD/halcyon/connection/XMLBaseConnection.as +++ b/net/systemeD/halcyon/connection/XMLBaseConnection.as @@ -13,7 +13,8 @@ package net.systemeD.halcyon.connection { */ public class XMLBaseConnection extends Connection { - public function XMLBaseConnection() { + public function XMLBaseConnection(name:String,api:String,policy:String,initparams:Object) { + super(name,api,policy,initparams); } protected function loadedMap(event:Event):void { diff --git a/net/systemeD/halcyon/connection/XMLConnection.as b/net/systemeD/halcyon/connection/XMLConnection.as index 12c6c4a9..4f72b737 100644 --- a/net/systemeD/halcyon/connection/XMLConnection.as +++ b/net/systemeD/halcyon/connection/XMLConnection.as @@ -19,12 +19,10 @@ package net.systemeD.halcyon.connection { public function XMLConnection(name:String,api:String,policy:String,initparams:Object) { super(name,api,policy,initparams); - if (Connection.policyURL!='') - Security.loadPolicyFile(Connection.policyURL); - var oauthPolicy:String = Connection.getParam("oauth_policy", ""); - if ( oauthPolicy != "" ) { - Security.loadPolicyFile(oauthPolicy); - } + if (policyURL != "") Security.loadPolicyFile(policyURL); + + var oauthPolicy:String = getParam("oauth_policy", ""); + if (oauthPolicy != "") Security.loadPolicyFile(oauthPolicy); } override public function loadBbox(left:Number,right:Number, @@ -441,7 +439,7 @@ package net.systemeD.halcyon.connection { clearTraces(); var files:XML = new XML(URLLoader(event.target).data); for each(var traceData:XML in files.gpx_file) { - var t:Trace = new Trace().fromXML(traceData); + var t:Trace = new Trace(this).fromXML(traceData); addTrace(t); } traces_loaded = true; diff --git a/net/systemeD/halcyon/connection/actions/CreatePOIAction.as b/net/systemeD/halcyon/connection/actions/CreatePOIAction.as index 99d0b58d..42a35fbf 100644 --- a/net/systemeD/halcyon/connection/actions/CreatePOIAction.as +++ b/net/systemeD/halcyon/connection/actions/CreatePOIAction.as @@ -10,9 +10,11 @@ package net.systemeD.halcyon.connection.actions { private var tags:Object; private var lat:Number; private var lon:Number; + private var connection:Connection; - public function CreatePOIAction(tags:Object, lat:Number, lon:Number) { + public function CreatePOIAction(connection:Connection, tags:Object, lat:Number, lon:Number) { super("Create POI"); + this.connection = connection; this.tags = tags; this.lat = lat; this.lon = lon; @@ -20,17 +22,17 @@ package net.systemeD.halcyon.connection.actions { public override function doAction():uint { if (newNode == null) { - newNode = Connection.getConnection().createNode(tags,lat,lon,push); + newNode = connection.createNode(tags,lat,lon,push); } super.doAction(); - Connection.getConnection().registerPOI(newNode); + connection.registerPOI(newNode); return SUCCESS; } public override function undoAction():uint { super.undoAction(); - Connection.getConnection().unregisterPOI(newNode); + connection.unregisterPOI(newNode); return SUCCESS; } diff --git a/net/systemeD/halcyon/connection/actions/DeleteNodeAction.as b/net/systemeD/halcyon/connection/actions/DeleteNodeAction.as index b5bebfa4..beda1c7f 100644 --- a/net/systemeD/halcyon/connection/actions/DeleteNodeAction.as +++ b/net/systemeD/halcyon/connection/actions/DeleteNodeAction.as @@ -49,7 +49,7 @@ package net.systemeD.halcyon.connection.actions { } else { markClean(); } - Connection.getConnection().dispatchEvent(new EntityEvent(Connection.NEW_NODE, entity)); + node.connection.dispatchEvent(new EntityEvent(Connection.NEW_NODE, entity)); if ( effects != null ) effects.undoAction(); return SUCCESS; diff --git a/net/systemeD/halcyon/connection/actions/DeleteWayAction.as b/net/systemeD/halcyon/connection/actions/DeleteWayAction.as index 3ed4e856..331826a8 100644 --- a/net/systemeD/halcyon/connection/actions/DeleteWayAction.as +++ b/net/systemeD/halcyon/connection/actions/DeleteWayAction.as @@ -56,7 +56,7 @@ package net.systemeD.halcyon.connection.actions { } else { markClean(); } - Connection.getConnection().dispatchEvent(new EntityEvent(Connection.NEW_WAY, way)); + entity.connection.dispatchEvent(new EntityEvent(Connection.NEW_WAY, way)); effects.undoAction(); for each(var node:Node in oldNodeList) { nodeList.push(node); diff --git a/net/systemeD/halcyon/connection/actions/SplitWayAction.as b/net/systemeD/halcyon/connection/actions/SplitWayAction.as index b79efbdf..d88ddaee 100644 --- a/net/systemeD/halcyon/connection/actions/SplitWayAction.as +++ b/net/systemeD/halcyon/connection/actions/SplitWayAction.as @@ -16,7 +16,7 @@ package net.systemeD.halcyon.connection.actions { public override function doAction():uint { if (newWay==null) { - newWay = Connection.getConnection().createWay( + newWay = selectedWay.connection.createWay( selectedWay.getTagsCopy(), selectedWay.sliceNodes(nodeIndex,selectedWay.length), push); diff --git a/net/systemeD/halcyon/connection/actions/UnjoinNodeAction.as b/net/systemeD/halcyon/connection/actions/UnjoinNodeAction.as index a9e14e84..f6abba57 100644 --- a/net/systemeD/halcyon/connection/actions/UnjoinNodeAction.as +++ b/net/systemeD/halcyon/connection/actions/UnjoinNodeAction.as @@ -25,7 +25,7 @@ package net.systemeD.halcyon.connection.actions { way.dispatchEvent(new EntityEvent(Connection.WAY_REORDERED, way)); // no longer a junction, so force redraw continue; } else { - var newNode:Node = Connection.getConnection().createNode(node.getTagsCopy(), node.lat, node.lon, push); + var newNode:Node = way.connection.createNode(node.getTagsCopy(), node.lat, node.lon, push); for (var i:int = 0; i < way.length; i++) { if(way.getNode(i) == node) { way.removeNodeByIndex(i, push); diff --git a/net/systemeD/potlatch2/collections/Stylesheets.as b/net/systemeD/potlatch2/collections/Stylesheets.as index cc6db63d..f10d079f 100644 --- a/net/systemeD/potlatch2/collections/Stylesheets.as +++ b/net/systemeD/potlatch2/collections/Stylesheets.as @@ -74,7 +74,8 @@ package net.systemeD.potlatch2.collections { } public function setStylesheet(name:String,url:String):void { - _map.setStyle(url); + _map.editableLayer.setStyle(url); + // >>>> REFACTOR: not great to have a reference to editableLayer in here var obj:SharedObject = SharedObject.getLocal("user_state"); obj.setProperty("stylesheet_url",url); obj.setProperty("stylesheet_name",name); diff --git a/net/systemeD/potlatch2/controller/ControllerState.as b/net/systemeD/potlatch2/controller/ControllerState.as index 4788e7f8..94c62f79 100644 --- a/net/systemeD/potlatch2/controller/ControllerState.as +++ b/net/systemeD/potlatch2/controller/ControllerState.as @@ -67,7 +67,7 @@ package net.systemeD.potlatch2.controller { case 66: setSourceTag(); break; // B - set source tag for current object case 67: controller.connection.closeChangeset(); break; // C - close changeset case 68: editableLayer.alpha=1.3-editableLayer.alpha; return null; // D - dim - case 83: SaveManager.saveChanges(); break; // S - save + case 83: SaveManager.saveChanges(controller.connection); break; // S - save case 84: controller.tagViewer.togglePanel(); return null; // T - toggle tags panel case 90: if (!event.shiftKey) { MainUndoStack.getGlobalStack().undo(); return null;}// Z - undo else { MainUndoStack.getGlobalStack().redo(); return null; } // Shift-Z - redo diff --git a/net/systemeD/potlatch2/controller/DrawWay.as b/net/systemeD/potlatch2/controller/DrawWay.as index 21aef75f..d66f5e0a 100644 --- a/net/systemeD/potlatch2/controller/DrawWay.as +++ b/net/systemeD/potlatch2/controller/DrawWay.as @@ -56,6 +56,7 @@ package net.systemeD.potlatch2.controller { MainUndoStack.getGlobalStack().undo(); // undo the BeginWayAction that (presumably?) just happened var newPoiAction:CreatePOIAction = new CreatePOIAction( + editableLayer.connection, {}, controller.map.coord2lat(event.localY), controller.map.coord2lon(event.localX)); diff --git a/net/systemeD/potlatch2/controller/SelectedMultiple.as b/net/systemeD/potlatch2/controller/SelectedMultiple.as index 26015771..3feb114b 100644 --- a/net/systemeD/potlatch2/controller/SelectedMultiple.as +++ b/net/systemeD/potlatch2/controller/SelectedMultiple.as @@ -64,7 +64,7 @@ package net.systemeD.potlatch2.controller { for each (var conflict:String in conflictTags) conflictTags2.push(conflict); if (conflictTags2.length>0) msg += " *Warning* The following tags conflicted and need attention: " + conflictTags2; - map.connection.dispatchEvent(new AttentionEvent(AttentionEvent.ALERT, null, msg)); + // >>>> somethingorother.dispatchEvent(new AttentionEvent(AttentionEvent.ALERT, null, msg)); } return controller.findStateForSelection(waylist); diff --git a/net/systemeD/potlatch2/controller/SelectedWayNode.as b/net/systemeD/potlatch2/controller/SelectedWayNode.as index 5bb16b00..77a050a6 100644 --- a/net/systemeD/potlatch2/controller/SelectedWayNode.as +++ b/net/systemeD/potlatch2/controller/SelectedWayNode.as @@ -180,7 +180,7 @@ package net.systemeD.potlatch2.controller { var q:Point = map.localToGlobal(p); // First, look for POI nodes in 20x20 pixel box around the current node - var hitnodes:Array = map.connection.getObjectsByBbox( + var hitnodes:Array = controller.connection.getObjectsByBbox( map.coord2lon(p.x-10), map.coord2lon(p.x+10), map.coord2lat(p.y-10), @@ -221,7 +221,7 @@ package net.systemeD.potlatch2.controller { if (MergeNodesAction.lastProblemTags) { msg += " *Warning* The following tags conflicted and need attention: " + MergeNodesAction.lastProblemTags; } - map.connection.dispatchEvent(new AttentionEvent(AttentionEvent.ALERT, null, msg)); + // somethingorother.dispatchEvent(new AttentionEvent(AttentionEvent.ALERT, null, msg)); return new SelectedWayNode(n.parentWays[0], Way(n.parentWays[0]).indexOfNode(n)); } diff --git a/net/systemeD/potlatch2/save/SaveDialog.mxml b/net/systemeD/potlatch2/save/SaveDialog.mxml index ae3e60f6..4d87dd13 100644 --- a/net/systemeD/potlatch2/save/SaveDialog.mxml +++ b/net/systemeD/potlatch2/save/SaveDialog.mxml @@ -83,12 +83,16 @@ import net.systemeD.halcyon.connection.*; import net.systemeD.halcyon.AttentionEvent; - private var conn:Connection = Connection.getConnection(); + private var _connection:Connection; private var doSkip:Boolean = false; [Bindable] private var failureText:String = ""; + public function setConnection(connection:Connection):void { + _connection=connection; + } + public function dontPrompt():void { if (processSequence.initialized) { skipInput(); } else { doSkip=true; } } @@ -131,9 +135,9 @@ } // add the listeners - conn.addEventListener(Connection.NEW_CHANGESET, changesetCreated); - conn.addEventListener(Connection.NEW_CHANGESET_ERROR, changesetError); - conn.createChangeset(tags); + _connection.addEventListener(Connection.NEW_CHANGESET, changesetCreated); + _connection.addEventListener(Connection.NEW_CHANGESET_ERROR, changesetError); + _connection.createChangeset(tags); } private function allowForEdit(event:DataGridEvent):void { @@ -159,12 +163,12 @@ } private function changesetCreated(event:EntityEvent=null):void { - var changeset:Changeset = conn.getActiveChangeset(); + var changeset:Changeset = _connection.getActiveChangeset(); addStatus("Saving to changeset "+changeset.id); saveProgress.label = "Uploading changes"; - conn.addEventListener(Connection.SAVE_COMPLETED, saveCompleted); - conn.uploadChanges(); + _connection.addEventListener(Connection.SAVE_COMPLETED, saveCompleted); + _connection.uploadChanges(); } private function changesetError(event:Event):void { @@ -173,7 +177,7 @@ private function saveCompleted(event:SaveCompleteEvent):void { if ( event.saveOK ) { - conn.dispatchEvent(new AttentionEvent(AttentionEvent.ALERT, null, "Changes successfully saved")); + _connection.dispatchEvent(new AttentionEvent(AttentionEvent.ALERT, null, "Changes successfully saved")); close(); } else { fail("Failure when uploading data"); @@ -195,9 +199,9 @@ } private function close():void { - conn.removeEventListener(Connection.NEW_CHANGESET, changesetCreated); - conn.removeEventListener(Connection.NEW_CHANGESET_ERROR, changesetError); - conn.removeEventListener(Connection.SAVE_COMPLETED, saveCompleted); + _connection.removeEventListener(Connection.NEW_CHANGESET, changesetCreated); + _connection.removeEventListener(Connection.NEW_CHANGESET_ERROR, changesetError); + _connection.removeEventListener(Connection.SAVE_COMPLETED, saveCompleted); PopUpManager.removePopUp(this); } ]]> diff --git a/net/systemeD/potlatch2/save/SaveManager.as b/net/systemeD/potlatch2/save/SaveManager.as index e5cd2339..bc9ab3d5 100644 --- a/net/systemeD/potlatch2/save/SaveManager.as +++ b/net/systemeD/potlatch2/save/SaveManager.as @@ -10,18 +10,19 @@ package net.systemeD.potlatch2.save { public class SaveManager { private static var instance:SaveManager = new SaveManager(); + private var _connection:Connection; - public static function saveChanges():void { - instance.save(instance.saveData); + public static function saveChanges(connection:Connection):void { + instance.save(instance.saveData,connection); } - public static function ensureAccess(callback:Function):void { - instance.save(callback); + public static function ensureAccess(callback:Function, connection:Connection):void { + instance.save(callback,connection); } - private function save(callback:Function):void { - var conn:Connection = Connection.getConnection(); - if (conn.hasAccessToken()) { + private function save(callback:Function, connection:Connection):void { + _connection=connection; + if (connection.hasAccessToken()) { callback(); } else { getNewToken(callback); @@ -49,11 +50,10 @@ package net.systemeD.potlatch2.save { private function saveData():void { var saveDialog:SaveDialog = SaveDialog( PopUpManager.createPopUp(Application(Application.application), SaveDialog, true)); + saveDialog.setConnection(_connection); PopUpManager.centerPopUp(saveDialog); - if (Connection.getConnection().getActiveChangeset()) { - saveDialog.dontPrompt(); - } + if (_connection.getActiveChangeset()) saveDialog.dontPrompt(); } } diff --git a/net/systemeD/potlatch2/tools/Parallelise.as b/net/systemeD/potlatch2/tools/Parallelise.as index ed49b968..6f231294 100644 --- a/net/systemeD/potlatch2/tools/Parallelise.as +++ b/net/systemeD/potlatch2/tools/Parallelise.as @@ -20,7 +20,7 @@ package net.systemeD.potlatch2.tools { * */ public function Parallelise(way:Way) { var a:Number, b:Number, h:Number, i:uint, j:uint, k:int; - connection = Connection.getConnection(); + connection = way.connection; originalWay = way; parallelWay = connection.createWay({}, [], MainUndoStack.getGlobalStack().addAction); diff --git a/net/systemeD/potlatch2/tools/Quadrilateralise.as b/net/systemeD/potlatch2/tools/Quadrilateralise.as index b050fc47..9f11e07f 100644 --- a/net/systemeD/potlatch2/tools/Quadrilateralise.as +++ b/net/systemeD/potlatch2/tools/Quadrilateralise.as @@ -29,7 +29,7 @@ package net.systemeD.potlatch2.tools { functor.step(); var newScore:Number = functor.goodness; if (newScore > score) { - Connection.getConnection().dispatchEvent(new AttentionEvent(AttentionEvent.ALERT, null, "Corners too sharp to straighten")); + // somethingorother.dispatchEvent(new AttentionEvent(AttentionEvent.ALERT, null, "Corners too sharp to straighten")); return false; } score = newScore; diff --git a/potlatch2.mxml b/potlatch2.mxml index 94f364ce..133c5f40 100644 --- a/potlatch2.mxml +++ b/potlatch2.mxml @@ -56,7 +56,7 @@ + click="SaveManager.saveChanges(theMap.editableLayer.connection);" id="saveButton" enabled="false"/> @@ -467,11 +467,12 @@ var createAction:CompositeUndoableAction = new CompositeUndoableAction("Create POI"); - var node:Node = Connection.getConnection().createNode({}, lat, lon, createAction.push); + var conn:Connection = theMap.editableLayer.connection; + var node:Node = conn.createNode({}, lat, lon, createAction.push); for each ( var tag:Object in tags ) { node.setTag(tag.k, tag.v, createAction.push); } - Connection.getConnection().registerPOI(node); + conn.registerPOI(node); MainUndoStack.getGlobalStack().addAction(createAction); theController.setState(new SelectedPOINode(node)); } @@ -482,7 +483,7 @@ } private function loadTrace(id:Number):void { - var conn:Connection = Connection.getConnection(); + var conn:Connection = theMap.editableLayer.connection; conn.addEventListener(Connection.TRACES_LOADED, function (e:Event):void { for each (var trace:Trace in conn.getTraces()) { if (trace.id == id) { trace.addToMap(); } From 5f98ce71f80b93d3f14a2295bab5482a3180cb73 Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Sat, 21 May 2011 18:18:05 +0100 Subject: [PATCH 07/89] More refactoring work-in-progress --- REFACTOR.txt | 1 - net/systemeD/potlatch2/EditController.as | 7 ------- net/systemeD/potlatch2/RelationLoaderPanel.mxml | 14 +++++++------- net/systemeD/potlatch2/RelationSelectPanel.mxml | 2 +- net/systemeD/potlatch2/Toolbox.mxml | 2 +- .../potlatch2/controller/ControllerState.as | 8 ++++---- net/systemeD/potlatch2/controller/DragWayNode.as | 4 ++-- .../potlatch2/controller/DrawQuadrilateral.as | 2 +- net/systemeD/potlatch2/controller/DrawWay.as | 6 +++--- net/systemeD/potlatch2/controller/NoSelection.as | 5 +++-- .../potlatch2/controller/SelectedPOINode.as | 2 +- net/systemeD/potlatch2/controller/SelectedWay.as | 2 +- .../potlatch2/controller/SelectedWayNode.as | 4 ++-- .../mapfeatures/editors/TurnRestrictionEditor.mxml | 3 +-- .../mapfeatures/editors/TurnRestrictionIcon.mxml | 7 ++++--- net/systemeD/potlatch2/save/OAuthPanel.mxml | 10 ++++++---- net/systemeD/potlatch2/save/SaveManager.as | 1 + net/systemeD/potlatch2/tools/Circularise.as | 2 +- 18 files changed, 39 insertions(+), 43 deletions(-) diff --git a/REFACTOR.txt b/REFACTOR.txt index a0747982..632e6aeb 100644 --- a/REFACTOR.txt +++ b/REFACTOR.txt @@ -24,7 +24,6 @@ Global changes: - move lots of connection.map to connection.map.editableLayer - remove all references to getConnection etc. - there can now be more than one Connection - remove all back-references to Map except where necessary for lat/long/scale -- Controllers are full of references to controller.map and to controller.connection - getParam is broken - there needs to be a global equivalent (not in Connection) for stuff sent via flashvars - i.e. loaderInfo.parameters (but that's Flex-only) - Look for Connection. - lots of static stuff which shouldn't be that any more diff --git a/net/systemeD/potlatch2/EditController.as b/net/systemeD/potlatch2/EditController.as index 88361dd4..48a47716 100644 --- a/net/systemeD/potlatch2/EditController.as +++ b/net/systemeD/potlatch2/EditController.as @@ -23,7 +23,6 @@ package net.systemeD.potlatch2 { private var toolbox:Toolbox; public var state:ControllerState; - private var _connection:Connection; private var keys:Object={}; public var clipboards:Object={}; @@ -65,7 +64,6 @@ package net.systemeD.potlatch2 { public function setActive():void { map.setController(this); - _connection = map.connection; } /** Accesses map object. */ @@ -73,11 +71,6 @@ package net.systemeD.potlatch2 { return _map; } - /** Accesss connection object. */ - public function get connection():Connection { - return _connection; - } - /** * Updates the various user interfaces that change when the selection changes. * Currently this is the TagViewer and the Toolbox diff --git a/net/systemeD/potlatch2/RelationLoaderPanel.mxml b/net/systemeD/potlatch2/RelationLoaderPanel.mxml index 39fb79fa..2a617a14 100644 --- a/net/systemeD/potlatch2/RelationLoaderPanel.mxml +++ b/net/systemeD/potlatch2/RelationLoaderPanel.mxml @@ -21,30 +21,30 @@ import mx.managers.PopUpManager; private var entity:Entity; + private var connection:Connection; private var relid:Number; public function setEntity(e:Entity):void { entity=e; + connection=e.connection; } private function loadRelation():void { relid = Number(requestedID.text); PopUpManager.removePopUp(this); - var conn:Connection = Connection.getConnection(); if (!relid) return; - if (conn.getRelation(relid)) { + if (connection.getRelation(relid)) { relationLoaded(null); } else { - conn.loadEntityByID("relation",relid); - conn.addEventListener(Connection.LOAD_COMPLETED, relationLoaded); + connection.loadEntityByID("relation",relid); + connection.addEventListener(Connection.LOAD_COMPLETED, relationLoaded); } } private function relationLoaded(event:Event):void { - var conn:Connection = Connection.getConnection(); - var relation:Relation = conn.getRelation(relid); - conn.removeEventListener(Connection.LOAD_COMPLETED, relationLoaded); + var relation:Relation = connection.getRelation(relid); + connection.removeEventListener(Connection.LOAD_COMPLETED, relationLoaded); if (!relation) return; var undo:CompositeUndoableAction = new CompositeUndoableAction("Add to relation"); diff --git a/net/systemeD/potlatch2/RelationSelectPanel.mxml b/net/systemeD/potlatch2/RelationSelectPanel.mxml index 3c17eaff..f10440d2 100644 --- a/net/systemeD/potlatch2/RelationSelectPanel.mxml +++ b/net/systemeD/potlatch2/RelationSelectPanel.mxml @@ -23,6 +23,7 @@ */ public function init(e:Entity, t:Object):void { entity = e; + conn = e.connection; defaulttags = {}; for (var k:String in t) { //tagmatches[k]=t[k];// deep copy match pattern tags @@ -32,7 +33,6 @@ PopUpManager.centerPopUp(this); var titles:Array = []; - conn = Connection.getConnection(); relationList = conn.getMatchingRelationIDs(t); if (relationList.length == 0) { warning.text = "No relations available"; diff --git a/net/systemeD/potlatch2/Toolbox.mxml b/net/systemeD/potlatch2/Toolbox.mxml index a553ab6a..dcb05c35 100644 --- a/net/systemeD/potlatch2/Toolbox.mxml +++ b/net/systemeD/potlatch2/Toolbox.mxml @@ -223,7 +223,7 @@ public function doDelete():void { var undo:CompositeUndoableAction = new CompositeUndoableAction("Delete objects"); for each (var entity:Entity in controller.state.selection) { - if (entity is Node) { controller.connection.unregisterPOI(Node(entity)); } + if (entity is Node) { entity.connection.unregisterPOI(Node(entity)); } entity.remove(undo.push); } MainUndoStack.getGlobalStack().addAction(undo); diff --git a/net/systemeD/potlatch2/controller/ControllerState.as b/net/systemeD/potlatch2/controller/ControllerState.as index 94c62f79..e442dba6 100644 --- a/net/systemeD/potlatch2/controller/ControllerState.as +++ b/net/systemeD/potlatch2/controller/ControllerState.as @@ -65,9 +65,9 @@ package net.systemeD.potlatch2.controller { protected function sharedKeyboardEvents(event:KeyboardEvent):ControllerState { switch (event.keyCode) { case 66: setSourceTag(); break; // B - set source tag for current object - case 67: controller.connection.closeChangeset(); break; // C - close changeset + case 67: editableLayer.connection.closeChangeset(); break; // C - close changeset case 68: editableLayer.alpha=1.3-editableLayer.alpha; return null; // D - dim - case 83: SaveManager.saveChanges(controller.connection); break; // S - save + case 83: SaveManager.saveChanges(editableLayer.connection); break; // S - save case 84: controller.tagViewer.togglePanel(); return null; // T - toggle tags panel case 90: if (!event.shiftKey) { MainUndoStack.getGlobalStack().undo(); return null;}// Z - undo else { MainUndoStack.getGlobalStack().redo(); return null; } // Shift-Z - redo @@ -87,7 +87,7 @@ package net.systemeD.potlatch2.controller { if ( paint && paint.isBackground ) { if ( event.type == MouseEvent.MOUSE_DOWN && ((event.shiftKey && event.ctrlKey) || event.altKey) ) { // alt-click to pull data out of vector background layer - var newEntity:Entity=paint.findSource().pullThrough(entity,controller.connection); + var newEntity:Entity=paint.findSource().pullThrough(entity,editableLayer.connection); if (entity is Way) { return new SelectedWay(newEntity as Way); } else if (entity is Node) { return new SelectedPOINode(newEntity as Node); } } else if (event.type == MouseEvent.MOUSE_DOWN && entity is Marker) { @@ -206,7 +206,7 @@ package net.systemeD.potlatch2.controller { protected function revertHandler(event:CloseEvent):void { if (event.detail==Alert.CANCEL) return; for each (var item:Entity in _selection) { - controller.connection.loadEntity(item); + item.connection.loadEntity(item); } } diff --git a/net/systemeD/potlatch2/controller/DragWayNode.as b/net/systemeD/potlatch2/controller/DragWayNode.as index f53a7172..1b618fd9 100644 --- a/net/systemeD/potlatch2/controller/DragWayNode.as +++ b/net/systemeD/potlatch2/controller/DragWayNode.as @@ -43,7 +43,7 @@ package net.systemeD.potlatch2.controller { var lat:Number = controller.map.coord2lat(event.localY); var lon:Number = controller.map.coord2lon(event.localX); var undo:CompositeUndoableAction = new CompositeUndoableAction("Insert node"); - var node:Node = controller.connection.createNode({}, lat, lon, undo.push); + var node:Node = selectedWay.connection.createNode({}, lat, lon, undo.push); var index:int = selectedWay.insertNodeAtClosestPosition(node, true, undo.push); for each (w in ways) { w.insertNodeAtClosestPosition(node, true, undo.push); } MainUndoStack.getGlobalStack().addAction(undo); @@ -59,7 +59,7 @@ package net.systemeD.potlatch2.controller { return new SelectedWayNode(parentWay,draggingIndex); } else if (event.shiftKey && !isNew) { // start new way - var way:Way = controller.connection.createWay({}, [entity], + var way:Way = entity.connection.createWay({}, [entity], MainUndoStack.getGlobalStack().addAction); return new DrawWay(way, true, false); } else if (event.shiftKey && isNew) { diff --git a/net/systemeD/potlatch2/controller/DrawQuadrilateral.as b/net/systemeD/potlatch2/controller/DrawQuadrilateral.as index 4fc55890..a7dc4005 100644 --- a/net/systemeD/potlatch2/controller/DrawQuadrilateral.as +++ b/net/systemeD/potlatch2/controller/DrawQuadrilateral.as @@ -54,7 +54,7 @@ package net.systemeD.potlatch2.controller { override public function enterState():void { controller.map.draggable=false; - var conn:Connection=controller.connection; + var conn:Connection=sourceNode.connection; var undo:CompositeUndoableAction = new CompositeUndoableAction("Draw quadrilateral"); var cornerlon:Number =controller.map.coord2lon(controller.map.mouseX); var cornerlat:Number =controller.map.coord2lat(controller.map.mouseY); diff --git a/net/systemeD/potlatch2/controller/DrawWay.as b/net/systemeD/potlatch2/controller/DrawWay.as index d66f5e0a..84a95497 100644 --- a/net/systemeD/potlatch2/controller/DrawWay.as +++ b/net/systemeD/potlatch2/controller/DrawWay.as @@ -92,7 +92,7 @@ package net.systemeD.potlatch2.controller { var lat:Number = controller.map.coord2lat(event.localY); var lon:Number = controller.map.coord2lon(event.localX); var undo:CompositeUndoableAction = new CompositeUndoableAction("Insert node"); - node = controller.connection.createNode({}, lat, lon, undo.push); + node = firstSelected.connection.createNode({}, lat, lon, undo.push); Way(firstSelected).insertNodeAtClosestPosition(node, true, undo.push); appendNode(node,undo.push); MainUndoStack.getGlobalStack().addAction(undo); @@ -211,7 +211,7 @@ package net.systemeD.potlatch2.controller { var lat:Number = controller.map.coord2lat(event.localY); var lon:Number = controller.map.coord2lon(event.localX); - var node:Node = controller.connection.createNode({}, lat, lon, undo.push); + var node:Node = firstSelected.connection.createNode({}, lat, lon, undo.push); appendNode(node, undo.push); performAction(undo); @@ -245,7 +245,7 @@ package net.systemeD.potlatch2.controller { // Only actually delete the node if it has no other tags, and is not part of other ways (or part of this way twice) if (node.numParentWays==1 && Way(firstSelected).hasOnceOnly(node) && !node.hasInterestingTags()) { editableLayer.setPurgable([node], true); - controller.connection.unregisterPOI(node); + node.connection.unregisterPOI(node); node.remove(undo.push); } diff --git a/net/systemeD/potlatch2/controller/NoSelection.as b/net/systemeD/potlatch2/controller/NoSelection.as index c65c6f2b..5c5f8800 100644 --- a/net/systemeD/potlatch2/controller/NoSelection.as +++ b/net/systemeD/potlatch2/controller/NoSelection.as @@ -26,11 +26,12 @@ package net.systemeD.potlatch2.controller { if (event.type==MouseEvent.MOUSE_UP && (focus==null || (paint && paint.isBackground)) && map.dragstate!=map.DRAGGING) { map.dragstate=map.NOT_DRAGGING; var undo:CompositeUndoableAction = new BeginWayAction(); - var startNode:Node = controller.connection.createNode( + var conn:Connection = editableLayer.connection; + var startNode:Node = conn.createNode( {}, controller.map.coord2lat(event.localY), controller.map.coord2lon(event.localX), undo.push); - var way:Way = controller.connection.createWay({}, [startNode], undo.push); + var way:Way = conn.createWay({}, [startNode], undo.push); MainUndoStack.getGlobalStack().addAction(undo); return new DrawWay(way, true, false); } diff --git a/net/systemeD/potlatch2/controller/SelectedPOINode.as b/net/systemeD/potlatch2/controller/SelectedPOINode.as index 278759db..2710dc99 100644 --- a/net/systemeD/potlatch2/controller/SelectedPOINode.as +++ b/net/systemeD/potlatch2/controller/SelectedPOINode.as @@ -53,7 +53,7 @@ package net.systemeD.potlatch2.controller { } public function deletePOI():ControllerState { - controller.connection.unregisterPOI(firstSelected as Node); + firstSelected.connection.unregisterPOI(firstSelected as Node); firstSelected.remove(MainUndoStack.getGlobalStack().addAction); return new NoSelection(); } diff --git a/net/systemeD/potlatch2/controller/SelectedWay.as b/net/systemeD/potlatch2/controller/SelectedWay.as index 50f02ede..a24ce7b9 100644 --- a/net/systemeD/potlatch2/controller/SelectedWay.as +++ b/net/systemeD/potlatch2/controller/SelectedWay.as @@ -48,7 +48,7 @@ package net.systemeD.potlatch2.controller { if ( event.type == MouseEvent.MOUSE_UP && entity is Node && event.shiftKey ) { // start new way - var way:Way = controller.connection.createWay({}, [entity], MainUndoStack.getGlobalStack().addAction); + var way:Way = entity.connection.createWay({}, [entity], MainUndoStack.getGlobalStack().addAction); return new DrawWay(way, true, false); } else if ( event.type == MouseEvent.MOUSE_DOWN && entity is Way && focus==firstSelected && event.shiftKey) { // insert node within way (shift-click) diff --git a/net/systemeD/potlatch2/controller/SelectedWayNode.as b/net/systemeD/potlatch2/controller/SelectedWayNode.as index 77a050a6..22e48029 100644 --- a/net/systemeD/potlatch2/controller/SelectedWayNode.as +++ b/net/systemeD/potlatch2/controller/SelectedWayNode.as @@ -49,7 +49,7 @@ package net.systemeD.potlatch2.controller { if ( event.type == MouseEvent.MOUSE_UP && entity is Node && event.shiftKey ) { // start new way - var way:Way = controller.connection.createWay({}, [entity], + var way:Way = entity.connection.createWay({}, [entity], MainUndoStack.getGlobalStack().addAction); return new DrawWay(way, true, false); } else if ( event.type == MouseEvent.MOUSE_UP && entity is Node && focus == parentWay ) { @@ -180,7 +180,7 @@ package net.systemeD.potlatch2.controller { var q:Point = map.localToGlobal(p); // First, look for POI nodes in 20x20 pixel box around the current node - var hitnodes:Array = controller.connection.getObjectsByBbox( + var hitnodes:Array = editableLayer.connection.getObjectsByBbox( map.coord2lon(p.x-10), map.coord2lon(p.x+10), map.coord2lat(p.y-10), diff --git a/net/systemeD/potlatch2/mapfeatures/editors/TurnRestrictionEditor.mxml b/net/systemeD/potlatch2/mapfeatures/editors/TurnRestrictionEditor.mxml index 852c4b94..69b97026 100644 --- a/net/systemeD/potlatch2/mapfeatures/editors/TurnRestrictionEditor.mxml +++ b/net/systemeD/potlatch2/mapfeatures/editors/TurnRestrictionEditor.mxml @@ -30,8 +30,7 @@ } public function addNewTurnRestriction():void { - var conn:Connection = Connection.getConnection(); - var relation:Relation = conn.createRelation( + var relation:Relation = _entity.connection.createRelation( { type: 'restriction' }, [ new RelationMember(_entity, 'via') ], MainUndoStack.getGlobalStack().addAction); diff --git a/net/systemeD/potlatch2/mapfeatures/editors/TurnRestrictionIcon.mxml b/net/systemeD/potlatch2/mapfeatures/editors/TurnRestrictionIcon.mxml index 943a41c9..f7cebe68 100644 --- a/net/systemeD/potlatch2/mapfeatures/editors/TurnRestrictionIcon.mxml +++ b/net/systemeD/potlatch2/mapfeatures/editors/TurnRestrictionIcon.mxml @@ -63,6 +63,7 @@ import net.systemeD.potlatch2.RelationEditorPanel; import net.systemeD.potlatch2.mapfeatures.*; import net.systemeD.halcyon.Map; + import net.systemeD.halcyon.MapPaint; import net.systemeD.halcyon.Globals; import flash.events.*; import mx.collections.ArrayCollection; @@ -161,9 +162,9 @@ } private function setHighlights(bool:Boolean):void { - var map:Map = Globals.vars.root; - var from:Object=findSelected('from'); if (from) { map.setHighlight(from.data, { restrictfrom: bool } ); } - var to:Object =findSelected('to' ); if (to ) { map.setHighlight(to.data , { restrictto: bool } ); } + var paint:MapPaint = Map(Globals.vars.root).editableLayer; // ** FIXME: should really be the mapPaint layer where the objects are located + var from:Object=findSelected('from'); if (from) { paint.setHighlight(from.data, { restrictfrom: bool } ); } + var to:Object =findSelected('to' ); if (to ) { paint.setHighlight(to.data , { restrictto: bool } ); } } ]]> diff --git a/net/systemeD/potlatch2/save/OAuthPanel.mxml b/net/systemeD/potlatch2/save/OAuthPanel.mxml index 350df9be..c01a542f 100644 --- a/net/systemeD/potlatch2/save/OAuthPanel.mxml +++ b/net/systemeD/potlatch2/save/OAuthPanel.mxml @@ -86,9 +86,13 @@ private function getAuthText():String { return "To save data you must authorise this application to edit "+ - Connection.serverName + " on your behalf."; + connection.serverName + " on your behalf."; } + public function setConnection(connection:Connection):void { + this.connection=connection; + } + private function openURL(url:String):void { if (ExternalInterface.available) { var winH:int = 560; @@ -105,8 +109,6 @@ } private function getRequestToken():void { - connection = Connection.getConnection(); - var sig:IOAuthSignatureMethod = new OAuthSignatureMethod_HMAC_SHA1(); var consumer:OAuthConsumer = getConsumer(); var url:String = Connection.getParam("oauth_request_url", "http://127.0.0.1:3000/oauth/request_token"); @@ -192,7 +194,7 @@ PopUpManager.removePopUp(this); _accessToken = getResponseToken(URLLoader(event.target)); - Connection.getConnection().setAuthToken(_accessToken); + connection.setAuthToken(_accessToken); dispatchEvent(new Event(ACCESS_TOKEN_EVENT)); } diff --git a/net/systemeD/potlatch2/save/SaveManager.as b/net/systemeD/potlatch2/save/SaveManager.as index bc9ab3d5..c2b95685 100644 --- a/net/systemeD/potlatch2/save/SaveManager.as +++ b/net/systemeD/potlatch2/save/SaveManager.as @@ -33,6 +33,7 @@ package net.systemeD.potlatch2.save { var oauthPanel:OAuthPanel = OAuthPanel( PopUpManager.createPopUp(Application(Application.application), OAuthPanel, true)); PopUpManager.centerPopUp(oauthPanel); + oauthPanel.setConnection(_connection); var listener:Function = function(event:Event):void { var accessToken:OAuthToken = oauthPanel.accessToken; diff --git a/net/systemeD/potlatch2/tools/Circularise.as b/net/systemeD/potlatch2/tools/Circularise.as index 6a0cf9f4..88bf1e84 100644 --- a/net/systemeD/potlatch2/tools/Circularise.as +++ b/net/systemeD/potlatch2/tools/Circularise.as @@ -163,7 +163,7 @@ package net.systemeD.potlatch2.tools { var lon:Number = cx+Math.sin(ang*Math.PI/180)*d; lats.splice(index, 0, lat); lons.splice(index, 0, lon); - var newNode:Node = map.connection.createNode({}, map.latp2lat(lat), lon, action.push); + var newNode:Node = way.connection.createNode({}, map.latp2lat(lat), lon, action.push); way.insertNode(index, newNode, action.push); } } From f841959d8ccebfe25858487fb0d9996825c4d432 Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Sat, 21 May 2011 22:43:15 +0100 Subject: [PATCH 08/89] The branch now loads maps again. Lots of messy code; most of the VectorLayer stuff is commented out and/or derelict. See REFACTOR.txt for more details. --- REFACTOR.txt | 40 +++++++------ net/systemeD/halcyon/Map.as | 3 +- net/systemeD/halcyon/MapPaint.as | 13 ++--- net/systemeD/halcyon/VectorLayer.as | 57 +++++++++++-------- net/systemeD/halcyon/connection/Connection.as | 5 +- net/systemeD/halcyon/connection/Trace.as | 5 +- .../halcyon/connection/XMLConnection.as | 16 +++--- .../potlatch2/BackgroundSelector.mxml | 4 +- net/systemeD/potlatch2/EditController.as | 7 ++- net/systemeD/potlatch2/TagViewer.mxml | 25 ++++---- .../collections/VectorBackgrounds.as | 7 ++- net/systemeD/potlatch2/mygpx/MyGpxDialog.mxml | 5 +- net/systemeD/potlatch2/save/OAuthPanel.mxml | 10 ++-- .../potlatch2/utils/BikeShopLoader.as | 17 +++--- net/systemeD/potlatch2/utils/BugLoader.as | 18 +++--- net/systemeD/potlatch2/utils/TrackLoader.as | 14 +++-- potlatch2.mxml | 43 +++++++------- 17 files changed, 160 insertions(+), 129 deletions(-) diff --git a/REFACTOR.txt b/REFACTOR.txt index 632e6aeb..7945e604 100644 --- a/REFACTOR.txt +++ b/REFACTOR.txt @@ -4,30 +4,34 @@ Aims: - to enable multiple Maps to be shown on-screen (e.g. for junction editor) - to bring Connection and VectorLayer code together -Map.as changes: -becomes a collection of MapPaint objects, all with the same lat/long/scale +Current status: +- it loads a map and lets you edit it! +- VectorLayers (of any shape) will not work - lots of them are commented out +- Save/OAuth not tested + +== Changes overall == + +Map.as becomes a collection of MapPaint objects, all with the same lat/long/scale (plus a backdrop sprite and a background imagery sprite) -√ move listeners to Connection to MapPaint (e.g. new way created in the Connection - MapPaint should know about it, not Map) +Map.editableLayer returns a reference to the single MapPaint object where isBackground is false + +MapPaint.as gains a reference to a Connection - i.e. the source data for this layer -MapPaint.as changes: -- gains a reference to a Connection - i.e. the source data for this layer -- needs an 'interactive' flag -√ UpdateEntityUIs no longer needs a set of entities passing to it - it can read directly from the Connection -- consider whether it's better to have a backreference to Map or for Map to update edges/lat/long/scale etc. +== Stuff to look at == + +There are lots more of these throughout the code, marked with fixmes of the form '>>>> REFACTOR' + +MapPaint.as - wayuis, nodeuis etc. should ideally be private - removeLayer should blank -VectorLayer.as changes: +VectorLayer.as is completely derelict - move into Connection +- references in Loader classes etc. currently commented out +- everything derived from VectorLayers (e.g. Traces, Bugs, BikeShopLoader) needs completely refactoring Global changes: -- move lots of connection.map to connection.map.editableLayer -- remove all references to getConnection etc. - there can now be more than one Connection - remove all back-references to Map except where necessary for lat/long/scale -- getParam is broken - there needs to be a global equivalent (not in Connection) for stuff sent via flashvars - i.e. loaderInfo.parameters (but that's Flex-only) -- Look for Connection. - lots of static stuff which shouldn't be that any more - -Further refactoring probably needed: -- move AttentionEvent stuff (some may be commented out) -- Traces (e.g. in potlatch2.mxml) - seems a bit mixed up -- refactor tileset/setbackground stuff? +- getParam is messy - stuff sent via flashvars needs somewhere to live: currently in Globals which is ugly +- AttentionEvents are derelict and commented out +- tileset/setbackground stuff is screwed up again and needs refactoring a little diff --git a/net/systemeD/halcyon/Map.as b/net/systemeD/halcyon/Map.as index c0fdd699..a2299f8a 100644 --- a/net/systemeD/halcyon/Map.as +++ b/net/systemeD/halcyon/Map.as @@ -75,7 +75,7 @@ package net.systemeD.halcyon { /** background tile object */ public var tileset:TileSet; /** background tile URL, name and scheme */ - private var tileparams:Object={ url:'' }; + public var tileparams:Object={ url:'' }; /** show all objects, even if unstyled? */ public var showall:Boolean=true; @@ -224,6 +224,7 @@ package net.systemeD.halcyon { * The bounding box for the download is taken from the current map edges. */ public function download():void { +trace("download "+edge_l+","+edge_r+","+edge_t+","+edge_b) this.dispatchEvent(new MapEvent(MapEvent.DOWNLOAD, {minlon:edge_l, maxlon:edge_r, maxlat:edge_t, minlat:edge_b} )); for (var i:uint=0; i>>> REFACTOR: remove this public function findSource():VectorLayer { - var v:VectorLayer; - for each (v in map.vectorlayers) { - if (v.paint==this) { return v; } - } +// var v:VectorLayer; +// for each (v in map.vectorlayers) { +// if (v.paint==this) { return v; } +// } return null; } diff --git a/net/systemeD/halcyon/VectorLayer.as b/net/systemeD/halcyon/VectorLayer.as index 4631b0e4..04e2ba80 100644 --- a/net/systemeD/halcyon/VectorLayer.as +++ b/net/systemeD/halcyon/VectorLayer.as @@ -37,7 +37,8 @@ package net.systemeD.halcyon { name=n; map=m; style=s; - paint=new MapPaint(m,0,0); + // >>>> REFACTOR: VectorLayer commented out +// paint=new MapPaint(m,0,0); redrawFromCSS(style); } @@ -52,9 +53,11 @@ package net.systemeD.halcyon { * e.g. layer.paint.updateEntityUIs(...); */ public function createNode(tags:Object,lat:Number,lon:Number):Node { - var node:Node = new Node(this, negativeID, 0, tags, true, lat, lon); - nodes[negativeID]=node; negativeID--; - return node; + // >>>> REFACTOR: VectorLayer commented out +// var node:Node = new Node(this, negativeID, 0, tags, true, lat, lon); +// nodes[negativeID]=node; negativeID--; +// return node; + return null; } /** @@ -62,9 +65,11 @@ package net.systemeD.halcyon { * @param nodes An array of Node objects */ public function createWay(tags:Object,nodes:Array):Way { - var way:Way = new Way(this, negativeID, 0, tags, true, nodes.concat()); - ways[negativeID]=way; negativeID--; - return way; + // >>>> REFACTOR: VectorLayer commented out +// var way:Way = new Way(this, negativeID, 0, tags, true, nodes.concat()); +// ways[negativeID]=way; negativeID--; +// return way; + return null; } /** @@ -72,9 +77,11 @@ package net.systemeD.halcyon { * @param members An array of RelationMember objects */ public function createRelation(tags:Object,members:Array):Relation { - var relation:Relation = new Relation(this, negativeID, 0, tags, true, members.concat()); - relations[negativeID]=relation; negativeID--; - return relation; + // >>>> REFACTOR: VectorLayer commented out +// var relation:Relation = new Relation(this, negativeID, 0, tags, true, members.concat()); +// relations[negativeID]=relation; negativeID--; +// return relation; + return null; } /** @@ -91,12 +98,14 @@ package net.systemeD.halcyon { id = negativeID; negativeID--; } - var marker:Marker = markers[id]; - if (marker == null) { - marker = new Marker(this, id, 0, tags, true, lat, lon); - markers[id]=marker; - } - return marker; + // >>>> REFACTOR: VectorLayer commented out +// var marker:Marker = markers[id]; +// if (marker == null) { +// marker = new Marker(this, id, 0, tags, true, lat, lon); +// markers[id]=marker; +// } +// return marker; + return null; } public function registerPOI(node:Node):void { @@ -161,7 +170,7 @@ package net.systemeD.halcyon { } paint.wayuis[oldWay.id].redraw(); delete ways[oldWay.id]; - map.paint.createWayUI(newWay); + paint.createWayUI(newWay); return newWay; } else if (entity is Node && !entity.hasParentWays) { @@ -169,12 +178,14 @@ package net.systemeD.halcyon { // ** should be properly undoable oldNode=Node(entity); unregisterPOI(oldNode); - var newPoiAction:CreatePOIAction = new CreatePOIAction( - this, oldNode.getTagsCopy(), oldNode.lat, oldNode.lon); - MainUndoStack.getGlobalStack().addAction(newPoiAction); - paint.deleteNodeUI(oldNode); - delete nodes[oldNode.id]; - return newPoiAction.getNode(); + // >>>> REFACTOR: VectorLayer commented out +// var newPoiAction:CreatePOIAction = new CreatePOIAction( +// this, oldNode.getTagsCopy(), oldNode.lat, oldNode.lon); +// MainUndoStack.getGlobalStack().addAction(newPoiAction); +// paint.deleteNodeUI(oldNode); +// delete nodes[oldNode.id]; +// return newPoiAction.getNode(); + return null; } return null; } diff --git a/net/systemeD/halcyon/connection/Connection.as b/net/systemeD/halcyon/connection/Connection.as index dced4d3a..5f5737cc 100644 --- a/net/systemeD/halcyon/connection/Connection.as +++ b/net/systemeD/halcyon/connection/Connection.as @@ -7,6 +7,7 @@ package net.systemeD.halcyon.connection { import net.systemeD.halcyon.AttentionEvent; import net.systemeD.halcyon.MapEvent; import net.systemeD.halcyon.connection.actions.*; + import net.systemeD.halcyon.Globals; public class Connection extends EventDispatcher { @@ -24,7 +25,9 @@ package net.systemeD.halcyon.connection { } public function getParam(name:String, defaultValue:String):String { - return params[name] == null ? defaultValue : params[name]; + if (params[name]) return params[name]; + if (Globals.vars.flashvars[name]) return Globals.vars.flashvars[name]; + return defaultValue; } public function get apiBase():String { diff --git a/net/systemeD/halcyon/connection/Trace.as b/net/systemeD/halcyon/connection/Trace.as index 4c7597e7..2c0c1a5f 100644 --- a/net/systemeD/halcyon/connection/Trace.as +++ b/net/systemeD/halcyon/connection/Trace.as @@ -74,8 +74,9 @@ package net.systemeD.halcyon.connection { private function get layer():VectorLayer { if (!_layer) { - _layer=new VectorLayer(filename,map,STYLESHEET); - map.addVectorLayer(_layer); + // >>>> REFACTOR: VectorLayer commented out + // _layer=new VectorLayer(filename,map,STYLESHEET); + // map.addVectorLayer(_layer); } return _layer; } diff --git a/net/systemeD/halcyon/connection/XMLConnection.as b/net/systemeD/halcyon/connection/XMLConnection.as index 4f72b737..8a428fcd 100644 --- a/net/systemeD/halcyon/connection/XMLConnection.as +++ b/net/systemeD/halcyon/connection/XMLConnection.as @@ -38,15 +38,16 @@ package net.systemeD.halcyon.connection { var mapVars:URLVariables = new URLVariables(); mapVars.bbox= left+","+bottom+","+right+","+top; +trace("requesting "+mapVars.bbox); - var mapRequest:URLRequest = new URLRequest(Connection.apiBaseURL+"map"); + var mapRequest:URLRequest = new URLRequest(apiBaseURL+"map"); mapRequest.data = mapVars; sendLoadRequest(mapRequest); } override public function loadEntityByID(type:String, id:Number):void { - var url:String=Connection.apiBaseURL + type + "/" + id; + var url:String=apiBaseURL + type + "/" + id; if (type=='way') url+="/full"; sendLoadRequest(new URLRequest(url)); } @@ -130,7 +131,7 @@ package net.systemeD.halcyon.connection { changesetXML.changeset.appendChild(tagXML); } - sendOAuthPut(Connection.apiBaseURL+"changeset/create", + sendOAuthPut(apiBaseURL+"changeset/create", changesetXML, changesetCreateComplete, changesetCreateError, recordStatus); } @@ -151,7 +152,7 @@ package net.systemeD.halcyon.connection { var cs:Changeset = getActiveChangeset(); if (!cs) return; - sendOAuthPut(Connection.apiBaseURL+"changeset/"+cs.id+"/close", + sendOAuthPut(apiBaseURL+"changeset/"+cs.id+"/close", null, changesetCloseComplete, changesetCloseError, recordStatus); closeActiveChangeset(); @@ -215,7 +216,7 @@ package net.systemeD.halcyon.connection { // now actually upload them // make an OAuth query - var url:String = Connection.apiBaseURL+"changeset/" + changeset.id + "/upload"; + var url:String = apiBaseURL+"changeset/" + changeset.id + "/upload"; // build the actual request var serv:HTTPService=new HTTPService(); @@ -429,8 +430,7 @@ package net.systemeD.halcyon.connection { if (traces_loaded && !refresh) { dispatchEvent(new Event(TRACES_LOADED)); } else { - sendOAuthGet(Connection.apiBaseURL+"user/gpx_files", - tracesLoadComplete, errorOnMapLoad, mapLoadStatus); //needs error handlers + sendOAuthGet(apiBaseURL+"user/gpx_files", tracesLoadComplete, errorOnMapLoad, mapLoadStatus); //needs error handlers dispatchEvent(new Event(LOAD_STARTED)); //specific to map or reusable? } } @@ -448,7 +448,7 @@ package net.systemeD.halcyon.connection { } override public function fetchTrace(id:Number, callback:Function):void { - sendOAuthGet(Connection.apiBaseURL+"gpx/"+id+"/data.xml", + sendOAuthGet(apiBaseURL+"gpx/"+id+"/data.xml", function(e:Event):void { dispatchEvent(new Event(LOAD_COMPLETED)); callback(e); diff --git a/net/systemeD/potlatch2/BackgroundSelector.mxml b/net/systemeD/potlatch2/BackgroundSelector.mxml index 551e87fc..bc0922a3 100644 --- a/net/systemeD/potlatch2/BackgroundSelector.mxml +++ b/net/systemeD/potlatch2/BackgroundSelector.mxml @@ -18,10 +18,12 @@ - + >>> REFACTOR: vector file button was click="Application.application.bgButton.close(); new VectorSourceDialog().init();" but that's amazingly broken --> + import net.systemeD.halcyon.*; import net.systemeD.halcyon.connection.*; import net.systemeD.potlatch2.*; diff --git a/net/systemeD/potlatch2/EditController.as b/net/systemeD/potlatch2/EditController.as index 48a47716..7cdbae26 100644 --- a/net/systemeD/potlatch2/EditController.as +++ b/net/systemeD/potlatch2/EditController.as @@ -4,6 +4,7 @@ package net.systemeD.potlatch2 { import net.systemeD.halcyon.MapEvent; import net.systemeD.halcyon.connection.*; import net.systemeD.halcyon.VectorLayer; + import net.systemeD.halcyon.Globals; import net.systemeD.potlatch2.controller.*; import net.systemeD.potlatch2.FunctionKeyManager; import mx.managers.CursorManager; @@ -45,9 +46,9 @@ package net.systemeD.potlatch2 { this.tagViewer = tagViewer; this.toolbox = toolbox; this.toolbox.init(this); - this.maximiseFunction = Connection.getParam("maximise_function", null); - this.minimiseFunction = Connection.getParam("minimise_function", null); - this.moveFunction = Connection.getParam("move_function", null); + this.maximiseFunction = Globals.vars.flashvars["maximise_function"]; + this.minimiseFunction = Globals.vars.flashvars["minimise_function"]; + this.moveFunction = Globals.vars.flashvars["move_function"]; map.parent.addEventListener(MouseEvent.MOUSE_MOVE, mapMouseEvent); map.parent.addEventListener(MouseEvent.MOUSE_UP, mapMouseEvent); diff --git a/net/systemeD/potlatch2/TagViewer.mxml b/net/systemeD/potlatch2/TagViewer.mxml index 582d9212..eb9b636b 100644 --- a/net/systemeD/potlatch2/TagViewer.mxml +++ b/net/systemeD/potlatch2/TagViewer.mxml @@ -234,6 +234,7 @@ public var mapFeatures:MapFeatures; private var selectedEntity:Entity; + private var connection:Connection; private var currentCategorySelector:CategorySelector; private var categorySelectors:Object = {}; // hash of categorySelectors for each limitType private var feature:Feature = null; @@ -242,6 +243,7 @@ public function setEntity(entities:Array, layer:VectorLayer=null):void { UIComponent.suspendBackgroundProcessing(); + connection=null; var firstSelected:Entity=null; if (entities.length==1) { firstSelected=entities[0]; } @@ -259,6 +261,7 @@ } else if (entities.length==1) { // Single entity selected, so show tag panel selectedEntity=firstSelected; + connection=firstSelected.connection; if (selectedEntity!=null) { selectedEntity.addEventListener(Connection.TAG_CHANGED, tagChanged); } if (advancedID!=null) { setupAdvanced(firstSelected); } if (firstSelected is Relation) { stack.addChild(membersVBox); } @@ -279,7 +282,8 @@ selectedEntity.addEventListener(Connection.TAG_CHANGED, tagChanged); sidebar.selectedChild = multiplePanel; setupMultiAdvanced(selectedEntity); - + connection=entities[0].connection; + } else { //The selection contains elements which can't be edited all together. sidebar.selectedChild = multipleInvalidPanel; @@ -622,8 +626,7 @@ // but is at least robust for any kind of change. // Figuring out a better way is someone else's FIXME - var conn:Connection = Connection.getConnection(); - var rel:Relation = selectedEntity as Relation + var rel:Relation = selectedEntity as Relation; var action:CompositeUndoableAction = new CompositeUndoableAction("Rearrange relation members for "+rel); // drop members @@ -635,12 +638,10 @@ for each(var memberObject:Object in membersGrid.dataProvider) { var e:Entity; var id:Number = memberObject.id; - if(memberObject.type == 'node') { - e = conn.getNode(id); - } else if (memberObject.type == 'way') { - e = conn.getWay(id); - } else if (memberObject.type == 'relation') { - e = conn.getRelation(id); + switch (memberObject.type) { + case 'node': e = connection.getNode(id); break; + case 'way': e = connection.getWay(id); break; + case 'relation': e = connection.getRelation(id); break; } rel.appendMember(new RelationMember(e, memberObject.role), action.push); } @@ -650,7 +651,7 @@ private function editRelation(id:Number):void { var panel:RelationEditorPanel = RelationEditorPanel( PopUpManager.createPopUp(Application(Application.application), RelationEditorPanel, true)); - panel.setRelation(Connection.getConnection().getRelation(id)); + panel.setRelation(connection.getRelation(id)); PopUpManager.centerPopUp(panel); } @@ -742,7 +743,7 @@ public function openEntityPage():void { if (selectedEntity != null && selectedEntity.id >= 0) { // This is slightly hard-coded, but not drastically. The ../s could be changed for string manipulation of the apiBase - var urlBase:String = Connection.getConnection().apiBase + '../../browse/' + var urlBase:String = connection.apiBase + '../../browse/' navigateToURL(new URLRequest(urlBase+selectedEntity.getType()+'/'+selectedEntity.id), "potlatch_browse"); } } @@ -752,7 +753,7 @@ } private function removeFromRelation(id:Number, index:int=-1):void { - var rel:Relation=Connection.getConnection().getRelation(id); + var rel:Relation=connection.getRelation(id); if (index>-1) { rel.removeMemberByIndex(index, MainUndoStack.getGlobalStack().addAction); } else if (selectedEntity is EntityCollection) { diff --git a/net/systemeD/potlatch2/collections/VectorBackgrounds.as b/net/systemeD/potlatch2/collections/VectorBackgrounds.as index 6646e3d8..b84f8956 100644 --- a/net/systemeD/potlatch2/collections/VectorBackgrounds.as +++ b/net/systemeD/potlatch2/collections/VectorBackgrounds.as @@ -47,9 +47,10 @@ package net.systemeD.potlatch2.collections { if (set.url) { if (set.@loaded == "true") { name ||= 'GPX file'; - var layer:VectorLayer = new VectorLayer(name, _map, 'stylesheets/gpx.css'); - _map.addVectorLayer(layer); - var gpxImporter:GpxImporter = new GpxImporter(layer, layer.paint, [String(set.url)]); + // >>>> REFACTOR: VectorLayer commented out + // var layer:VectorLayer = new VectorLayer(name, _map, 'stylesheets/gpx.css'); + // _map.addVectorLayer(layer); + // var gpxImporter:GpxImporter = new GpxImporter(layer, layer.paint, [String(set.url)]); } else { trace("configured but not loaded isn't supported yet"); } diff --git a/net/systemeD/potlatch2/mygpx/MyGpxDialog.mxml b/net/systemeD/potlatch2/mygpx/MyGpxDialog.mxml index 3ca3c5c8..bdce15c1 100644 --- a/net/systemeD/potlatch2/mygpx/MyGpxDialog.mxml +++ b/net/systemeD/potlatch2/mygpx/MyGpxDialog.mxml @@ -27,11 +27,12 @@ PopUpManager.centerPopUp(this); this.addEventListener(CloseEvent.CLOSE, myGpxDialog_close); - conn = Connection.getConnection(); + // >>>> REFACTOR: really horrible way of getting both map and connection map = Globals.vars.root; + conn = map.editableLayer.connection; conn.addEventListener(Connection.TRACES_LOADED, onTracesLoaded); - SaveManager.ensureAccess(fetchList); + SaveManager.ensureAccess(fetchList, conn); } private function myGpxDialog_close(evt:CloseEvent):void { diff --git a/net/systemeD/potlatch2/save/OAuthPanel.mxml b/net/systemeD/potlatch2/save/OAuthPanel.mxml index c01a542f..5a9285fc 100644 --- a/net/systemeD/potlatch2/save/OAuthPanel.mxml +++ b/net/systemeD/potlatch2/save/OAuthPanel.mxml @@ -111,7 +111,7 @@ private function getRequestToken():void { var sig:IOAuthSignatureMethod = new OAuthSignatureMethod_HMAC_SHA1(); var consumer:OAuthConsumer = getConsumer(); - var url:String = Connection.getParam("oauth_request_url", "http://127.0.0.1:3000/oauth/request_token"); + var url:String = connection.getParam("oauth_request_url", "http://127.0.0.1:3000/oauth/request_token"); var params:Object = new Object(); var oauthRequest:OAuthRequest = new OAuthRequest("GET", url, params, consumer, null); @@ -150,7 +150,7 @@ trace("Yay! response: "+URLLoader(event.target).data); requestToken = getResponseToken(URLLoader(event.target)); - var url:String = Connection.getParam("oauth_auth_url", "http://127.0.0.1:3000/oauth/authorize"); + var url:String = connection.getParam("oauth_auth_url", "http://127.0.0.1:3000/oauth/authorize"); link.label = url; authoriseURL = url + "?oauth_token="+requestToken.key; progress.visible = false; @@ -170,7 +170,7 @@ private function getAccessToken():void { var sig:IOAuthSignatureMethod = new OAuthSignatureMethod_HMAC_SHA1(); var consumer:OAuthConsumer = getConsumer(); - var url:String = Connection.getParam("oauth_access_url", "http://127.0.0.1:3000/oauth/access_token"); + var url:String = connection.getParam("oauth_access_url", "http://127.0.0.1:3000/oauth/access_token"); var oauthRequest:OAuthRequest = new OAuthRequest("GET", url, null, consumer, requestToken); var urlStr:Object = oauthRequest.buildRequest(sig, OAuthRequest.RESULT_TYPE_URL_STRING) @@ -216,8 +216,8 @@ } private function getConsumer():OAuthConsumer { - var key:String = Connection.getParam("oauth_consumer_key", ""); - var secret:String = Connection.getParam("oauth_consumer_secret", ""); + var key:String = connection.getParam("oauth_consumer_key", ""); + var secret:String = connection.getParam("oauth_consumer_secret", ""); return new OAuthConsumer(key, secret); } diff --git a/net/systemeD/potlatch2/utils/BikeShopLoader.as b/net/systemeD/potlatch2/utils/BikeShopLoader.as index 6be59e01..86f203c0 100644 --- a/net/systemeD/potlatch2/utils/BikeShopLoader.as +++ b/net/systemeD/potlatch2/utils/BikeShopLoader.as @@ -67,14 +67,15 @@ package net.systemeD.potlatch2.utils { } private function get layer():VectorLayer { - if (!_layer) { - var policyFile:String = bikeShopBaseURL+"crossdomain.xml"; - Security.loadPolicyFile(policyFile); - - _layer=new VectorLayer(name,map,STYLESHEET); - map.addVectorLayer(_layer); - } - return _layer; + // >>>> REFACTOR: VectorLayer commented out + // if (!_layer) { + // var policyFile:String = bikeShopBaseURL+"crossdomain.xml"; + // Security.loadPolicyFile(policyFile); + // _layer=new VectorLayer(name,map,STYLESHEET); + // map.addVectorLayer(_layer); + // } + // return _layer; + return null; } } } \ No newline at end of file diff --git a/net/systemeD/potlatch2/utils/BugLoader.as b/net/systemeD/potlatch2/utils/BugLoader.as index 3ba731fa..5b70251f 100644 --- a/net/systemeD/potlatch2/utils/BugLoader.as +++ b/net/systemeD/potlatch2/utils/BugLoader.as @@ -33,15 +33,15 @@ package net.systemeD.potlatch2.utils { private function get layer():VectorLayer { - if (!_layer) { - - var policyFile:String = bugBaseURL+"crossdomain.xml"; - Security.loadPolicyFile(policyFile); - - _layer=new BugLayer(name,map,STYLESHEET,bugBaseURL,bugApiKey,bugDetailsURL); - map.addVectorLayer(_layer); - } - return _layer; + // >>>> REFACTOR: VectorLayer commented out + // if (!_layer) { + // var policyFile:String = bugBaseURL+"crossdomain.xml"; + // Security.loadPolicyFile(policyFile); + // _layer=new BugLayer(name,map,STYLESHEET,bugBaseURL,bugApiKey,bugDetailsURL); + // map.addVectorLayer(_layer); + // } + // return _layer; + return null; } } } \ No newline at end of file diff --git a/net/systemeD/potlatch2/utils/TrackLoader.as b/net/systemeD/potlatch2/utils/TrackLoader.as index 812c5078..2835030a 100644 --- a/net/systemeD/potlatch2/utils/TrackLoader.as +++ b/net/systemeD/potlatch2/utils/TrackLoader.as @@ -75,12 +75,14 @@ package net.systemeD.potlatch2.utils { } private function get layer():VectorLayer { - var vl:VectorLayer=map.findVectorLayer('GPS tracks'); - if (!vl) { - vl=new VectorLayer('GPS tracks',map,STYLESHEET); - map.addVectorLayer(vl); - } - return vl; + // >>>> REFACTOR: VectorLayer commented out + // var vl:VectorLayer=map.findVectorLayer('GPS tracks'); + // if (!vl) { + // vl=new VectorLayer('GPS tracks',map,STYLESHEET); + // map.addVectorLayer(vl); + // } + // return vl; + return null; } private function greatCircle(lat1:Number,lon1:Number,lat2:Number,lon2:Number):Number { diff --git a/potlatch2.mxml b/potlatch2.mxml index 133c5f40..d7744c23 100644 --- a/potlatch2.mxml +++ b/potlatch2.mxml @@ -37,7 +37,7 @@ else if (event.index==1) { new MyGpxDialog().init(); } else { mx.controls.Menu(gpsButton.popUp).selectedIndex=0; mx.controls.Menu(gpsButton.popUp).selectedIndex=0; /* Yes, we do need to call it twice */ - theMap.removeVectorLayer(theMap.findVectorLayer('GPS tracks')); }"> + theMap.removeLayerByName('GPS tracks'); }"> @@ -147,6 +147,7 @@ Globals.vars.root = map_area.rawChildren; // set up global reference to root level var _root:IChildList = map_area.rawChildren; // convenient local shorthand Globals.vars.nocache = loaderInfo.parameters['nocache'] == 'true'; + Globals.vars.flashvars = loaderInfo.parameters; // populate sharedObject with loaderInfo parameters if supplied var obj:SharedObject = SharedObject.getLocal("user_state"); @@ -179,18 +180,26 @@ for (k in SharedObject.getLocal('user_state').data) params[k]=SharedObject.getLocal('user_state').data[k]; // Create map - theMap=new Map(params); + theMap=new Map(); + theMap.backdrop=b; + theMap.updateSize(w,h); + theMap.addEventListener(MapEvent.SCALE, scaleHandler); + + yahoo=new Yahoo(theMap); + yahoo.hide(); + _root.addChild(yahoo); + _root.addChild(theMap); // Initialise 900913 background // >>>> REFACTOR: something odd about accessing map.tileparams here... - map.tileset.blocks=[new RegExp("google","i")]; // hard-coded block on Google tiles - map.tileset.init(map.tileparams, false, - initparams['background_dim'] ==null ? true : initparams['background_dim'], - initparams['background_sharpen']==null ? false : initparams['background_sharpen']); + theMap.tileset.blocks=[new RegExp("google","i")]; // hard-coded block on Google tiles + theMap.tileset.init(theMap.tileparams, false, + params['background_dim'] ==null ? true : params['background_dim'], + params['background_sharpen']==null ? false : params['background_sharpen']); // Add core data layer // >>>> REFACTOR: shouldn't be hardcoded to XMLConnection - var conn:Connection = new XMLConnection("Main", initparams['api'], initparams['policy'], initparams); + var conn:Connection = new XMLConnection("Main", params['api'], params['policy'], params); conn.addEventListener(Connection.LOAD_STARTED, onDataStart); conn.addEventListener(Connection.LOAD_COMPLETED, onDataComplete); conn.addEventListener(Connection.SAVE_STARTED, onDataStart); @@ -200,24 +209,17 @@ conn.addEventListener(MapEvent.ERROR, onMapError); conn.addEventListener(AttentionEvent.ATTENTION, onAttention); conn.addEventListener(AttentionEvent.ALERT, onAlert); - map.addLayer(conn,initparams['styleurl'],false); + // >>>> REFACTOR: shouldn't be trying to find out stylesheet from here + theMap.addLayer(conn,params['styleurl'] ? params['styleurl'] : 'stylesheets/potlatch.css',false); // Set start position of map // >>>> REFACTOR: what happens if lat/lon/zoom not supplied? (Hurleston GPX case) - map.init(initparams['lat'], initparams['lon'], initparams['zoom']); + theMap.init(params['lat'], params['lon'], params['zoom']); // Auto-load vector backgrounds from config // This could go spectacularly wrong if map.init completes before the event listener below is added theMap.addEventListener(MapEvent.INITIALISED, function(e:Event):void { VectorBackgrounds.instance().init(theMap); }); - theMap.backdrop=b; - yahoo=new Yahoo(theMap); - yahoo.hide(); - _root.addChild(yahoo); - _root.addChild(theMap); - theMap.updateSize(w,h); - theMap.addEventListener(MapEvent.SCALE, scaleHandler); - // add attribution/logo sprite var overlay:Sprite=new Sprite(); var attribution:TextField=new TextField(); @@ -278,7 +280,7 @@ if (conn.hasAccessToken()) { loadTrace(id); } else { - SaveManager.ensureAccess(function ():void { loadTrace(id); }); + SaveManager.ensureAccess(function ():void { loadTrace(id); }, conn); } } @@ -289,7 +291,8 @@ var gpx:GpxImporter=new GpxImporter(vectorlayer, vectorlayer.paint, [vectorlayer.url], function(success:Boolean,message:String=null):void { if (!success) return; - theMap.addVectorLayer(vectorlayer); + // >>>> REFACTOR: vectorlayer commented out +// theMap.addVectorLayer(vectorlayer); dispatchEvent(new Event("layers_changed")); }, false); } @@ -301,7 +304,7 @@ // force_auth == force => checks for access token, and displays OAuth panel if needed var force_auth:String = loaderInfo.parameters["force_auth"]; if (!conn.hasAccessToken() && force_auth == 'force') { - SaveManager.ensureAccess(onAccessChecked); + SaveManager.ensureAccess(onAccessChecked, conn); } // show help dialog on startup, if required From 32ff3c97a7980b62e98fb9696f1f9dc891262eab Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Sat, 21 May 2011 23:21:41 +0100 Subject: [PATCH 09/89] Remove a couple of debug traces. --- TODO.txt | 1 + net/systemeD/halcyon/Map.as | 1 - net/systemeD/halcyon/connection/XMLConnection.as | 1 - 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/TODO.txt b/TODO.txt index 91b3fe81..9566d4df 100644 --- a/TODO.txt +++ b/TODO.txt @@ -5,6 +5,7 @@ Potlatch 2: main outstanding issues * P1-style J (join) * Doing a '-' to remove a point from a junction doesn't redraw the point on other ways +* Circularise doesn't redraw the nodes on the selected way == Vector background layers == diff --git a/net/systemeD/halcyon/Map.as b/net/systemeD/halcyon/Map.as index a2299f8a..e24a6ce6 100644 --- a/net/systemeD/halcyon/Map.as +++ b/net/systemeD/halcyon/Map.as @@ -224,7 +224,6 @@ package net.systemeD.halcyon { * The bounding box for the download is taken from the current map edges. */ public function download():void { -trace("download "+edge_l+","+edge_r+","+edge_t+","+edge_b) this.dispatchEvent(new MapEvent(MapEvent.DOWNLOAD, {minlon:edge_l, maxlon:edge_r, maxlat:edge_t, minlat:edge_b} )); for (var i:uint=0; i Date: Mon, 23 May 2011 12:22:08 +0100 Subject: [PATCH 10/89] Update trackloader to avoid using VectorLayer --- net/systemeD/halcyon/Map.as | 3 +- net/systemeD/potlatch2/utils/TrackLoader.as | 35 +++++++++++---------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/net/systemeD/halcyon/Map.as b/net/systemeD/halcyon/Map.as index e24a6ce6..1c790931 100644 --- a/net/systemeD/halcyon/Map.as +++ b/net/systemeD/halcyon/Map.as @@ -245,10 +245,11 @@ package net.systemeD.halcyon { // ------------------------------------------------------------------------------------------ // Add layers - public function addLayer(connection:Connection, styleurl:String, backgroundlayer:Boolean=true):void { + public function addLayer(connection:Connection, styleurl:String, backgroundlayer:Boolean=true):MapPaint { var paint:MapPaint=new MapPaint(this, connection, styleurl, -5, 5); paintContainer.addChild(paint); paint.isBackground=backgroundlayer; + return paint; } public function removeLayerByName(name:String):void { diff --git a/net/systemeD/potlatch2/utils/TrackLoader.as b/net/systemeD/potlatch2/utils/TrackLoader.as index 2835030a..25b3b750 100644 --- a/net/systemeD/potlatch2/utils/TrackLoader.as +++ b/net/systemeD/potlatch2/utils/TrackLoader.as @@ -2,7 +2,7 @@ package net.systemeD.potlatch2.utils { import net.systemeD.halcyon.connection.*; import net.systemeD.halcyon.Map; - import net.systemeD.halcyon.VectorLayer; + import net.systemeD.halcyon.MapPaint; import flash.net.*; import flash.events.*; @@ -20,12 +20,15 @@ package net.systemeD.potlatch2.utils { private var map:Map; private var apiBaseURL:String; + private var connection:Connection; /* to store the nodes/ways that are faked up for GPX tracks */ private static const STYLESHEET:String="stylesheets/gpx.css"; + private static const LAYER:String="GPS tracks"; public function TrackLoader(map:Map, url:String) { this.map=map; apiBaseURL=url; + connection = new Connection(LAYER,apiBaseURL,null, null); } public function load(keep:Boolean=false):void { @@ -37,9 +40,10 @@ package net.systemeD.potlatch2.utils { top =map.edge_t; bottom=map.edge_b; page=0; - if (!keep) { } // ** TODO: blank the vector layer + if (!keep) { } // ** TODO: blank the connection objects } + /* This isn't great - conceptially it would be nicer for the connection to do the request */ var loader:URLLoader = new URLLoader(); loader.load(new URLRequest(apiBaseURL+"trackpoints?bbox="+left+","+bottom+","+right+","+top+"&page="+page)); loader.addEventListener(Event.COMPLETE, parseGPX); @@ -47,6 +51,7 @@ package net.systemeD.potlatch2.utils { public function parseGPX(event:Event):void { var file:XML = new XML(event.target.data); + var action:CompositeUndoableAction = new CompositeUndoableAction("add track objects"); for each (var ns:Namespace in file.namespaceDeclarations()) { if (ns.uri.match(/^http:\/\/www\.topografix\.com\/GPX\/1\/[01]$/)) { default xml namespace = ns; @@ -61,28 +66,26 @@ package net.systemeD.potlatch2.utils { lat = trkpt.@lat; lon = trkpt.@lon; if (lastlat && nodestring.length > 0 && greatCircle(lat, lon, lastlat, lastlon) > 30) { - layer.createWay({}, nodestring); + connection.createWay({}, nodestring, action.push); nodestring = []; } - nodestring.push(layer.createNode({}, lat, lon)); + nodestring.push(connection.createNode({}, lat, lon, action.push)); lastlat = lat; lastlon = lon; } - if (nodestring.length > 0) { layer.createWay({}, nodestring); } + if (nodestring.length > 0) { connection.createWay({}, nodestring, action.push); trace("create way");} } - + + action.doAction(); /* just do it, don't add to undo stack */ default xml namespace = new Namespace(""); - layer.paint.updateEntityUIs(false, false); + layer.updateEntityUIs(false, false); } - private function get layer():VectorLayer { - // >>>> REFACTOR: VectorLayer commented out - // var vl:VectorLayer=map.findVectorLayer('GPS tracks'); - // if (!vl) { - // vl=new VectorLayer('GPS tracks',map,STYLESHEET); - // map.addVectorLayer(vl); - // } - // return vl; - return null; + private function get layer():MapPaint { + var mp:MapPaint = map.findLayer(LAYER); + if (!mp) { + mp = map.addLayer(connection, STYLESHEET); + } + return mp; } private function greatCircle(lat1:Number,lon1:Number,lat2:Number,lon2:Number):Number { From 7555638e0e06d27fb63b7d8f3b12f639c56f1d42 Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Mon, 23 May 2011 12:48:22 +0100 Subject: [PATCH 11/89] Document the TrackLoader --- net/systemeD/potlatch2/utils/TrackLoader.as | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/net/systemeD/potlatch2/utils/TrackLoader.as b/net/systemeD/potlatch2/utils/TrackLoader.as index 25b3b750..d24e0d64 100644 --- a/net/systemeD/potlatch2/utils/TrackLoader.as +++ b/net/systemeD/potlatch2/utils/TrackLoader.as @@ -10,6 +10,7 @@ package net.systemeD.potlatch2.utils { - empty layer on reload - cope with tracks with timestamps */ + /** A TrackLoader will load the public GPX traces for the current map bounding box into a separate layer */ public class TrackLoader { private var left:Number=0; @@ -24,13 +25,20 @@ package net.systemeD.potlatch2.utils { private static const STYLESHEET:String="stylesheets/gpx.css"; private static const LAYER:String="GPS tracks"; - + + /** Create a new TrackLoader + * @param map The map object you want to the GPS tracks layer to be added to + * @param url The url of the server api base + */ public function TrackLoader(map:Map, url:String) { this.map=map; apiBaseURL=url; connection = new Connection(LAYER,apiBaseURL,null, null); } - + + /** Load the public traces for the current map extent + * @param keep not implemented + */ public function load(keep:Boolean=false):void { if (map.edge_l==left && map.edge_r==right && map.edge_t==top && map.edge_b==bottom) { page++; From c3f0affac1ad56a490bf2ae79b207d80bc18e514 Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Mon, 23 May 2011 12:48:42 +0100 Subject: [PATCH 12/89] No need for this to be a public function --- net/systemeD/potlatch2/utils/TrackLoader.as | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/systemeD/potlatch2/utils/TrackLoader.as b/net/systemeD/potlatch2/utils/TrackLoader.as index d24e0d64..a476d757 100644 --- a/net/systemeD/potlatch2/utils/TrackLoader.as +++ b/net/systemeD/potlatch2/utils/TrackLoader.as @@ -57,7 +57,7 @@ package net.systemeD.potlatch2.utils { loader.addEventListener(Event.COMPLETE, parseGPX); } - public function parseGPX(event:Event):void { + private function parseGPX(event:Event):void { var file:XML = new XML(event.target.data); var action:CompositeUndoableAction = new CompositeUndoableAction("add track objects"); for each (var ns:Namespace in file.namespaceDeclarations()) { From fac38a747f3bc40124461b07cace9341064aa319 Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Mon, 23 May 2011 14:59:52 +0100 Subject: [PATCH 13/89] Add Marker support to Connection - was previously only supported in VectorLayers --- net/systemeD/halcyon/connection/Connection.as | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/net/systemeD/halcyon/connection/Connection.as b/net/systemeD/halcyon/connection/Connection.as index 5f5737cc..38abeb9f 100644 --- a/net/systemeD/halcyon/connection/Connection.as +++ b/net/systemeD/halcyon/connection/Connection.as @@ -79,6 +79,7 @@ package net.systemeD.halcyon.connection { private var nodes:Object = {}; private var ways:Object = {}; private var relations:Object = {}; + private var markers:Object = {}; private var pois:Array = []; private var changeset:Changeset = null; private var changesetUpdated:Number; @@ -188,6 +189,10 @@ package net.systemeD.halcyon.connection { return relations[id]; } + public function getMarker(id:Number):Marker { + return markers[id]; + } + protected function findEntity(type:String, id:*):Entity { var i:Number=Number(id); switch (type.toLowerCase()) { @@ -276,6 +281,13 @@ package net.systemeD.halcyon.connection { return relation; } + /** Create a new marker. This can't be done as part of a Composite Action */ + public function createMarker(tags:Object,lat:Number,lon:Number):Marker { + var marker:Marker = new Marker(this, nextNegative, 0, tags, true, lat, lon); + markers[marker.id] = marker; + return marker; + } + public function getAllNodeIDs():Array { var list:Array = []; for each (var node:Node in nodes) @@ -316,7 +328,8 @@ package net.systemeD.halcyon.connection { } public function getObjectsByBbox(left:Number, right:Number, top:Number, bottom:Number):Object { - var o:Object = { poisInside: [], poisOutside: [], waysInside: [], waysOutside: [] }; + var o:Object = { poisInside: [], poisOutside: [], waysInside: [], waysOutside: [], + markersInside: [], markersOutside: [] }; for each (var way:Way in ways) { if (way.within(left,right,top,bottom)) { o.waysInside.push(way); } else { o.waysOutside.push(way); } @@ -325,6 +338,10 @@ package net.systemeD.halcyon.connection { if (poi.within(left,right,top,bottom)) { o.poisInside.push(poi); } else { o.poisOutside.push(poi); } } + for each (var marker:Marker in markers) { + if (marker.within(left,right,top,bottom)) { o.markersInside.push(marker); } + else { o.markersOutside.push(marker); } + } return o; } From 67036a9bf6db651904107826d253b6708c8ba0ba Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Mon, 23 May 2011 15:02:55 +0100 Subject: [PATCH 14/89] Adapt BikeShopLoader to the new world order --- .../potlatch2/utils/BikeShopLoader.as | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/net/systemeD/potlatch2/utils/BikeShopLoader.as b/net/systemeD/potlatch2/utils/BikeShopLoader.as index 86f203c0..b09946f8 100644 --- a/net/systemeD/potlatch2/utils/BikeShopLoader.as +++ b/net/systemeD/potlatch2/utils/BikeShopLoader.as @@ -1,9 +1,9 @@ package net.systemeD.potlatch2.utils { import net.systemeD.halcyon.Map; - import net.systemeD.halcyon.VectorLayer; + import net.systemeD.halcyon.MapPaint; + import net.systemeD.halcyon.connection.Connection; import net.systemeD.halcyon.connection.Marker; - import net.systemeD.potlatch2.BugLayer; import flash.net.*; import flash.events.*; import com.adobe.serialization.json.JSON; @@ -25,16 +25,19 @@ package net.systemeD.potlatch2.utils { private var map:Map; private var bikeShopBaseURL:String; private var name:String; - private var _layer:VectorLayer; + private var _layer:MapPaint; + private var connection:Connection; private static const STYLESHEET:String="stylesheets/bikeshops.css"; public function BikeShopLoader(map:Map, url:String, name:String) { this.map = map; this.bikeShopBaseURL = url; this.name = name; + this.connection = new Connection(name,url,null,null); } public function load():void { + // this would be better if the connection did the loading var loader:URLLoader = new URLLoader(); loader.load(new URLRequest(bikeShopBaseURL+"shop/missing.kml?bbox="+map.edge_l+","+map.edge_b+","+map.edge_r+","+map.edge_t)); loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, balls); @@ -60,22 +63,21 @@ package net.systemeD.potlatch2.utils { var tags:Object = {}; tags["name"] = String(placemark.name); tags["description"] = String(placemark.description); - var marker:Marker = layer.createMarker(tags, lat, lon); + var marker:Marker = connection.createMarker(tags, lat, lon); } default xml namespace = new Namespace(""); - layer.paint.updateEntityUIs(true, false); + layer.updateEntityUIs(true, false); } - private function get layer():VectorLayer { - // >>>> REFACTOR: VectorLayer commented out - // if (!_layer) { - // var policyFile:String = bikeShopBaseURL+"crossdomain.xml"; - // Security.loadPolicyFile(policyFile); - // _layer=new VectorLayer(name,map,STYLESHEET); - // map.addVectorLayer(_layer); - // } - // return _layer; - return null; + private function get layer():MapPaint { + if (!_layer) { + // this should be done by the connection, not here. + var policyFile:String = bikeShopBaseURL+"crossdomain.xml"; + Security.loadPolicyFile(policyFile); + + _layer = map.addLayer(connection, STYLESHEET); + } + return _layer; } } } \ No newline at end of file From 86530d714cdc298e8918fc43dd265d2158f12323 Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Mon, 23 May 2011 16:23:39 +0100 Subject: [PATCH 15/89] Remove unnecessary import statement --- net/systemeD/potlatch2/panels/MarkerPanel.mxml | 1 - 1 file changed, 1 deletion(-) diff --git a/net/systemeD/potlatch2/panels/MarkerPanel.mxml b/net/systemeD/potlatch2/panels/MarkerPanel.mxml index 251277cb..0aef7b32 100644 --- a/net/systemeD/potlatch2/panels/MarkerPanel.mxml +++ b/net/systemeD/potlatch2/panels/MarkerPanel.mxml @@ -16,7 +16,6 @@ import net.systemeD.halcyon.connection.*; import net.systemeD.halcyon.VectorLayer; - import net.systemeD.potlatch2.BugLayer; import mx.collections.*; private var selectedEntity:Entity; From 279b53410c9dcddede161eecf32b317bd989fa78 Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Mon, 23 May 2011 16:25:10 +0100 Subject: [PATCH 16/89] Expand createMarker to have the old VBL createmarker syntax. Needs renaming and/or refactoring, as noted --- net/systemeD/halcyon/connection/Connection.as | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/net/systemeD/halcyon/connection/Connection.as b/net/systemeD/halcyon/connection/Connection.as index 38abeb9f..588a7969 100644 --- a/net/systemeD/halcyon/connection/Connection.as +++ b/net/systemeD/halcyon/connection/Connection.as @@ -281,10 +281,19 @@ package net.systemeD.halcyon.connection { return relation; } - /** Create a new marker. This can't be done as part of a Composite Action */ - public function createMarker(tags:Object,lat:Number,lon:Number):Marker { - var marker:Marker = new Marker(this, nextNegative, 0, tags, true, lat, lon); - markers[marker.id] = marker; + /** Create a new marker. This can't be done as part of a Composite Action. */ + // REFACTOR This needs renaming and/or refactoring to behave more similarly to n/w/r + public function createMarker(tags:Object,lat:Number,lon:Number,id:Number=NaN):Marker { + if (!id) { + id = negativeID; + negativeID--; + } + var marker:Marker = markers[id]; + if (marker == null) { + trace("new marker"); + marker = new Marker(this, id, 0, tags, true, lat, lon); + markers[id]=marker; + } return marker; } From 0a49640bccdd95b153e9dfe285125e7323f7775e Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Mon, 23 May 2011 16:27:53 +0100 Subject: [PATCH 17/89] Fix the long-anticipated 'map.init completes first' failure mode --- potlatch2.mxml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/potlatch2.mxml b/potlatch2.mxml index d7744c23..2358b50d 100644 --- a/potlatch2.mxml +++ b/potlatch2.mxml @@ -212,14 +212,13 @@ // >>>> REFACTOR: shouldn't be trying to find out stylesheet from here theMap.addLayer(conn,params['styleurl'] ? params['styleurl'] : 'stylesheets/potlatch.css',false); + // Auto-load vector backgrounds from config + theMap.addEventListener(MapEvent.INITIALISED, function(e:Event):void { VectorBackgrounds.instance().init(theMap); }); + // Set start position of map // >>>> REFACTOR: what happens if lat/lon/zoom not supplied? (Hurleston GPX case) theMap.init(params['lat'], params['lon'], params['zoom']); - // Auto-load vector backgrounds from config - // This could go spectacularly wrong if map.init completes before the event listener below is added - theMap.addEventListener(MapEvent.INITIALISED, function(e:Event):void { VectorBackgrounds.instance().init(theMap); }); - // add attribution/logo sprite var overlay:Sprite=new Sprite(); var attribution:TextField=new TextField(); From ea3a233b39125a0b6e7ac954f03e29235f1d81bf Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Mon, 23 May 2011 16:30:25 +0100 Subject: [PATCH 18/89] Refactor BugLayer to extend connection, and rename it to BugConnection to save confusion --- .../{BugLayer.as => BugConnection.as} | 9 +++--- net/systemeD/potlatch2/TagViewer.mxml | 4 +-- .../collections/VectorBackgrounds.as | 26 ++++++++-------- net/systemeD/potlatch2/panels/BugPanel.mxml | 18 +++++------ net/systemeD/potlatch2/utils/BugLoader.as | 30 ++++++++++--------- 5 files changed, 44 insertions(+), 43 deletions(-) rename net/systemeD/potlatch2/{BugLayer.as => BugConnection.as} (92%) diff --git a/net/systemeD/potlatch2/BugLayer.as b/net/systemeD/potlatch2/BugConnection.as similarity index 92% rename from net/systemeD/potlatch2/BugLayer.as rename to net/systemeD/potlatch2/BugConnection.as index df6681c6..006e5b9c 100644 --- a/net/systemeD/potlatch2/BugLayer.as +++ b/net/systemeD/potlatch2/BugConnection.as @@ -11,7 +11,7 @@ package net.systemeD.potlatch2 { /** A VectorLayer that can be used to load and display bugs from MapDust-compatible APIs. See utils/BugLoader.as for the corresponding loader. */ - public class BugLayer extends VectorLayer { + public class BugConnection extends Connection { private var baseUrl:String; private var apiKey:String; @@ -31,11 +31,11 @@ package net.systemeD.potlatch2 { public static var BUG_STATUS_INVALID:String = "3"; // or 'non-reproduceable' public static const status:Array = ["", "open", "fixed", "invalid"]; - public function BugLayer(n:String, map:Map, s:String, baseUrl:String, apiKey:String, detailsURL:String) { + public function BugConnection(n:String, baseUrl:String, apiKey:String, detailsURL:String) { this.baseUrl = baseUrl; this.apiKey = apiKey; this.detailsUrl = detailsURL; - super(n,map,s); + super(n, baseUrl, null, null); } public function closeBug(m:Marker, nickname:String, comment:String, status:String = null):void { @@ -67,7 +67,7 @@ package net.systemeD.potlatch2 { public override function loadBbox(left:Number, right:Number, top:Number, bottom:Number):void { var loader:URLLoader = new URLLoader(); - loader.load(new URLRequest(baseUrl+"getBugs?bbox="+map.edge_l+","+map.edge_b+","+map.edge_r+","+map.edge_t+"&key="+apiKey+"&filter_status="+filter_status+"&filter_type="+filter_type+commentType)); + loader.load(new URLRequest(baseUrl+"getBugs?bbox="+left+","+bottom+","+right+","+top+"&key="+apiKey+"&filter_status="+filter_status+"&filter_type="+filter_type+commentType)); loader.addEventListener(Event.COMPLETE, parseJSON); loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, handleError); loader.addEventListener(IOErrorEvent.IO_ERROR, handleError); @@ -97,7 +97,6 @@ package net.systemeD.potlatch2 { tags["status"] = status[int(feature.properties.status)]; var marker:Marker = createMarker(tags, lat, lon, Number(feature.id)); } - paint.updateEntityUIs(true, false); } } diff --git a/net/systemeD/potlatch2/TagViewer.mxml b/net/systemeD/potlatch2/TagViewer.mxml index eb9b636b..915cebc7 100644 --- a/net/systemeD/potlatch2/TagViewer.mxml +++ b/net/systemeD/potlatch2/TagViewer.mxml @@ -265,8 +265,8 @@ if (selectedEntity!=null) { selectedEntity.addEventListener(Connection.TAG_CHANGED, tagChanged); } if (advancedID!=null) { setupAdvanced(firstSelected); } if (firstSelected is Relation) { stack.addChild(membersVBox); } - if (selectedEntity is Marker && layer is BugLayer) { - bugPanelContents.init(selectedEntity, layer); + if (selectedEntity is Marker && connection is BugConnection) { + bugPanelContents.init(selectedEntity, BugConnection(connection)); sidebar.selectedChild = bugPanel; } else if (selectedEntity is Marker) { markerPanelContents.init(selectedEntity, layer); diff --git a/net/systemeD/potlatch2/collections/VectorBackgrounds.as b/net/systemeD/potlatch2/collections/VectorBackgrounds.as index b84f8956..1ced4e35 100644 --- a/net/systemeD/potlatch2/collections/VectorBackgrounds.as +++ b/net/systemeD/potlatch2/collections/VectorBackgrounds.as @@ -44,19 +44,19 @@ package net.systemeD.potlatch2.collections { case "KMLImporter": break; case "GPXImporter": - if (set.url) { - if (set.@loaded == "true") { - name ||= 'GPX file'; - // >>>> REFACTOR: VectorLayer commented out - // var layer:VectorLayer = new VectorLayer(name, _map, 'stylesheets/gpx.css'); - // _map.addVectorLayer(layer); - // var gpxImporter:GpxImporter = new GpxImporter(layer, layer.paint, [String(set.url)]); - } else { - trace("configured but not loaded isn't supported yet"); - } - } else { - trace("AutoVectorBackground: no url for GPXImporter"); - } +// if (set.url) { +// if (set.@loaded == "true") { +// name ||= 'GPX file'; +// // >>>> REFACTOR: VectorLayer commented out +// // var layer:VectorLayer = new VectorLayer(name, _map, 'stylesheets/gpx.css'); +// // _map.addVectorLayer(layer); +// // var gpxImporter:GpxImporter = new GpxImporter(layer, layer.paint, [String(set.url)]); +// } else { +// trace("configured but not loaded isn't supported yet"); +// } +// } else { +// trace("AutoVectorBackground: no url for GPXImporter"); +// } break; case "BugLoader": diff --git a/net/systemeD/potlatch2/panels/BugPanel.mxml b/net/systemeD/potlatch2/panels/BugPanel.mxml index b5237ce5..6e3d96ad 100644 --- a/net/systemeD/potlatch2/panels/BugPanel.mxml +++ b/net/systemeD/potlatch2/panels/BugPanel.mxml @@ -60,12 +60,12 @@ import net.systemeD.halcyon.connection.*; import net.systemeD.halcyon.VectorLayer; - import net.systemeD.potlatch2.BugLayer; + import net.systemeD.potlatch2.BugConnection; import mx.collections.*; import com.adobe.utils.DateUtil; private var selectedEntity:Entity; - private var layer:VectorLayer; + private var connection:BugConnection; [Bindable] private var bugId:String; [Bindable] private var bugStatus:String; @@ -77,8 +77,8 @@ [Bindable] private var bugUpdated:Date; [Bindable] private var bugDetails:String; - public function init(entity:Entity, layer:VectorLayer):void { - this.layer = layer; + public function init(entity:Entity, connection:BugConnection):void { + this.connection = connection; selectedEntity=entity; bugId = selectedEntity.getTag("bug_id"); @@ -90,15 +90,15 @@ bugCreated = DateUtil.parseW3CDTF(selectedEntity.getTag("date_created")); bugUpdated = DateUtil.parseW3CDTF(selectedEntity.getTag("date_updated")); - if ( bugStatus == BugLayer.status[int(BugLayer.BUG_STATUS_FIXED)] ) { + if ( bugStatus == BugConnection.status[int(BugConnection.BUG_STATUS_FIXED)] ) { bugControlStack.selectedChild = bugFixed; - } else if ( bugStatus == BugLayer.status[int(BugLayer.BUG_STATUS_INVALID)] ) { + } else if ( bugStatus == BugConnection.status[int(BugConnection.BUG_STATUS_INVALID)] ) { bugControlStack.selectedChild = bugInvalid; } else { bugControlStack.selectedChild = bugControl; } - var u:String = BugLayer(layer).bugDetailsUrl(Marker(selectedEntity)); + var u:String = connection.bugDetailsUrl(Marker(selectedEntity)); if (u) { bugDetails = u; bugDetailsHbox.visible=true; @@ -106,9 +106,9 @@ } private function closeBug():void { - var status:String = option_invalid.selected ? BugLayer.BUG_STATUS_INVALID : BugLayer.BUG_STATUS_FIXED; + var status:String = option_invalid.selected ? BugConnection.BUG_STATUS_INVALID : BugConnection.BUG_STATUS_FIXED; trace(status); - BugLayer(layer).closeBug(selectedEntity as Marker, nickName.text, closeComment.text, status); + connection.closeBug(selectedEntity as Marker, nickName.text, closeComment.text, status); bugStatus = selectedEntity.getTag("status"); // this should really be a 'saving...' state, with a callback depending on the server result bugControlStack.selectedChild = option_invalid.selected ? bugInvalid : bugFixed; diff --git a/net/systemeD/potlatch2/utils/BugLoader.as b/net/systemeD/potlatch2/utils/BugLoader.as index 5b70251f..34ca32a8 100644 --- a/net/systemeD/potlatch2/utils/BugLoader.as +++ b/net/systemeD/potlatch2/utils/BugLoader.as @@ -1,9 +1,9 @@ package net.systemeD.potlatch2.utils { import net.systemeD.halcyon.Map; - import net.systemeD.halcyon.VectorLayer; + import net.systemeD.halcyon.MapPaint; import net.systemeD.halcyon.connection.Marker; - import net.systemeD.potlatch2.BugLayer; + import net.systemeD.potlatch2.BugConnection; import flash.net.*; import flash.events.*; import flash.system.Security; @@ -14,9 +14,10 @@ package net.systemeD.potlatch2.utils { private var bugBaseURL:String; private var bugApiKey:String; private var bugDetailsURL:String; - private var _layer:VectorLayer; + private var _layer:MapPaint; private var name:String; private static const STYLESHEET:String="stylesheets/bugs.css"; + private var connection:BugConnection; public function BugLoader(map:Map, url:String, bugApiKey:String, name:String, details:String = ''):void { @@ -25,23 +26,24 @@ package net.systemeD.potlatch2.utils { this.bugApiKey = bugApiKey; this.name = name; this.bugDetailsURL = details; + connection = new BugConnection(name, url, bugApiKey, details); } public function load():void { - layer.loadBbox(map.edge_l, map.edge_r, map.edge_t, map.edge_b); + connection.loadBbox(map.edge_l, map.edge_r, map.edge_t, map.edge_b); + // FIXME Note this fires too early, since loadBbox is asynchronous + layer.updateEntityUIs(true, false); } + private function get layer():MapPaint { + if (!_layer) { + // should be done by the connection + var policyFile:String = bugBaseURL+"crossdomain.xml"; + Security.loadPolicyFile(policyFile); - private function get layer():VectorLayer { - // >>>> REFACTOR: VectorLayer commented out - // if (!_layer) { - // var policyFile:String = bugBaseURL+"crossdomain.xml"; - // Security.loadPolicyFile(policyFile); - // _layer=new BugLayer(name,map,STYLESHEET,bugBaseURL,bugApiKey,bugDetailsURL); - // map.addVectorLayer(_layer); - // } - // return _layer; - return null; + _layer = map.addLayer(connection, STYLESHEET); + } + return _layer; } } } \ No newline at end of file From 2da83a8c2645e69595dc993af4de76f45cdfdd3e Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Mon, 23 May 2011 17:05:26 +0100 Subject: [PATCH 19/89] Dispatch NEW_MARKER events when markers are created --- net/systemeD/halcyon/connection/Connection.as | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/systemeD/halcyon/connection/Connection.as b/net/systemeD/halcyon/connection/Connection.as index 588a7969..ed8de476 100644 --- a/net/systemeD/halcyon/connection/Connection.as +++ b/net/systemeD/halcyon/connection/Connection.as @@ -53,6 +53,7 @@ package net.systemeD.halcyon.connection { public static var NEW_WAY:String = "new_way"; public static var NEW_RELATION:String = "new_relation"; public static var NEW_POI:String = "new_poi"; + public static var NEW_MARKER:String = "new_marker"; public static var NODE_RENUMBERED:String = "node_renumbered"; public static var WAY_RENUMBERED:String = "way_renumbered"; public static var RELATION_RENUMBERED:String = "relation_renumbered"; @@ -293,6 +294,7 @@ package net.systemeD.halcyon.connection { trace("new marker"); marker = new Marker(this, id, 0, tags, true, lat, lon); markers[id]=marker; + sendEvent(new EntityEvent(NEW_MARKER, marker),false); } return marker; } From ae50dad823558c7db1adae0f810e38b8a37a227d Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Mon, 23 May 2011 17:06:42 +0100 Subject: [PATCH 20/89] Draw new markers when they are created, and save the data loaders from worrying about the UI --- net/systemeD/halcyon/MapPaint.as | 7 +++++++ net/systemeD/potlatch2/utils/BugLoader.as | 2 -- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/net/systemeD/halcyon/MapPaint.as b/net/systemeD/halcyon/MapPaint.as index f87cfeeb..b00149b8 100644 --- a/net/systemeD/halcyon/MapPaint.as +++ b/net/systemeD/halcyon/MapPaint.as @@ -67,6 +67,7 @@ package net.systemeD.halcyon { connection.addEventListener(Connection.NEW_POI, newPOICreatedListener); connection.addEventListener(Connection.WAY_RENUMBERED, wayRenumberedListener); connection.addEventListener(Connection.NODE_RENUMBERED, nodeRenumberedListener); + connection.addEventListener(Connection.NEW_MARKER, newMarkerCreatedListener); // Add paint sprites for (l=minlayer; l<=maxlayer; l++) { // each layer (10 is +5, 0 is -5) @@ -369,6 +370,12 @@ package net.systemeD.halcyon { createNodeUI(node); } + private function newMarkerCreatedListener(event:EntityEvent):void { + var marker:Marker = event.entity as Marker; + if (!marker.within(map.edge_l, map.edge_r, map.edge_t, map.edge_b)) { return; } + createMarkerUI(marker); + } + private function wayRenumberedListener(event:EntityRenumberedEvent):void { var way:Way = event.entity as Way; renumberWayUI(way,event.oldID); diff --git a/net/systemeD/potlatch2/utils/BugLoader.as b/net/systemeD/potlatch2/utils/BugLoader.as index 34ca32a8..b9532cbd 100644 --- a/net/systemeD/potlatch2/utils/BugLoader.as +++ b/net/systemeD/potlatch2/utils/BugLoader.as @@ -31,8 +31,6 @@ package net.systemeD.potlatch2.utils { public function load():void { connection.loadBbox(map.edge_l, map.edge_r, map.edge_t, map.edge_b); - // FIXME Note this fires too early, since loadBbox is asynchronous - layer.updateEntityUIs(true, false); } private function get layer():MapPaint { From 03d1ac7a0692fab004e80926b4782c2e2121e364 Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Mon, 23 May 2011 18:45:11 +0100 Subject: [PATCH 21/89] Move security file handling down into the connection for buglayers --- net/systemeD/potlatch2/BugConnection.as | 9 +++++++-- net/systemeD/potlatch2/utils/BugLoader.as | 10 +--------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/net/systemeD/potlatch2/BugConnection.as b/net/systemeD/potlatch2/BugConnection.as index 006e5b9c..9e369069 100644 --- a/net/systemeD/potlatch2/BugConnection.as +++ b/net/systemeD/potlatch2/BugConnection.as @@ -6,6 +6,7 @@ package net.systemeD.potlatch2 { import net.systemeD.halcyon.connection.actions.*; import flash.net.*; import flash.events.*; + import flash.system.Security; import com.adobe.serialization.json.JSON; /** A VectorLayer that can be used to load and display bugs from MapDust-compatible APIs. @@ -35,7 +36,7 @@ package net.systemeD.potlatch2 { this.baseUrl = baseUrl; this.apiKey = apiKey; this.detailsUrl = detailsURL; - super(n, baseUrl, null, null); + super(n, baseUrl, baseUrl+"crossdomain.xml", null); } public function closeBug(m:Marker, nickname:String, comment:String, status:String = null):void { @@ -66,11 +67,15 @@ package net.systemeD.potlatch2 { public override function loadBbox(left:Number, right:Number, top:Number, bottom:Number):void { + + // Should be guarded against multiple calls really. + if (policyURL != "") { Security.loadPolicyFile(policyURL); trace("policy");}; + var loader:URLLoader = new URLLoader(); - loader.load(new URLRequest(baseUrl+"getBugs?bbox="+left+","+bottom+","+right+","+top+"&key="+apiKey+"&filter_status="+filter_status+"&filter_type="+filter_type+commentType)); loader.addEventListener(Event.COMPLETE, parseJSON); loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, handleError); loader.addEventListener(IOErrorEvent.IO_ERROR, handleError); + loader.load(new URLRequest(baseUrl+"getBugs?bbox="+left+","+bottom+","+right+","+top+"&key="+apiKey+"&filter_status="+filter_status+"&filter_type="+filter_type+commentType)); } private function handleError(event:Event):void { diff --git a/net/systemeD/potlatch2/utils/BugLoader.as b/net/systemeD/potlatch2/utils/BugLoader.as index b9532cbd..7cb6bf40 100644 --- a/net/systemeD/potlatch2/utils/BugLoader.as +++ b/net/systemeD/potlatch2/utils/BugLoader.as @@ -30,18 +30,10 @@ package net.systemeD.potlatch2.utils { } public function load():void { - connection.loadBbox(map.edge_l, map.edge_r, map.edge_t, map.edge_b); - } - - private function get layer():MapPaint { if (!_layer) { - // should be done by the connection - var policyFile:String = bugBaseURL+"crossdomain.xml"; - Security.loadPolicyFile(policyFile); - _layer = map.addLayer(connection, STYLESHEET); } - return _layer; + connection.loadBbox(map.edge_l, map.edge_r, map.edge_t, map.edge_b); } } } \ No newline at end of file From 5f93339d84c562afc7e903b179d613fa3f79478b Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Mon, 23 May 2011 18:47:23 +0100 Subject: [PATCH 22/89] tidy --- net/systemeD/potlatch2/BugConnection.as | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/systemeD/potlatch2/BugConnection.as b/net/systemeD/potlatch2/BugConnection.as index 9e369069..ee569342 100644 --- a/net/systemeD/potlatch2/BugConnection.as +++ b/net/systemeD/potlatch2/BugConnection.as @@ -69,7 +69,7 @@ package net.systemeD.potlatch2 { top:Number, bottom:Number):void { // Should be guarded against multiple calls really. - if (policyURL != "") { Security.loadPolicyFile(policyURL); trace("policy");}; + if (policyURL != "") { Security.loadPolicyFile(policyURL); } var loader:URLLoader = new URLLoader(); loader.addEventListener(Event.COMPLETE, parseJSON); From 0315ebd9eeb0041ddce6ccea451d296386a6a515 Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Mon, 23 May 2011 18:49:56 +0100 Subject: [PATCH 23/89] Rework BikeShopLoader/Layer so that it responds to loadBbox calls --- .../potlatch2/utils/BikeShopConnection.as | 50 +++++++++++++++++++ .../potlatch2/utils/BikeShopLoader.as | 43 ++-------------- 2 files changed, 53 insertions(+), 40 deletions(-) create mode 100644 net/systemeD/potlatch2/utils/BikeShopConnection.as diff --git a/net/systemeD/potlatch2/utils/BikeShopConnection.as b/net/systemeD/potlatch2/utils/BikeShopConnection.as new file mode 100644 index 00000000..ff262aee --- /dev/null +++ b/net/systemeD/potlatch2/utils/BikeShopConnection.as @@ -0,0 +1,50 @@ +package net.systemeD.potlatch2.utils { + + import net.systemeD.halcyon.connection.Connection; + import net.systemeD.halcyon.connection.Marker; + import com.adobe.serialization.json.JSON; + import flash.system.Security; + import flash.net.*; + import flash.events.*; + + public class BikeShopConnection extends Connection { + + public function BikeShopConnection(cname:String,api:String,policy:String,initparams:Object=null) { + super(cname,api,policy,initparams); + } + + public override function loadBbox(left:Number, right:Number, top:Number, bottom:Number):void { + + // Should be guarded against multiple calls really. + if (policyURL != "") { Security.loadPolicyFile(policyURL); } + + var loader:URLLoader = new URLLoader(); + loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, balls); + loader.addEventListener(Event.COMPLETE, parseKML); + loader.load(new URLRequest(apiBaseURL+"shop/missing.kml?bbox="+left+","+bottom+","+right+","+top)); + } + + public function balls(event:SecurityErrorEvent):void { + } + + private function parseKML(event:Event):void { + //trace(event.target.data); + default xml namespace = new Namespace("http://www.opengis.net/kml/2.2"); + var kml:XML = new XML(event.target.data); + //trace(kml.attributes()); + //var document:XMLList = kml.Document; + for each (var placemark:XML in kml..Placemark) { + trace("name:"+placemark.name); + var coords:Array = placemark..coordinates.split(","); + var lon:Number = coords[0]; + var lat:Number = coords[1]; + //var ele:Number = coords[2]; + var tags:Object = {}; + tags["name"] = String(placemark.name); + tags["description"] = String(placemark.description); + var marker:Marker = createMarker(tags, lat, lon); + } + default xml namespace = new Namespace(""); + } + } +} \ No newline at end of file diff --git a/net/systemeD/potlatch2/utils/BikeShopLoader.as b/net/systemeD/potlatch2/utils/BikeShopLoader.as index b09946f8..87996f3e 100644 --- a/net/systemeD/potlatch2/utils/BikeShopLoader.as +++ b/net/systemeD/potlatch2/utils/BikeShopLoader.as @@ -33,51 +33,14 @@ package net.systemeD.potlatch2.utils { this.map = map; this.bikeShopBaseURL = url; this.name = name; - this.connection = new Connection(name,url,null,null); + this.connection = new BikeShopConnection(name,url,bikeShopBaseURL+"crossdomain.xml",null); } public function load():void { - // this would be better if the connection did the loading - var loader:URLLoader = new URLLoader(); - loader.load(new URLRequest(bikeShopBaseURL+"shop/missing.kml?bbox="+map.edge_l+","+map.edge_b+","+map.edge_r+","+map.edge_t)); - loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, balls); - loader.addEventListener(Event.COMPLETE, parseKML); - } - - public function balls(event:SecurityErrorEvent):void { - trace(event); - } - - private function parseKML(event:Event):void { - //trace(event.target.data); - default xml namespace = new Namespace("http://www.opengis.net/kml/2.2"); - var kml:XML = new XML(event.target.data); - //trace(kml.attributes()); - //var document:XMLList = kml.Document; - for each (var placemark:XML in kml..Placemark) { - trace("name:"+placemark.name); - var coords:Array = placemark..coordinates.split(","); - var lon:Number = coords[0]; - var lat:Number = coords[1]; - //var ele:Number = coords[2]; - var tags:Object = {}; - tags["name"] = String(placemark.name); - tags["description"] = String(placemark.description); - var marker:Marker = connection.createMarker(tags, lat, lon); - } - default xml namespace = new Namespace(""); - layer.updateEntityUIs(true, false); - } - - private function get layer():MapPaint { if (!_layer) { - // this should be done by the connection, not here. - var policyFile:String = bikeShopBaseURL+"crossdomain.xml"; - Security.loadPolicyFile(policyFile); - - _layer = map.addLayer(connection, STYLESHEET); + _layer = map.addLayer(connection, STYLESHEET); } - return _layer; + connection.loadBbox(map.edge_l, map.edge_r, map.edge_t, map.edge_b); } } } \ No newline at end of file From 6f1d09f07d63d553674e71747f593c0749a99929 Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Tue, 24 May 2011 11:51:51 +0100 Subject: [PATCH 24/89] Allow knowledge of the style in use in MapPaint - similar to VectorBackground did for VectorSourceDialog reasons --- net/systemeD/halcyon/MapPaint.as | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/systemeD/halcyon/MapPaint.as b/net/systemeD/halcyon/MapPaint.as index b00149b8..0dafd34d 100644 --- a/net/systemeD/halcyon/MapPaint.as +++ b/net/systemeD/halcyon/MapPaint.as @@ -34,6 +34,9 @@ package net.systemeD.halcyon { /** Hash of index->position */ public var sublayerIndex:Object={}; + /** The url of the style in use */ + public var style:String = ''; + private const VERYBIG:Number=Math.pow(2,16); private static const NO_LAYER:int=-99999; // same as NodeUI @@ -341,6 +344,7 @@ package net.systemeD.halcyon { /** Switch to new MapCSS. */ public function setStyle(url:String):void { + style = url; ruleset=new RuleSet(map.MINSCALE,map.MAXSCALE,redraw,redrawPOIs); ruleset.loadFromCSS(url); } From 20ab3f463d1588eca63e8c30088d1fd7bf2adbf8 Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Tue, 24 May 2011 12:27:20 +0100 Subject: [PATCH 25/89] Partial refactoring of VectorSourceDialog. Not happy with iterating over Map.paintContainer though --- .../potlatch2/VectorSourceDialog.mxml | 76 ++++++++++--------- 1 file changed, 40 insertions(+), 36 deletions(-) diff --git a/net/systemeD/potlatch2/VectorSourceDialog.mxml b/net/systemeD/potlatch2/VectorSourceDialog.mxml index ba041579..5f6b85b5 100644 --- a/net/systemeD/potlatch2/VectorSourceDialog.mxml +++ b/net/systemeD/potlatch2/VectorSourceDialog.mxml @@ -56,8 +56,9 @@ From 51f1821d6fb67d572944012c851da10eb87b8573 Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Tue, 24 May 2011 12:28:21 +0100 Subject: [PATCH 26/89] Re-enable VectorSourceDialog --- net/systemeD/potlatch2/BackgroundSelector.mxml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/systemeD/potlatch2/BackgroundSelector.mxml b/net/systemeD/potlatch2/BackgroundSelector.mxml index bc0922a3..2c483390 100644 --- a/net/systemeD/potlatch2/BackgroundSelector.mxml +++ b/net/systemeD/potlatch2/BackgroundSelector.mxml @@ -18,11 +18,10 @@ - + >>> REFACTOR: vector file button was click="Application.application.bgButton.close(); new VectorSourceDialog().init();" but that's amazingly broken --> import net.systemeD.halcyon.*; import net.systemeD.halcyon.connection.*; From 0c2c46b3815c0083c3f91bd877b12fadf073afef Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Tue, 24 May 2011 12:44:53 +0100 Subject: [PATCH 27/89] Update connections to use instance copies of apiBaseURL. Untested, but allows docs to compile again. --- net/systemeD/halcyon/connection/AMFConnection.as | 4 ++-- net/systemeD/halcyon/connection/OSMConnection.as | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/net/systemeD/halcyon/connection/AMFConnection.as b/net/systemeD/halcyon/connection/AMFConnection.as index d0152328..1c1e58b1 100644 --- a/net/systemeD/halcyon/connection/AMFConnection.as +++ b/net/systemeD/halcyon/connection/AMFConnection.as @@ -32,11 +32,11 @@ package net.systemeD.halcyon.connection { readConnection=new NetConnection(); readConnection.objectEncoding = flash.net.ObjectEncoding.AMF0; - readConnection.connect(Connection.apiBaseURL+"amf/read"); + readConnection.connect(apiBaseURL+"amf/read"); writeConnection=new NetConnection(); writeConnection.objectEncoding = flash.net.ObjectEncoding.AMF0; - writeConnection.connect(Connection.apiBaseURL+"amf/write"); + writeConnection.connect(apiBaseURL+"amf/write"); } diff --git a/net/systemeD/halcyon/connection/OSMConnection.as b/net/systemeD/halcyon/connection/OSMConnection.as index 79774aa4..6e08f517 100644 --- a/net/systemeD/halcyon/connection/OSMConnection.as +++ b/net/systemeD/halcyon/connection/OSMConnection.as @@ -97,7 +97,7 @@ package net.systemeD.halcyon.connection { private function loadFile(box:Array):void { bboxes[box]=LOADING; - var mapRequest:URLRequest = new URLRequest(Connection.apiBaseURL+"/"+box[0]+"_"+box[1]+"_"+box[2]+"_"+box[3]+".osm"); + var mapRequest:URLRequest = new URLRequest(apiBaseURL+"/"+box[0]+"_"+box[1]+"_"+box[2]+"_"+box[3]+".osm"); var mapLoader:ExtendedURLLoader = new ExtendedURLLoader(); mapLoader.info['bbox']=box; mapLoader.addEventListener(Event.COMPLETE, markMapLoaded); From e9374be0178fbfac323297c91bcba6a2668e8700 Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Tue, 24 May 2011 14:10:56 +0100 Subject: [PATCH 28/89] Make paintContainer private, and add a method to access all MapPaint objects --- net/systemeD/halcyon/Map.as | 12 +++++++++++- net/systemeD/potlatch2/VectorSourceDialog.mxml | 5 ++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/net/systemeD/halcyon/Map.as b/net/systemeD/halcyon/Map.as index 1c790931..9dcb118a 100644 --- a/net/systemeD/halcyon/Map.as +++ b/net/systemeD/halcyon/Map.as @@ -29,7 +29,7 @@ package net.systemeD.halcyon { public const MAXSCALE:uint=23; // Container for MapPaint objects - public var paintContainer:Sprite; + private var paintContainer:Sprite; /** map scale */ public var scale:uint=14; @@ -269,6 +269,16 @@ package net.systemeD.halcyon { private function getLayerAt(i:uint):MapPaint { return MapPaint(paintContainer.getChildAt(i)); } + + /** Get all the layers available for this Map object + * @return An array of MapPaint objects */ + public function getLayers():Array { + var a:Array = []; + for (var i:uint=0; i Date: Tue, 24 May 2011 14:41:31 +0100 Subject: [PATCH 29/89] Should we remove Globals access from Connection? --- net/systemeD/halcyon/connection/Connection.as | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/systemeD/halcyon/connection/Connection.as b/net/systemeD/halcyon/connection/Connection.as index ed8de476..3fafeaed 100644 --- a/net/systemeD/halcyon/connection/Connection.as +++ b/net/systemeD/halcyon/connection/Connection.as @@ -26,7 +26,7 @@ package net.systemeD.halcyon.connection { public function getParam(name:String, defaultValue:String):String { if (params[name]) return params[name]; - if (Globals.vars.flashvars[name]) return Globals.vars.flashvars[name]; + if (Globals.vars.flashvars[name]) return Globals.vars.flashvars[name]; // REFACTOR - given the profusion of connections, should this be removed? return defaultValue; } From 06754c42dce94642864388d6f163d0b552bebdba Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Tue, 24 May 2011 15:29:43 +0100 Subject: [PATCH 30/89] Curvies, not squaries --- net/systemeD/potlatch2/VectorSourceDialog.mxml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/systemeD/potlatch2/VectorSourceDialog.mxml b/net/systemeD/potlatch2/VectorSourceDialog.mxml index 33948ebd..5dbbe723 100644 --- a/net/systemeD/potlatch2/VectorSourceDialog.mxml +++ b/net/systemeD/potlatch2/VectorSourceDialog.mxml @@ -112,7 +112,7 @@ } private function toggleVisibility(event:Event):void { - map.findLayer[dataGrid.selectedItem.name].visible = !map.findLayer[dataGrid.selectedItem.name].visible; + map.findLayer(dataGrid.selectedItem.name).visible = !map.findLayer(dataGrid.selectedItem.name).visible; } private function dataEdited(event:DataGridEvent):void { From 4e73172a82ab5eb77c79f47edf1075531238dd3c Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Tue, 24 May 2011 15:31:08 +0100 Subject: [PATCH 31/89] Refactor Trace.as --- net/systemeD/halcyon/connection/Trace.as | 48 +++++++++++++++--------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/net/systemeD/halcyon/connection/Trace.as b/net/systemeD/halcyon/connection/Trace.as index 2c0c1a5f..8a361cf6 100644 --- a/net/systemeD/halcyon/connection/Trace.as +++ b/net/systemeD/halcyon/connection/Trace.as @@ -8,7 +8,7 @@ package net.systemeD.halcyon.connection { import net.systemeD.halcyon.connection.*; import net.systemeD.halcyon.Map; import net.systemeD.halcyon.Globals; - import net.systemeD.halcyon.VectorLayer; + import net.systemeD.halcyon.MapPaint; /** * Implements trace objects loaded from the OSM API. @@ -23,18 +23,24 @@ package net.systemeD.halcyon.connection { private var _filename:String; private var _traceData:String; private var map:Map; - private var _connection:Connection; - private var _layer:VectorLayer; + private var _layer:MapPaint; + private var masterConnection:XMLConnection; // The authenticated connection + private var _connection:Connection; // The one we store our fake nodes/ways in. private var simplify:Boolean = false; private static const STYLESHEET:String="stylesheets/gpx.css"; - public function Trace(connection:Connection) { - _connection = connection; - map = Globals.vars.root; + /** Create a new trace. + * @param masterConnection The authenticated connection to communicate with the server + */ + public function Trace(masterConnection:XMLConnection) { + this.masterConnection = masterConnection; + map = Globals.vars.root; // REFACTOR this prevents traces being added to arbitrary maps } - /* Create a new trace, from the XML description given by the user/traces call */ + /** Create a new trace, from the XML description given by the user/traces call. + * This only creates the object itself, the actual trace contents (trkseg etc) are + * lazily downloaded later. */ public function fromXML(xml:XML):Trace { _id = Number(xml.@id); _filename = xml.@name; @@ -63,7 +69,7 @@ package net.systemeD.halcyon.connection { private function fetchFromServer():void { // todo - needs proper error handling - _connection.fetchTrace(id, saveTraceData); + masterConnection.fetchTrace(id, saveTraceData); dispatchEvent(new Event("loading_data")); } @@ -72,11 +78,17 @@ package net.systemeD.halcyon.connection { dispatchEvent(new Event("loaded_data")); } - private function get layer():VectorLayer { + private function get connection():Connection { + if (!_connection) { + // create a new layer for every trace, to they can be turned on/off individually + _connection = new Connection(filename, null, null, null); //fixme shouldn't rely on policy being loaded already. + } + return _connection + } + + private function get layer():MapPaint { if (!_layer) { - // >>>> REFACTOR: VectorLayer commented out - // _layer=new VectorLayer(filename,map,STYLESHEET); - // map.addVectorLayer(_layer); + _layer = map.addLayer(connection, STYLESHEET); } return _layer; } @@ -104,6 +116,7 @@ package net.systemeD.halcyon.connection { private function process():void { var file:XML = new XML(_traceData); + var action:CompositeUndoableAction = new CompositeUndoableAction("add trace objects"); for each (var ns:Namespace in file.namespaceDeclarations()) { if (ns.uri.match(/^http:\/\/www\.topografix\.com\/GPX\/1\/[01]$/)) { default xml namespace = ns; @@ -114,10 +127,10 @@ package net.systemeD.halcyon.connection { var way:Way; var nodestring:Array = []; for each (var trkpt:XML in trkseg.trkpt) { - nodestring.push(layer.createNode({}, trkpt.@lat, trkpt.@lon)); + nodestring.push(connection.createNode({}, trkpt.@lat, trkpt.@lon, action.push)); } if (nodestring.length > 0) { - way = layer.createWay({}, nodestring); + way = connection.createWay({}, nodestring, action.push); //if (simplify) { Simplify.simplify(way, paint.map, false); } } } @@ -127,12 +140,13 @@ package net.systemeD.halcyon.connection { for each (var tag:XML in wpt.children()) { tags[tag.name().localName]=tag.toString(); } - var node:Node = layer.createNode(tags, wpt.@lat, wpt.@lon); - layer.registerPOI(node); + var node:Node = connection.createNode(tags, wpt.@lat, wpt.@lon, action.push); + connection.registerPOI(node); } + action.doAction(); /* just do it, don't add to undo stack */ default xml namespace = new Namespace(""); - layer.paint.updateEntityUIs(true, false); + layer.updateEntityUIs(true, false); } } } From bf5e1fdce9e02179b112c38171c185351570de5c Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Tue, 24 May 2011 15:44:39 +0100 Subject: [PATCH 32/89] Refactor the comments --- net/systemeD/halcyon/connection/Trace.as | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/systemeD/halcyon/connection/Trace.as b/net/systemeD/halcyon/connection/Trace.as index 8a361cf6..33eb6e23 100644 --- a/net/systemeD/halcyon/connection/Trace.as +++ b/net/systemeD/halcyon/connection/Trace.as @@ -80,14 +80,15 @@ package net.systemeD.halcyon.connection { private function get connection():Connection { if (!_connection) { - // create a new layer for every trace, to they can be turned on/off individually - _connection = new Connection(filename, null, null, null); //fixme shouldn't rely on policy being loaded already. + // create a new connection so that the ids don't impact the main layer. + _connection = new Connection(filename, null, null, null); } return _connection } private function get layer():MapPaint { if (!_layer) { + // create a new layer for every trace, so they can be turned on/off individually _layer = map.addLayer(connection, STYLESHEET); } return _layer; From 9da49c227d310a84ffd1f70d3e181a8b7970643b Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Tue, 24 May 2011 16:26:36 +0100 Subject: [PATCH 33/89] explain some of the variables --- net/systemeD/halcyon/connection/Trace.as | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/net/systemeD/halcyon/connection/Trace.as b/net/systemeD/halcyon/connection/Trace.as index 33eb6e23..22a0b64e 100644 --- a/net/systemeD/halcyon/connection/Trace.as +++ b/net/systemeD/halcyon/connection/Trace.as @@ -16,12 +16,12 @@ package net.systemeD.halcyon.connection { * loading GPX files (and other formats) from arbitrary urls. */ public class Trace extends EventDispatcher { - private var _id:Number; - private var _description:String; + private var _id:Number; // id of the trace, as reported by the server + private var _description:String; // description, as reported by the server private var tags:Array = []; // N.B. trace tags are NOT k/v pairs - private var _isLoaded:Boolean; - private var _filename:String; - private var _traceData:String; + private var _isLoaded:Boolean; // Flag for when the data has been downloaded and parsed + private var _filename:String; // The original name of the file, as reported by the server + private var _traceData:String; // the trace data, saved as a string private var map:Map; private var _layer:MapPaint; private var masterConnection:XMLConnection; // The authenticated connection From 5a05ab722344b8b796cf702016f8f681b40c30f8 Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Thu, 26 May 2011 14:13:34 +0100 Subject: [PATCH 34/89] Remove VectorLayer from EditController and fix up references in various sidebar panels --- net/systemeD/potlatch2/EditController.as | 4 ++-- net/systemeD/potlatch2/TagViewer.mxml | 4 ++-- net/systemeD/potlatch2/controller/ControllerState.as | 2 +- net/systemeD/potlatch2/controller/SelectedMarker.as | 6 +++--- net/systemeD/potlatch2/panels/MarkerPanel.mxml | 6 +++--- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/net/systemeD/potlatch2/EditController.as b/net/systemeD/potlatch2/EditController.as index 7cdbae26..21b84b3b 100644 --- a/net/systemeD/potlatch2/EditController.as +++ b/net/systemeD/potlatch2/EditController.as @@ -1,9 +1,9 @@ package net.systemeD.potlatch2 { import net.systemeD.halcyon.Map; + import net.systemeD.halcyon.MapPaint; import net.systemeD.halcyon.MapController; import net.systemeD.halcyon.MapEvent; import net.systemeD.halcyon.connection.*; - import net.systemeD.halcyon.VectorLayer; import net.systemeD.halcyon.Globals; import net.systemeD.potlatch2.controller.*; import net.systemeD.potlatch2.FunctionKeyManager; @@ -78,7 +78,7 @@ package net.systemeD.potlatch2 { * * @param layer Optionally pass the layer of the currently selected entity, eg for BugLayers */ - public function updateSelectionUI(layer:VectorLayer = null):void { + public function updateSelectionUI(layer:MapPaint = null):void { tagViewer.setEntity(state.selection, layer); toolbox.updateSelectionUI(); } diff --git a/net/systemeD/potlatch2/TagViewer.mxml b/net/systemeD/potlatch2/TagViewer.mxml index 915cebc7..5da5c225 100644 --- a/net/systemeD/potlatch2/TagViewer.mxml +++ b/net/systemeD/potlatch2/TagViewer.mxml @@ -208,7 +208,7 @@ Date: Thu, 26 May 2011 14:19:30 +0100 Subject: [PATCH 35/89] Remove VectorLayer import statements from refactored files --- net/systemeD/potlatch2/BugConnection.as | 3 +-- net/systemeD/potlatch2/mygpx/MyGpxDialog.mxml | 1 - net/systemeD/potlatch2/panels/BugPanel.mxml | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/net/systemeD/potlatch2/BugConnection.as b/net/systemeD/potlatch2/BugConnection.as index ee569342..92bc5787 100644 --- a/net/systemeD/potlatch2/BugConnection.as +++ b/net/systemeD/potlatch2/BugConnection.as @@ -1,6 +1,5 @@ package net.systemeD.potlatch2 { - import net.systemeD.halcyon.VectorLayer; import net.systemeD.halcyon.Map; import net.systemeD.halcyon.connection.*; import net.systemeD.halcyon.connection.actions.*; @@ -9,7 +8,7 @@ package net.systemeD.potlatch2 { import flash.system.Security; import com.adobe.serialization.json.JSON; - /** A VectorLayer that can be used to load and display bugs from MapDust-compatible APIs. + /** A Connection that can be used to load and display bugs from MapDust-compatible APIs. See utils/BugLoader.as for the corresponding loader. */ public class BugConnection extends Connection { diff --git a/net/systemeD/potlatch2/mygpx/MyGpxDialog.mxml b/net/systemeD/potlatch2/mygpx/MyGpxDialog.mxml index bdce15c1..f7120ded 100644 --- a/net/systemeD/potlatch2/mygpx/MyGpxDialog.mxml +++ b/net/systemeD/potlatch2/mygpx/MyGpxDialog.mxml @@ -14,7 +14,6 @@ import net.systemeD.potlatch2.save.*; import net.systemeD.halcyon.Map; import net.systemeD.halcyon.Globals; - import net.systemeD.halcyon.VectorLayer; import net.systemeD.potlatch2.utils.Importer; import net.systemeD.potlatch2.utils.GpxImporter; import mx.controls.Alert; diff --git a/net/systemeD/potlatch2/panels/BugPanel.mxml b/net/systemeD/potlatch2/panels/BugPanel.mxml index 6e3d96ad..0f606d2c 100644 --- a/net/systemeD/potlatch2/panels/BugPanel.mxml +++ b/net/systemeD/potlatch2/panels/BugPanel.mxml @@ -59,7 +59,6 @@ Date: Thu, 26 May 2011 14:56:31 +0100 Subject: [PATCH 36/89] While I notice it, simplify.as adds undostack items when e.g. importing GPX into background layers --- TODO.txt | 3 +++ net/systemeD/potlatch2/tools/Simplify.as | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/TODO.txt b/TODO.txt index 9566d4df..9d2ed053 100644 --- a/TODO.txt +++ b/TODO.txt @@ -73,6 +73,9 @@ Potlatch 2: main outstanding issues == l10n == * Fix the en_US / default locale problem +== other == +* Simplify.as shouldn't add an action to the global undo stack, since it's called from e.g. importing into other layers + Requested enhancements ---------------------- diff --git a/net/systemeD/potlatch2/tools/Simplify.as b/net/systemeD/potlatch2/tools/Simplify.as index 3732e254..5e414472 100644 --- a/net/systemeD/potlatch2/tools/Simplify.as +++ b/net/systemeD/potlatch2/tools/Simplify.as @@ -14,7 +14,10 @@ package net.systemeD.potlatch2.tools { * @param way Way to be simplified. * @param map Map it belongs to, for computing offscreen-ness. * @param keepOffscreen If true, don't delete any nodes that are not currently visible. - * */ + * */ + + /* FIXME this should take an action, and push the work onto that. Simplify is called from various places + * so shouldn't be adding to the global undo stack */ public static function simplify(way:Way, map:Map, keepOffscreen:Boolean):void { if (way.length<3) { return; } From 54d82c9c2e8bc82dc483edfa91b8b8bacee91460 Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Thu, 26 May 2011 16:03:39 +0100 Subject: [PATCH 37/89] Refactor all the Importer classes to use connections instead of vectorlayers --- .../potlatch2/VectorSourceDialog.mxml | 52 +++++++++---------- net/systemeD/potlatch2/utils/GpxImporter.as | 19 +++---- net/systemeD/potlatch2/utils/Importer.as | 21 ++++---- net/systemeD/potlatch2/utils/KmlImporter.as | 37 ++++++------- net/systemeD/potlatch2/utils/OsmImporter.as | 14 ++--- net/systemeD/potlatch2/utils/ShpImporter.as | 15 +++--- potlatch2.mxml | 20 +++---- 7 files changed, 91 insertions(+), 87 deletions(-) diff --git a/net/systemeD/potlatch2/VectorSourceDialog.mxml b/net/systemeD/potlatch2/VectorSourceDialog.mxml index 5dbbe723..754d19c4 100644 --- a/net/systemeD/potlatch2/VectorSourceDialog.mxml +++ b/net/systemeD/potlatch2/VectorSourceDialog.mxml @@ -33,7 +33,7 @@ - + @@ -129,7 +129,7 @@ } } - private function removeVectorLayer():void { + private function removeLayer():void { map.removeLayerByName(dataGrid.selectedItem.name); dispatchEvent(new Event("layers_changed")); } @@ -144,31 +144,29 @@ if (type=='gpx') { stylesheet="stylesheets/gpx.css"; } var connection:Connection = new Connection(name, url, null, null); - var mp:MapPaint = map.addLayer(connection, stylesheet); - -// REFACTOR this. commented out to let docs compile. - trace("loadFiles not implemented"); -// var filesLoaded:Function = function(success:Boolean,message:String=null):void { -// if (success) { -// map.addVectorLayer(vectorlayer); -// dispatchEvent(new Event("layers_changed")); -// } else { -// Alert.show(message, 'Error', mx.controls.Alert.OK); -// } -// } - -// if (type=='gpx') { -// var gpx:GpxImporter=new GpxImporter(vectorlayer, vectorlayer.paint, [url], filesLoaded, simplify); -// } else if (type=='kml') { -// var kml:KmlImporter=new KmlImporter(vectorlayer, vectorlayer.paint, [url], filesLoaded, simplify); -// } else if (type=='osm') { -// var osm:OsmImporter=new OsmImporter(vectorlayer, vectorlayer.paint, [url], filesLoaded, simplify); -// } else { -// var re:RegExp=/.shp$/i; url=url.replace(re,''); -// var shp:ShpImporter=new ShpImporter(vectorlayer, -// vectorlayer.paint, -// [url+".shp",url+".shx",url+".dbf"], filesLoaded, simplify); -// } + + var filesLoaded:Function = function(success:Boolean,message:String=null):void { + if (success) { + var paint:MapPaint = map.addLayer(connection, stylesheet); + paint.updateEntityUIs(false, false); + dispatchEvent(new Event("layers_changed")); + } else { + Alert.show(message, 'Error', mx.controls.Alert.OK); + } + } + + if (type=='gpx') { + var gpx:GpxImporter=new GpxImporter(connection, map, [url], filesLoaded, simplify); + } else if (type=='kml') { + var kml:KmlImporter=new KmlImporter(connection, map, [url], filesLoaded, simplify); + } else if (type=='osm') { + var osm:OsmImporter=new OsmImporter(connection, map, [url], filesLoaded, simplify); + } else { + var re:RegExp=/.shp$/i; url=url.replace(re,''); + var shp:ShpImporter=new ShpImporter(connection, + map, + [url+".shp",url+".shx",url+".dbf"], filesLoaded, simplify); + } } ]]> diff --git a/net/systemeD/potlatch2/utils/GpxImporter.as b/net/systemeD/potlatch2/utils/GpxImporter.as index 6c6eac4b..c3d64190 100644 --- a/net/systemeD/potlatch2/utils/GpxImporter.as +++ b/net/systemeD/potlatch2/utils/GpxImporter.as @@ -1,6 +1,7 @@ package net.systemeD.potlatch2.utils { - import net.systemeD.halcyon.MapPaint; + import net.systemeD.halcyon.Map; + import net.systemeD.halcyon.connection.Connection; import net.systemeD.halcyon.connection.Node; import net.systemeD.halcyon.connection.Way; import net.systemeD.potlatch2.tools.Simplify; @@ -11,11 +12,11 @@ package net.systemeD.potlatch2.utils { */ public class GpxImporter extends Importer { - public function GpxImporter(container:*, paint:MapPaint, filenames:Array, callback:Function=null, simplify:Boolean=false) { - super(container,paint,filenames,callback,simplify); + public function GpxImporter(connection:Connection, map:Map, filenames:Array, callback:Function=null, simplify:Boolean=false) { + super(connection,map,filenames,callback,simplify); } - override protected function doImport(): void { + override protected function doImport(push:Function): void { var file:XML = new XML(files[0]); for each (var ns:Namespace in file.namespaceDeclarations()) { if (ns.uri.match(/^http:\/\/www\.topografix\.com\/GPX\/1\/[01]$/)) { @@ -27,11 +28,11 @@ package net.systemeD.potlatch2.utils { var way:Way; var nodestring:Array = []; for each (var trkpt:XML in trkseg.trkpt) { - nodestring.push(container.createNode({}, trkpt.@lat, trkpt.@lon)); + nodestring.push(connection.createNode({}, trkpt.@lat, trkpt.@lon, push)); } if (nodestring.length > 0) { - way = container.createWay({}, nodestring); - if (simplify) { Simplify.simplify(way, paint.map, false); } + way = connection.createWay({}, nodestring, push); + if (simplify) { Simplify.simplify(way, map, false); } } } @@ -40,8 +41,8 @@ package net.systemeD.potlatch2.utils { for each (var tag:XML in wpt.children()) { tags[tag.name().localName]=tag.toString(); } - var node:Node = container.createNode(tags, wpt.@lat, wpt.@lon); - container.registerPOI(node); + var node:Node = connection.createNode(tags, wpt.@lat, wpt.@lon, push); + connection.registerPOI(node); } default xml namespace = new Namespace(""); diff --git a/net/systemeD/potlatch2/utils/Importer.as b/net/systemeD/potlatch2/utils/Importer.as index 7e228423..c664530d 100644 --- a/net/systemeD/potlatch2/utils/Importer.as +++ b/net/systemeD/potlatch2/utils/Importer.as @@ -1,6 +1,6 @@ package net.systemeD.potlatch2.utils { - import net.systemeD.halcyon.MapPaint; + import net.systemeD.halcyon.Map; import net.systemeD.halcyon.ExtendedURLLoader; import net.systemeD.halcyon.DebugURLRequest; import net.systemeD.halcyon.connection.*; @@ -11,8 +11,8 @@ package net.systemeD.potlatch2.utils { public class Importer { - protected var container:Object; // destination object for way/node/relations data - protected var paint:MapPaint; // destination sprite for WayUIs/NodeUIs + protected var connection:Connection; // destination connection for way/node/relations data + protected var map:Map; // map being used - used only in Simplify calls public var files:Array=[]; protected var filenames:Array; @@ -20,9 +20,9 @@ package net.systemeD.potlatch2.utils { protected var callback:Function; protected var simplify:Boolean; - public function Importer(container:*, paint:MapPaint, filenames:Array, callback:Function, simplify:Boolean) { - this.container = container; - this.paint = paint; + public function Importer(connection:Connection, map:Map, filenames:Array, callback:Function, simplify:Boolean) { + this.connection = connection; + this.map = map; this.filenames=filenames; this.callback=callback; this.simplify=simplify; @@ -48,14 +48,15 @@ package net.systemeD.potlatch2.utils { trace("loaded file "+filenum); files[filenum]=e.target.data; filesloaded++; - if (filesloaded==filenames.length) { - doImport(); - paint.updateEntityUIs(false, false); + if (filesloaded==filenames.length) { + var action:CompositeUndoableAction = new CompositeUndoableAction("Import layer "+connection.name); + doImport(action.push); + action.doAction(); // just do it, don't add to undo stack if (callback!=null) { callback(true); } } } - protected function doImport():void { + protected function doImport(push:Function):void { } protected function securityErrorHandler( event:SecurityErrorEvent ):void { callback(false,"You don't have permission to open that file."); } diff --git a/net/systemeD/potlatch2/utils/KmlImporter.as b/net/systemeD/potlatch2/utils/KmlImporter.as index 947240a8..cfed8331 100644 --- a/net/systemeD/potlatch2/utils/KmlImporter.as +++ b/net/systemeD/potlatch2/utils/KmlImporter.as @@ -1,6 +1,7 @@ package net.systemeD.potlatch2.utils { - import net.systemeD.halcyon.MapPaint; + import net.systemeD.halcyon.Map; + import net.systemeD.halcyon.connection.Connection; import net.systemeD.halcyon.connection.Node; import net.systemeD.halcyon.connection.Way; import net.systemeD.halcyon.connection.Relation; @@ -12,11 +13,11 @@ package net.systemeD.potlatch2.utils { */ public class KmlImporter extends Importer { - public function KmlImporter(container:*, paint:MapPaint, filenames:Array, callback:Function=null, simplify:Boolean=false) { - super(container, paint, filenames, callback, simplify); + public function KmlImporter(connection:Connection, map:Map, filenames:Array, callback:Function=null, simplify:Boolean=false) { + super(connection, map, filenames, callback, simplify); } - override protected function doImport(): void { + override protected function doImport(push:Function): void { var kml:XML = new XML(files[0]); for each (var ns:Namespace in kml.namespaceDeclarations()) { @@ -39,15 +40,15 @@ package net.systemeD.potlatch2.utils { } for each (var point:XML in placemark.Point) { - importNode(point.coordinates, tags); + importNode(point.coordinates, tags, push); } for each (var linestring:XML in placemark.LineString) { - importWay(linestring.coordinates, tags, false); + importWay(linestring.coordinates, tags, false, push); } for each (var linearring:XML in placemark.LinearRing) { - importWay(linearring.coordinates, tags, true); + importWay(linearring.coordinates, tags, true, push); } for each (var polygon:XML in placemark.Polygon) { @@ -55,39 +56,39 @@ package net.systemeD.potlatch2.utils { var members:Array = []; var way:Way; - way = importWay(polygon.outerBoundaryIs.LinearRing.coordinates, {}, true); + way = importWay(polygon.outerBoundaryIs.LinearRing.coordinates, {}, true, push); members.push(new RelationMember(way, "outer")); for each (var inner:XML in polygon.innerBoundaryIs) { - way = importWay(inner.LinearRing.coordinates, {}, true); + way = importWay(inner.LinearRing.coordinates, {}, true, push); members.push(new RelationMember(way, "inner")); } tags["type"] = "multipolygon"; - container.createRelation(tags, members); + connection.createRelation(tags, members, push); } else { - importWay(polygon.outerBoundaryIs.LinearRing.coordinates, tags, true); + importWay(polygon.outerBoundaryIs.LinearRing.coordinates, tags, true, push); } } } default xml namespace = new Namespace(""); } - private function importNode(coordinates:String, tags:Object): Node { + private function importNode(coordinates:String, tags:Object, push:Function): Node { var coords:Array = coordinates.split(","); var lon:Number = coords[0]; var lat:Number = coords[1]; //var ele:Number = coords[2]; - var node:Node = container.createNode(tags, lat, lon); + var node:Node = connection.createNode(tags, lat, lon, push); - container.registerPOI(node); + connection.registerPOI(node); return node; } - private function importWay(coordinates:String, tags:Object, polygon:Boolean): Way { + private function importWay(coordinates:String, tags:Object, polygon:Boolean, push:Function): Way { var way:Way; var nodestring:Array = []; @@ -101,7 +102,7 @@ package net.systemeD.potlatch2.utils { var lat:Number = coords[1]; //var ele:Number = coords[2]; - nodestring.push(container.createNode({}, lat, lon)); + nodestring.push(connection.createNode({}, lat, lon, push)); } if (polygon) { @@ -109,8 +110,8 @@ package net.systemeD.potlatch2.utils { } if (nodestring.length > 0) { - way = container.createWay(tags, nodestring); - if (simplify) { Simplify.simplify(way, paint.map, false); } + way = connection.createWay(tags, nodestring, push); + if (simplify) { Simplify.simplify(way, map, false); } } return way; diff --git a/net/systemeD/potlatch2/utils/OsmImporter.as b/net/systemeD/potlatch2/utils/OsmImporter.as index f456899f..c3d84f2f 100644 --- a/net/systemeD/potlatch2/utils/OsmImporter.as +++ b/net/systemeD/potlatch2/utils/OsmImporter.as @@ -1,16 +1,16 @@ package net.systemeD.potlatch2.utils { - import net.systemeD.halcyon.MapPaint; + import net.systemeD.halcyon.Map; import net.systemeD.halcyon.connection.*; import net.systemeD.potlatch2.tools.Simplify; public class OsmImporter extends Importer { - public function OsmImporter(container:*, paint:MapPaint, filenames:Array, callback:Function=null, simplify:Boolean=false) { - super(container,paint,filenames,callback,simplify); + public function OsmImporter(connection:Connection, map:Map, filenames:Array, callback:Function=null, simplify:Boolean=false) { + super(connection,map,filenames,callback,simplify); } - override protected function doImport():void { + override protected function doImport(push:Function):void { var map:XML = new XML(files[0]); var data:XML; @@ -23,14 +23,14 @@ package net.systemeD.potlatch2.utils { for each(data in map.node) { oldid = Number(data.@id); - nodemap[oldid] = container.createNode(parseTags(data.tag), Number(data.@lat), Number(data.@lon)); + nodemap[oldid] = connection.createNode(parseTags(data.tag), Number(data.@lat), Number(data.@lon), push); } for each(data in map.way) { oldid = Number(data.@id); var nodes:Array = []; for each(var nd:XML in data.nd) { nodes.push(nodemap[Number(nd.@ref)]); } - waymap[oldid] = container.createWay(parseTags(data.tag), nodes); + waymap[oldid] = connection.createWay(parseTags(data.tag), nodes, push); } for each(data in map.relation) { @@ -48,7 +48,7 @@ package net.systemeD.potlatch2.utils { } if (member!=null) { members.push(new RelationMember(member,role)); } } - relationmap[oldid] = container.createRelation(parseTags(data.tag), members); + relationmap[oldid] = connection.createRelation(parseTags(data.tag), members, push); } } diff --git a/net/systemeD/potlatch2/utils/ShpImporter.as b/net/systemeD/potlatch2/utils/ShpImporter.as index 6c46fab6..9f5cd9ce 100644 --- a/net/systemeD/potlatch2/utils/ShpImporter.as +++ b/net/systemeD/potlatch2/utils/ShpImporter.as @@ -2,18 +2,19 @@ package net.systemeD.potlatch2.utils { import org.vanrijkom.shp.*; import org.vanrijkom.dbf.*; - import net.systemeD.halcyon.MapPaint; + import net.systemeD.halcyon.Map; + import net.systemeD.halcyon.connection.Connection; import net.systemeD.halcyon.connection.Node; import net.systemeD.halcyon.connection.Way; import net.systemeD.potlatch2.tools.Simplify; public class ShpImporter extends Importer { - public function ShpImporter(container:*, paint:MapPaint, filenames:Array, callback:Function=null, simplify:Boolean=false) { - super(container,paint,filenames,callback,simplify); + public function ShpImporter(connection:Connection, map:Map, filenames:Array, callback:Function=null, simplify:Boolean=false) { + super(connection,map,filenames,callback,simplify); } - override protected function doImport(): void { + override protected function doImport(push:Function): void { // we load .shp as files[0], .shx as files[1], .dbf as files[2] var shp:ShpHeader=new ShpHeader(files[0]); var dbf:DbfHeader=new DbfHeader(files[2]); @@ -36,12 +37,12 @@ package net.systemeD.potlatch2.utils { if (points!=null) { for (var k:int=0; k < points.length; k++) { var p:ShpPoint = ShpPoint(points[k]); - nodestring.push(container.createNode({}, p.y, p.x)); + nodestring.push(connection.createNode({}, p.y, p.x, push)); } } if (nodestring.length>0) { - way=container.createWay({}, nodestring); - if (simplify) { Simplify.simplify(way, paint.map, false); } + way=connection.createWay({}, nodestring, push); + if (simplify) { Simplify.simplify(way, map, false); } } } } diff --git a/potlatch2.mxml b/potlatch2.mxml index 2358b50d..d439af39 100644 --- a/potlatch2.mxml +++ b/potlatch2.mxml @@ -285,15 +285,17 @@ // Load arbitrary GPX from provided URL if (loaderInfo.parameters['gpx_url']) { - var vectorlayer:VectorLayer=new VectorLayer(name,theMap,"stylesheets/gpx.css"); - vectorlayer.url=loaderInfo.parameters['gpx_url']; - var gpx:GpxImporter=new GpxImporter(vectorlayer, vectorlayer.paint, [vectorlayer.url], - function(success:Boolean,message:String=null):void { - if (!success) return; - // >>>> REFACTOR: vectorlayer commented out -// theMap.addVectorLayer(vectorlayer); - dispatchEvent(new Event("layers_changed")); - }, false); + + var gpx_url:String = loaderInfo.parameters['gpx_url']; + + var connection:Connection = new Connection(name, gpx_url, null, null); + var gpx:GpxImporter=new GpxImporter(connection, theMap, [gpx_url], + function(success:Boolean,message:String=null):void { + if (!success) return; + var paint:MapPaint = theMap.addLayer(connection, "stylesheets/gpx.css"); + paint.updateEntityUIs(false, false); + dispatchEvent(new Event("layers_changed")); + }, false); } // create GPS trackloader From d57d4a79ef0cd0ec16aad8f826b81c89e7e249fa Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Thu, 26 May 2011 16:10:41 +0100 Subject: [PATCH 38/89] Re-enable loading gpx files from vectors.xml --- .../collections/VectorBackgrounds.as | 35 +++++++++++-------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/net/systemeD/potlatch2/collections/VectorBackgrounds.as b/net/systemeD/potlatch2/collections/VectorBackgrounds.as index 1ced4e35..0a120e94 100644 --- a/net/systemeD/potlatch2/collections/VectorBackgrounds.as +++ b/net/systemeD/potlatch2/collections/VectorBackgrounds.as @@ -4,8 +4,9 @@ package net.systemeD.potlatch2.collections { import flash.net.* import flash.system.Security; import net.systemeD.halcyon.Map; + import net.systemeD.halcyon.MapPaint; + import net.systemeD.halcyon.connection.Connection; import net.systemeD.halcyon.DebugURLRequest; - import net.systemeD.halcyon.VectorLayer; import net.systemeD.potlatch2.utils.*; public class VectorBackgrounds extends EventDispatcher { @@ -44,19 +45,25 @@ package net.systemeD.potlatch2.collections { case "KMLImporter": break; case "GPXImporter": -// if (set.url) { -// if (set.@loaded == "true") { -// name ||= 'GPX file'; -// // >>>> REFACTOR: VectorLayer commented out -// // var layer:VectorLayer = new VectorLayer(name, _map, 'stylesheets/gpx.css'); -// // _map.addVectorLayer(layer); -// // var gpxImporter:GpxImporter = new GpxImporter(layer, layer.paint, [String(set.url)]); -// } else { -// trace("configured but not loaded isn't supported yet"); -// } -// } else { -// trace("AutoVectorBackground: no url for GPXImporter"); -// } + if (set.url) { + if (set.@loaded == "true") { + name ||= 'GPX file'; + var gpx_url:String = String(set.url); + + var connection:Connection = new Connection(name, gpx_url, null, null); + var gpx:GpxImporter=new GpxImporter(connection, _map, [gpx_url], + function(success:Boolean,message:String=null):void { + if (!success) return; + var paint:MapPaint = _map.addLayer(connection, "stylesheets/gpx.css"); + paint.updateEntityUIs(false, false); + dispatchEvent(new Event("layers_changed")); + }, false); + } else { + trace("configured but not loaded isn't supported yet"); + } + } else { + trace("AutoVectorBackground: no url for GPXImporter"); + } break; case "BugLoader": From fb053909986857ffc43a65f31df94dfc07eba0fa Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Thu, 26 May 2011 17:09:35 +0100 Subject: [PATCH 39/89] Reimplement pullThrough in a more undo-friendly fashion - only one undo to reverse it all --- net/systemeD/halcyon/MapPaint.as | 57 ++++++++++++++++--- .../potlatch2/controller/ControllerState.as | 2 +- 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/net/systemeD/halcyon/MapPaint.as b/net/systemeD/halcyon/MapPaint.as index 0dafd34d..123265d4 100644 --- a/net/systemeD/halcyon/MapPaint.as +++ b/net/systemeD/halcyon/MapPaint.as @@ -5,6 +5,7 @@ package net.systemeD.halcyon { import net.systemeD.halcyon.NodeUI; import net.systemeD.halcyon.WayUI; import net.systemeD.halcyon.connection.*; + import net.systemeD.halcyon.connection.actions.CreatePOIAction; import net.systemeD.halcyon.styleparser.RuleSet; /** Manages the drawing of map entities, allocating their sprites etc. */ @@ -349,15 +350,6 @@ package net.systemeD.halcyon { ruleset.loadFromCSS(url); } - // >>>> REFACTOR: remove this - public function findSource():VectorLayer { -// var v:VectorLayer; -// for each (v in map.vectorlayers) { -// if (v.paint==this) { return v; } -// } - return null; - } - // ==================== Start of code moved from Map.as // Listeners for Connection events @@ -437,5 +429,52 @@ package net.systemeD.halcyon { // ==================== End of code moved from Map.as + /** + * Transfers an entity from this layer into another layer + * @param entity The entity from this layer that you want to transfer. + * @param target The layer to transfer to + * + * @return either the newly created entity, or null + */ + public function pullThrough(entity:Entity, target:MapPaint):Entity { + // TODO - check the entity actually resides in this layer. + + var action:CompositeUndoableAction = new CompositeUndoableAction("pull through"); + if (entity is Way) { + // copy way through to main layer + // ** shouldn't do this if the nodes are already in the main layer + // (or maybe we should just match on lat/long to avoid ways in background having nodes in foreground) + var oldWay:Way=Way(entity); + var newWay:Way=target.connection.createWay(oldWay.getTagsCopy(), [], action.push); + var nodemap:Object={}; + for (var i:uint=0; i Date: Thu, 26 May 2011 17:15:22 +0100 Subject: [PATCH 40/89] Remove VectorLayer.as. Cursory check suggests all the vectorlayer-based refactoring is complete. --- REFACTOR.txt | 5 - net/systemeD/halcyon/VectorLayer.as | 212 ---------------------------- 2 files changed, 217 deletions(-) delete mode 100644 net/systemeD/halcyon/VectorLayer.as diff --git a/REFACTOR.txt b/REFACTOR.txt index 7945e604..e4a639bd 100644 --- a/REFACTOR.txt +++ b/REFACTOR.txt @@ -25,11 +25,6 @@ MapPaint.as - wayuis, nodeuis etc. should ideally be private - removeLayer should blank -VectorLayer.as is completely derelict -- move into Connection -- references in Loader classes etc. currently commented out -- everything derived from VectorLayers (e.g. Traces, Bugs, BikeShopLoader) needs completely refactoring - Global changes: - remove all back-references to Map except where necessary for lat/long/scale - getParam is messy - stuff sent via flashvars needs somewhere to live: currently in Globals which is ugly diff --git a/net/systemeD/halcyon/VectorLayer.as b/net/systemeD/halcyon/VectorLayer.as deleted file mode 100644 index 04e2ba80..00000000 --- a/net/systemeD/halcyon/VectorLayer.as +++ /dev/null @@ -1,212 +0,0 @@ -package net.systemeD.halcyon { - - import net.systemeD.halcyon.Map; - import net.systemeD.halcyon.MapPaint; - import net.systemeD.halcyon.connection.*; - import net.systemeD.halcyon.connection.actions.*; - import net.systemeD.halcyon.styleparser.RuleSet; - - /** The VectorLayer class is used for the concept of Vector Background Layers. - * It is similar in concept to the various Connection layers used for the core - * OpenStreetMap data, and as such it stores its own list of nodes, ways and relations. - * The most interesting function is pullThrough which allows moving entities out - * of a VectorLayer and into the main map layer - */ - public class VectorLayer extends Object { - - public var map:Map; - public var paint:MapPaint; // sprites - public var name:String; - public var url:String; - public var style:String=''; - - public var ways:Object=new Object(); // geodata - public var nodes:Object=new Object(); // | - public var relations:Object=new Object(); // | - private var pois:Array=[]; // | - - private var markers:Object=new Object(); // markers - private var negativeID:Number = -1; - - /** Create a new VectorLayer - * @param n The name of the VectorLayer (eg 'GPS tracks') - * @param m The map. You probably have a global reference to this - * @param s The style you wish to use (eg 'gpx.css') - */ - public function VectorLayer(n:String,m:Map,s:String) { - name=n; - map=m; - style=s; - // >>>> REFACTOR: VectorLayer commented out -// paint=new MapPaint(m,0,0); - redrawFromCSS(style); - } - - public function redrawFromCSS(style:String):void { - paint.ruleset=new RuleSet(map.MINSCALE,map.MAXSCALE,paint.redraw,paint.redrawPOIs); - paint.ruleset.loadFromCSS(style); - } - - /** Create a new node on the vector layer. Note that the node won't show up until on the map - * until the the relevant nodeUI is created, so you will need to instruct the paint to create one - * - * e.g. layer.paint.updateEntityUIs(...); - */ - public function createNode(tags:Object,lat:Number,lon:Number):Node { - // >>>> REFACTOR: VectorLayer commented out -// var node:Node = new Node(this, negativeID, 0, tags, true, lat, lon); -// nodes[negativeID]=node; negativeID--; -// return node; - return null; - } - - /** - * @param tags The tags for the new Way - * @param nodes An array of Node objects - */ - public function createWay(tags:Object,nodes:Array):Way { - // >>>> REFACTOR: VectorLayer commented out -// var way:Way = new Way(this, negativeID, 0, tags, true, nodes.concat()); -// ways[negativeID]=way; negativeID--; -// return way; - return null; - } - - /** - * @param tags The tags for the new relation - * @param members An array of RelationMember objects - */ - public function createRelation(tags:Object,members:Array):Relation { - // >>>> REFACTOR: VectorLayer commented out -// var relation:Relation = new Relation(this, negativeID, 0, tags, true, members.concat()); -// relations[negativeID]=relation; negativeID--; -// return relation; - return null; - } - - /** - * Create a new Marker on the VectorLayer. If you pass in an id it'll check first whether that - * marker has been created already, and won't duplicate it. - * - * @param tags The tags for the new Marker - * @param lat The latitude - * @param lon The longitude - * @param id Use this id for the marker, useful for when layer might be reloaded during panning - */ - public function createMarker(tags:Object,lat:Number,lon:Number,id:Number=NaN):Marker { - if (!id) { - id = negativeID; - negativeID--; - } - // >>>> REFACTOR: VectorLayer commented out -// var marker:Marker = markers[id]; -// if (marker == null) { -// marker = new Marker(this, id, 0, tags, true, lat, lon); -// markers[id]=marker; -// } -// return marker; - return null; - } - - public function registerPOI(node:Node):void { - if (pois.indexOf(node)<0) { pois.push(node); } - } - public function unregisterPOI(node:Node):void { - var index:uint = pois.indexOf(node); - if ( index >= 0 ) { pois.splice(index,1); } - } - - public function getObjectsByBbox(left:Number, right:Number, top:Number, bottom:Number):Object { - // ** FIXME: this is just copied-and-pasted from Connection.as, which really isn't very - // good practice. Is there a more elegant way of doing it? - var o:Object = { poisInside: [], poisOutside: [], waysInside: [], waysOutside: [], - markersInside: [], markersOutside: [] }; - - for each (var way:Way in ways) { - if (way.within(left,right,top,bottom)) { o.waysInside.push(way); } - else { o.waysOutside.push(way); } - } - for each (var poi:Node in pois) { - if (poi.within(left,right,top,bottom)) { o.poisInside.push(poi); } - else { o.poisOutside.push(poi); } - } - for each (var marker:Marker in markers) { - if (marker.within(left,right,top,bottom)) { o.markersInside.push(marker); } - else { o.markersOutside.push(marker); } - } - return o; - } - - /** - * Transfers an entity from the VectorLayer into the main layer - * @param entity The entity from the VectorLayer that you want to transfer. - * @param connection The Connection instance to transfer to (eg Connection.getConnection() ) - * - * @return either the newly created entity, or null - */ - public function pullThrough(entity:Entity,connection:Connection):Entity { - var i:uint=0; - var oldNode:Node, newNode:Node; - if (entity is Way) { - // copy way through to main layer - // ** shouldn't do this if the nodes are already in the main layer - // (or maybe we should just match on lat/long to avoid ways in background having nodes in foreground) - var oldWay:Way=Way(entity); - var newWay:Way=connection.createWay(oldWay.getTagsCopy(), [], MainUndoStack.getGlobalStack().addAction); - var nodemap:Object={}; - for (i=0; i>>> REFACTOR: VectorLayer commented out -// var newPoiAction:CreatePOIAction = new CreatePOIAction( -// this, oldNode.getTagsCopy(), oldNode.lat, oldNode.lon); -// MainUndoStack.getGlobalStack().addAction(newPoiAction); -// paint.deleteNodeUI(oldNode); -// delete nodes[oldNode.id]; -// return newPoiAction.getNode(); - return null; - } - return null; - } - - /** - * Remove all the nodes, ways, and relations from the VectorLayer. - * Also removes the associated NodeUIs, WayUIs and POIs - */ - public function blank():void { - for each (var node:Node in nodes) { paint.deleteNodeUI(node); } - for each (var way:Way in ways) { paint.deleteWayUI(way); } - relations={}; nodes={}; ways={}; pois=[]; - } - - /** - * Load more data, eg during panning of the map. This can be overridden by - * vector layers if it makes sense to support it. - */ - public function loadBbox(left:Number, right:Number, - top:Number, bottom:Number):void { - } - - } -} From 53ae9eac920dc39fec84fa3ce6a163a551e355b4 Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Thu, 2 Jun 2011 14:35:22 +0100 Subject: [PATCH 41/89] Little tweaks to documentation --- net/systemeD/potlatch2/EditController.as | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/net/systemeD/potlatch2/EditController.as b/net/systemeD/potlatch2/EditController.as index 21b84b3b..5daee281 100644 --- a/net/systemeD/potlatch2/EditController.as +++ b/net/systemeD/potlatch2/EditController.as @@ -22,7 +22,8 @@ package net.systemeD.potlatch2 { private var _map:Map; public var tagViewer:TagViewer; private var toolbox:Toolbox; - + + /** The current ControllerState */ public var state:ControllerState; private var keys:Object={}; @@ -144,7 +145,9 @@ package net.systemeD.potlatch2 { return true; } - /** Exit the current state and switch to a new one. */ + /** Exit the current state and switch to a new one. + * + * @param newState The ControllerState to switch to. */ public function setState(newState:ControllerState):void { if ( newState == state ) return; From 91a33c0933cdc26aa9bd6cc2d7edd7efa6e8b505 Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Thu, 2 Jun 2011 14:38:04 +0100 Subject: [PATCH 42/89] New SnapshotLoader and associated connections --- .../collections/VectorBackgrounds.as | 12 +++++++++ .../potlatch2/utils/SnapshotConnection.as | 14 ++++++++++ .../potlatch2/utils/SnapshotLoader.as | 27 +++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 net/systemeD/potlatch2/utils/SnapshotConnection.as create mode 100644 net/systemeD/potlatch2/utils/SnapshotLoader.as diff --git a/net/systemeD/potlatch2/collections/VectorBackgrounds.as b/net/systemeD/potlatch2/collections/VectorBackgrounds.as index 0a120e94..6381feed 100644 --- a/net/systemeD/potlatch2/collections/VectorBackgrounds.as +++ b/net/systemeD/potlatch2/collections/VectorBackgrounds.as @@ -90,6 +90,18 @@ package net.systemeD.potlatch2.collections { } break; + case "SnapshotLoader": + if (set.url) { + name ||= 'Snapshot Server' + var snapshotLoader:SnapshotLoader = new SnapshotLoader(_map, String(set.url), name); + if (set.@loaded == "true") { + snapshotLoader.load(); + } + } else { + trace("VectorBackground: no url for SnapshotLoader"); + } + break; + default: trace("AutoVectorBackground: unknown loader"); } diff --git a/net/systemeD/potlatch2/utils/SnapshotConnection.as b/net/systemeD/potlatch2/utils/SnapshotConnection.as new file mode 100644 index 00000000..5159e095 --- /dev/null +++ b/net/systemeD/potlatch2/utils/SnapshotConnection.as @@ -0,0 +1,14 @@ +package net.systemeD.potlatch2.utils { + + import net.systemeD.halcyon.connection.XMLConnection; + + public class SnapshotConnection extends XMLConnection { + + public function SnapshotConnection(cname:String,api:String,policy:String,initparams:Object=null) { + super(cname,api,policy,initparams); + } + + /* todo - stuff about marking nodes/ways as complete */ + + } +} \ No newline at end of file diff --git a/net/systemeD/potlatch2/utils/SnapshotLoader.as b/net/systemeD/potlatch2/utils/SnapshotLoader.as new file mode 100644 index 00000000..b0feaed1 --- /dev/null +++ b/net/systemeD/potlatch2/utils/SnapshotLoader.as @@ -0,0 +1,27 @@ +package net.systemeD.potlatch2.utils { + + import net.systemeD.halcyon.Map; + import net.systemeD.halcyon.MapPaint; + import net.systemeD.potlatch2.utils.SnapshotConnection; + + public class SnapshotLoader { + + private var map:Map; + private var _layer:MapPaint; + private static const STYLESHEET:String="stylesheets/wireframe.css"; //TODO take from xml + private var connection:SnapshotConnection; + + + public function SnapshotLoader(map:Map, url:String, name:String):void { + this.map = map; + connection = new SnapshotConnection(name, url, ''); + } + + public function load():void { + if (!_layer) { + _layer = map.addLayer(connection, STYLESHEET); + } + connection.loadBbox(map.edge_l, map.edge_r, map.edge_t, map.edge_b); + } + } +} \ No newline at end of file From 167019ab969ecc7eab9d9c71650b9d8f5c9d8b98 Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Thu, 2 Jun 2011 14:39:02 +0100 Subject: [PATCH 43/89] Documentation --- net/systemeD/potlatch2/controller/ControllerState.as | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/net/systemeD/potlatch2/controller/ControllerState.as b/net/systemeD/potlatch2/controller/ControllerState.as index db0ef103..d635e461 100644 --- a/net/systemeD/potlatch2/controller/ControllerState.as +++ b/net/systemeD/potlatch2/controller/ControllerState.as @@ -50,11 +50,19 @@ package net.systemeD.potlatch2.controller { return this; } + /** Retrieves the map associated with the current EditController */ public function get map():Map { return controller.map; } + /** This is called when the EditController sets this ControllerState as the active state. + * Override this with whatever is needed, such as adding highlights to entities + */ public function enterState():void {} + + /** This is called by the EditController as the current controllerstate is exiting. + * Override this with whatever cleanup is needed, such as removing highlights from entities + */ public function exitState(newState:ControllerState):void {} /** Represent the state in text for debugging. */ From 2268d4025f4bcc814844c38e56a6e56b7583fb71 Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Thu, 2 Jun 2011 14:44:32 +0100 Subject: [PATCH 44/89] Add the ability to select, but not edit, a background way --- .../potlatch2/controller/ControllerState.as | 6 +- .../controller/SelectedBackgroundWay.as | 86 +++++++++++++++++++ 2 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 net/systemeD/potlatch2/controller/SelectedBackgroundWay.as diff --git a/net/systemeD/potlatch2/controller/ControllerState.as b/net/systemeD/potlatch2/controller/ControllerState.as index d635e461..0aeddaa6 100644 --- a/net/systemeD/potlatch2/controller/ControllerState.as +++ b/net/systemeD/potlatch2/controller/ControllerState.as @@ -7,6 +7,7 @@ package net.systemeD.potlatch2.controller { import net.systemeD.potlatch2.collections.Imagery; import net.systemeD.potlatch2.EditController; import net.systemeD.potlatch2.save.SaveManager; + import net.systemeD.potlatch2.utils.SnapshotConnection; import flash.ui.Keyboard; import mx.controls.Alert; import mx.events.CloseEvent; @@ -93,7 +94,10 @@ package net.systemeD.potlatch2.controller { var focus:Entity = getTopLevelFocusEntity(entity); if ( paint && paint.isBackground ) { - if ( event.type == MouseEvent.MOUSE_DOWN && ((event.shiftKey && event.ctrlKey) || event.altKey) ) { + if ( event.type == MouseEvent.MOUSE_DOWN && entity.connection is SnapshotConnection) { + if (entity is Way) { return new SelectedBackgroundWay(entity as Way); } + else if (entity is Node) { return new SelectedPOINode(entity as Node); } + } else if ( event.type == MouseEvent.MOUSE_DOWN && ((event.shiftKey && event.ctrlKey) || event.altKey) ) { // alt-click to pull data out of vector background layer var newEntity:Entity=paint.pullThrough(entity,editableLayer); if (entity is Way) { return new SelectedWay(newEntity as Way); } diff --git a/net/systemeD/potlatch2/controller/SelectedBackgroundWay.as b/net/systemeD/potlatch2/controller/SelectedBackgroundWay.as new file mode 100644 index 00000000..934010c4 --- /dev/null +++ b/net/systemeD/potlatch2/controller/SelectedBackgroundWay.as @@ -0,0 +1,86 @@ +package net.systemeD.potlatch2.controller { + import flash.events.*; + import flash.geom.Point; + import flash.ui.Keyboard; + + import net.systemeD.halcyon.WayUI; + import net.systemeD.halcyon.connection.*; + import net.systemeD.potlatch2.tools.Quadrilateralise; + import net.systemeD.potlatch2.tools.Simplify; + + /** Behaviour that takes place while a way is selected includes: adding a node to the way, straightening/reshaping the way, dragging it. */ + public class SelectedBackgroundWay extends ControllerState { + /** The selected way itself. */ + protected var initWay:Way; + private var clicked:Point; // did the user enter this state by clicking at a particular point? + private var wayList:Array; // list of ways to cycle through with '/' keypress + private var initIndex: int; // index of last selected node if entered from SelectedWayNode + + /** + * @param way The way that is now selected. + * @param point The location that was clicked. + * @param ways An ordered list of ways sharing a node, to make "way cycling" work. */ + public function SelectedBackgroundWay(way:Way, point:Point=null, ways:Array=null, index:int=0) { + initWay = way; + clicked = point; + wayList = ways; + initIndex=index; + } + + private function updateSelectionUI(e:Event):void { + controller.updateSelectionUIWithoutTagChange(); + } + + /** Tidy up UI as we transition to a new state without the current selection. */ + protected function clearSelection(newState:ControllerState):void { + if ( selectCount ) { + editableLayer.setHighlight(firstSelected, { selected: false, hover: false }); + editableLayer.setHighlightOnNodes(firstSelected as Way, { selectedway: false }); + selection = []; + if (!newState.isSelectionState()) { controller.updateSelectionUI(); } + } + } + + /** The only things we want to do here are deselect and stay selected */ + override public function processMouseEvent(event:MouseEvent, entity:Entity):ControllerState { + if (event.type==MouseEvent.MOUSE_MOVE) { return this; } + if (event.type==MouseEvent.MOUSE_UP) { return this; } + var cs:ControllerState = sharedMouseEvents(event, entity); + return cs ? cs : this; + } + + /** TODO - key press for "completing" a way */ + override public function processKeyboardEvent(event:KeyboardEvent):ControllerState { + switch (event.keyCode) { + + + } + var cs:ControllerState = sharedKeyboardEvents(event); + return cs ? cs : this; + } + + /** Officially enter this state by marking the previously nominated way as selected. */ + override public function enterState():void { + if (firstSelected!=initWay) { + clearSelection(this); + editableLayer.setHighlight(initWay, { selected: true, hover: false }); + editableLayer.setHighlightOnNodes(initWay, { selectedway: true }); + selection = [initWay]; + controller.updateSelectionUI(); + } + editableLayer.setPurgable(selection,false); + } + + /** Officially leave the state */ + override public function exitState(newState:ControllerState):void { + editableLayer.setPurgable(selection,true); + clearSelection(newState); + } + + /** @return "SelectedWay" */ + override public function toString():String { + return "SelectedBackgroundWay"; + } + + } +} From db0b97668056c654c4757bb2687add6dead7398a Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Fri, 3 Jun 2011 13:47:36 +0100 Subject: [PATCH 45/89] Add a panel for background features - based on the marker panel --- net/systemeD/potlatch2/TagViewer.mxml | 10 ++++ .../potlatch2/panels/BackgroundPanel.mxml | 46 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 net/systemeD/potlatch2/panels/BackgroundPanel.mxml diff --git a/net/systemeD/potlatch2/TagViewer.mxml b/net/systemeD/potlatch2/TagViewer.mxml index 5da5c225..d477a57d 100644 --- a/net/systemeD/potlatch2/TagViewer.mxml +++ b/net/systemeD/potlatch2/TagViewer.mxml @@ -204,12 +204,19 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From ecb4b81aa3abaeac1a6c776663e297df3f776c9e Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Thu, 9 Jun 2011 15:16:43 +0100 Subject: [PATCH 46/89] Make wayuis, nodeuis and markeruis private --- REFACTOR.txt | 21 ++++++----- net/systemeD/halcyon/MapPaint.as | 30 ++++++++++++--- net/systemeD/halcyon/WayUI.as | 37 ++++++++----------- .../potlatch2/controller/DragWayNode.as | 10 +---- .../potlatch2/controller/SelectedWay.as | 7 +--- .../potlatch2/controller/SelectedWayNode.as | 27 +++++++------- 6 files changed, 67 insertions(+), 65 deletions(-) diff --git a/REFACTOR.txt b/REFACTOR.txt index e4a639bd..a9c60844 100644 --- a/REFACTOR.txt +++ b/REFACTOR.txt @@ -4,29 +4,30 @@ Aims: - to enable multiple Maps to be shown on-screen (e.g. for junction editor) - to bring Connection and VectorLayer code together -Current status: -- it loads a map and lets you edit it! -- VectorLayers (of any shape) will not work - lots of them are commented out +Current known problems: +- pull-through creates the way, but doesn't draw it +- AttentionEvents don't work + +To check: +- MapDust +- VectorLayers from GPX +- VectorLayers from shapefiles - Save/OAuth not tested +- removeLayer in MapPaint.as should blank - does it? == Changes overall == Map.as becomes a collection of MapPaint objects, all with the same lat/long/scale (plus a backdrop sprite and a background imagery sprite) + Map.editableLayer returns a reference to the single MapPaint object where isBackground is false MapPaint.as gains a reference to a Connection - i.e. the source data for this layer -== Stuff to look at == +== Code tidying == There are lots more of these throughout the code, marked with fixmes of the form '>>>> REFACTOR' -MapPaint.as -- wayuis, nodeuis etc. should ideally be private -- removeLayer should blank - -Global changes: - remove all back-references to Map except where necessary for lat/long/scale - getParam is messy - stuff sent via flashvars needs somewhere to live: currently in Globals which is ugly -- AttentionEvents are derelict and commented out - tileset/setbackground stuff is screwed up again and needs refactoring a little diff --git a/net/systemeD/halcyon/MapPaint.as b/net/systemeD/halcyon/MapPaint.as index 123265d4..2019ae44 100644 --- a/net/systemeD/halcyon/MapPaint.as +++ b/net/systemeD/halcyon/MapPaint.as @@ -24,12 +24,11 @@ package net.systemeD.halcyon { /** The MapCSS rules used for drawing entities. */ public var ruleset:RuleSet; /** WayUI objects attached to Way entities that are currently visible. */ - public var wayuis:Object=new Object(); // sprites for ways and (POI/tagged) nodes + private var wayuis:Object=new Object(); /** NodeUI objects attached to POI/tagged node entities that are currently visible. */ - // confirm this - it seems to me all nodes in ways get nodeuis? --Steve B - public var nodeuis:Object=new Object(); + private var nodeuis:Object=new Object(); /** MarkerUI objects attached to Marker entities that are currently visible. */ - public var markeruis:Object=new Object(); + private var markeruis:Object=new Object(); /** Is this a background layer or the core paint object? */ public var isBackground:Boolean = true; /** Hash of index->position */ @@ -330,6 +329,7 @@ package net.systemeD.halcyon { return s; } + /** Redraw all entities */ public function redraw():void { for each (var w:WayUI in wayuis) { w.recalculate(); w.invalidateStyleList(); w.redraw(); } /* sometimes (e.g. in Map.setStyle) Mappaint.redrawPOIs() is called immediately afterwards anyway. FIXME? */ @@ -337,12 +337,21 @@ package net.systemeD.halcyon { for each (var m:MarkerUI in markeruis) { m.invalidateStyleList(); m.redraw(); } } - /** Redraw nodes and markers */ + /** Redraw nodes and markers only */ public function redrawPOIs():void { for each (var p:NodeUI in nodeuis) { p.invalidateStyleList(); p.redraw(); } for each (var m:MarkerUI in markeruis) { m.invalidateStyleList(); m.redraw(); } } + /** Redraw a single entity if it exists */ + public function redrawEntity(e:Entity):Boolean { + if (e is Way && wayuis[e.id]) wayuis[e.id].redraw(); + else if (e is Node && nodeuis[e.id]) nodeuis[e.id].redraw(); + else if (e is Marker && markeruis[e.id]) markeruis[e.id].redraw(); + else return false; + return true; + } + /** Switch to new MapCSS. */ public function setStyle(url:String):void { style = url; @@ -429,6 +438,17 @@ package net.systemeD.halcyon { // ==================== End of code moved from Map.as + /** Find all ways whose WayUI passes a given screen co-ordinate. */ + + public function findWaysAtPoint(x:Number, y:Number, ignore:Way=null):Array { + var ways:Array=[]; var w:Way; + for each (var wayui:WayUI in wayuis) { + w=wayui.hitTest(x,y); + if (w && w!=ignore) { ways.push(w); } + } + return ways; + } + /** * Transfers an entity from this layer into another layer * @param entity The entity from this layer that you want to transfer. diff --git a/net/systemeD/halcyon/WayUI.as b/net/systemeD/halcyon/WayUI.as index c07d9e9c..00007f0c 100644 --- a/net/systemeD/halcyon/WayUI.as +++ b/net/systemeD/halcyon/WayUI.as @@ -84,9 +84,7 @@ package net.systemeD.halcyon { if (!event.node.hasParent(event.way)) { event.node.removeEventListener(Connection.NODE_MOVED, nodeMoved); } - if (paint.nodeuis[event.node.id]) { - paint.nodeuis[event.node.id].redraw(); - } + paint.redrawEntity(event.node); recalculate(); redraw(); redrawMultis(); @@ -137,9 +135,7 @@ package net.systemeD.halcyon { for each (var m:Relation in multis) { var outers:Array=m.findMembersByRole('outer'); for each (var e:Entity in outers) { - if (e is Way && paint.wayuis[e.id]) { - paint.wayuis[e.id].redraw(); - } + paint.redrawEntity(e); } } } @@ -151,23 +147,20 @@ package net.systemeD.halcyon { public function setHighlightOnNodes(settings:Object):void { for (var i:uint = 0; i < Way(entity).length; i++) { var node:Node = Way(entity).getNode(i); - if (paint.nodeuis[node.id]) { - // Speed things up a bit by only setting the highlight if it's either: - // a) an "un-highlight" (so we don't leave mess behind when scrolling) - // b) currently onscreen - // Currently this means if you highlight an object then scroll, nodes will scroll - // into view that should be highlighted but aren't. - if (settings.hoverway==false || - settings.selectedway==false || - node.lat >= paint.map.edge_b && node.lat <= paint.map.edge_t && - node.lon >= paint.map.edge_l && node.lon <= paint.map.edge_r) { - paint.nodeuis[node.id].setHighlight(settings); // Triggers redraw if required - } - if (settings.selectedway || settings.hoverway) - nodehighlightsettings=settings; - else - nodehighlightsettings={}; + // Speed things up a bit by only setting the highlight if it's either: + // a) an "un-highlight" (so we don't leave mess behind when scrolling) + // b) currently onscreen + // Currently this means if you highlight an object then scroll, nodes will scroll + // into view that should be highlighted but aren't. + if (settings.hoverway==false || + settings.selectedway==false || + node.within(paint.map.edge_l, paint.map.edge_r, paint.map.edge_t, paint.map.edge_b)) { + paint.setHighlight(node,settings); // Triggers redraw if required } + if (settings.selectedway || settings.hoverway) + nodehighlightsettings=settings; + else + nodehighlightsettings={}; } } diff --git a/net/systemeD/potlatch2/controller/DragWayNode.as b/net/systemeD/potlatch2/controller/DragWayNode.as index 1b618fd9..3625b17c 100644 --- a/net/systemeD/potlatch2/controller/DragWayNode.as +++ b/net/systemeD/potlatch2/controller/DragWayNode.as @@ -33,19 +33,13 @@ package net.systemeD.potlatch2.controller { } private function addNode(selectedWay:Way,event:MouseEvent):int { - // find which other ways are under the mouse - var ways:Array=[]; var w:Way; - for each (var wayui:WayUI in editableLayer.wayuis) { - w=wayui.hitTest(event.stageX, event.stageY); - if (w && w!=selectedWay) { ways.push(w); } - } - + var ways:Array = editableLayer.findWaysAtPoint(event.stageX, event.stageY, selectedWay); var lat:Number = controller.map.coord2lat(event.localY); var lon:Number = controller.map.coord2lon(event.localX); var undo:CompositeUndoableAction = new CompositeUndoableAction("Insert node"); var node:Node = selectedWay.connection.createNode({}, lat, lon, undo.push); var index:int = selectedWay.insertNodeAtClosestPosition(node, true, undo.push); - for each (w in ways) { w.insertNodeAtClosestPosition(node, true, undo.push); } + for each (var w:Way in ways) { w.insertNodeAtClosestPosition(node, true, undo.push); } MainUndoStack.getGlobalStack().addAction(undo); return index; } diff --git a/net/systemeD/potlatch2/controller/SelectedWay.as b/net/systemeD/potlatch2/controller/SelectedWay.as index a24ce7b9..1c15243c 100644 --- a/net/systemeD/potlatch2/controller/SelectedWay.as +++ b/net/systemeD/potlatch2/controller/SelectedWay.as @@ -3,7 +3,6 @@ package net.systemeD.potlatch2.controller { import flash.geom.Point; import flash.ui.Keyboard; - import net.systemeD.halcyon.WayUI; import net.systemeD.halcyon.connection.*; import net.systemeD.potlatch2.tools.Quadrilateralise; import net.systemeD.potlatch2.tools.Simplify; @@ -86,11 +85,7 @@ package net.systemeD.potlatch2.controller { if (!clicked || (wayList && wayList.length<2)) { return this; } if (!wayList) { - wayList=[initWay]; - for each (var wayui:WayUI in editableLayer.wayuis) { - var w:Way=wayui.hitTest(clicked.x, clicked.y); - if (w && w!=initWay) { wayList.push(w); } - } + wayList=[initWay].concat(editableLayer.findWaysAtPoint(clicked.x,clicked.y,initWay)); } wayList=wayList.slice(1).concat(wayList[0]); // Find the new way's index of the currently "selected" node, to facilitate keyboard navigation diff --git a/net/systemeD/potlatch2/controller/SelectedWayNode.as b/net/systemeD/potlatch2/controller/SelectedWayNode.as index 22e48029..def771b7 100644 --- a/net/systemeD/potlatch2/controller/SelectedWayNode.as +++ b/net/systemeD/potlatch2/controller/SelectedWayNode.as @@ -174,12 +174,14 @@ package net.systemeD.potlatch2.controller { /** Attempt to either merge the currently selected node with another very nearby node, or failing that, * attach it mid-way along a very nearby way. */ + // FIXME: why are we only merging one node at once? after all, shift-click to insert a node adds into all ways public function join():ControllerState { var p:Point = new Point(controller.map.lon2coord(Node(firstSelected).lon), controller.map.latp2coord(Node(firstSelected).latp)); var q:Point = map.localToGlobal(p); // First, look for POI nodes in 20x20 pixel box around the current node + // FIXME: why aren't we using a hitTest for this? var hitnodes:Array = editableLayer.connection.getObjectsByBbox( map.coord2lon(p.x-10), map.coord2lon(p.x+10), @@ -192,21 +194,17 @@ package net.systemeD.potlatch2.controller { } } - var ways:Array=[]; var w:Way; - for each (var wayui:WayUI in editableLayer.wayuis) { - w=wayui.hitTest(q.x, q.y); - if (w && w!=selectedWay) { + var ways:Array=editableLayer.findWaysAtPoint(q.x, q.y, selectedWay); + for each (var w:Way in ways) { // hit a way, now let's see if we hit a specific node - for (var i:uint = 0; i < w.length; i++) { - n = w.getNode(i); - var x:Number = map.lon2coord(n.lon); - var y:Number = map.latp2coord(n.latp); - if (n != selectedNode && Math.abs(x-p.x) + Math.abs(y-p.y) < 10) { - return doMergeNodes(n); - } - } - ways.push(w); - } + for (var i:uint = 0; i < w.length; i++) { + n = w.getNode(i); + var x:Number = map.lon2coord(n.lon); + var y:Number = map.latp2coord(n.latp); + if (n != selectedNode && Math.abs(x-p.x) + Math.abs(y-p.y) < 10) { + return doMergeNodes(n); + } + } } // No nodes hit, so join our node onto any overlapping ways. @@ -219,6 +217,7 @@ package net.systemeD.potlatch2.controller { // only merge one node at a time - too confusing otherwise? var msg:String = "Nodes merged." if (MergeNodesAction.lastProblemTags) { + // FIXME: ugh, just ugh. msg += " *Warning* The following tags conflicted and need attention: " + MergeNodesAction.lastProblemTags; } // somethingorother.dispatchEvent(new AttentionEvent(AttentionEvent.ALERT, null, msg)); From 45f71c266b020f54bb1147361f84ad964dd593c4 Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Thu, 9 Jun 2011 15:38:00 +0100 Subject: [PATCH 47/89] Pull-through wasn't working because appendNode doesn't force a redraw - fix that --- REFACTOR.txt | 1 - net/systemeD/halcyon/MapPaint.as | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/REFACTOR.txt b/REFACTOR.txt index a9c60844..53eea81e 100644 --- a/REFACTOR.txt +++ b/REFACTOR.txt @@ -5,7 +5,6 @@ Aims: - to bring Connection and VectorLayer code together Current known problems: -- pull-through creates the way, but doesn't draw it - AttentionEvents don't work To check: diff --git a/net/systemeD/halcyon/MapPaint.as b/net/systemeD/halcyon/MapPaint.as index 2019ae44..22a16dcc 100644 --- a/net/systemeD/halcyon/MapPaint.as +++ b/net/systemeD/halcyon/MapPaint.as @@ -465,18 +465,18 @@ package net.systemeD.halcyon { // ** shouldn't do this if the nodes are already in the main layer // (or maybe we should just match on lat/long to avoid ways in background having nodes in foreground) var oldWay:Way=Way(entity); - var newWay:Way=target.connection.createWay(oldWay.getTagsCopy(), [], action.push); var nodemap:Object={}; + var nodes:Array=[]; for (var i:uint=0; i Date: Thu, 9 Jun 2011 16:15:44 +0100 Subject: [PATCH 48/89] EditController can now throw AttentionEvents too, so they don't all have to go through a Connection --- REFACTOR.txt | 3 --- TODO.txt | 4 ++-- net/systemeD/potlatch2/EditController.as | 2 +- net/systemeD/potlatch2/controller/SelectedMultiple.as | 2 +- net/systemeD/potlatch2/controller/SelectedWayNode.as | 2 +- net/systemeD/potlatch2/tools/Quadrilateralise.as | 1 - potlatch2.mxml | 2 ++ 7 files changed, 7 insertions(+), 9 deletions(-) diff --git a/REFACTOR.txt b/REFACTOR.txt index 53eea81e..391dbacf 100644 --- a/REFACTOR.txt +++ b/REFACTOR.txt @@ -4,9 +4,6 @@ Aims: - to enable multiple Maps to be shown on-screen (e.g. for junction editor) - to bring Connection and VectorLayer code together -Current known problems: -- AttentionEvents don't work - To check: - MapDust - VectorLayers from GPX diff --git a/TODO.txt b/TODO.txt index 9d2ed053..79f1076d 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,5 +1,4 @@ -Potlatch 2: main outstanding issues ------------------------------------ += Potlatch 2: main outstanding issues = == Core geometry == @@ -34,6 +33,7 @@ Potlatch 2: main outstanding issues ** Keypress detection is very erratic, depending on focus - need to work out where events are going (Application.application?) and sense them there * Failing to parse map_features should be an error state +* Quadrilateralise should throw an AttentionEvent if it's too sharp to straighten * Escape should rewind the entity to how it was before the current ControllerState. (Record a position in the undo stack when exiting a ControllerState, and escape would rewind to that) * Custom imagery dialog fixes * Ctrl-clicking two areas (one inside the other) should create a multipolygon diff --git a/net/systemeD/potlatch2/EditController.as b/net/systemeD/potlatch2/EditController.as index 21b84b3b..c1ac2fc8 100644 --- a/net/systemeD/potlatch2/EditController.as +++ b/net/systemeD/potlatch2/EditController.as @@ -17,7 +17,7 @@ package net.systemeD.potlatch2 { /** Controller for the main map editing window itself. The logic that responds to mouse and keyboard events is all * buried in various ControllerState classes. */ - public class EditController implements MapController { + public class EditController extends EventDispatcher implements MapController { private var _map:Map; public var tagViewer:TagViewer; diff --git a/net/systemeD/potlatch2/controller/SelectedMultiple.as b/net/systemeD/potlatch2/controller/SelectedMultiple.as index 3feb114b..aa895515 100644 --- a/net/systemeD/potlatch2/controller/SelectedMultiple.as +++ b/net/systemeD/potlatch2/controller/SelectedMultiple.as @@ -64,7 +64,7 @@ package net.systemeD.potlatch2.controller { for each (var conflict:String in conflictTags) conflictTags2.push(conflict); if (conflictTags2.length>0) msg += " *Warning* The following tags conflicted and need attention: " + conflictTags2; - // >>>> somethingorother.dispatchEvent(new AttentionEvent(AttentionEvent.ALERT, null, msg)); + controller.dispatchEvent(new AttentionEvent(AttentionEvent.ALERT, null, msg)); } return controller.findStateForSelection(waylist); diff --git a/net/systemeD/potlatch2/controller/SelectedWayNode.as b/net/systemeD/potlatch2/controller/SelectedWayNode.as index def771b7..fbe7cea4 100644 --- a/net/systemeD/potlatch2/controller/SelectedWayNode.as +++ b/net/systemeD/potlatch2/controller/SelectedWayNode.as @@ -220,7 +220,7 @@ package net.systemeD.potlatch2.controller { // FIXME: ugh, just ugh. msg += " *Warning* The following tags conflicted and need attention: " + MergeNodesAction.lastProblemTags; } - // somethingorother.dispatchEvent(new AttentionEvent(AttentionEvent.ALERT, null, msg)); + controller.dispatchEvent(new AttentionEvent(AttentionEvent.ALERT, null, msg)); return new SelectedWayNode(n.parentWays[0], Way(n.parentWays[0]).indexOfNode(n)); } diff --git a/net/systemeD/potlatch2/tools/Quadrilateralise.as b/net/systemeD/potlatch2/tools/Quadrilateralise.as index 9f11e07f..c8f2f236 100644 --- a/net/systemeD/potlatch2/tools/Quadrilateralise.as +++ b/net/systemeD/potlatch2/tools/Quadrilateralise.as @@ -29,7 +29,6 @@ package net.systemeD.potlatch2.tools { functor.step(); var newScore:Number = functor.goodness; if (newScore > score) { - // somethingorother.dispatchEvent(new AttentionEvent(AttentionEvent.ALERT, null, "Corners too sharp to straighten")); return false; } score = newScore; diff --git a/potlatch2.mxml b/potlatch2.mxml index d439af39..9ad70000 100644 --- a/potlatch2.mxml +++ b/potlatch2.mxml @@ -268,6 +268,8 @@ theController = new EditController(theMap, tagViewer, toolbox); theController.setActive(); + theController.addEventListener(AttentionEvent.ATTENTION, onAttention); + theController.addEventListener(AttentionEvent.ALERT, onAlert); // set the access token from saved cookie var tokenObject:SharedObject = SharedObject.getLocal("access_token"); From ced5608c9608f0af199242c3baa8a9d144051445 Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Thu, 9 Jun 2011 16:49:24 +0100 Subject: [PATCH 49/89] Don't ask for the requestToken if we haven't told OAuthPanel which connection to use yet --- REFACTOR.txt | 1 - net/systemeD/potlatch2/save/OAuthPanel.mxml | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/REFACTOR.txt b/REFACTOR.txt index 391dbacf..dc76e3de 100644 --- a/REFACTOR.txt +++ b/REFACTOR.txt @@ -8,7 +8,6 @@ To check: - MapDust - VectorLayers from GPX - VectorLayers from shapefiles -- Save/OAuth not tested - removeLayer in MapPaint.as should blank - does it? == Changes overall == diff --git a/net/systemeD/potlatch2/save/OAuthPanel.mxml b/net/systemeD/potlatch2/save/OAuthPanel.mxml index 5a9285fc..f972f927 100644 --- a/net/systemeD/potlatch2/save/OAuthPanel.mxml +++ b/net/systemeD/potlatch2/save/OAuthPanel.mxml @@ -81,6 +81,7 @@ private var _accessToken:OAuthToken; private var authoriseURL:String; private var lastHTTPStatus:int = 0; + private var waiting:Boolean = false; public static var ACCESS_TOKEN_EVENT:String = "gotAccessToken"; @@ -91,6 +92,7 @@ public function setConnection(connection:Connection):void { this.connection=connection; + if (waiting) { waiting=false; getRequestToken(); } } private function openURL(url:String):void { @@ -109,6 +111,8 @@ } private function getRequestToken():void { + if (!connection) { waiting=true; return; } // in case the connection hasn't been set yet + var sig:IOAuthSignatureMethod = new OAuthSignatureMethod_HMAC_SHA1(); var consumer:OAuthConsumer = getConsumer(); var url:String = connection.getParam("oauth_request_url", "http://127.0.0.1:3000/oauth/request_token"); From 7fd55b03a7b989c031af673600aae4935cd3efb0 Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Thu, 9 Jun 2011 18:28:58 +0100 Subject: [PATCH 50/89] Fix closure problem when importing multiple files --- REFACTOR.txt | 6 ------ net/systemeD/potlatch2/utils/Importer.as | 12 +++++------- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/REFACTOR.txt b/REFACTOR.txt index dc76e3de..fd67b902 100644 --- a/REFACTOR.txt +++ b/REFACTOR.txt @@ -4,12 +4,6 @@ Aims: - to enable multiple Maps to be shown on-screen (e.g. for junction editor) - to bring Connection and VectorLayer code together -To check: -- MapDust -- VectorLayers from GPX -- VectorLayers from shapefiles -- removeLayer in MapPaint.as should blank - does it? - == Changes overall == Map.as becomes a collection of MapPaint objects, all with the same lat/long/scale diff --git a/net/systemeD/potlatch2/utils/Importer.as b/net/systemeD/potlatch2/utils/Importer.as index c664530d..e53355de 100644 --- a/net/systemeD/potlatch2/utils/Importer.as +++ b/net/systemeD/potlatch2/utils/Importer.as @@ -27,21 +27,19 @@ package net.systemeD.potlatch2.utils { this.callback=callback; this.simplify=simplify; - var sp:uint=0; - for each (var fn:String in filenames) { - var thissp:uint=sp; // scope within this block for the URLLoader 'complete' closure - trace("requesting file "+fn); + // Use forEach to avoid closure problem (http://stackoverflow.com/questions/422784/how-to-fix-closure-problem-in-actionscript-3-as3#3971784) + filenames.forEach(function(fn:String, index:int, array:Array):void { + trace("requesting file "+index); var request:DebugURLRequest = new DebugURLRequest(fn); var loader:URLLoader = new URLLoader(); loader.dataFormat=URLLoaderDataFormat.BINARY; - loader.addEventListener(Event.COMPLETE,function(e:Event):void { fileLoaded(e,thissp); }); + loader.addEventListener(Event.COMPLETE,function(e:Event):void { fileLoaded(e,index); }); if (callback!=null) { loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler); loader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler); } loader.load(request.request); - sp++; - } + }); } protected function fileLoaded(e:Event,filenum:uint):void { From 616495edad6d00d7cecfe3494bf8a66ddec346b8 Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Fri, 10 Jun 2011 09:18:44 +0100 Subject: [PATCH 51/89] Understand shapefiles in different projections (notably OSGB) --- com/gradoservice/proj4as/Datum.as | 413 ++++++++++++++++++ com/gradoservice/proj4as/LICENCE.txt | 10 + com/gradoservice/proj4as/Proj4as.as | 157 +++++++ com/gradoservice/proj4as/ProjConstants.as | 288 ++++++++++++ com/gradoservice/proj4as/ProjPoint.as | 50 +++ com/gradoservice/proj4as/ProjProjection.as | 282 ++++++++++++ .../proj4as/proj/AbstractProjProjection.as | 113 +++++ com/gradoservice/proj4as/proj/IProjection.as | 14 + com/gradoservice/proj4as/proj/ProjAea.as | 145 ++++++ com/gradoservice/proj4as/proj/ProjAeqd.as | 93 ++++ com/gradoservice/proj4as/proj/ProjEqc.as | 55 +++ com/gradoservice/proj4as/proj/ProjEqdc.as | 156 +++++++ com/gradoservice/proj4as/proj/ProjEqui.as | 90 ++++ com/gradoservice/proj4as/proj/ProjGauss.as | 62 +++ com/gradoservice/proj4as/proj/ProjGstmerc.as | 74 ++++ com/gradoservice/proj4as/proj/ProjLaea.as | 127 ++++++ com/gradoservice/proj4as/proj/ProjLcc.as | 161 +++++++ com/gradoservice/proj4as/proj/ProjLonglat.as | 13 + com/gradoservice/proj4as/proj/ProjMerc.as | 120 +++++ com/gradoservice/proj4as/proj/ProjMill.as | 83 ++++ com/gradoservice/proj4as/proj/ProjMoll.as | 113 +++++ com/gradoservice/proj4as/proj/ProjNzmg.as | 292 +++++++++++++ com/gradoservice/proj4as/proj/ProjOmerc.as | 299 +++++++++++++ com/gradoservice/proj4as/proj/ProjOrtho.as | 131 ++++++ com/gradoservice/proj4as/proj/ProjParams.as | 71 +++ com/gradoservice/proj4as/proj/ProjSinu.as | 95 ++++ com/gradoservice/proj4as/proj/ProjSoMerc.as | 135 ++++++ com/gradoservice/proj4as/proj/ProjStere.as | 278 ++++++++++++ com/gradoservice/proj4as/proj/ProjSterea.as | 74 ++++ com/gradoservice/proj4as/proj/ProjTmerc.as | 154 +++++++ com/gradoservice/proj4as/proj/ProjUtm.as | 50 +++ com/gradoservice/proj4as/proj/ProjVandg.as | 154 +++++++ .../potlatch2/VectorSourceDialog.mxml | 28 +- net/systemeD/potlatch2/utils/ShpImporter.as | 32 +- 34 files changed, 4402 insertions(+), 10 deletions(-) create mode 100755 com/gradoservice/proj4as/Datum.as create mode 100755 com/gradoservice/proj4as/LICENCE.txt create mode 100755 com/gradoservice/proj4as/Proj4as.as create mode 100755 com/gradoservice/proj4as/ProjConstants.as create mode 100755 com/gradoservice/proj4as/ProjPoint.as create mode 100755 com/gradoservice/proj4as/ProjProjection.as create mode 100755 com/gradoservice/proj4as/proj/AbstractProjProjection.as create mode 100755 com/gradoservice/proj4as/proj/IProjection.as create mode 100755 com/gradoservice/proj4as/proj/ProjAea.as create mode 100755 com/gradoservice/proj4as/proj/ProjAeqd.as create mode 100755 com/gradoservice/proj4as/proj/ProjEqc.as create mode 100755 com/gradoservice/proj4as/proj/ProjEqdc.as create mode 100755 com/gradoservice/proj4as/proj/ProjEqui.as create mode 100755 com/gradoservice/proj4as/proj/ProjGauss.as create mode 100755 com/gradoservice/proj4as/proj/ProjGstmerc.as create mode 100755 com/gradoservice/proj4as/proj/ProjLaea.as create mode 100755 com/gradoservice/proj4as/proj/ProjLcc.as create mode 100755 com/gradoservice/proj4as/proj/ProjLonglat.as create mode 100755 com/gradoservice/proj4as/proj/ProjMerc.as create mode 100755 com/gradoservice/proj4as/proj/ProjMill.as create mode 100755 com/gradoservice/proj4as/proj/ProjMoll.as create mode 100755 com/gradoservice/proj4as/proj/ProjNzmg.as create mode 100755 com/gradoservice/proj4as/proj/ProjOmerc.as create mode 100755 com/gradoservice/proj4as/proj/ProjOrtho.as create mode 100755 com/gradoservice/proj4as/proj/ProjParams.as create mode 100755 com/gradoservice/proj4as/proj/ProjSinu.as create mode 100755 com/gradoservice/proj4as/proj/ProjSoMerc.as create mode 100755 com/gradoservice/proj4as/proj/ProjStere.as create mode 100755 com/gradoservice/proj4as/proj/ProjSterea.as create mode 100755 com/gradoservice/proj4as/proj/ProjTmerc.as create mode 100755 com/gradoservice/proj4as/proj/ProjUtm.as create mode 100755 com/gradoservice/proj4as/proj/ProjVandg.as diff --git a/com/gradoservice/proj4as/Datum.as b/com/gradoservice/proj4as/Datum.as new file mode 100755 index 00000000..0632a67a --- /dev/null +++ b/com/gradoservice/proj4as/Datum.as @@ -0,0 +1,413 @@ +package com.gradoservice.proj4as +{ + import com.gradoservice.proj4as.proj.AbstractProjProjection; + import com.gradoservice.proj4as.ProjConstants; + + public class Datum + { + public var datum_type:int; + public var a:Number; + public var b:Number; + public var es:Number; + public var ep2:Number; + public var datum_params:Array; + public var params:Array; + + public function Datum(proj:ProjProjection) + { + this.datum_type = ProjConstants.PJD_WGS84; //default setting + if (proj.datumCode && proj.datumCode == 'none') + { + this.datum_type = ProjConstants.PJD_NODATUM; + } + if (proj && proj.datum_params) + { + for (var i:int=0; i 3) + { + if (proj.datum_params[3] != 0 || proj.datum_params[4] != 0 || + proj.datum_params[5] != 0 || proj.datum_params[6] != 0 ) + { + this.datum_type = ProjConstants.PJD_7PARAM; + proj.datum_params[3] *= ProjConstants.SEC_TO_RAD; + proj.datum_params[4] *= ProjConstants.SEC_TO_RAD; + proj.datum_params[5] *= ProjConstants.SEC_TO_RAD; + proj.datum_params[6] = (proj.datum_params[6]/1000000.0) + 1.0; + } + } + } + if (proj) + { + this.a = proj.a; //datum object also uses these values + this.b = proj.b; + this.es = proj.es; + this.ep2 = proj.ep2; + this.datum_params = proj.datum_params; + } + } + + /****************************************************************/ + // cs_compare_datums() + // Returns 1 (TRUE) if the two datums match, otherwise 0 (FALSE). + public function compare_datums( dest:Datum ):Boolean + { + if( this.datum_type != dest.datum_type ) + { + return false; // false, datums are not equal + } + else if( this.a != dest.a || Math.abs(this.es-dest.es) > 0.000000000050 ) + { + // the tolerence for es is to ensure that GRS80 and WGS84 + // are considered identical + return false; + } + else if( this.datum_type == ProjConstants.PJD_3PARAM ) + { + return (this.datum_params[0] == dest.datum_params[0] + && this.datum_params[1] == dest.datum_params[1] + && this.datum_params[2] == dest.datum_params[2]); + } else if( this.datum_type == ProjConstants.PJD_7PARAM ) + { + return (this.datum_params[0] == dest.datum_params[0] + && this.datum_params[1] == dest.datum_params[1] + && this.datum_params[2] == dest.datum_params[2] + && this.datum_params[3] == dest.datum_params[3] + && this.datum_params[4] == dest.datum_params[4] + && this.datum_params[5] == dest.datum_params[5] + && this.datum_params[6] == dest.datum_params[6]); + } + else if( this.datum_type == ProjConstants.PJD_GRIDSHIFT ) + { + /*return strcmp( pj_param(this.params,"snadgrids").s, + pj_param(dest.params,"snadgrids").s ) == 0; */ + return false; + } else + { + return true; // datums are equal + } + } // cs_compare_datums() + + + public function geodetic_to_geocentric(p:ProjPoint):int + { + var Longitude:Number = p.x; + var Latitude:Number = p.y; + var Height:Number = p.z ? p.z : 0; //Z value not always supplied + var X:Number; // output + var Y:Number; + var Z:Number; + + var Error_Code:int=0; // GEOCENT_NO_ERROR; + var Rn:Number; /* Earth radius at location */ + var Sin_Lat:Number; /* Math.sin(Latitude) */ + var Sin2_Lat:Number; /* Square of Math.sin(Latitude) */ + var Cos_Lat:Number; /* Math.cos(Latitude) */ + + /* + ** Don't blow up if Latitude is just a little out of the value + ** range as it may just be a rounding issue. Also removed longitude + ** test, it should be wrapped by Math.cos() and Math.sin(). NFW for PROJ.4, Sep/2001. + */ + if( Latitude < -ProjConstants.HALF_PI && Latitude > -1.001 *ProjConstants.HALF_PI ) { + Latitude = -ProjConstants.HALF_PI; + } else if( Latitude > ProjConstants.HALF_PI && Latitude < 1.001 * ProjConstants.HALF_PI ) { + Latitude = ProjConstants.HALF_PI; + } else if ((Latitude < -ProjConstants.HALF_PI) || (Latitude > ProjConstants.HALF_PI)) { + /* Latitude out of range */ + trace('geocent:lat out of range:'+Latitude); + return 0; + } + + if (Longitude > ProjConstants.PI) {Longitude -= (2*ProjConstants.PI);} + Sin_Lat = Math.sin(Latitude); + Cos_Lat = Math.cos(Latitude); + Sin2_Lat = Sin_Lat * Sin_Lat; + Rn = this.a / (Math.sqrt(1.0e0 - this.es * Sin2_Lat)); + X = (Rn + Height) * Cos_Lat * Math.cos(Longitude); + Y = (Rn + Height) * Cos_Lat * Math.sin(Longitude); + Z = ((Rn * (1 - this.es)) + Height) * Sin_Lat; + + p.x = X; + p.y = Y; + p.z = Z; + return Error_Code; + } // cs_geodetic_to_geocentric() + + + public function geocentric_to_geodetic(p:ProjPoint):ProjPoint + { + /* local defintions and variables */ + /* end-criterium of loop, accuracy of sin(Latitude) */ + var genau:Number = 1.E-12; + var genau2:Number = (genau*genau); + var maxiter:int = 30; + + var P:Number; /* distance between semi-minor axis and location */ + var RR:Number; /* distance between center and location */ + var CT:Number; /* sin of geocentric latitude */ + var ST:Number; /* cos of geocentric latitude */ + var RX:Number; + var RK:Number; + var RN:Number; /* Earth radius at location */ + var CPHI0:Number; /* cos of start or old geodetic latitude in iterations */ + var SPHI0:Number; /* sin of start or old geodetic latitude in iterations */ + var CPHI:Number; /* cos of searched geodetic latitude */ + var SPHI:Number; /* sin of searched geodetic latitude */ + var SDPHI:Number; /* end-criterium: addition-theorem of sin(Latitude(iter)-Latitude(iter-1)) */ + var At_Pole:Boolean; /* indicates location is in polar region */ + var iter:Number; /* # of continous iteration, max. 30 is always enough (s.a.) */ + + var X:Number = p.x; + var Y:Number = p.y; + var Z:Number = p.z ? p.z : 0.0; //Z value not always supplied + var Longitude:Number; + var Latitude:Number; + var Height:Number; + + At_Pole = false; + P = Math.sqrt(X*X+Y*Y); + RR = Math.sqrt(X*X+Y*Y+Z*Z); + +/* special cases for latitude and longitude */ + if (P/this.a < genau) + { + /* special case, if P=0. (X=0., Y=0.) */ + At_Pole = true; + Longitude = 0.0; +/* if (X,Y,Z)=(0.,0.,0.) then Height becomes semi-minor axis + * of ellipsoid (=center of mass), Latitude becomes PI/2 */ + if (RR/this.a < genau) { + Latitude = ProjConstants.HALF_PI; + Height = -this.b; + return null; + } + } else { +/* ellipsoidal (geodetic) longitude + * interval: -PI < Longitude <= +PI */ + Longitude=Math.atan2(Y,X); + } + +/* -------------------------------------------------------------- + * Following iterative algorithm was developped by + * "Institut fьr Erdmessung", University of Hannover, July 1988. + * Internet: www.ife.uni-hannover.de + * Iterative computation of CPHI,SPHI and Height. + * Iteration of CPHI and SPHI to 10**-12 radian resp. + * 2*10**-7 arcsec. + * -------------------------------------------------------------- + */ + CT = Z/RR; + ST = P/RR; + RX = 1.0/Math.sqrt(1.0-this.es*(2.0-this.es)*ST*ST); + CPHI0 = ST*(1.0-this.es)*RX; + SPHI0 = CT*RX; + iter = 0; + +/* loop to find sin(Latitude) resp. Latitude + * until |sin(Latitude(iter)-Latitude(iter-1))| < genau */ + do + { + iter++; + RN = this.a/Math.sqrt(1.0-this.es*SPHI0*SPHI0); + +/* ellipsoidal (geodetic) height */ + Height = P*CPHI0+Z*SPHI0-RN*(1.0-this.es*SPHI0*SPHI0); + + RK = this.es*RN/(RN+Height); + RX = 1.0/Math.sqrt(1.0-RK*(2.0-RK)*ST*ST); + CPHI = ST*(1.0-RK)*RX; + SPHI = CT*RX; + SDPHI = SPHI*CPHI0-CPHI*SPHI0; + CPHI0 = CPHI; + SPHI0 = SPHI; + } + while (SDPHI*SDPHI > genau2 && iter < maxiter); + +/* ellipsoidal (geodetic) latitude */ + Latitude=Math.atan(SPHI/Math.abs(CPHI)); + + p.x = Longitude; + p.y = Latitude; + p.z = Height; + return p; + } // cs_geocentric_to_geodetic() + + + public function geocentric_to_geodetic_noniter(p:ProjPoint):ProjPoint + { + var X:Number = p.x; + var Y:Number = p.y; + var Z:Number = p.z ? p.z : 0; //Z value not always supplied + var Longitude:Number; + var Latitude:Number; + var Height:Number; + + var W:Number; /* distance from Z axis */ + var W2:Number; /* square of distance from Z axis */ + var T0:Number; /* initial estimate of vertical component */ + var T1:Number; /* corrected estimate of vertical component */ + var S0:Number; /* initial estimate of horizontal component */ + var S1:Number; /* corrected estimate of horizontal component */ + var Sin_B0:Number; /* Math.sin(B0), B0 is estimate of Bowring aux variable */ + var Sin3_B0:Number; /* cube of Math.sin(B0) */ + var Cos_B0:Number; /* Math.cos(B0) */ + var Sin_p1:Number; /* Math.sin(phi1), phi1 is estimated latitude */ + var Cos_p1:Number; /* Math.cos(phi1) */ + var Rn:Number; /* Earth radius at location */ + var Sum:Number; /* numerator of Math.cos(phi1) */ + var At_Pole:Boolean; /* indicates location is in polar region */ + + At_Pole = false; + if (X != 0.0) + { + Longitude = Math.atan2(Y,X); + } + else + { + if (Y > 0) + { + Longitude = ProjConstants.HALF_PI; + } + else if (Y < 0) + { + Longitude = -ProjConstants.HALF_PI; + } + else + { + At_Pole = true; + Longitude = 0.0; + if (Z > 0.0) + { /* north pole */ + Latitude = ProjConstants.HALF_PI; + } + else if (Z < 0.0) + { /* south pole */ + Latitude = -ProjConstants.HALF_PI; + } + else + { /* center of earth */ + Latitude = ProjConstants.HALF_PI; + Height = -this.b; + return null; + } + } + } + W2 = X*X + Y*Y; + W = Math.sqrt(W2); + T0 = Z * ProjConstants.AD_C; + S0 = Math.sqrt(T0 * T0 + W2); + Sin_B0 = T0 / S0; + Cos_B0 = W / S0; + Sin3_B0 = Sin_B0 * Sin_B0 * Sin_B0; + T1 = Z + this.b * this.ep2 * Sin3_B0; + Sum = W - this.a * this.es * Cos_B0 * Cos_B0 * Cos_B0; + S1 = Math.sqrt(T1*T1 + Sum * Sum); + Sin_p1 = T1 / S1; + Cos_p1 = Sum / S1; + Rn = this.a / Math.sqrt(1.0 - this.es * Sin_p1 * Sin_p1); + if (Cos_p1 >= ProjConstants.COS_67P5) + { + Height = W / Cos_p1 - Rn; + } + else if (Cos_p1 <= -ProjConstants.COS_67P5) + { + Height = W / -Cos_p1 - Rn; + } + else + { + Height = Z / Sin_p1 + Rn * (this.es - 1.0); + } + if (At_Pole == false) + { + Latitude = Math.atan(Sin_p1 / Cos_p1); + } + + p.x = Longitude; + p.y = Latitude; + p.z = Height; + return p; + } // geocentric_to_geodetic_noniter() + + /****************************************************************/ + // pj_geocentic_to_wgs84( p ) + // p = point to transform in geocentric coordinates (x,y,z) + public function geocentric_to_wgs84( p:ProjPoint ):void + { + + if( this.datum_type == ProjConstants.PJD_3PARAM ) + { + // if( x[io] == HUGE_VAL ) + // continue; + p.x += this.datum_params[0]; + p.y += this.datum_params[1]; + p.z += this.datum_params[2]; + + } + else if (this.datum_type == ProjConstants.PJD_7PARAM) + { + var Dx_BF:Number =this.datum_params[0]; + var Dy_BF:Number =this.datum_params[1]; + var Dz_BF:Number =this.datum_params[2]; + var Rx_BF:Number =this.datum_params[3]; + var Ry_BF:Number =this.datum_params[4]; + var Rz_BF:Number =this.datum_params[5]; + var M_BF:Number =this.datum_params[6]; + // if( x[io] == HUGE_VAL ) + // continue; + var x_out:Number = M_BF*( p.x - Rz_BF*p.y + Ry_BF*p.z) + Dx_BF; + var y_out:Number = M_BF*( Rz_BF*p.x + p.y - Rx_BF*p.z) + Dy_BF; + var z_out:Number = M_BF*(-Ry_BF*p.x + Rx_BF*p.y + p.z) + Dz_BF; + p.x = x_out; + p.y = y_out; + p.z = z_out; + } + } // cs_geocentric_to_wgs84 + + /****************************************************************/ + // pj_geocentic_from_wgs84() + // coordinate system definition, + // point to transform in geocentric coordinates (x,y,z) + public function geocentric_from_wgs84( p:ProjPoint ):void + { + + if( this.datum_type == ProjConstants.PJD_3PARAM ) + { + //if( x[io] == HUGE_VAL ) + // continue; + p.x -= this.datum_params[0]; + p.y -= this.datum_params[1]; + p.z -= this.datum_params[2]; + + } + else if (this.datum_type == ProjConstants.PJD_7PARAM) + { + var Dx_BF:Number =this.datum_params[0]; + var Dy_BF:Number =this.datum_params[1]; + var Dz_BF:Number =this.datum_params[2]; + var Rx_BF:Number =this.datum_params[3]; + var Ry_BF:Number =this.datum_params[4]; + var Rz_BF:Number =this.datum_params[5]; + var M_BF:Number =this.datum_params[6]; + var x_tmp:Number = (p.x - Dx_BF) / M_BF; + var y_tmp:Number = (p.y - Dy_BF) / M_BF; + var z_tmp:Number = (p.z - Dz_BF) / M_BF; + //if( x[io] == HUGE_VAL ) + // continue; + + p.x = x_tmp + Rz_BF*y_tmp - Ry_BF*z_tmp; + p.y = -Rz_BF*x_tmp + y_tmp + Rx_BF*z_tmp; + p.z = Ry_BF*x_tmp - Rx_BF*y_tmp + z_tmp; + } //cs_geocentric_from_wgs84() + } + + + + } +} \ No newline at end of file diff --git a/com/gradoservice/proj4as/LICENCE.txt b/com/gradoservice/proj4as/LICENCE.txt new file mode 100755 index 00000000..3ce7c3e2 --- /dev/null +++ b/com/gradoservice/proj4as/LICENCE.txt @@ -0,0 +1,10 @@ +Copyright (c) German Osin, 2009 +All rights reserved. +[see http://groups.google.com/group/openscales-dev/msg/425f736fd9d07884 for licence declaration] + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/com/gradoservice/proj4as/Proj4as.as b/com/gradoservice/proj4as/Proj4as.as new file mode 100755 index 00000000..745e3140 --- /dev/null +++ b/com/gradoservice/proj4as/Proj4as.as @@ -0,0 +1,157 @@ +package com.gradoservice.proj4as +{ + import com.gradoservice.proj4as.proj.AbstractProjProjection; + + public class Proj4as + { + + static public const defaultDatum:String = 'WGS84'; + static public const WGS84:ProjProjection = new ProjProjection('WGS84'); + + + public function Proj4as() + { + } + + public function transform(source:ProjProjection, dest:ProjProjection, point:ProjPoint):ProjPoint + { + + if (source==null || dest==null || point==null) + { + trace("Parametrs not created!"); + return null; + } + + if (!source.readyToUse || !dest.readyToUse) + { + trace("Proj4js initialization for "+source.srsCode+" not yet complete"); + return point; + } + + // Workaround for Spherical Mercator + if ((source.srsProjNumber =="900913" && dest.datumCode != "WGS84") || + (dest.srsProjNumber == "900913" && source.datumCode != "WGS84")) { + var wgs84:ProjProjection = WGS84; + this.transform(source, wgs84, point); + source = wgs84; + } + + // Transform source points to long/lat, if they aren't already. + if ( source.projName=="longlat") { + point.x *= ProjConstants.D2R; // convert degrees to radians + point.y *= ProjConstants.D2R; + } else { + if (source.to_meter) { + point.x *= source.to_meter; + point.y *= source.to_meter; + } + source.inverse(point); // Convert Cartesian to longlat + } + + // Adjust for the prime meridian if necessary + if (source.from_greenwich) { + point.x += source.from_greenwich; + } + + // Convert datums if needed, and if possible. + point = this.datum_transform( source.datum, dest.datum, point ); + + // Adjust for the prime meridian if necessary + if (dest.from_greenwich) { + point.x -= dest.from_greenwich; + } + + if( dest.projName=="longlat" ) { + // convert radians to decimal degrees + point.x *= ProjConstants.R2D; + point.y *= ProjConstants.R2D; + } else { // else project + dest.forward(point); + if (dest.to_meter) { + point.x /= dest.to_meter; + point.y /= dest.to_meter; + } + } + return point; + } + + + public function datum_transform( source:Datum, dest:Datum, point:ProjPoint ):ProjPoint + { + + // Short cut if the datums are identical. + if( source.compare_datums( dest ) ) { + return point; // in this case, zero is sucess, + // whereas cs_compare_datums returns 1 to indicate TRUE + // confusing, should fix this + } + + // Explicitly skip datum transform by setting 'datum=none' as parameter for either source or dest + if( source.datum_type == ProjConstants.PJD_NODATUM + || dest.datum_type == ProjConstants.PJD_NODATUM) { + return point; + } + + // If this datum requires grid shifts, then apply it to geodetic coordinates. + if( source.datum_type == ProjConstants.PJD_GRIDSHIFT ) + { + trace("ERROR: Grid shift transformations are not implemented yet."); + /* + pj_apply_gridshift( pj_param(source.params,"snadgrids").s, 0, + point_count, point_offset, x, y, z ); + CHECK_RETURN; + + src_a = SRS_WGS84_SEMIMAJOR; + src_es = 0.006694379990; + */ + } + + if( dest.datum_type == ProjConstants.PJD_GRIDSHIFT ) + { + trace("ERROR: Grid shift transformations are not implemented yet."); + /* + dst_a = ; + dst_es = 0.006694379990; + */ + } + + // Do we need to go through geocentric coordinates? + if( source.es != dest.es || source.a != dest.a + || source.datum_type == ProjConstants.PJD_3PARAM + || source.datum_type == ProjConstants.PJD_7PARAM + || dest.datum_type == ProjConstants.PJD_3PARAM + || dest.datum_type == ProjConstants.PJD_7PARAM) + { + + // Convert to geocentric coordinates. + source.geodetic_to_geocentric( point ); + // CHECK_RETURN; + + // Convert between datums + if( source.datum_type == ProjConstants.PJD_3PARAM || source.datum_type == ProjConstants.PJD_7PARAM ) { + source.geocentric_to_wgs84(point); + // CHECK_RETURN; + } + + if( dest.datum_type == ProjConstants.PJD_3PARAM || dest.datum_type == ProjConstants.PJD_7PARAM ) { + dest.geocentric_from_wgs84(point); + // CHECK_RETURN; + } + + // Convert back to geodetic coordinates + dest.geocentric_to_geodetic( point ); + // CHECK_RETURN; + } + + // Apply grid shift to destination if required + if( dest.datum_type == ProjConstants.PJD_GRIDSHIFT ) + { + trace("ERROR: Grid shift transformations are not implemented yet."); + // pj_apply_gridshift( pj_param(dest.params,"snadgrids").s, 1, point); + // CHECK_RETURN; + } + return point; + } + + } +} \ No newline at end of file diff --git a/com/gradoservice/proj4as/ProjConstants.as b/com/gradoservice/proj4as/ProjConstants.as new file mode 100755 index 00000000..d4be0768 --- /dev/null +++ b/com/gradoservice/proj4as/ProjConstants.as @@ -0,0 +1,288 @@ +package com.gradoservice.proj4as +{ + public class ProjConstants + { + + static public const PI:Number=3.141592653589793238; //Math.PI, + static public const HALF_PI:Number=1.570796326794896619; //Math.PI*0.5, + static public const TWO_PI:Number=6.283185307179586477; //Math.PI*2, + static public const FORTPI:Number=0.78539816339744833; + static public const R2D:Number=57.29577951308232088; + static public const D2R:Number=0.01745329251994329577; + static public const SEC_TO_RAD:Number=4.84813681109535993589914102357e-6; /* SEC_TO_RAD = Pi/180/3600 */ + static public const EPSLN:Number=1.0e-10; + static public const MAX_ITER:Number=20; + // following constants from geocent.c + static public const COS_67P5:Number=0.38268343236508977; /* cosine of 67.5 degrees */ + static public const AD_C:Number=1.0026000; /* Toms region 1 constant */ + + /* datum_type values */ + static public const PJD_UNKNOWN:int=0; + static public const PJD_3PARAM:int=1; + static public const PJD_7PARAM:int=2; + static public const PJD_GRIDSHIFT:int=3; + static public const PJD_WGS84:int=4; // WGS84 or equivalent + static public const PJD_NODATUM:int=5; // WGS84 or equivalent + static public const SRS_WGS84_SEMIMAJOR:int=6378137; // only used in grid shift transforms + + // ellipoid pj_set_ell.c + static public const SIXTH :Number=0.1666666666666666667; /* 1/6 */ + static public const RA4:Number=0.04722222222222222222; /* 17/360 */ + static public const RA6:Number=0.02215608465608465608; /* 67/3024 */ + static public const RV4:Number=0.06944444444444444444; /* 5/72 */ + static public const RV6:Number=0.04243827160493827160; /* 55/1296 */ + + + + static public const PrimeMeridian:Object = { + "greenwich": 0.0, //"0dE", + "lisbon": -9.131906111111, //"9d07'54.862\"W", + "paris": 2.337229166667, //"2d20'14.025\"E", + "bogota": -74.080916666667, //"74d04'51.3\"W", + "madrid": -3.687938888889, //"3d41'16.58\"W", + "rome": 12.452333333333, //"12d27'8.4\"E", + "bern": 7.439583333333, //"7d26'22.5\"E", + "jakarta": 106.807719444444, //"106d48'27.79\"E", + "ferro": -17.666666666667, //"17d40'W", + "brussels": 4.367975, //"4d22'4.71\"E", + "stockholm": 18.058277777778, //"18d3'29.8\"E", + "athens": 23.7163375, //"23d42'58.815\"E", + "oslo": 10.722916666667 //"10d43'22.5\"E" + }; + + static public const Ellipsoid:Object = { + "MERIT": {a:6378137.0, rf:298.257, ellipseName:"MERIT 1983"}, + "SGS85": {a:6378136.0, rf:298.257, ellipseName:"Soviet Geodetic System 85"}, + "GRS80": {a:6378137.0, rf:298.257222101, ellipseName:"GRS 1980(IUGG, 1980)"}, + "IAU76": {a:6378140.0, rf:298.257, ellipseName:"IAU 1976"}, + "airy": {a:6377563.396, b:6356256.910, ellipseName:"Airy 1830"}, + "APL4.": {a:6378137, rf:298.25, ellipseName:"Appl. Physics. 1965"}, + "NWL9D": {a:6378145.0, rf:298.25, ellipseName:"Naval Weapons Lab., 1965"}, + "mod_airy": {a:6377340.189, b:6356034.446, ellipseName:"Modified Airy"}, + "andrae": {a:6377104.43, rf:300.0, ellipseName:"Andrae 1876 (Den., Iclnd.)"}, + "aust_SA": {a:6378160.0, rf:298.25, ellipseName:"Australian Natl & S. Amer. 1969"}, + "GRS67": {a:6378160.0, rf:298.2471674270, ellipseName:"GRS 67(IUGG 1967)"}, + "bessel": {a:6377397.155, rf:299.1528128, ellipseName:"Bessel 1841"}, + "bess_nam": {a:6377483.865, rf:299.1528128, ellipseName:"Bessel 1841 (Namibia)"}, + "clrk66": {a:6378206.4, b:6356583.8, ellipseName:"Clarke 1866"}, + "clrk80": {a:6378249.145, rf:293.4663, ellipseName:"Clarke 1880 mod."}, + "CPM": {a:6375738.7, rf:334.29, ellipseName:"Comm. des Poids et Mesures 1799"}, + "delmbr": {a:6376428.0, rf:311.5, ellipseName:"Delambre 1810 (Belgium)"}, + "engelis": {a:6378136.05, rf:298.2566, ellipseName:"Engelis 1985"}, + "evrst30": {a:6377276.345, rf:300.8017, ellipseName:"Everest 1830"}, + "evrst48": {a:6377304.063, rf:300.8017, ellipseName:"Everest 1948"}, + "evrst56": {a:6377301.243, rf:300.8017, ellipseName:"Everest 1956"}, + "evrst69": {a:6377295.664, rf:300.8017, ellipseName:"Everest 1969"}, + "evrstSS": {a:6377298.556, rf:300.8017, ellipseName:"Everest (Sabah & Sarawak)"}, + "fschr60": {a:6378166.0, rf:298.3, ellipseName:"Fischer (Mercury Datum) 1960"}, + "fschr60m": {a:6378155.0, rf:298.3, ellipseName:"Fischer 1960"}, + "fschr68": {a:6378150.0, rf:298.3, ellipseName:"Fischer 1968"}, + "helmert": {a:6378200.0, rf:298.3, ellipseName:"Helmert 1906"}, + "hough": {a:6378270.0, rf:297.0, ellipseName:"Hough"}, + "intl": {a:6378388.0, rf:297.0, ellipseName:"International 1909 (Hayford)"}, + "kaula": {a:6378163.0, rf:298.24, ellipseName:"Kaula 1961"}, + "lerch": {a:6378139.0, rf:298.257, ellipseName:"Lerch 1979"}, + "mprts": {a:6397300.0, rf:191.0, ellipseName:"Maupertius 1738"}, + "new_intl": {a:6378157.5, b:6356772.2, ellipseName:"New International 1967"}, + "plessis": {a:6376523.0, rf:6355863.0, ellipseName:"Plessis 1817 (France)"}, + "krass": {a:6378245.0, rf:298.3, ellipseName:"Krassovsky, 1942"}, + "SEasia": {a:6378155.0, b:6356773.3205, ellipseName:"Southeast Asia"}, + "walbeck": {a:6376896.0, b:6355834.8467, ellipseName:"Walbeck"}, + "WGS60": {a:6378165.0, rf:298.3, ellipseName:"WGS 60"}, + "WGS66": {a:6378145.0, rf:298.25, ellipseName:"WGS 66"}, + "WGS72": {a:6378135.0, rf:298.26, ellipseName:"WGS 72"}, + "WGS84": {a:6378137.0, rf:298.257223563, ellipseName:"WGS 84"}, + "sphere": {a:6370997.0, b:6370997.0, ellipseName:"Normal Sphere (r=6370997)"} +}; + + static public const Datum:Object = { + "WGS84": {towgs84: "0,0,0", ellipse: "WGS84", datumName: "WGS84"}, + "GGRS87": {towgs84: "-199.87,74.79,246.62", ellipse: "GRS80", datumName: "Greek_Geodetic_Reference_System_1987"}, + "NAD83": {towgs84: "0,0,0", ellipse: "GRS80", datumName: "North_American_Datum_1983"}, + "NAD27": {nadgrids: "@conus,@alaska,@ntv2_0.gsb,@ntv1_can.dat", ellipse: "clrk66", datumName: "North_American_Datum_1927"}, + "potsdam": {towgs84: "606.0,23.0,413.0", ellipse: "bessel", datumName: "Potsdam Rauenberg 1950 DHDN"}, + "carthage": {towgs84: "-263.0,6.0,431.0", ellipse: "clark80", datumName: "Carthage 1934 Tunisia"}, + "hermannskogel": {towgs84: "653.0,-212.0,449.0", ellipse: "bessel", datumName: "Hermannskogel"}, + "ire65": {towgs84: "482.530,-130.596,564.557,-1.042,-0.214,-0.631,8.15", ellipse: "mod_airy", datumName: "Ireland 1965"}, + "nzgd49": {towgs84: "59.47,-5.04,187.44,0.47,-0.1,1.024,-4.5993", ellipse: "intl", datumName: "New Zealand Geodetic Datum 1949"}, + "OSGB36": {towgs84: "446.448,-125.157,542.060,0.1502,0.2470,0.8421,-20.4894", ellipse: "airy", datumName: "Airy 1830"} +}; + + + + public function ProjConstants() + { + } + + + // Function to compute the constant small m which is the radius of + // a parallel of latitude, phi, divided by the semimajor axis. + // ----------------------------------------------------------------- + static public function msfnz (eccent:Number, sinphi:Number, cosphi:Number):Number + { + var con:Number = eccent * sinphi; + return cosphi/(Math.sqrt(1.0 - con * con)); + } + + // Function to compute the constant small t for use in the forward + // computations in the Lambert Conformal Conic and the Polar + // Stereographic projections. + // ----------------------------------------------------------------- + static public function tsfnz(eccent:Number, phi:Number, sinphi:Number):Number + { + var con:Number = eccent * sinphi; + var com:Number = 0.5 * eccent; + con = Math.pow(((1.0 - con) / (1.0 + con)), com); + return (Math.tan(0.5 * (ProjConstants.HALF_PI - phi))/con); + } + + // Function to compute the latitude angle, phi2, for the inverse of the + // Lambert Conformal Conic and Polar Stereographic projections. + // ---------------------------------------------------------------- + static public function phi2z(eccent:Number, ts:Number):Number + { + var eccnth:Number = .5 * eccent; + var con:Number =0; + var dphi:Number =0; + var phi:Number = ProjConstants.HALF_PI - 2 * Math.atan(ts); + for (var i:int = 0; i <= 15; i++) { + con = eccent * Math.sin(phi); + dphi = ProjConstants.HALF_PI - 2 * Math.atan(ts *(Math.pow(((1.0 - con)/(1.0 + con)),eccnth))) - phi; + phi += dphi; + if (Math.abs(dphi) <= .0000000001) return phi; + } + trace("phi2z has NoConvergence"); + return -9999; + } + + /* Function to compute constant small q which is the radius of a + parallel of latitude, phi, divided by the semimajor axis. + ------------------------------------------------------------*/ + static public function qsfnz(eccent:Number,sinphi:Number,cosphi:Number):Number + { + var con:Number = 0; + if (eccent > 1.0e-7) { + con = eccent * sinphi; + return (( 1.0- eccent * eccent) * (sinphi /(1.0 - con * con) - (.5/eccent)*Math.log((1.0 - con)/(1.0 + con)))); + } else { + return 2.0 * sinphi; + } + } + + /* Function to eliminate roundoff errors in asin + ----------------------------------------------*/ + static public function asinz(x:Number):Number + { + if (Math.abs(x)>1.0) { + x=(x>1.0)?1.0:-1.0; + } + return Math.asin(x); + } + + // following functions from gctpc cproj.c for transverse mercator projections + static public function e0fn(x:Number):Number {return(1.0-0.25*x*(1.0+x/16.0*(3.0+1.25*x)));} + static public function e1fn(x:Number):Number {return(0.375*x*(1.0+0.25*x*(1.0+0.46875*x)));} + static public function e2fn(x:Number):Number {return(0.05859375*x*x*(1.0+0.75*x));} + static public function e3fn(x:Number):Number {return(x*x*x*(35.0/3072.0));} + static public function mlfn(e0:Number,e1:Number,e2:Number,e3:Number,phi:Number):Number {return(e0*phi-e1*Math.sin(2.0*phi)+e2*Math.sin(4.0*phi)-e3*Math.sin(6.0*phi));} + + static public function srat(esinp:Number, exp:Number):Number + { + return(Math.pow((1.0-esinp)/(1.0+esinp), exp)); + } + +// Function to return the sign of an argument + static public function sign(x:Number):Number { if (x < 0.0) return(-1); else return(1);} + +// Function to adjust longitude to -180 to 180; input in radians + static public function adjust_lon(x:Number):Number { + x = (Math.abs(x) < ProjConstants.PI) ? x: (x - (ProjConstants.sign(x)*ProjConstants.TWO_PI) ); + return x; + } + +// IGNF - DGR : algorithms used by IGN France + +// Function to adjust latitude to -90 to 90; input in radians + static public function adjust_lat(x:Number):Number { + x= (Math.abs(x) < ProjConstants.HALF_PI) ? x: (x - (ProjConstants.sign(x)*ProjConstants.PI) ); + return x; + } + +// Latitude Isometrique - close to tsfnz ... + static public function latiso(eccent:Number, phi:Number, sinphi:Number):Number + { + if (Math.abs(phi) > ProjConstants.HALF_PI) return +Number.NaN; + if (phi==ProjConstants.HALF_PI) return Number.POSITIVE_INFINITY; + if (phi==-1.0*ProjConstants.HALF_PI) return -1.0*Number.POSITIVE_INFINITY; + + var con:Number= eccent*sinphi; + return Math.log(Math.tan((ProjConstants.HALF_PI+phi)/2.0))+eccent*Math.log((1.0-con)/(1.0+con))/2.0; + } + + static public function fL(x:Number,L:Number):Number { + return 2.0*Math.atan(x*Math.exp(L)) - ProjConstants.HALF_PI; + } + +// Inverse Latitude Isometrique - close to ph2z + static public function invlatiso(eccent:Number, ts:Number):Number { + var phi:Number= ProjConstants.fL(1.0,ts); + var Iphi:Number= 0.0; + var con:Number= 0.0; + do { + Iphi= phi; + con= eccent*Math.sin(Iphi); + phi= ProjConstants.fL(Math.exp(eccent*Math.log((1.0+con)/(1.0-con))/2.0),ts) + } while (Math.abs(phi-Iphi)>1.0e-12); + return phi; + } + +// Needed for Gauss Laborde +// Original: Denis Makarov (info@binarythings.com) +// Web Site: http://www.binarythings.com + static public function sinh(x:Number):Number + { + var r:Number= Math.exp(x); + r= (r-1.0/r)/2.0; + return r; + } + + static public function cosh(x:Number):Number + { + var r:Number= Math.exp(x); + r= (r+1.0/r)/2.0; + return r; + } + + static public function tanh(x:Number):Number + { + var r:Number= Math.exp(x); + r= (r-1.0/r)/(r+1.0/r); + return r; + } + + static public function asinh(x:Number):Number + { + var s:Number= (x>= 0? 1.0:-1.0); + return s*(Math.log( Math.abs(x) + Math.sqrt(x*x+1.0) )); + } + + static public function acosh(x:Number):Number + { + return 2.0*Math.log(Math.sqrt((x+1.0)/2.0) + Math.sqrt((x-1.0)/2.0)); + } + + static public function atanh(x:Number):Number + { + return Math.log((x-1.0)/(x+1.0))/2.0; + } + +// Grande Normale + static public function gN(a:Number,e:Number,sinphi:Number):Number + { + var temp:Number= e*sinphi; + return a/Math.sqrt(1.0 - temp*temp); + } + + + } +} \ No newline at end of file diff --git a/com/gradoservice/proj4as/ProjPoint.as b/com/gradoservice/proj4as/ProjPoint.as new file mode 100755 index 00000000..f56dc1b4 --- /dev/null +++ b/com/gradoservice/proj4as/ProjPoint.as @@ -0,0 +1,50 @@ +package com.gradoservice.proj4as +{ + public class ProjPoint + { + public var x:Number; + public var y:Number; + public var z:Number; + + public function ProjPoint(x:Number,y:Number,z:Number) + { + this.x = x; + this.y = y; + this.z = z; + } + + public function clone():ProjPoint + { + return new ProjPoint(this.x, this.y, this.z); + } + + /** + * APIMethod: toString + * Return a readable string version of the point + * + * Return: + * {String} String representation of Proj4js.Point object. + * (ex. "x=5,y=42") + */ + public function toString():String + { + return ("x=" + this.x + ",y=" + this.y); + } + + /** + * APIMethod: toShortString + * Return a short string version of the point. + * + * Return: + * {String} Shortened String representation of Proj4js.Point object. + * (ex. "5, 42") + */ + public function toShortString ():String + { + return (this.x + ", " + this.y); + } + + + + } +} \ No newline at end of file diff --git a/com/gradoservice/proj4as/ProjProjection.as b/com/gradoservice/proj4as/ProjProjection.as new file mode 100755 index 00000000..9b0a2906 --- /dev/null +++ b/com/gradoservice/proj4as/ProjProjection.as @@ -0,0 +1,282 @@ +package com.gradoservice.proj4as +{ + import com.gradoservice.proj4as.proj.*; + + public class ProjProjection + { + /** + * Property: readyToUse + * Flag to indicate if initialization is complete for this Proj object + */ + public var readyToUse:Boolean = false; + + /** + * Property: title + * The title to describe the projection + */ + protected var projParams:ProjParams = new ProjParams(); + + static public const defs:Object = { + 'EPSG:900913': "+title=Google Mercator EPSG:900913 +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs", + 'WGS84': "+title=long/lat:WGS84 +proj=longlat +ellps=WGS84 +datum=WGS84 +units=degrees", + 'EPSG:4326': "+title=long/lat:WGS84 +proj=longlat +a=6378137.0 +b=6356752.31424518 +ellps=WGS84 +datum=WGS84 +units=degrees", + 'EPSG:4269': "+title=long/lat:NAD83 +proj=longlat +a=6378137.0 +b=6356752.31414036 +ellps=GRS80 +datum=NAD83 +units=degrees", + 'EPSG:32639': "+title=WGS 84 / UTM zone 39N +proj=utm +zone=39 +ellps=WGS84 +datum=WGS84 +units=m +no_defs", + 'EPSG:27700': "+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +ellps=airy +datum=OSGB36 +units=m +no_defs" + } + + + + protected var proj:IProjection; + + public function get srsCode():String + { + return projParams.srsCode; + } + + public function get srsProjNumber():String + { + return projParams.srsProjNumber; + } + + public function get projName():String + { + return projParams.projName; + } + + public function get datum():Datum + { + return projParams.datum; + } + + public function get datumCode():String + { + return projParams.datumCode; + } + + public function get from_greenwich():Number + { + return projParams.from_greenwich; + } + + public function get to_meter():Number + { + return projParams.to_meter; + } + + public function get a():Number + { + return projParams.a; + } + + public function get b():Number + { + return projParams.b; + } + + public function get ep2():Number + { + return projParams.ep2; + } + + public function get es():Number + { + return projParams.es; + } + + public function get datum_params():Array + { + return projParams.datum_params; + } + + public function ProjProjection(srsCode:String) + { + this.projParams.srsCode = srsCode.toUpperCase(); + + if (this.projParams.srsCode.indexOf("EPSG") == 0) { + this.projParams.srsAuth = 'epsg'; + this.projParams.srsProjNumber = this.projParams.srsCode.substring(5); + // DGR 2007-11-20 : authority IGNF + } else if (this.projParams.srsCode.indexOf("IGNF") == 0) { + this.projParams.srsAuth = 'IGNF'; + this.projParams.srsProjNumber = this.projParams.srsCode.substring(5); + // DGR 2008-06-19 : pseudo-authority CRS for WMS + } else if (this.projParams.srsCode.indexOf("CRS") == 0) { + this.projParams.srsAuth = 'CRS'; + this.projParams.srsProjNumber = this.projParams.srsCode.substring(4); + } else { + this.projParams.srsAuth = ''; + this.projParams.srsProjNumber = this.projParams.srsCode; + } + this.loadProjDefinition(); + } + + private function loadProjDefinition():void + { + if (this.srsCode!=null && ProjProjection.defs[this.srsCode]!=null) + { + this.parseDef(ProjProjection.defs[this.projParams.srsCode]); + this.initTransforms(); + } + } + + protected function initTransforms():void + { + switch (this.projParams.projName) + { + case "aea": this.proj = new ProjAea(this.projParams); break; + case "aeqd": this.proj = new ProjAeqd(this.projParams); break; + case "eqc": this.proj = new ProjEqc(this.projParams); break; + case "eqdc": this.proj = new ProjEqdc(this.projParams); break; + case "equi": this.proj = new ProjEqui(this.projParams); break; + case "gauss": this.proj = new ProjGauss(this.projParams); break; + case "gstmerc": this.proj = new ProjGstmerc(this.projParams); break; + case "laea": this.proj = new ProjLaea(this.projParams); break; + case "lcc": this.proj = new ProjLcc(this.projParams); break; + case "longlat": this.proj = new ProjLonglat(this.projParams); break; + case "merc": this.proj = new ProjMerc(this.projParams); break; + case "mill": this.proj = new ProjMill(this.projParams); break; + case "moll": this.proj = new ProjMoll(this.projParams); break; + case "nzmg": this.proj = new ProjNzmg(this.projParams); break; + case "omerc": this.proj = new ProjOmerc(this.projParams); break; + case "ortho": this.proj = new ProjOrtho(this.projParams); break; + case "sinu": this.proj = new ProjSinu(this.projParams); break; + case "omerc": this.proj = new ProjOmerc(this.projParams); break; + case "stere": this.proj = new ProjStere(this.projParams); break; + case "sterea": this.proj = new ProjSterea(this.projParams); break; + case "tmerc": this.proj = new ProjTmerc(this.projParams); break; + case "utm": this.proj = new ProjUtm(this.projParams); break; + case "vandg": this.proj = new ProjVandg(this.projParams); break; + } + if (this.proj!=null) { + this.proj.init(); + this.readyToUse = true; + } + } + + private function parseDef(definition:String):void + { + var paramName:String = ''; + var paramVal:String = ''; + var paramArray:Array=definition.split("+"); + for (var prop:int=0; prop ProjConstants.EPSLN) { + this.ns0 = (this.ms1 * this.ms1 - this.ms2 *this.ms2)/ (this.qs2 - this.qs1); + } else { + this.ns0 = this.con; + } + this.c = this.ms1 * this.ms1 + this.ns0 * this.qs1; + this.rh = this.a * Math.sqrt(this.c - this.ns0 * this.qs0)/this.ns0; + } + +/* Albers Conical Equal Area forward equations--mapping lat,long to x,y + -------------------------------------------------------------------*/ + override public function forward(p:ProjPoint):ProjPoint + { + var lon:Number=p.x; + var lat:Number=p.y; + + this.sin_phi=Math.sin(lat); + this.cos_phi=Math.cos(lat); + + var qs:Number = ProjConstants.qsfnz(this.e3,this.sin_phi,this.cos_phi); + var rh1:Number =this.a * Math.sqrt(this.c - this.ns0 * qs)/this.ns0; + var theta:Number = this.ns0 * ProjConstants.adjust_lon(lon - this.long0); + var x:Number = rh1 * Math.sin(theta) + this.x0; + var y:Number = this.rh - rh1 * Math.cos(theta) + this.y0; + + p.x = x; + p.y = y; + return p; + } + + + override public function inverse(p:ProjPoint):ProjPoint + { + var rh1:Number; + var qs:Number; + var con:Number; + var theta:Number + var lon:Number; + var lat:Number; + + p.x -= this.x0; + p.y = this.rh - p.y + this.y0; + if (this.ns0 >= 0) { + rh1 = Math.sqrt(p.x *p.x + p.y * p.y); + con = 1.0; + } else { + rh1 = -Math.sqrt(p.x * p.x + p.y *p.y); + con = -1.0; + } + theta = 0.0; + if (rh1 != 0.0) { + theta = Math.atan2(con * p.x, con * p.y); + } + con = rh1 * this.ns0 / this.a; + qs = (this.c - con * con) / this.ns0; + if (this.e3 >= 1e-10) { + con = 1 - .5 * (1.0 -this.es) * Math.log((1.0 - this.e3) / (1.0 + this.e3))/this.e3; + if (Math.abs(Math.abs(con) - Math.abs(qs)) > .0000000001 ) { + lat = this.phi1z(this.e3,qs); + } else { + if (qs >= 0) { + lat = .5 * Math.PI; + } else { + lat = -.5 * Math.PI; + } + } + } else { + lat = this.phi1z(e3,qs); + } + + lon = ProjConstants.adjust_lon(theta/this.ns0 + this.long0); + p.x = lon; + p.y = lat; + return p; + } + +/* Function to compute phi1, the latitude for the inverse of the + Albers Conical Equal-Area projection. +-------------------------------------------*/ + private function phi1z (eccent:Number,qs:Number):Number + { + var con:Number; + var com:Number + var dphi:Number; + var phi:Number = ProjConstants.asinz(.5 * qs); + if (eccent < ProjConstants.EPSLN) return phi; + + var eccnts:Number = eccent * eccent; + for (var i:int = 1; i <= 25; i++) { + sinphi = Math.sin(phi); + cosphi = Math.cos(phi); + con = eccent * sinphi; + com = 1.0 - con * con; + dphi = .5 * com * com / cosphi * (qs / (1.0 - eccnts) - sinphi / com + .5 / eccent * Math.log((1.0 - con) / (1.0 + con))); + phi = phi + dphi; + if (Math.abs(dphi) <= 1e-7) return phi; + } + trace("aea:phi1z:Convergence error"); + return 0; + } + + + } +} \ No newline at end of file diff --git a/com/gradoservice/proj4as/proj/ProjAeqd.as b/com/gradoservice/proj4as/proj/ProjAeqd.as new file mode 100755 index 00000000..408470a4 --- /dev/null +++ b/com/gradoservice/proj4as/proj/ProjAeqd.as @@ -0,0 +1,93 @@ +package com.gradoservice.proj4as.proj +{ + import com.gradoservice.proj4as.ProjPoint; + import com.gradoservice.proj4as.ProjConstants; + import com.gradoservice.proj4as.Datum; + + public class ProjAeqd extends AbstractProjProjection + { + public function ProjAeqd(data:ProjParams) + { + super(data); + } + + override public function init():void + { + this.sin_p12=Math.sin(this.lat0) + this.cos_p12=Math.cos(this.lat0) + } + + override public function forward(p:ProjPoint):ProjPoint + { + var lon:Number=p.x; + var lat:Number=p.y; + var ksp:Number; + + var sinphi:Number=Math.sin(p.y); + var cosphi:Number=Math.cos(p.y); + var dlon:Number = ProjConstants.adjust_lon(lon - this.long0); + var coslon:Number = Math.cos(dlon); + var g:Number = this.sin_p12 * sinphi + this.cos_p12 * cosphi * coslon; + if (Math.abs(Math.abs(g) - 1.0) < ProjConstants.EPSLN) { + ksp = 1.0; + if (g < 0.0) { + trace("aeqd:Fwd:PointError"); + return null; + } + } else { + var z:Number = Math.acos(g); + ksp = z/Math.sin(z); + } + p.x = this.x0 + this.a * ksp * cosphi * Math.sin(dlon); + p.y = this.y0 + this.a * ksp * (this.cos_p12 * sinphi - this.sin_p12 * cosphi * coslon); + return p; + } + + override public function inverse(p:ProjPoint):ProjPoint + { + p.x -= this.x0; + p.y -= this.y0; + + var rh:Number = Math.sqrt(p.x * p.x + p.y *p.y); + if (rh > (2.0 * ProjConstants.HALF_PI * this.a)) + { + trace("aeqdInvDataError"); + return null; + } + var z:Number = rh / this.a; + + var sinz:Number=Math.sin(z) + var cosz:Number=Math.cos(z) + + var lon:Number = this.long0; + var lat:Number; + if (Math.abs(rh) <= ProjConstants.EPSLN) { + lat = this.lat0; + } else { + lat = ProjConstants.asinz(cosz * this.sin_p12 + (p.y * sinz * this.cos_p12) / rh); + var con:Number = Math.abs(this.lat0) - ProjConstants.HALF_PI; + if (Math.abs(con) <= ProjConstants.EPSLN) { + if (lat0 >= 0.0) { + lon = ProjConstants.adjust_lon(this.long0 + Math.atan2(p.x , -p.y)); + } else { + lon = ProjConstants.adjust_lon(this.long0 - Math.atan2(-p.x , p.y)); + } + } else { + con = cosz - this.sin_p12 * Math.sin(lat); + if ((Math.abs(con) < ProjConstants.EPSLN) && (Math.abs(p.x) < ProjConstants.EPSLN)) { + //no-op, just keep the lon value as is + } else { + var temp:Number = Math.atan2((p.x * sinz * this.cos_p12), (con * rh)); + lon = ProjConstants.adjust_lon(this.long0 + Math.atan2((p.x * sinz * this.cos_p12), (con * rh))); + } + } + } + + p.x = lon; + p.y = lat; + return p; + } + + + } +} \ No newline at end of file diff --git a/com/gradoservice/proj4as/proj/ProjEqc.as b/com/gradoservice/proj4as/proj/ProjEqc.as new file mode 100755 index 00000000..18e8315b --- /dev/null +++ b/com/gradoservice/proj4as/proj/ProjEqc.as @@ -0,0 +1,55 @@ +package com.gradoservice.proj4as.proj +{ + import com.gradoservice.proj4as.ProjPoint; + import com.gradoservice.proj4as.ProjConstants; + import com.gradoservice.proj4as.Datum; + + public class ProjEqc extends AbstractProjProjection + { + public function ProjEqc(data:ProjParams) + { + super(data); + } + + override public function init():void + { + if(!this.x0) this.x0=0; + if(!this.y0) this.y0=0; + if(!this.lat0) this.lat0=0; + if(!this.long0) this.long0=0; + if(!this.lat_ts) this.lat_ts=0; + if (!this.title) this.title = "Equidistant Cylindrical (Plate Carre)"; + this.rc= Math.cos(this.lat_ts); + } + + + // forward equations--mapping lat,long to x,y + // ----------------------------------------------------------------- + override public function forward(p:ProjPoint):ProjPoint + { + var lon:Number= p.x; + var lat:Number= p.y; + + var dlon:Number = ProjConstants.adjust_lon(lon - this.long0); + var dlat:Number = ProjConstants.adjust_lat(lat - this.lat0 ); + p.x= this.x0 + (this.a*dlon*this.rc); + p.y= this.y0 + (this.a*dlat ); + return p; + } + + // inverse equations--mapping x,y to lat/long + // ----------------------------------------------------------------- + override public function inverse(p:ProjPoint):ProjPoint + { + var x:Number= p.x; + var y:Number= p.y; + + p.x= ProjConstants.adjust_lon(this.long0 + ((x - this.x0)/(this.a*this.rc))); + p.y= ProjConstants.adjust_lat(this.lat0 + ((y - this.y0)/(this.a ))); + return p; + } + + + + } +} \ No newline at end of file diff --git a/com/gradoservice/proj4as/proj/ProjEqdc.as b/com/gradoservice/proj4as/proj/ProjEqdc.as new file mode 100755 index 00000000..0d7a6a32 --- /dev/null +++ b/com/gradoservice/proj4as/proj/ProjEqdc.as @@ -0,0 +1,156 @@ +/******************************************************************************* +NAME EQUIDISTANT CONIC + +PURPOSE: Transforms input longitude and latitude to Easting and Northing + for the Equidistant Conic projection. The longitude and + latitude must be in radians. The Easting and Northing values + will be returned in meters. + +PROGRAMMER DATE +---------- ---- +T. Mittan Mar, 1993 + +ALGORITHM REFERENCES + +1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological + Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United + State Government Printing Office, Washington D.C., 1987. + +2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections", + U.S. Geological Survey Professional Paper 1453 , United State Government + Printing Office, Washington D.C., 1989. +*******************************************************************************/ + +package com.gradoservice.proj4as.proj +{ + import com.gradoservice.proj4as.ProjPoint; + import com.gradoservice.proj4as.ProjConstants; + import com.gradoservice.proj4as.Datum; + + public class ProjEqdc extends AbstractProjProjection + { + public function ProjEqdc(data:ProjParams) + { + super(data); + } + + +/* Variables common to all subroutines in this code file + -----------------------------------------------------*/ + +/* Initialize the Equidistant Conic projection + ------------------------------------------*/ + override public function init():void + { + /* Place parameters in static storage for common use + -------------------------------------------------*/ + if(!this.mode) this.mode=0;//chosen default mode + this.temp = this.b / this.a; + this.es = 1.0 - Math.pow(this.temp,2); + this.e = Math.sqrt(this.es); + this.e0 = ProjConstants.e0fn(this.es); + this.e1 = ProjConstants.e1fn(this.es); + this.e2 = ProjConstants.e2fn(this.es); + this.e3 = ProjConstants.e3fn(this.es); + + this.sinphi=Math.sin(this.lat1); + this.cosphi=Math.cos(this.lat1); + + this.ms1 = ProjConstants.msfnz(this.e,this.sinphi,this.cosphi); + this.ml1 = ProjConstants.mlfn(this.e0, this.e1, this.e2,this.e3, this.lat1); + + /* format B + ---------*/ + if (this.mode != 0) { + if (Math.abs(this.lat1 + this.lat2) < ProjConstants.EPSLN) { + trace("eqdc:Init:EqualLatitudes"); + //return(81); + } + this.sinphi=Math.sin(this.lat2); + this.cosphi=Math.cos(this.lat2); + + this.ms2 = ProjConstants.msfnz(this.e,this.sinphi,this.cosphi); + this.ml2 = ProjConstants.mlfn(this.e0, this.e1, this.e2, this.e3, this.lat2); + if (Math.abs(this.lat1 - this.lat2) >= ProjConstants.EPSLN) { + this.ns = (this.ms1 - this.ms2) / (this.ml2 - this.ml1); + } else { + this.ns = this.sinphi; + } + } else { + this.ns = this.sinphi; + } + this.g = this.ml1 + this.ms1/this.ns; + this.ml0 = ProjConstants.mlfn(this.e0, this.e1,this. e2, this.e3, this.lat0); + this.rh = this.a * (this.g - this.ml0); + } + + +/* Equidistant Conic forward equations--mapping lat,long to x,y + -----------------------------------------------------------*/ + override public function forward(p:ProjPoint):ProjPoint + { + var lon:Number=p.x; + var lat:Number=p.y; + + /* Forward equations + -----------------*/ + var ml:Number = ProjConstants.mlfn(this.e0, this.e1, this.e2, this.e3, lat); + var rh1:Number = this.a * (this.g - ml); + var theta:Number = this.ns * ProjConstants.adjust_lon(lon - this.long0); + + var x:Number = this.x0 + rh1 * Math.sin(theta); + var y:Number = this.y0 + this.rh - rh1 * Math.cos(theta); + p.x=x; + p.y=y; + return p; + } + +/* Inverse equations + -----------------*/ + override public function inverse(p:ProjPoint):ProjPoint + { + p.x -= this.x0; + p.y = this.rh - p.y + this.y0; + var con:Number; + var rh1:Number; + if (this.ns >= 0) { + rh1 = Math.sqrt(p.x *p.x + p.y * p.y); + con = 1.0; + } else { + rh1 = -Math.sqrt(p.x *p. x +p. y * p.y); + con = -1.0; + } + var theta:Number = 0.0; + if (rh1 != 0.0) theta = Math.atan2(con *p.x, con *p.y); + var ml:Number = this.g - rh1 /this.a; + var lat:Number = this.phi3z(this.ml,this.e0,this.e1,this.e2,this.e3); + var lon:Number = ProjConstants.adjust_lon(this.long0 + theta / this.ns); + + p.x=lon; + p.y=lat; + return p; + } + +/* Function to compute latitude, phi3, for the inverse of the Equidistant + Conic projection. +-----------------------------------------------------------------*/ + private function phi3z(ml:Number,e0:Number,e1:Number,e2:Number,e3:Number):Number + { + var phi:Number; + var dphi:Number; + + phi = ml; + for (var i:int = 0; i < 15; i++) { + dphi = (ml + e1 * Math.sin(2.0 * phi) - e2 * Math.sin(4.0 * phi) + e3 * Math.sin(6.0 * phi))/ e0 - phi; + phi += dphi; + if (Math.abs(dphi) <= .0000000001) { + return phi; + } + } + trace("PHI3Z-CONV:Latitude failed to converge after 15 iterations"); + return 0; + } + + + } +} \ No newline at end of file diff --git a/com/gradoservice/proj4as/proj/ProjEqui.as b/com/gradoservice/proj4as/proj/ProjEqui.as new file mode 100755 index 00000000..f0bd98f9 --- /dev/null +++ b/com/gradoservice/proj4as/proj/ProjEqui.as @@ -0,0 +1,90 @@ +/******************************************************************************* +NAME EQUIRECTANGULAR + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the Equirectangular projection. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + +PROGRAMMER DATE +---------- ---- +T. Mittan Mar, 1993 + +ALGORITHM REFERENCES + +1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological + Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United + State Government Printing Office, Washington D.C., 1987. + +2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections", + U.S. Geological Survey Professional Paper 1453 , United State Government + Printing Office, Washington D.C., 1989. +*******************************************************************************/ +package com.gradoservice.proj4as.proj +{ + import com.gradoservice.proj4as.Datum; + import com.gradoservice.proj4as.ProjConstants; + import com.gradoservice.proj4as.ProjPoint; + + public class ProjEqui extends AbstractProjProjection + { + public function ProjEqui(data:ProjParams) + { + super(data); + } + + + + override public function init():void + { + if(!this.x0) this.x0=0; + if(!this.y0) this.y0=0; + if(!this.lat0) this.lat0=0; + if(!this.long0) this.long0=0; + ///this.t2; + } + + + +/* Equirectangular forward equations--mapping lat,long to x,y + ---------------------------------------------------------*/ + override public function forward(p:ProjPoint):ProjPoint + { + + var lon:Number=p.x; + var lat:Number=p.y; + + var dlon:Number = ProjConstants.adjust_lon(lon - this.long0); + var x:Number = this.x0 +this. a * dlon *Math.cos(this.lat0); + var y:Number = this.y0 + this.a * lat; + + this.t1=x; + this.t2=Math.cos(this.lat0); + p.x=x; + p.y=y; + return p; + } //equiFwd() + + + +/* Equirectangular inverse equations--mapping x,y to lat/long + ---------------------------------------------------------*/ + override public function inverse(p:ProjPoint):ProjPoint + { + + p.x -= this.x0; + p.y -= this.y0; + var lat:Number = p.y /this. a; + + if ( Math.abs(lat) > ProjConstants.HALF_PI) { + trace("equi:Inv:DataError"); + } + var lon:Number = ProjConstants.adjust_lon(this.long0 + p.x / (this.a * Math.cos(this.lat0))); + p.x=lon; + p.y=lat; + + return p; + }//equiInv() + + } +} \ No newline at end of file diff --git a/com/gradoservice/proj4as/proj/ProjGauss.as b/com/gradoservice/proj4as/proj/ProjGauss.as new file mode 100755 index 00000000..621912b2 --- /dev/null +++ b/com/gradoservice/proj4as/proj/ProjGauss.as @@ -0,0 +1,62 @@ +package com.gradoservice.proj4as.proj +{ + import com.gradoservice.proj4as.ProjPoint; + import com.gradoservice.proj4as.ProjConstants; + import com.gradoservice.proj4as.Datum; + + public class ProjGauss extends AbstractProjProjection + { + + protected var phic0:Number; + protected var ratexp:Number; + + public function ProjGauss(data:ProjParams) + { + super(data); + } + + override public function init():void + { + var sphi:Number = Math.sin(this.lat0); + var cphi:Number = Math.cos(this.lat0); + cphi *= cphi; + this.rc = Math.sqrt(1.0 - this.es) / (1.0 - this.es * sphi * sphi); + this.c = Math.sqrt(1.0 + this.es * cphi * cphi / (1.0 - this.es)); + this.phic0 = Math.asin(sphi / this.c); + this.ratexp = 0.5 * this.c * this.e; + this.k = Math.tan(0.5 * this.phic0 + ProjConstants.FORTPI) / (Math.pow(Math.tan(0.5*this.lat0 + ProjConstants.FORTPI), this.c) * ProjConstants.srat(this.e*sphi, this.ratexp)); + } + + override public function forward(p:ProjPoint):ProjPoint + { + var lon:Number = p.x; + var lat:Number = p.y; + + p.y = 2.0 * Math.atan( this.k * Math.pow(Math.tan(0.5 * lat + ProjConstants.FORTPI), this.c) * ProjConstants.srat(this.e * Math.sin(lat), this.ratexp) ) - ProjConstants.HALF_PI; + p.x = this.c * lon; + return p; + } + + override public function inverse(p:ProjPoint):ProjPoint + { + var DEL_TOL:Number = 1e-14; + var lon:Number = p.x / this.c; + var lat:Number = p.y; + var num:Number = Math.pow(Math.tan(0.5 * lat + ProjConstants.FORTPI)/this.k, 1./this.c); + for (var i:int = ProjConstants.MAX_ITER; i>0; --i) { + lat = 2.0 * Math.atan(num * ProjConstants.srat(this.e * Math.sin(p.y), -0.5 * this.e)) - ProjConstants.HALF_PI; + if (Math.abs(lat - p.y) < DEL_TOL) break; + p.y = lat; + } + /* convergence failed */ + if (!i) { + trace("gauss:inverse:convergence failed"); + return null; + } + p.x = lon; + p.y = lat; + return p; + } + + } +} \ No newline at end of file diff --git a/com/gradoservice/proj4as/proj/ProjGstmerc.as b/com/gradoservice/proj4as/proj/ProjGstmerc.as new file mode 100755 index 00000000..c7325b56 --- /dev/null +++ b/com/gradoservice/proj4as/proj/ProjGstmerc.as @@ -0,0 +1,74 @@ +package com.gradoservice.proj4as.proj +{ + import com.gradoservice.proj4as.ProjPoint; + import com.gradoservice.proj4as.ProjConstants; + import com.gradoservice.proj4as.Datum; + + public class ProjGstmerc extends AbstractProjProjection + { + + private var cp:Number; + private var lc:Number; + private var n2:Number; + private var rs:Number; + private var xs:Number; + private var ys:Number; + + public function ProjGstmerc(data:ProjParams) + { + super(data); + } + + override public function init():void + { + // array of: a, b, lon0, lat0, k0, x0, y0 + var temp:Number = this.b / this.a; + this.e = Math.sqrt(1.0 - temp*temp); + this.lc= this.long0; + this.rs= Math.sqrt(1.0+this.e*this.e*Math.pow(Math.cos(this.lat0),4.0)/(1.0-this.e*this.e)); + var sinz:Number= Math.sin(this.lat0); + var pc:Number= Math.asin(sinz/this.rs); + var sinzpc:Number= Math.sin(pc); + this.cp= ProjConstants.latiso(0.0,pc,sinzpc)-this.rs*ProjConstants.latiso(this.e,this.lat0,sinz); + this.n2= this.k0*this.a*Math.sqrt(1.0-this.e*this.e)/(1.0-this.e*this.e*sinz*sinz); + this.xs= this.x0; + this.ys= this.y0-this.n2*pc; + + if (!this.title) this.title = "Gauss Schreiber transverse mercator"; + } + + + // forward equations--mapping lat,long to x,y + // ----------------------------------------------------------------- + override public function forward(p:ProjPoint):ProjPoint + { + var lon:Number= p.x; + var lat:Number= p.y; + + var L:Number= this.rs*(lon-this.lc); + var Ls:Number= this.cp+(this.rs*ProjConstants.latiso(this.e,lat,Math.sin(lat))); + var lat1:Number= Math.asin(Math.sin(L)/ProjConstants.cosh(Ls)); + var Ls1:Number= ProjConstants.latiso(0.0,lat1,Math.sin(lat1)); + p.x= this.xs+(this.n2*Ls1); + p.y= this.ys+(this.n2*Math.atan(ProjConstants.sinh(Ls)/Math.cos(L))); + return p; + } + + // inverse equations--mapping x,y to lat/long + // ----------------------------------------------------------------- + override public function inverse(p:ProjPoint):ProjPoint + { + var x:Number= p.x; + var y:Number= p.y; + + var L:Number= Math.atan(ProjConstants.sinh((x-this.xs)/this.n2)/Math.cos((y-this.ys)/this.n2)); + var lat1:Number= Math.asin(Math.sin((y-this.ys)/this.n2)/ProjConstants.cosh((x-this.xs)/this.n2)); + var LC:Number= ProjConstants.latiso(0.0,lat1,Math.sin(lat1)); + p.x= this.lc+L/this.rs; + p.y= ProjConstants.invlatiso(this.e,(LC-this.cp)/this.rs); + return p; + } + + + } +} \ No newline at end of file diff --git a/com/gradoservice/proj4as/proj/ProjLaea.as b/com/gradoservice/proj4as/proj/ProjLaea.as new file mode 100755 index 00000000..9af7a6ba --- /dev/null +++ b/com/gradoservice/proj4as/proj/ProjLaea.as @@ -0,0 +1,127 @@ +/******************************************************************************* +NAME LAMBERT AZIMUTHAL EQUAL-AREA + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the Lambert Azimuthal Equal-Area projection. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + +PROGRAMMER DATE +---------- ---- +D. Steinwand, EROS March, 1991 + +This function was adapted from the Lambert Azimuthal Equal Area projection +code (FORTRAN) in the General Cartographic Transformation Package software +which is available from the U.S. Geological Survey National Mapping Division. + +ALGORITHM REFERENCES + +1. "New Equal-Area Map Projections for Noncircular Regions", John P. Snyder, + The American Cartographer, Vol 15, No. 4, October 1988, pp. 341-355. + +2. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological + Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United + State Government Printing Office, Washington D.C., 1987. + +3. "Software Documentation for GCTP General Cartographic Transformation + Package", U.S. Geological Survey National Mapping Division, May 1982. +*******************************************************************************/ + +package com.gradoservice.proj4as.proj +{ + import com.gradoservice.proj4as.ProjPoint; + import com.gradoservice.proj4as.ProjConstants; + import com.gradoservice.proj4as.Datum; + + public class ProjLaea extends AbstractProjProjection + { + private var sin_lat_o:Number; + private var cos_lat_o:Number; + + public function ProjLaea(data:ProjParams) + { + super(data); + } + + /* Initialize the Lambert Azimuthal Equal Area projection + ------------------------------------------------------*/ + override public function init():void + { + this.sin_lat_o=Math.sin(this.lat0); + this.cos_lat_o=Math.cos(this.lat0); + } + + /* Lambert Azimuthal Equal Area forward equations--mapping lat,long to x,y + -----------------------------------------------------------------------*/ + override public function forward(p:ProjPoint):ProjPoint + { + + /* Forward equations + -----------------*/ + var lon:Number=p.x; + var lat:Number=p.y; + var delta_lon:Number = ProjConstants.adjust_lon(lon - this.long0); + + //v 1.0 + var sin_lat:Number=Math.sin(lat); + var cos_lat:Number=Math.cos(lat); + + var sin_delta_lon:Number=Math.sin(delta_lon); + var cos_delta_lon:Number=Math.cos(delta_lon); + + var g:Number =this.sin_lat_o * sin_lat +this.cos_lat_o * cos_lat * cos_delta_lon; + if (g == -1.0) { + trace("laea:fwd:Point projects to a circle of radius "); + return null; + } + var ksp:Number = this.a * Math.sqrt(2.0 / (1.0 + g)); + var x:Number = ksp * cos_lat * sin_delta_lon + this.x0; + var y:Number = ksp * (this.cos_lat_o * sin_lat - this.sin_lat_o * cos_lat * cos_delta_lon) + this.y0; + p.x = x; + p.y = y + return p; + }//lamazFwd() + + /* Inverse equations + -----------------*/ + override public function inverse(p:ProjPoint):ProjPoint + { + p.x -= this.x0; + p.y -= this.y0; + + var Rh:Number = Math.sqrt(p.x *p.x +p.y * p.y); + var temp:Number = Rh / (2.0 * this.a); + + if (temp > 1) { + trace("laea:Inv:DataError"); + return null; + } + + var z:Number = 2.0 * ProjConstants.asinz(temp); + var sin_z:Number=Math.sin(z); + var cos_z:Number=Math.cos(z); + + var lon:Number =this.long0; + if (Math.abs(Rh) > ProjConstants.EPSLN) { + var lat:Number = ProjConstants.asinz(this.sin_lat_o * cos_z +this. cos_lat_o * sin_z *p.y / Rh); + temp =Math.abs(this.lat0) - ProjConstants.HALF_PI; + if (Math.abs(temp) > ProjConstants.EPSLN) { + temp = cos_z -this.sin_lat_o * Math.sin(lat); + if(temp!=0.0) lon=ProjConstants.adjust_lon(this.long0+Math.atan2(p.x*sin_z*this.cos_lat_o,temp*Rh)); + } else if (this.lat0 < 0.0) { + lon = ProjConstants.adjust_lon(this.long0 - Math.atan2(-p.x,p.y)); + } else { + lon = ProjConstants.adjust_lon(this.long0 + Math.atan2(p.x, -p.y)); + } + } else { + lat = this.lat0; + } + //return(OK); + p.x = lon; + p.y = lat; + return p; + }//lamazInv() + + + } +} \ No newline at end of file diff --git a/com/gradoservice/proj4as/proj/ProjLcc.as b/com/gradoservice/proj4as/proj/ProjLcc.as new file mode 100755 index 00000000..6e043abd --- /dev/null +++ b/com/gradoservice/proj4as/proj/ProjLcc.as @@ -0,0 +1,161 @@ +/******************************************************************************* +NAME LAMBERT CONFORMAL CONIC + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the Lambert Conformal Conic projection. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + + +ALGORITHM REFERENCES + +1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological + Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United + State Government Printing Office, Washington D.C., 1987. + +2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections", + U.S. Geological Survey Professional Paper 1453 , United State Government +*******************************************************************************/ + + +//<2104> +proj=lcc +lat_1=10.16666666666667 +lat_0=10.16666666666667 +lon_0=-71.60561777777777 +k_0=1 +x0=-17044 +x0=-23139.97 +ellps=intl +units=m +no_defs no_defs + +package com.gradoservice.proj4as.proj +{ + import com.gradoservice.proj4as.ProjPoint; + import com.gradoservice.proj4as.ProjConstants; + import com.gradoservice.proj4as.Datum; + + public class ProjLcc extends AbstractProjProjection + { + private var f0:Number; + + public function ProjLcc(data:ProjParams) + { + super(data); + } + + override public function init():void + { + // array of: r_maj,r_min,lat1,lat2,c_lon,c_lat,false_east,false_north + //double c_lat; /* center latitude */ + //double c_lon; /* center longitude */ + //double lat1; /* first standard parallel */ + //double lat2; /* second standard parallel */ + //double r_maj; /* major axis */ + //double r_min; /* minor axis */ + //double false_east; /* x offset in meters */ + //double false_north; /* y offset in meters */ + + if (!this.lat2){this.lat2=this.lat0;}//if lat2 is not defined + if (!this.k0) this.k0 = 1.0; + + // Standard Parallels cannot be equal and on opposite sides of the equator + if (Math.abs(this.lat1+this.lat2) < ProjConstants.EPSLN) { + trace("lcc:init: Equal Latitudes"); + return; + } + + var temp:Number = this.b / this.a; + this.e = Math.sqrt(1.0 - temp*temp); + + var sin1:Number = Math.sin(this.lat1); + var cos1:Number = Math.cos(this.lat1); + var ms1:Number= ProjConstants.msfnz(this.e, sin1, cos1); + var ts1:Number = ProjConstants.tsfnz(this.e, this.lat1, sin1); + + var sin2:Number = Math.sin(this.lat2); + var cos2:Number = Math.cos(this.lat2); + var ms2:Number = ProjConstants.msfnz(this.e, sin2, cos2); + var ts2:Number = ProjConstants.tsfnz(this.e, this.lat2, sin2); + + var ts0:Number = ProjConstants.tsfnz(this.e, this.lat0, Math.sin(this.lat0)); + + if (Math.abs(this.lat1 - this.lat2) > ProjConstants.EPSLN) { + this.ns = Math.log(ms1/ms2)/Math.log(ts1/ts2); + } else { + this.ns = sin1; + } + this.f0 = ms1 / (this.ns * Math.pow(ts1, this.ns)); + this.rh = this.a * this.f0 * Math.pow(ts0, this.ns); + if (!this.title) this.title = "Lambert Conformal Conic"; + } + + + // Lambert Conformal conic forward equations--mapping lat,long to x,y + // ----------------------------------------------------------------- + override public function forward(p:ProjPoint):ProjPoint + { + var lon:Number = p.x; + var lat:Number = p.y; + + // convert to radians + if ( lat <= 90.0 && lat >= -90.0 && lon <= 180.0 && lon >= -180.0) { + //lon = lon * Proj4js.common.D2R; + //lat = lat * Proj4js.common.D2R; + } else { + trace("lcc:forward: llInputOutOfRange: "+ lon +" : " + lat); + return null; + } + + var con:Number = Math.abs( Math.abs(lat) - ProjConstants.HALF_PI); + var ts:Number; + var rh1:Number; + if (con > ProjConstants.EPSLN) { + ts = ProjConstants.tsfnz(this.e, lat, Math.sin(lat) ); + rh1 = this.a * this.f0 * Math.pow(ts, this.ns); + } else { + con = lat * this.ns; + if (con <= 0) { + trace("lcc:forward: No Projection"); + return null; + } + rh1 = 0; + } + var theta:Number = this.ns * ProjConstants.adjust_lon(lon - this.long0); + p.x = this.k0 * (rh1 * Math.sin(theta)) + this.x0; + p.y = this.k0 * (this.rh - rh1 * Math.cos(theta)) + this.y0; + + return p; + } + + // Lambert Conformal Conic inverse equations--mapping x,y to lat/long + // ----------------------------------------------------------------- + override public function inverse(p:ProjPoint):ProjPoint + { + var rh1:Number; + var con:Number; + var ts:Number; + var lat:Number; + var lon:Number; + var x:Number = (p.x - this.x0)/this.k0; + var y:Number = (this.rh - (p.y - this.y0)/this.k0); + if (this.ns > 0) { + rh1 = Math.sqrt (x * x + y * y); + con = 1.0; + } else { + rh1 = -Math.sqrt (x * x + y * y); + con = -1.0; + } + var theta:Number = 0.0; + if (rh1 != 0) { + theta = Math.atan2((con * x),(con * y)); + } + if ((rh1 != 0) || (this.ns > 0.0)) { + con = 1.0/this.ns; + ts = Math.pow((rh1/(this.a * this.f0)), con); + lat = ProjConstants.phi2z(this.e, ts); + if (lat == -9999) return null; + } else { + lat = -ProjConstants.HALF_PI; + } + lon = ProjConstants.adjust_lon(theta/this.ns + this.long0); + + p.x = lon; + p.y = lat; + return p; + } + + + } +} \ No newline at end of file diff --git a/com/gradoservice/proj4as/proj/ProjLonglat.as b/com/gradoservice/proj4as/proj/ProjLonglat.as new file mode 100755 index 00000000..e9075931 --- /dev/null +++ b/com/gradoservice/proj4as/proj/ProjLonglat.as @@ -0,0 +1,13 @@ +package com.gradoservice.proj4as.proj +{ + import com.gradoservice.proj4as.Datum; + + public class ProjLonglat extends AbstractProjProjection + { + public function ProjLonglat(data:ProjParams) + { + super(data); + } + + } +} \ No newline at end of file diff --git a/com/gradoservice/proj4as/proj/ProjMerc.as b/com/gradoservice/proj4as/proj/ProjMerc.as new file mode 100755 index 00000000..88543599 --- /dev/null +++ b/com/gradoservice/proj4as/proj/ProjMerc.as @@ -0,0 +1,120 @@ +/******************************************************************************* +NAME MERCATOR + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the Mercator projection. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + +PROGRAMMER DATE +---------- ---- +D. Steinwand, EROS Nov, 1991 +T. Mittan Mar, 1993 + +ALGORITHM REFERENCES + +1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological + Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United + State Government Printing Office, Washington D.C., 1987. + +2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections", + U.S. Geological Survey Professional Paper 1453 , United State Government + Printing Office, Washington D.C., 1989. +*******************************************************************************/ + +package com.gradoservice.proj4as.proj +{ + import com.gradoservice.proj4as.ProjPoint; + import com.gradoservice.proj4as.ProjConstants; + import com.gradoservice.proj4as.Datum; + + public class ProjMerc extends AbstractProjProjection + { + public function ProjMerc(data:ProjParams) + { + super(data); + } + + override public function init():void + { + //?this.temp = this.r_minor / this.r_major; + //this.temp = this.b / this.a; + //this.es = 1.0 - Math.sqrt(this.temp); + //this.e = Math.sqrt( this.es ); + //?this.m1 = Math.cos(this.lat_origin) / (Math.sqrt( 1.0 - this.es * Math.sin(this.lat_origin) * Math.sin(this.lat_origin))); + //this.m1 = Math.cos(0.0) / (Math.sqrt( 1.0 - this.es * Math.sin(0.0) * Math.sin(0.0))); + if (this.lat_ts) { + if (this.sphere) { + this.k0 = Math.cos(this.lat_ts); + } else { + this.k0 = ProjConstants.msfnz(this.es, Math.sin(this.lat_ts), Math.cos(this.lat_ts)); + } + } + } + + /* Mercator forward equations--mapping lat,long to x,y + --------------------------------------------------*/ + + override public function forward(p:ProjPoint):ProjPoint + { + //alert("ll2m coords : "+coords); + var lon:Number = p.x; + var lat:Number = p.y; + // convert to radians + if ( lat*ProjConstants.R2D > 90.0 && + lat*ProjConstants.R2D < -90.0 && + lon*ProjConstants.R2D > 180.0 && + lon*ProjConstants.R2D < -180.0) { + trace("merc:forward: llInputOutOfRange: "+ lon +" : " + lat); + return null; + } + + var x:Number,y:Number; + if(Math.abs( Math.abs(lat) - ProjConstants.HALF_PI) <= ProjConstants.EPSLN) { + trace("merc:forward: ll2mAtPoles"); + return null; + } else { + if (this.sphere) { + x = this.x0 + this.a * this.k0 * ProjConstants.adjust_lon(lon - this.long0); + y = this.y0 + this.a * this.k0 * Math.log(Math.tan(ProjConstants.FORTPI + 0.5*lat)); + } else { + var sinphi:Number = Math.sin(lat); + var ts:Number = ProjConstants.tsfnz(this.e,lat,sinphi); + x = this.x0 + this.a * this.k0 * ProjConstants.adjust_lon(lon - this.long0); + y = this.y0 - this.a * this.k0 * Math.log(ts); + } + p.x = x; + p.y = y; + return p; + } + } + + + /* Mercator inverse equations--mapping x,y to lat/long + --------------------------------------------------*/ + override public function inverse(p:ProjPoint):ProjPoint + { + var x:Number = p.x - this.x0; + var y:Number = p.y - this.y0; + var lon:Number,lat:Number; + + if (this.sphere) { + lat = ProjConstants.HALF_PI - 2.0 * Math.atan(Math.exp(-y / this.a * this.k0)); + } else { + var ts:Number = Math.exp(-y / (this.a * this.k0)); + lat = ProjConstants.phi2z(this.e,ts); + if(lat == -9999) { + trace("merc:inverse: lat = -9999"); + return null; + } + } + lon = ProjConstants.adjust_lon(this.long0+ x / (this.a * this.k0)); + + p.x = lon; + p.y = lat; + return p; + } + + + } +} \ No newline at end of file diff --git a/com/gradoservice/proj4as/proj/ProjMill.as b/com/gradoservice/proj4as/proj/ProjMill.as new file mode 100755 index 00000000..36ebb4d1 --- /dev/null +++ b/com/gradoservice/proj4as/proj/ProjMill.as @@ -0,0 +1,83 @@ +/******************************************************************************* +NAME MILLER CYLINDRICAL + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the Miller Cylindrical projection. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + +PROGRAMMER DATE +---------- ---- +T. Mittan March, 1993 + +This function was adapted from the Lambert Azimuthal Equal Area projection +code (FORTRAN) in the General Cartographic Transformation Package software +which is available from the U.S. Geological Survey National Mapping Division. + +ALGORITHM REFERENCES + +1. "New Equal-Area Map Projections for Noncircular Regions", John P. Snyder, + The American Cartographer, Vol 15, No. 4, October 1988, pp. 341-355. + +2. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological + Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United + State Government Printing Office, Washington D.C., 1987. + +3. "Software Documentation for GCTP General Cartographic Transformation + Package", U.S. Geological Survey National Mapping Division, May 1982. +*******************************************************************************/ + + +package com.gradoservice.proj4as.proj +{ + import com.gradoservice.proj4as.ProjPoint; + import com.gradoservice.proj4as.ProjConstants; + import com.gradoservice.proj4as.Datum; + + public class ProjMill extends AbstractProjProjection + { + public function ProjMill(data:ProjParams) + { + super(data); + } + + override public function init():void + { + //no-op + } + + + /* Miller Cylindrical forward equations--mapping lat,long to x,y + ------------------------------------------------------------*/ + override public function forward(p:ProjPoint):ProjPoint + { + var lon:Number=p.x; + var lat:Number=p.y; + /* Forward equations + -----------------*/ + var dlon:Number = ProjConstants.adjust_lon(lon -this.long0); + var x:Number = this.x0 + this.a * dlon; + var y:Number = this.y0 + this.a * Math.log(Math.tan((ProjConstants.PI / 4.0) + (lat / 2.5))) * 1.25; + + p.x=x; + p.y=y; + return p; + }//millFwd() + + /* Miller Cylindrical inverse equations--mapping x,y to lat/long + ------------------------------------------------------------*/ + override public function inverse(p:ProjPoint):ProjPoint + { + p.x -= this.x0; + p.y -= this.y0; + + var lon:Number = ProjConstants.adjust_lon(this.long0 + p.x /this.a); + var lat:Number = 2.5 * (Math.atan(Math.exp(0.8*p.y/this.a)) - ProjConstants.PI / 4.0); + + p.x=lon; + p.y=lat; + return p; + }//millInv() + + } +} \ No newline at end of file diff --git a/com/gradoservice/proj4as/proj/ProjMoll.as b/com/gradoservice/proj4as/proj/ProjMoll.as new file mode 100755 index 00000000..5e29222f --- /dev/null +++ b/com/gradoservice/proj4as/proj/ProjMoll.as @@ -0,0 +1,113 @@ +/******************************************************************************* +NAME MOLLWEIDE + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the MOllweide projection. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + +PROGRAMMER DATE +---------- ---- +D. Steinwand, EROS May, 1991; Updated Sept, 1992; Updated Feb, 1993 +S. Nelson, EDC Jun, 2993; Made corrections in precision and + number of iterations. + +ALGORITHM REFERENCES + +1. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections", + U.S. Geological Survey Professional Paper 1453 , United State Government + Printing Office, Washington D.C., 1989. + +2. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological + Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United + State Government Printing Office, Washington D.C., 1987. +*******************************************************************************/ + + +package com.gradoservice.proj4as.proj +{ + import com.gradoservice.proj4as.ProjPoint; + import com.gradoservice.proj4as.ProjConstants; + import com.gradoservice.proj4as.Datum; + + public class ProjMoll extends AbstractProjProjection + { + public function ProjMoll(data:ProjParams) + { + super(data); + } + + override public function init():void + { + //no-op + } + + /* Mollweide forward equations--mapping lat,long to x,y + ----------------------------------------------------*/ + override public function forward(p:ProjPoint):ProjPoint + { + /* Forward equations + -----------------*/ + var lon:Number=p.x; + var lat:Number=p.y; + + var delta_lon:Number = ProjConstants.adjust_lon(lon - this.long0); + var theta:Number = lat; + var con:Number = ProjConstants.PI * Math.sin(lat); + + /* Iterate using the Newton-Raphson method to find theta + -----------------------------------------------------*/ + for (var i:int=0;;i++) { + var delta_theta:Number = -(theta + Math.sin(theta) - con)/ (1.0 + Math.cos(theta)); + theta += delta_theta; + if (Math.abs(delta_theta) < ProjConstants.EPSLN) break; + if (i >= 50) { + trace("moll:Fwd:IterationError"); + //return(241); + } + } + theta /= 2.0; + + /* If the latitude is 90 deg, force the x coordinate to be "0 + false easting" + this is done here because of precision problems with "cos(theta)" + --------------------------------------------------------------------------*/ + if (ProjConstants.PI/2 - Math.abs(lat) < ProjConstants.EPSLN) delta_lon =0; + var x:Number = 0.900316316158 * this.a * delta_lon * Math.cos(theta) + this.x0; + var y:Number = 1.4142135623731 * this.a * Math.sin(theta) + this.y0; + + p.x=x; + p.y=y; + return p; + } + + override public function inverse(p:ProjPoint):ProjPoint + { + var theta:Number; + var arg:Number; + + /* Inverse equations + -----------------*/ + p.x-= this.x0; + //~ p.y -= this.y0; + arg = p.y / (1.4142135623731 * this.a); + + /* Because of division by zero problems, 'arg' can not be 1.0. Therefore + a number very close to one is used instead. + -------------------------------------------------------------------*/ + if(Math.abs(arg) > 0.999999999999) arg=0.999999999999; + theta =Math.asin(arg); + var lon:Number = ProjConstants.adjust_lon(this.long0 + (p.x / (0.900316316158 * this.a * Math.cos(theta)))); + if(lon < (-ProjConstants.PI)) lon= -ProjConstants.PI; + if(lon > ProjConstants.PI) lon= ProjConstants.PI; + arg = (2.0 * theta + Math.sin(2.0 * theta)) / ProjConstants.PI; + if(Math.abs(arg) > 1.0)arg=1.0; + var lat:Number = Math.asin(arg); + //return(OK); + + p.x=lon; + p.y=lat; + return p; + } + + } +} \ No newline at end of file diff --git a/com/gradoservice/proj4as/proj/ProjNzmg.as b/com/gradoservice/proj4as/proj/ProjNzmg.as new file mode 100755 index 00000000..d34eeba2 --- /dev/null +++ b/com/gradoservice/proj4as/proj/ProjNzmg.as @@ -0,0 +1,292 @@ +/******************************************************************************* +NAME NEW ZEALAND MAP GRID + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the New Zealand Map Grid projection. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + + +ALGORITHM REFERENCES + +1. Department of Land and Survey Technical Circular 1973/32 + http://www.linz.govt.nz/docs/miscellaneous/nz-map-definition.pdf + +2. OSG Technical Report 4.1 + http://www.linz.govt.nz/docs/miscellaneous/nzmg.pdf + + +IMPLEMENTATION NOTES + +The two references use different symbols for the calculated values. This +implementation uses the variable names similar to the symbols in reference [1]. + +The alogrithm uses different units for delta latitude and delta longitude. +The delta latitude is assumed to be in units of seconds of arc x 10^-5. +The delta longitude is the usual radians. Look out for these conversions. + +The algorithm is described using complex arithmetic. There were three +options: + * find and use a Javascript library for complex arithmetic + * write my own complex library + * expand the complex arithmetic by hand to simple arithmetic + +This implementation has expanded the complex multiplication operations +into parallel simple arithmetic operations for the real and imaginary parts. +The imaginary part is way over to the right of the display; this probably +violates every coding standard in the world, but, to me, it makes it much +more obvious what is going on. + +The following complex operations are used: + - addition + - multiplication + - division + - complex number raised to integer power + - summation + +A summary of complex arithmetic operations: + (from http://en.wikipedia.org/wiki/Complex_arithmetic) + addition: (a + bi) + (c + di) = (a + c) + (b + d)i + subtraction: (a + bi) - (c + di) = (a - c) + (b - d)i + multiplication: (a + bi) x (c + di) = (ac - bd) + (bc + ad)i + division: (a + bi) / (c + di) = [(ac + bd)/(cc + dd)] + [(bc - ad)/(cc + dd)]i + +The algorithm needs to calculate summations of simple and complex numbers. This is +implemented using a for-loop, pre-loading the summed value to zero. + +The algorithm needs to calculate theta^2, theta^3, etc while doing a summation. +There are three possible implementations: + - use Math.pow in the summation loop - except for complex numbers + - precalculate the values before running the loop + - calculate theta^n = theta^(n-1) * theta during the loop +This implementation uses the third option for both real and complex arithmetic. + +For example + psi_n = 1; + sum = 0; + for (n = 1; n <=6; n++) { + psi_n1 = psi_n * psi; // calculate psi^(n+1) + psi_n = psi_n1; + sum = sum + A[n] * psi_n; + } + + +TEST VECTORS + +NZMG E, N: 2487100.638 6751049.719 metres +NZGD49 long, lat: 172.739194 -34.444066 degrees + +NZMG E, N: 2486533.395 6077263.661 metres +NZGD49 long, lat: 172.723106 -40.512409 degrees + +NZMG E, N: 2216746.425 5388508.765 metres +NZGD49 long, lat: 169.172062 -46.651295 degrees + +Note that these test vectors convert from NZMG metres to lat/long referenced +to NZGD49, not the more usual WGS84. The difference is about 70m N/S and about +10m E/W. + +These test vectors are provided in reference [1]. Many more test +vectors are available in + http://www.linz.govt.nz/docs/topography/topographicdata/placenamesdatabase/nznamesmar08.zip +which is a catalog of names on the 260-series maps. + + +EPSG CODES + +NZMG EPSG:27200 +NZGD49 EPSG:4272 + +http://spatialreference.org/ defines these as + Proj4js.defs["EPSG:4272"] = "+proj=longlat +ellps=intl +datum=nzgd49 +no_defs "; + Proj4js.defs["EPSG:27200"] = "+proj=nzmg +lat_0=-41 +lon_0=173 +x_0=2510000 +y_0=6023150 +ellps=intl +datum=nzgd49 +units=m +no_defs "; + + +LICENSE + Copyright: Stephen Irons 2008 + Released under terms of the LGPL as per: http://www.gnu.org/copyleft/lesser.html + +*******************************************************************************/ + +package com.gradoservice.proj4as.proj +{ + import com.gradoservice.proj4as.ProjPoint; + import com.gradoservice.proj4as.ProjConstants; + import com.gradoservice.proj4as.Datum; + + public class ProjNzmg extends AbstractProjProjection + { + private var A:Array = []; + private var B_re:Array = []; + private var B_im:Array = []; + private var C_re:Array = []; + private var C_im:Array = []; + private var D:Array = []; + private var iterations:int = 1; + + public function ProjNzmg(data:ProjParams) + { + super(data); + } + + override public function init():void + { + this.A[1] = +0.6399175073; + this.A[2] = -0.1358797613; + this.A[3] = +0.063294409; + this.A[4] = -0.02526853; + this.A[5] = +0.0117879; + this.A[6] = -0.0055161; + this.A[7] = +0.0026906; + this.A[8] = -0.001333; + this.A[9] = +0.00067; + this.A[10] = -0.00034; + + this.B_re[1] = +0.7557853228; this.B_im[1] = 0.0; + this.B_re[2] = +0.249204646; this.B_im[2] = +0.003371507; + this.B_re[3] = -0.001541739; this.B_im[3] = +0.041058560; + this.B_re[4] = -0.10162907; this.B_im[4] = +0.01727609; + this.B_re[5] = -0.26623489; this.B_im[5] = -0.36249218; + this.B_re[6] = -0.6870983; this.B_im[6] = -1.1651967; + + this.C_re[1] = +1.3231270439; this.C_im[1] = 0.0; + this.C_re[2] = -0.577245789; this.C_im[2] = -0.007809598; + this.C_re[3] = +0.508307513; this.C_im[3] = -0.112208952; + this.C_re[4] = -0.15094762; this.C_im[4] = +0.18200602; + this.C_re[5] = +1.01418179; this.C_im[5] = +1.64497696; + this.C_re[6] = +1.9660549; this.C_im[6] = +2.5127645; + + this.D[1] = +1.5627014243; + this.D[2] = +0.5185406398; + this.D[3] = -0.03333098; + this.D[4] = -0.1052906; + this.D[5] = -0.0368594; + this.D[6] = +0.007317; + this.D[7] = +0.01220; + this.D[8] = +0.00394; + this.D[9] = -0.0013; + } + + /** + New Zealand Map Grid Forward - long/lat to x/y + long/lat in radians + */ + override public function forward(p:ProjPoint):ProjPoint + { + var lon:Number = p.x; + var lat:Number = p.y; + + var delta_lat:Number = lat - this.lat0; + var delta_lon:Number = lon - this.long0; + + // 1. Calculate d_phi and d_psi ... // and d_lambda + // For this algorithm, delta_latitude is in seconds of arc x 10-5, so we need to scale to those units. Longitude is radians. + var d_phi:Number = delta_lat / ProjConstants.SEC_TO_RAD * 1E-5; var d_lambda:Number = delta_lon; + var d_phi_n:Number = 1; // d_phi^0 + + var d_psi:Number = 0; + for (var n:int = 1; n <= 10; n++) { + d_phi_n = d_phi_n * d_phi; + d_psi = d_psi + this.A[n] * d_phi_n; + } + + // 2. Calculate theta + var th_re:Number = d_psi; var th_im:Number = d_lambda; + + // 3. Calculate z + var th_n_re:Number = 1; var th_n_im:Number = 0; // theta^0 + var th_n_re1:Number; var th_n_im1:Number; + + var z_re:Number = 0; var z_im:Number = 0; + for (n = 1; n <= 6; n++) { + th_n_re1 = th_n_re*th_re - th_n_im*th_im; th_n_im1 = th_n_im*th_re + th_n_re*th_im; + th_n_re = th_n_re1; th_n_im = th_n_im1; + z_re = z_re + this.B_re[n]*th_n_re - this.B_im[n]*th_n_im; z_im = z_im + this.B_im[n]*th_n_re + this.B_re[n]*th_n_im; + } + + // 4. Calculate easting and northing + var x:Number = (z_im * this.a) + this.x0; + var y:Number = (z_re * this.a) + this.y0; + + p.x = x; p.y = y; + + return p; + } + + + /** + New Zealand Map Grid Inverse - x/y to long/lat + */ + override public function inverse(p:ProjPoint):ProjPoint + { + var x:Number = p.x; + var y:Number = p.y; + + var delta_x:Number = x - this.x0; + var delta_y:Number = y - this.y0; + + // 1. Calculate z + var z_re:Number = delta_y / this.a; var z_im:Number = delta_x / this.a; + + // 2a. Calculate theta - first approximation gives km accuracy + var z_n_re:Number = 1; var z_n_im:Number = 0; // z^0 + var z_n_re1:Number; var z_n_im1:Number; + + var th_re:Number = 0; var th_im:Number = 0; + for (var n:int = 1; n <= 6; n++) { + z_n_re1 = z_n_re*z_re - z_n_im*z_im; z_n_im1 = z_n_im*z_re + z_n_re*z_im; + z_n_re = z_n_re1; z_n_im = z_n_im1; + th_re = th_re + this.C_re[n]*z_n_re - this.C_im[n]*z_n_im; th_im = th_im + this.C_im[n]*z_n_re + this.C_re[n]*z_n_im; + } + + // 2b. Iterate to refine the accuracy of the calculation + // 0 iterations gives km accuracy + // 1 iteration gives m accuracy -- good enough for most mapping applications + // 2 iterations bives mm accuracy + for (var i:int = 0; i < this.iterations; i++) { + var th_n_re:Number = th_re; var th_n_im:Number = th_im; + var th_n_re1:Number; var th_n_im1:Number; + + var num_re:Number = z_re; var num_im:Number = z_im; + for (n = 2; n <= 6; n++) { + th_n_re1 = th_n_re*th_re - th_n_im*th_im; th_n_im1 = th_n_im*th_re + th_n_re*th_im; + th_n_re = th_n_re1; th_n_im = th_n_im1; + num_re = num_re + (n-1)*(this.B_re[n]*th_n_re - this.B_im[n]*th_n_im); num_im = num_im + (n-1)*(this.B_im[n]*th_n_re + this.B_re[n]*th_n_im); + } + + th_n_re = 1; th_n_im = 0; + var den_re:Number = this.B_re[1]; var den_im:Number = this.B_im[1]; + for (n = 2; n <= 6; n++) { + th_n_re1 = th_n_re*th_re - th_n_im*th_im; th_n_im1 = th_n_im*th_re + th_n_re*th_im; + th_n_re = th_n_re1; th_n_im = th_n_im1; + den_re = den_re + n * (this.B_re[n]*th_n_re - this.B_im[n]*th_n_im); den_im = den_im + n * (this.B_im[n]*th_n_re + this.B_re[n]*th_n_im); + } + + // Complex division + var den2:Number = den_re*den_re + den_im*den_im; + th_re = (num_re*den_re + num_im*den_im) / den2; th_im = (num_im*den_re - num_re*den_im) / den2; + } + + // 3. Calculate d_phi ... // and d_lambda + var d_psi:Number = th_re; var d_lambda:Number = th_im; + var d_psi_n:Number = 1; // d_psi^0 + + var d_phi:Number = 0; + for (n = 1; n <= 9; n++) { + d_psi_n = d_psi_n * d_psi; + d_phi = d_phi + this.D[n] * d_psi_n; + } + + // 4. Calculate latitude and longitude + // d_phi is calcuated in second of arc * 10^-5, so we need to scale back to radians. d_lambda is in radians. + var lat:Number = this.lat0 + (d_phi * ProjConstants.SEC_TO_RAD * 1E5); + var lon:Number = this.long0 + d_lambda; + + p.x = lon; + p.y = lat; + + return p; + } + + } +} \ No newline at end of file diff --git a/com/gradoservice/proj4as/proj/ProjOmerc.as b/com/gradoservice/proj4as/proj/ProjOmerc.as new file mode 100755 index 00000000..1a262f5b --- /dev/null +++ b/com/gradoservice/proj4as/proj/ProjOmerc.as @@ -0,0 +1,299 @@ +/******************************************************************************* +NAME OBLIQUE MERCATOR (HOTINE) + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the Oblique Mercator projection. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + +PROGRAMMER DATE +---------- ---- +T. Mittan Mar, 1993 + +ALGORITHM REFERENCES + +1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological + Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United + State Government Printing Office, Washington D.C., 1987. + +2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections", + U.S. Geological Survey Professional Paper 1453 , United State Government + Printing Office, Washington D.C., 1989. +*******************************************************************************/ + +package com.gradoservice.proj4as.proj +{ + import com.gradoservice.proj4as.ProjPoint; + import com.gradoservice.proj4as.ProjConstants; + import com.gradoservice.proj4as.Datum; + + public class ProjOmerc extends AbstractProjProjection + { + private var d:Number; + private var f:Number; + private var h:Number; + private var j:Number; + private var l:Number; + private var p:Number; + private var u:Number; + private var dlon:Number; + private var al:Number; + private var bl:Number; + private var el:Number; + private var com:Number; + private var cos_p20:Number; + private var cosaz:Number; + private var cosgam:Number; + private var at1:Number; + private var gam:Number; + private var gama:Number; + private var lon1:Number; + private var lon2:Number; + private var sin_p20:Number; + private var sinaz:Number; + private var singam:Number; + private var ts:Number; + private var ts1:Number; + private var ts2:Number; + + public function ProjOmerc(data:ProjParams) + { + super(data); + } + + + override public function init():void + { + if (!this.mode) this.mode=0; + if (!this.lon1) {this.lon1=0;this.mode=1;} + if (!this.lon2) this.lon2=0; + if (!this.lat2) this.lat2=0; + + /* Place parameters in static storage for common use + -------------------------------------------------*/ + var temp:Number = this.b/ this.a; + var es:Number = 1.0 - Math.pow(temp,2); + var e:Number = Math.sqrt(es); + + this.sin_p20=Math.sin(this.lat0); + this.cos_p20=Math.cos(this.lat0); + + this.con = 1.0 - this.es * this.sin_p20 * this.sin_p20; + this.com = Math.sqrt(1.0 - es); + this.bl = Math.sqrt(1.0 + this.es * Math.pow(this.cos_p20,4.0)/(1.0 - es)); + this.al = this.a * this.bl * this.k0 * this.com / this.con; + if (Math.abs(this.lat0) < ProjConstants.EPSLN) { + this.ts = 1.0; + this.d = 1.0; + this.el = 1.0; + } else { + this.ts = ProjConstants.tsfnz(this.e,this.lat0,this.sin_p20); + this.con = Math.sqrt(this.con); + this.d = this.bl * this.com / (this.cos_p20 * this.con); + if ((this.d * this.d - 1.0) > 0.0) { + if (this.lat0 >= 0.0) { + this.f = this.d + Math.sqrt(this.d * this.d - 1.0); + } else { + this.f = this.d - Math.sqrt(this.d * this.d - 1.0); + } + } else { + this.f = this.d; + } + this.el = this.f * Math.pow(this.ts,this.bl); + } + + //this.longc=52.60353916666667; + + if (this.mode != 0) { + this.g = .5 * (this.f - 1.0/this.f); + this.gama = ProjConstants.asinz(Math.sin(this.alpha) / this.d); + this.longc= this.longc - ProjConstants.asinz(this.g * Math.tan(this.gama))/this.bl; + + /* Report parameters common to format B + -------------------------------------*/ + //genrpt(azimuth * R2D,"Azimuth of Central Line: "); + //cenlon(lon_origin); + // cenlat(lat_origin); + + this.con = Math.abs(this.lat0); + if ((this.con > ProjConstants.EPSLN) && (Math.abs(this.con - ProjConstants.HALF_PI) > ProjConstants.EPSLN)) { + this.singam=Math.sin(this.gama); + this.cosgam=Math.cos(this.gama); + + this.sinaz=Math.sin(this.alpha); + this.cosaz=Math.cos(this.alpha); + + if (this.lat0>= 0) { + this.u = (this.al / this.bl) * Math.atan(Math.sqrt(this.d*this.d - 1.0)/this.cosaz); + } else { + this.u = -(this.al / this.bl) *Math.atan(Math.sqrt(this.d*this.d - 1.0)/this.cosaz); + } + } else { + trace("omerc:Init:DataError"); + } + } else { + this.sinphi =Math. sin(this.at1); + this.ts1 = ProjConstants.tsfnz(this.e,this.lat1,this.sinphi); + this.sinphi = Math.sin(this.lat2); + this.ts2 = ProjConstants.tsfnz(this.e,this.lat2,this.sinphi); + this.h = Math.pow(this.ts1,this.bl); + this.l = Math.pow(this.ts2,this.bl); + this.f = this.el/this.h; + this.g = .5 * (this.f - 1.0/this.f); + this.j = (this.el * this.el - this.l * this.h)/(this.el * this.el + this.l * this.h); + this.p = (this.l - this.h) / (this.l + this.h); + this.dlon = this.lon1 - this.lon2; + if (this.dlon < -ProjConstants.PI) this.lon2 = this.lon2 - 2.0 * ProjConstants.PI; + if (this.dlon > ProjConstants.PI) this.lon2 = this.lon2 + 2.0 * ProjConstants.PI; + this.dlon = this.lon1 - this.lon2; + this.longc = .5 * (this.lon1 + this.lon2) -Math.atan(this.j * Math.tan(.5 * this.bl * this.dlon)/this.p)/this.bl; + this.dlon = ProjConstants.adjust_lon(this.lon1 - this.longc); + this.gama = Math.atan(Math.sin(this.bl * this.dlon)/this.g); + this.alpha = ProjConstants.asinz(this.d * Math.sin(this.gama)); + + /* Report parameters common to format A + -------------------------------------*/ + + if (Math.abs(this.lat1 - this.lat2) <= ProjConstants.EPSLN) { + trace("omercInitDataError"); + //return(202); + } else { + this.con = Math.abs(this.lat1); + } + if ((this.con <= ProjConstants.EPSLN) || (Math.abs(this.con - ProjConstants.HALF_PI) <= ProjConstants.EPSLN)) { + trace("omercInitDataError"); + //return(202); + } else { + if (Math.abs(Math.abs(this.lat0) - ProjConstants.HALF_PI) <= ProjConstants.EPSLN) { + trace("omercInitDataError"); + //return(202); + } + } + + this.singam=Math.sin(this.gam); + this.cosgam=Math.cos(this.gam); + + this.sinaz=Math.sin(this.alpha); + this.cosaz=Math.cos(this.alpha); + + + if (this.lat0 >= 0) { + this.u = (this.al/this.bl) * Math.atan(Math.sqrt(this.d * this.d - 1.0)/this.cosaz); + } else { + this.u = -(this.al/this.bl) * Math.atan(Math.sqrt(this.d * this.d - 1.0)/this.cosaz); + } + } + } + + + /* Oblique Mercator forward equations--mapping lat,long to x,y + ----------------------------------------------------------*/ + override public function forward(p:ProjPoint):ProjPoint + { + var theta:Number; /* angle */ + var sin_phi:Number, cos_phi:Number;/* sin and cos value */ + var b:Number; /* temporary values */ + var c:Number, t:Number, tq:Number; /* temporary values */ + var con:Number, n:Number, ml:Number; /* cone constant, small m */ + var q:Number,us:Number,vl:Number; + var ul:Number,vs:Number; + var s:Number; + var dlon:Number; + var ts1:Number; + + var lon:Number=p.x; + var lat:Number=p.y; + /* Forward equations + -----------------*/ + sin_phi = Math.sin(lat); + dlon = ProjConstants.adjust_lon(lon - this.longc); + vl = Math.sin(this.bl * dlon); + if (Math.abs(Math.abs(lat) - ProjConstants.HALF_PI) > ProjConstants.EPSLN) { + ts1 = ProjConstants.tsfnz(this.e,lat,sin_phi); + q = this.el / (Math.pow(ts1,this.bl)); + s = .5 * (q - 1.0 / q); + t = .5 * (q + 1.0/ q); + ul = (s * this.singam - vl * this.cosgam) / t; + con = Math.cos(this.bl * dlon); + if (Math.abs(con) < .0000001) { + us = this.al * this.bl * dlon; + } else { + us = this.al * Math.atan((s * this.cosgam + vl * this.singam) / con)/this.bl; + if (con < 0) us = us + ProjConstants.PI * this.al / this.bl; + } + } else { + if (lat >= 0) { + ul = this.singam; + } else { + ul = -this.singam; + } + us = this.al * lat / this.bl; + } + if (Math.abs(Math.abs(ul) - 1.0) <= ProjConstants.EPSLN) { + //alert("Point projects into infinity","omer-for"); + trace("omercFwdInfinity"); + //return(205); + } + vs = .5 * this.al * Math.log((1.0 - ul)/(1.0 + ul)) / this.bl; + us = us - this.u; + var x:Number = this.x0 + vs * this.cosaz + us * this.sinaz; + var y:Number = this.y0 + us * this.cosaz - vs * this.sinaz; + + p.x=x; + p.y=y; + return p; + } + + override public function inverse(p:ProjPoint):ProjPoint + { + var delta_lon:Number; /* Delta longitude (Given longitude - center */ + var theta:Number; /* angle */ + var delta_theta:Number; /* adjusted longitude */ + var sin_phi:Number, cos_phi:Number;/* sin and cos value */ + var b:Number; /* temporary values */ + var c:Number, t:Number, tq:Number; /* temporary values */ + var con:Number, n:Number, ml:Number; /* cone constant, small m */ + var vs:Number,us:Number,q:Number,s:Number,ts1:Number; + var vl:Number,ul:Number,bs:Number; + var dlon:Number; + var flag:Number; + + /* Inverse equations + -----------------*/ + p.x -= this.x0; + p.y -= this.y0; + flag = 0; + vs = p.x * this.cosaz - p.y * this.sinaz; + us = p.y * this.cosaz + p.x * this.sinaz; + us = us + this.u; + q = Math.exp(-this.bl * vs / this.al); + s = .5 * (q - 1.0/q); + t = .5 * (q + 1.0/q); + vl = Math.sin(this.bl * us / this.al); + ul = (vl * this.cosgam + s * this.singam)/t; + if (Math.abs(Math.abs(ul) - 1.0) <= ProjConstants.EPSLN) + { + var lon:Number = this.longc; + if (ul >= 0.0) { + var lat:Number = ProjConstants.HALF_PI; + } else { + lat = -ProjConstants.HALF_PI; + } + } else { + con = 1.0 / this.bl; + ts1 =Math.pow((this.el / Math.sqrt((1.0 + ul) / (1.0 - ul))),con); + lat = ProjConstants.phi2z(this.e,ts1); + //if (flag != 0) + //return(flag); + //~ con = Math.cos(this.bl * us /al); + theta = this.longc - Math.atan2((s * this.cosgam - vl * this.singam) , con)/this.bl; + lon = ProjConstants.adjust_lon(theta); + } + p.x=lon; + p.y=lat; + return p; + } + + + } +} \ No newline at end of file diff --git a/com/gradoservice/proj4as/proj/ProjOrtho.as b/com/gradoservice/proj4as/proj/ProjOrtho.as new file mode 100755 index 00000000..2f38a6cf --- /dev/null +++ b/com/gradoservice/proj4as/proj/ProjOrtho.as @@ -0,0 +1,131 @@ +/******************************************************************************* +NAME ORTHOGRAPHIC + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the Orthographic projection. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + +PROGRAMMER DATE +---------- ---- +T. Mittan Mar, 1993 + +ALGORITHM REFERENCES + +1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological + Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United + State Government Printing Office, Washington D.C., 1987. + +2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections", + U.S. Geological Survey Professional Paper 1453 , United State Government + Printing Office, Washington D.C., 1989. +*******************************************************************************/ + +package com.gradoservice.proj4as.proj +{ + import com.gradoservice.proj4as.ProjPoint; + import com.gradoservice.proj4as.ProjConstants; + import com.gradoservice.proj4as.Datum; + + public class ProjOrtho extends AbstractProjProjection + { + + private var cos_p14:Number; + private var sin_p14:Number; + + public function ProjOrtho(data:ProjParams) + { + super(data); + } + + override public function init():void + { + //double temp; /* temporary variable */ + + /* Place parameters in static storage for common use + -------------------------------------------------*/; + this.sin_p14=Math.sin(this.lat0); + this.cos_p14=Math.cos(this.lat0); + } + + + /* Orthographic forward equations--mapping lat,long to x,y + ---------------------------------------------------*/ + override public function forward(p:ProjPoint):ProjPoint + { + var sinphi:Number, cosphi:Number; /* sin and cos value */ + var dlon:Number; /* delta longitude value */ + var coslon:Number; /* cos of longitude */ + var ksp:Number; /* scale factor */ + var g:Number; + var lon:Number=p.x; + var lat:Number=p.y; + var x:Number,y:Number; + /* Forward equations + -----------------*/ + dlon = ProjConstants.adjust_lon(lon - this.long0); + + sinphi=Math.sin(lat); + cosphi=Math.cos(lat); + + coslon = Math.cos(dlon); + g = this.sin_p14 * sinphi + this.cos_p14 * cosphi * coslon; + ksp = 1.0; + if ((g > 0) || (Math.abs(g) <= ProjConstants.EPSLN)) { + x = this.a * ksp * cosphi * Math.sin(dlon); + y = this.y0 + this.a * ksp * (this.cos_p14 * sinphi - this.sin_p14 * cosphi * coslon); + } else { + trace("orthoFwdPointError"); + } + p.x=x; + p.y=y; + return p; + } + + + override public function inverse(p:ProjPoint):ProjPoint + { + var rh:Number; /* height above ellipsoid */ + var x:Number,y:Number,z:Number; /* angle */ + var sinz:Number,cosz:Number,cosi:Number; /* sin of z and cos of z */ + var temp:Number; + var con:Number; + var lon:Number , lat:Number; + /* Inverse equations + -----------------*/ + p.x -= this.x0; + p.y -= this.y0; + rh = Math.sqrt(p.x * p.x + p.y * p.y); + if (rh > this.a + .0000001) { + trace("orthoInvDataError"); + } + z = ProjConstants.asinz(rh / this.a); + + sinz=Math.sin(z); + cosi=Math.cos(z); + + lon = this.long0; + if (Math.abs(rh) <= ProjConstants.EPSLN) { + lat = this.lat0; + } + lat = ProjConstants.asinz(cosz * this.sin_p14 + (y * sinz * this.cos_p14)/rh); + con = Math.abs(lat0) - ProjConstants.HALF_PI; + if (Math.abs(con) <= ProjConstants.EPSLN) { + if (this.lat0 >= 0) { + lon = ProjConstants.adjust_lon(this.long0 + Math.atan2(p.x, -p.y)); + } else { + lon = ProjConstants.adjust_lon(this.long0 -Math.atan2(-p.x, p.y)); + } + } + con = cosz - this.sin_p14 * Math.sin(lat); + if ((Math.abs(con) >= ProjConstants.EPSLN) || (Math.abs(x) >= ProjConstants.EPSLN)) { + lon = ProjConstants.adjust_lon(this.long0 + Math.atan2((p.x * sinz * this.cos_p14), (con * rh))); + } + p.x=lon; + p.y=lat; + return p; + } + + + } +} \ No newline at end of file diff --git a/com/gradoservice/proj4as/proj/ProjParams.as b/com/gradoservice/proj4as/proj/ProjParams.as new file mode 100755 index 00000000..782f5a85 --- /dev/null +++ b/com/gradoservice/proj4as/proj/ProjParams.as @@ -0,0 +1,71 @@ +package com.gradoservice.proj4as.proj +{ + import com.gradoservice.proj4as.Datum; + + public class ProjParams + { + + public var title:Object; + + /** + * Property: projName + * The projection class for this projection, e.g. lcc (lambert conformal conic, + * or merc for mercator. These are exactly equicvalent to their Proj4 + * counterparts. + */ + public var projName:String; + /** + * Property: units + * The units of the projection. Values include 'm' and 'degrees' + /** + * Property: units + * The units of the projection. Values include 'm' and 'degrees' + */ + public var units:String; + /** + * Property: datum + * The datum specified for the projection + */ + public var datum:Datum; + public var datumCode:String; + public var datumName:String; + public var nagrids:String; + public var ellps:String; + public var a:Number; + public var b:Number; + public var a2:Number; + public var b2:Number; + public var e:Number; + public var es:Number; + public var ep2:Number; + public var rf:Number; + public var long0:Number; + public var lat0:Number; + public var lat1:Number; + public var lat2:Number; + public var lat_ts:Number; + public var alpha:Number; + public var longc:Number; + public var x0:Number; + public var y0:Number; + public var k0:Number; + public var k:Number; + public var R_A:Boolean = false; + public var zone:int; + public var utmSouth:Boolean = false; + public var to_meter:Number; + public var from_greenwich:Number; + public var datum_params:Array; + public var sphere:Boolean = false; + public var ellipseName:String; + + public var srsCode:String; + public var srsAuth:String; + public var srsProjNumber:String; + + public function ProjParams() + { + } + + } +} \ No newline at end of file diff --git a/com/gradoservice/proj4as/proj/ProjSinu.as b/com/gradoservice/proj4as/proj/ProjSinu.as new file mode 100755 index 00000000..c5e7d334 --- /dev/null +++ b/com/gradoservice/proj4as/proj/ProjSinu.as @@ -0,0 +1,95 @@ +/******************************************************************************* +NAME SINUSOIDAL + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the Sinusoidal projection. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + +PROGRAMMER DATE +---------- ---- +D. Steinwand, EROS May, 1991 + +This function was adapted from the Sinusoidal projection code (FORTRAN) in the +General Cartographic Transformation Package software which is available from +the U.S. Geological Survey National Mapping Division. + +ALGORITHM REFERENCES + +1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological + Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United + State Government Printing Office, Washington D.C., 1987. + +2. "Software Documentation for GCTP General Cartographic Transformation + Package", U.S. Geological Survey National Mapping Division, May 1982. +*******************************************************************************/ + +package com.gradoservice.proj4as.proj +{ + import com.gradoservice.proj4as.ProjPoint; + import com.gradoservice.proj4as.ProjConstants; + import com.gradoservice.proj4as.Datum; + + public class ProjSinu extends AbstractProjProjection + { + private var R:Number; + public function ProjSinu(data:ProjParams) + { + super(data); + } + + /* Initialize the Sinusoidal projection + ------------------------------------*/ + override public function init():void + { + /* Place parameters in static storage for common use + -------------------------------------------------*/ + this.R = 6370997.0; //Radius of earth + } + + /* Sinusoidal forward equations--mapping lat,long to x,y + -----------------------------------------------------*/ + override public function forward(p:ProjPoint):ProjPoint + { + var x:Number,y:Number,delta_lon:Number; + var lon:Number=p.x; + var lat:Number=p.y; + /* Forward equations + -----------------*/ + delta_lon = ProjConstants.adjust_lon(lon - this.long0); + x = this.R * delta_lon * Math.cos(lat) + this.x0; + y = this.R * lat + this.y0; + + p.x=x; + p.y=y; + return p; + } + + override public function inverse(p:ProjPoint):ProjPoint + { + var lat:Number,temp:Number,lon:Number; + + /* Inverse equations + -----------------*/ + p.x -= this.x0; + p.y -= this.y0; + lat = p.y / this.R; + if (Math.abs(lat) > ProjConstants.HALF_PI) { + trace("sinu:Inv:DataError"); + } + temp = Math.abs(lat) - ProjConstants.HALF_PI; + if (Math.abs(temp) > ProjConstants.EPSLN) { + temp = this.long0+ p.x / (this.R *Math.cos(lat)); + lon = ProjConstants.adjust_lon(temp); + } else { + lon = this.long0; + } + + p.x=lon; + p.y=lat; + return p; + } + + + } +} \ No newline at end of file diff --git a/com/gradoservice/proj4as/proj/ProjSoMerc.as b/com/gradoservice/proj4as/proj/ProjSoMerc.as new file mode 100755 index 00000000..ccaaa685 --- /dev/null +++ b/com/gradoservice/proj4as/proj/ProjSoMerc.as @@ -0,0 +1,135 @@ +/******************************************************************************* +NAME SWISS OBLIQUE MERCATOR + +PURPOSE: Swiss projection. +WARNING: X and Y are inverted (weird) in the swiss coordinate system. Not + here, since we want X to be horizontal and Y vertical. + +ALGORITHM REFERENCES +1. "Formules et constantes pour le Calcul pour la + projection cylindrique conforme Г  axe oblique et pour la transformation entre + des systГЁmes de rГ©fГ©rence". + http://www.swisstopo.admin.ch/internet/swisstopo/fr/home/topics/survey/sys/refsys/switzerland.parsysrelated1.31216.downloadList.77004.DownloadFile.tmp/swissprojectionfr.pdf + +*******************************************************************************/ + + +package com.gradoservice.proj4as.proj +{ + import com.gradoservice.proj4as.ProjPoint; + import com.gradoservice.proj4as.ProjConstants; + import com.gradoservice.proj4as.Datum; + + public class ProjSoMerc extends AbstractProjProjection + { + private var lambda0:Number; + private var R:Number; + private var b0:Number; + private var K:Number; + + + public function ProjSoMerc(data:ProjParams) + { + super(data); + } + + + override public function init():void + { + var phy0:Number = this.lat0; + this.lambda0 = this.long0; + var sinPhy0:Number = Math.sin(phy0); + var semiMajorAxis:Number = this.a; + var invF:Number = this.rf; + var flattening:Number = 1 / invF; + var e2:Number = 2 * flattening - Math.pow(flattening, 2); + var e:Number = this.e = Math.sqrt(e2); + this.R = semiMajorAxis * Math.sqrt(1 - e2) / (1 - e2 * Math.pow(sinPhy0, 2.0)); + this.alpha = Math.sqrt(1 + e2 / (1 - e2) * Math.pow(Math.cos(phy0), 4.0)); + this.b0 = Math.asin(sinPhy0 / this.alpha); + this.K = Math.log(Math.tan(Math.PI / 4.0 + this.b0 / 2.0)) + - this.alpha + * Math.log(Math.tan(Math.PI / 4.0 + phy0 / 2.0)) + + this.alpha + * e / 2 + * Math.log((1 + e * sinPhy0) + / (1 - e * sinPhy0)); + } + + + override public function forward(p:ProjPoint):ProjPoint + { + var Sa1:Number = Math.log(Math.tan(Math.PI / 4.0 - p.y / 2.0)); + var Sa2:Number = this.e / 2.0 + * Math.log((1 + this.e * Math.sin(p.y)) + / (1 - this.e * Math.sin(p.y))); + var S:Number = -this.alpha * (Sa1 + Sa2) + this.K; + + // spheric latitude + var b:Number = 2.0 * (Math.atan(Math.exp(S)) - Math.PI / 4.0); + + // spheric longitude + var I:Number = this.alpha * (p.x - this.lambda0); + + // psoeudo equatorial rotation + var rotI:Number = Math.atan(Math.sin(I) + / (Math.sin(this.b0) * Math.tan(b) + + Math.cos(this.b0) * Math.cos(I))); + + var rotB:Number = Math.asin(Math.cos(this.b0) * Math.sin(b) - + Math.sin(this.b0) * Math.cos(b) * Math.cos(I)); + + p.y = this.R / 2.0 + * Math.log((1 + Math.sin(rotB)) / (1 - Math.sin(rotB))) + + this.y0; + p.x = this.R * rotI + this.x0; + return p; + } + + override public function inverse(p:ProjPoint):ProjPoint + { + var Y:Number = p.x - this.x0; + var X:Number = p.y - this.y0; + + var rotI:Number = Y / this.R; + var rotB:Number = 2 * (Math.atan(Math.exp(X / this.R)) - Math.PI / 4.0); + + var b:Number = Math.asin(Math.cos(this.b0) * Math.sin(rotB) + + Math.sin(this.b0) * Math.cos(rotB) * Math.cos(rotI)); + var I:Number = Math.atan(Math.sin(rotI) + / (Math.cos(this.b0) * Math.cos(rotI) - Math.sin(this.b0) + * Math.tan(rotB))); + + var lambda:Number = this.lambda0 + I / this.alpha; + + var S:Number = 0.0; + var phy:Number = b; + var prevPhy:Number = -1000.0; + var iteration:Number = 0; + while (Math.abs(phy - prevPhy) > 0.0000001) + { + if (++iteration > 20) + { + trace("omercFwdInfinity"); + return null; + } + //S = Math.log(Math.tan(Math.PI / 4.0 + phy / 2.0)); + S = 1.0 + / this.alpha + * (Math.log(Math.tan(Math.PI / 4.0 + b / 2.0)) - this.K) + + this.e + * Math.log(Math.tan(Math.PI / 4.0 + + Math.asin(this.e * Math.sin(phy)) + / 2.0)); + prevPhy = phy; + phy = 2.0 * Math.atan(Math.exp(S)) - Math.PI / 2.0; + } + + p.x = lambda; + p.y = phy; + return p; + } + + + } +} \ No newline at end of file diff --git a/com/gradoservice/proj4as/proj/ProjStere.as b/com/gradoservice/proj4as/proj/ProjStere.as new file mode 100755 index 00000000..e03c85d1 --- /dev/null +++ b/com/gradoservice/proj4as/proj/ProjStere.as @@ -0,0 +1,278 @@ +package com.gradoservice.proj4as.proj +{ + import com.gradoservice.proj4as.ProjPoint; + import com.gradoservice.proj4as.ProjConstants; + import com.gradoservice.proj4as.Datum; + + public class ProjStere extends AbstractProjProjection + { + private const TOL:Number=1.e-8; + private const NITER:Number=8; + private const CONV:Number=1.e-10; + private const S_POLE:Number=0; + private const N_POLE:Number=1; + private const OBLIQ:Number=2; + private const EQUIT:Number=3; + + private var akm1:Number; + private var cosph0:Number; + private var cosX1:Number; + private var sinX1:Number; + private var phi0:Number; + private var phits:Number; + private var sinph0:Number; + + public function ProjStere(data:ProjParams) + { + super(data); + } + + private function ssfn_(phit:Number, sinphi:Number, eccen:Number):Number + { + sinphi *= eccen; + return (Math.tan (.5 * (ProjConstants.HALF_PI + phit)) * Math.pow((1. - sinphi) / (1. + sinphi), .5 * eccen)); + } + + + override public function init():void + { + this.phits = this.lat_ts ? this.lat_ts : ProjConstants.HALF_PI; + var t:Number = Math.abs(this.lat0); + if ((Math.abs(t) - ProjConstants.HALF_PI) < ProjConstants.EPSLN) { + this.mode = this.lat0 < 0. ? this.S_POLE : this.N_POLE; + } else { + this.mode = t > ProjConstants.EPSLN ? this.OBLIQ : this.EQUIT; + } + this.phits = Math.abs(this.phits); + if (this.es) { + var X:Number; + + switch (this.mode) { + case this.N_POLE: + case this.S_POLE: + if (Math.abs(this.phits - ProjConstants.HALF_PI) < ProjConstants.EPSLN) { + this.akm1 = 2. * this.k0 / Math.sqrt(Math.pow(1+this.e,1+this.e)*Math.pow(1-this.e,1-this.e)); + } else { + t = Math.sin(this.phits); + this.akm1 = Math.cos(this.phits) / ProjConstants.tsfnz(this.e, this.phits, t); + t *= this.e; + this.akm1 /= Math.sqrt(1. - t * t); + } + break; + case this.EQUIT: + this.akm1 = 2. * this.k0; + break; + case this.OBLIQ: + t = Math.sin(this.lat0); + X = 2. * Math.atan(this.ssfn_(this.lat0, t, this.e)) - ProjConstants.HALF_PI; + t *= this.e; + this.akm1 = 2. * this.k0 * Math.cos(this.lat0) / Math.sqrt(1. - t * t); + this.sinX1 = Math.sin(X); + this.cosX1 = Math.cos(X); + break; + } + } else { + switch (this.mode) { + case this.OBLIQ: + this.sinph0 = Math.sin(this.lat0); + this.cosph0 = Math.cos(this.lat0); + case this.EQUIT: + this.akm1 = 2. * this.k0; + break; + case this.S_POLE: + case this.N_POLE: + this.akm1 = Math.abs(this.phits - ProjConstants.HALF_PI) >= ProjConstants.EPSLN ? + Math.cos(this.phits) / Math.tan(ProjConstants.FORTPI - .5 * this.phits) : + 2. * this.k0 ; + break; + } + } + } + + // Stereographic forward equations--mapping lat,long to x,y + override public function forward(p:ProjPoint):ProjPoint + { + var lon:Number = p.x; + var lat:Number = p.y; + var x:Number, y:Number, A:Number, X:Number; + var sinX:Number,cosX:Number; + + if (this.sphere) { + var sinphi:Number, cosphi:Number, coslam:Number, sinlam:Number; + + sinphi = Math.sin(lat); + cosphi = Math.cos(lat); + coslam = Math.cos(lon); + sinlam = Math.sin(lon); + switch (this.mode) { + case this.EQUIT: + y = 1. + cosphi * coslam; + if (y <= ProjConstants.EPSLN) { + trace('ERROR'); + //F_ERROR; + } + y = this.akm1 / y; + x = y * cosphi * sinlam; + y *= sinphi; + break; + case this.OBLIQ: + y = 1. + this.sinph0 * sinphi + this.cosph0 * cosphi * coslam; + if (y <= ProjConstants.EPSLN) { + trace('ERROR'); + //F_ERROR; + } + y = this.akm1 / y; + x = y * cosphi * sinlam; + y *= this.cosph0 * sinphi - this.sinph0 * cosphi * coslam; + break; + case this.N_POLE: + coslam = -coslam; + lat = -lat; + //Note no break here so it conitnues through S_POLE + case this.S_POLE: + if (Math.abs(lat - ProjConstants.HALF_PI) < this.TOL) { + trace('ERROR'); + //F_ERROR; + } + y = this.akm1 * Math.tan(ProjConstants.FORTPI + .5 * lat) + x = sinlam * y; + y *= coslam; + break; + } + } else { + coslam = Math.cos(lon); + sinlam = Math.sin(lon); + sinphi = Math.sin(lat); + if (this.mode == this.OBLIQ || this.mode == this.EQUIT) { + X = 2. * Math.atan(this.ssfn_(lat, sinphi, this.e)); + sinX = Math.sin(X - ProjConstants.HALF_PI); + cosX = Math.cos(X); + } + switch (this.mode) { + case this.OBLIQ: + A = this.akm1 / (this.cosX1 * (1. + this.sinX1 * sinX + this.cosX1 * cosX * coslam)); + y = A * (this.cosX1 * sinX - this.sinX1 * cosX * coslam); + x = A * cosX; + break; + case this.EQUIT: + A = 2. * this.akm1 / (1. + cosX * coslam); + y = A * sinX; + x = A * cosX; + break; + case this.S_POLE: + lat = -lat; + coslam = - coslam; + sinphi = -sinphi; + case this.N_POLE: + x = this.akm1 * ProjConstants.tsfnz(this.e, lat, sinphi); + y = - x * coslam; + break; + } + x = x * sinlam; + } + p.x = x*this.a + this.x0; + p.y = y*this.a + this.y0; + return p; + } + + + //* Stereographic inverse equations--mapping x,y to lat/long + override public function inverse(p:ProjPoint):ProjPoint + { + var x:Number = (p.x - this.x0)/this.a; /* descale and de-offset */ + var y:Number = (p.y - this.y0)/this.a; + var lon:Number, lat:Number; + + var cosphi:Number, sinphi:Number, tp:Number=0.0, phi_l:Number=0.0, rho:Number, halfe:Number=0.0, pi2:Number=0.0; + var i:int; + + if (this.sphere) { + var c:Number, rh:Number, sinc:Number, cosc:Number; + + rh = Math.sqrt(x*x + y*y); + c = 2. * Math.atan(rh / this.akm1); + sinc = Math.sin(c); + cosc = Math.cos(c); + lon = 0.; + switch (this.mode) { + case this.EQUIT: + if (Math.abs(rh) <= ProjConstants.EPSLN) { + lat = 0.; + } else { + lat = Math.asin(y * sinc / rh); + } + if (cosc != 0. || x != 0.) lon = Math.atan2(x * sinc, cosc * rh); + break; + case this.OBLIQ: + if (Math.abs(rh) <= ProjConstants.EPSLN) { + lat = this.phi0; + } else { + lat = Math.asin(cosc * sinph0 + y * sinc * cosph0 / rh); + } + c = cosc - sinph0 * Math.sin(lat); + if (c != 0. || x != 0.) { + lon = Math.atan2(x * sinc * cosph0, c * rh); + } + break; + case this.N_POLE: + y = -y; + case this.S_POLE: + if (Math.abs(rh) <= ProjConstants.EPSLN) { + lat = this.phi0; + } else { + lat = Math.asin(this.mode == this.S_POLE ? -cosc : cosc); + } + lon = (x == 0. && y == 0.) ? 0. : Math.atan2(x, y); + break; + } + } else { + rho = Math.sqrt(x*x + y*y); + switch (this.mode) { + case this.OBLIQ: + case this.EQUIT: + tp = 2. * Math.atan2(rho * this.cosX1 , this.akm1); + cosphi = Math.cos(tp); + sinphi = Math.sin(tp); + if( rho == 0.0 ) { + phi_l = Math.asin(cosphi * this.sinX1); + } else { + phi_l = Math.asin(cosphi * this.sinX1 + (y * sinphi * this.cosX1 / rho)); + } + + tp = Math.tan(.5 * (ProjConstants.HALF_PI + phi_l)); + x *= sinphi; + y = rho * this.cosX1 * cosphi - y * this.sinX1* sinphi; + pi2 = ProjConstants.HALF_PI; + halfe = .5 * this.e; + break; + case this.N_POLE: + y = -y; + case this.S_POLE: + tp = - rho / this.akm1 + phi_l = ProjConstants.HALF_PI - 2. * Math.atan(tp); + pi2 = -ProjConstants.HALF_PI; + halfe = -.5 * this.e; + break; + } + for (i = this.NITER; i--; phi_l = lat) + { //check this + sinphi = this.e * Math.sin(phi_l); + lat = 2. * Math.atan(tp * Math.pow((1.+sinphi)/(1.-sinphi), halfe)) - pi2; + if (Math.abs(phi_l - lat) < this.CONV) + { + if (this.mode == this.S_POLE) lat = -lat; + lon = (x == 0. && y == 0.) ? 0. : Math.atan2(x, y); + p.x = lon; + p.y = lat + return p; + } + } + } + return null; + } + + + + + } +} \ No newline at end of file diff --git a/com/gradoservice/proj4as/proj/ProjSterea.as b/com/gradoservice/proj4as/proj/ProjSterea.as new file mode 100755 index 00000000..49b34599 --- /dev/null +++ b/com/gradoservice/proj4as/proj/ProjSterea.as @@ -0,0 +1,74 @@ +package com.gradoservice.proj4as.proj +{ + import com.gradoservice.proj4as.ProjPoint; + import com.gradoservice.proj4as.ProjConstants; + import com.gradoservice.proj4as.Datum; + + public class ProjSterea extends ProjGauss + { + + protected var sinc0:Number; + protected var cosc0:Number; + protected var R2:Number; + + public function ProjSterea(data:ProjParams) + { + super(data); + } + + override public function init():void + { + super.init(); + if (!this.rc) { + trace("sterea:init:E_ERROR_0"); + return; + } + this.sinc0 = Math.sin(this.phic0); + this.cosc0 = Math.cos(this.phic0); + this.R2 = 2.0 * this.rc; + if (!this.title) this.title = "Oblique Stereographic Alternative"; + } + + override public function forward(p:ProjPoint):ProjPoint + { + p.x = ProjConstants.adjust_lon(p.x-this.long0); /* adjust del longitude */ + super.forward(p); + var sinc:Number = Math.sin(p.y); + var cosc:Number = Math.cos(p.y); + var cosl:Number = Math.cos(p.x); + k = this.k0 * this.R2 / (1.0 + this.sinc0 * sinc + this.cosc0 * cosc * cosl); + p.x = k * cosc * Math.sin(p.x); + p.y = k * (this.cosc0 * sinc - this.sinc0 * cosc * cosl); + p.x = this.a * p.x + this.x0; + p.y = this.a * p.y + this.y0; + return p; + } + + override public function inverse(p:ProjPoint):ProjPoint + { + var lon:Number,lat:Number,rho:Number,sinc:Number,cosc:Number; + p.x = (p.x - this.x0) / this.a; /* descale and de-offset */ + p.y = (p.y - this.y0) / this.a; + + p.x /= this.k0; + p.y /= this.k0; + if ( (rho = Math.sqrt(p.x*p.x + p.y*p.y)) ) { + c = 2.0 * Math.atan2(rho, this.R2); + sinc = Math.sin(c); + cosc = Math.cos(c); + lat = Math.asin(cosc * this.sinc0 + p.y * sinc * this.cosc0 / rho); + lon = Math.atan2(p.x * sinc, rho * this.cosc0 * cosc - p.y * this.sinc0 * sinc); + } else { + lat = this.phic0; + lon = 0.; + } + + p.x = lon; + p.y = lat; + super.inverse(p); + p.x = ProjConstants.adjust_lon(p.x + this.long0); /* adjust longitude to CM */ + return p; + } + + } +} \ No newline at end of file diff --git a/com/gradoservice/proj4as/proj/ProjTmerc.as b/com/gradoservice/proj4as/proj/ProjTmerc.as new file mode 100755 index 00000000..b6d083ac --- /dev/null +++ b/com/gradoservice/proj4as/proj/ProjTmerc.as @@ -0,0 +1,154 @@ +/******************************************************************************* +NAME TRANSVERSE MERCATOR + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the Transverse Mercator projection. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + +ALGORITHM REFERENCES + +1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological + Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United + State Government Printing Office, Washington D.C., 1987. + +2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections", + U.S. Geological Survey Professional Paper 1453 , United State Government + Printing Office, Washington D.C., 1989. +*******************************************************************************/ + +package com.gradoservice.proj4as.proj +{ + import com.gradoservice.proj4as.ProjPoint; + import com.gradoservice.proj4as.ProjConstants; + import com.gradoservice.proj4as.Datum; + + public class ProjTmerc extends AbstractProjProjection + { + public function ProjTmerc(data:ProjParams) + { + super(data); + } + + override public function init():void + { + this.e0 = ProjConstants.e0fn(this.es); + this.e1 = ProjConstants.e1fn(this.es); + this.e2 = ProjConstants.e2fn(this.es); + this.e3 = ProjConstants.e3fn(this.es); + this.ml0 = this.a * ProjConstants.mlfn(this.e0, this.e1, this.e2, this.e3, this.lat0); + } + + /** + Transverse Mercator Forward - long/lat to x/y + long/lat in radians + */ + override public function forward(p:ProjPoint):ProjPoint + { + var lon:Number = p.x; + var lat:Number = p.y; + + var delta_lon:Number = ProjConstants.adjust_lon(lon - this.long0); // Delta longitude + var con:Number; // cone constant + var x:Number, y:Number; + var sin_phi:Number=Math.sin(lat); + var cos_phi:Number=Math.cos(lat); + + if (this.sphere) { /* spherical form */ + var b:Number = cos_phi * Math.sin(delta_lon); + if ((Math.abs(Math.abs(b) - 1.0)) < .0000000001) { + trace("tmerc:forward: Point projects into infinity"); + return null; + } else { + x = .5 * this.a * this.k0 * Math.log((1.0 + b)/(1.0 - b)); + con = Math.acos(cos_phi * Math.cos(delta_lon)/Math.sqrt(1.0 - b*b)); + if (lat < 0) con = - con; + y = this.a * this.k0 * (con - this.lat0); + } + } else { + var al:Number = cos_phi * delta_lon; + var als:Number = Math.pow(al,2); + var c:Number = this.ep2 * Math.pow(cos_phi,2); + var tq:Number = Math.tan(lat); + var t:Number = Math.pow(tq,2); + con = 1.0 - this.es * Math.pow(sin_phi,2); + var n:Number = this.a / Math.sqrt(con); + var ml:Number = this.a * ProjConstants.mlfn(this.e0, this.e1, this.e2, this.e3, lat); + + x = this.k0 * n * al * (1.0 + als / 6.0 * (1.0 - t + c + als / 20.0 * (5.0 - 18.0 * t + Math.pow(t,2) + 72.0 * c - 58.0 * this.ep2))) + this.x0; + y = this.k0 * (ml - this.ml0 + n * tq * (als * (0.5 + als / 24.0 * (5.0 - t + 9.0 * c + 4.0 * Math.pow(c,2) + als / 30.0 * (61.0 - 58.0 * t + Math.pow(t,2) + 600.0 * c - 330.0 * this.ep2))))) + this.y0; + + } + p.x = x; p.y = y; + return p; + } // tmercFwd() + + /** + Transverse Mercator Inverse - x/y to long/lat + */ + override public function inverse(p:ProjPoint):ProjPoint + { + var con:Number, phi:Number; /* temporary angles */ + var delta_phi:Number; /* difference between longitudes */ + var i:Number; + var max_iter:Number = 6; /* maximun number of iterations */ + var lat:Number, lon:Number; + + if (this.sphere) { /* spherical form */ + var f:Number = Math.exp(p.x/(this.a * this.k0)); + var g:Number = .5 * (f - 1/f); + var temp:Number = this.lat0 + p.y/(this.a * this.k0); + var h:Number = Math.cos(temp); + con = Math.sqrt((1.0 - h * h)/(1.0 + g * g)); + lat = ProjConstants.asinz(con); + if (temp < 0) + lat = -lat; + if ((g == 0) && (h == 0)) { + lon = this.long0; + } else { + lon = ProjConstants.adjust_lon(Math.atan2(g,h) + this.long0); + } + } else { // ellipsoidal form + var x:Number= p.x - this.x0; + var y:Number = p.y - this.y0; + + con = (this.ml0 + y / this.k0) / this.a; + phi = con; + for (i=0;;i++) { + delta_phi=((con + this.e1 * Math.sin(2.0*phi) - this.e2 * Math.sin(4.0*phi) + this.e3 * Math.sin(6.0*phi)) / this.e0) - phi; + phi += delta_phi; + if (Math.abs(delta_phi) <= ProjConstants.EPSLN) break; + if (i >= max_iter) { + trace("tmerc:inverse: Latitude failed to converge"); + return null; + } + } // for() + if (Math.abs(phi) < ProjConstants.HALF_PI) { + // sincos(phi, &sin_phi, &cos_phi); + var sin_phi:Number=Math.sin(phi); + var cos_phi:Number=Math.cos(phi); + var tan_phi:Number = Math.tan(phi); + var c:Number = this.ep2 * Math.pow(cos_phi,2); + var cs:Number = Math.pow(c,2); + var t:Number = Math.pow(tan_phi,2); + var ts :Number= Math.pow(t,2); + con = 1.0 - this.es * Math.pow(sin_phi,2); + var n:Number = this.a / Math.sqrt(con); + var r:Number = n * (1.0 - this.es) / con; + var d:Number = x / (n * this.k0); + var ds:Number = Math.pow(d,2); + lat = phi - (n * tan_phi * ds / r) * (0.5 - ds / 24.0 * (5.0 + 3.0 * t + 10.0 * c - 4.0 * cs - 9.0 * this.ep2 - ds / 30.0 * (61.0 + 90.0 * t + 298.0 * c + 45.0 * ts - 252.0 * this.ep2 - 3.0 * cs))); + lon = ProjConstants.adjust_lon(this.long0 + (d * (1.0 - ds / 6.0 * (1.0 + 2.0 * t + c - ds / 20.0 * (5.0 - 2.0 * c + 28.0 * t - 3.0 * cs + 8.0 * this.ep2 + 24.0 * ts))) / cos_phi)); + } else { + lat = ProjConstants.HALF_PI * ProjConstants.sign(y); + lon = this.long0; + } + } + p.x = lon; + p.y = lat; + return p; + } // tmercInv() + + + } +} \ No newline at end of file diff --git a/com/gradoservice/proj4as/proj/ProjUtm.as b/com/gradoservice/proj4as/proj/ProjUtm.as new file mode 100755 index 00000000..5e07f733 --- /dev/null +++ b/com/gradoservice/proj4as/proj/ProjUtm.as @@ -0,0 +1,50 @@ +/******************************************************************************* +NAME TRANSVERSE MERCATOR + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the Transverse Mercator projection. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + +ALGORITHM REFERENCES + +1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological + Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United + State Government Printing Office, Washington D.C., 1987. + +2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections", + U.S. Geological Survey Professional Paper 1453 , United State Government + Printing Office, Washington D.C., 1989. +*******************************************************************************/ + + +package com.gradoservice.proj4as.proj +{ + import com.gradoservice.proj4as.ProjConstants; + import com.gradoservice.proj4as.Datum; + + public class ProjUtm extends ProjTmerc + { + public function ProjUtm(data:ProjParams) + { + super(data); + } + + override public function init():void + { + if (!this.zone) { + trace("utm:init: zone must be specified for UTM"); + return; + } + this.lat0 = 0.0; + this.long0 = ((6 * Math.abs(this.zone)) - 183) * ProjConstants.D2R; + this.x0 = 500000.0; + this.y0 = this.utmSouth ? 10000000.0 : 0.0; + this.k0 = 0.9996; + + super.init(); + } + + + } +} \ No newline at end of file diff --git a/com/gradoservice/proj4as/proj/ProjVandg.as b/com/gradoservice/proj4as/proj/ProjVandg.as new file mode 100755 index 00000000..0a0cdbd4 --- /dev/null +++ b/com/gradoservice/proj4as/proj/ProjVandg.as @@ -0,0 +1,154 @@ +/******************************************************************************* +NAME VAN DER GRINTEN + +PURPOSE: Transforms input Easting and Northing to longitude and + latitude for the Van der Grinten projection. The + Easting and Northing must be in meters. The longitude + and latitude values will be returned in radians. + +PROGRAMMER DATE +---------- ---- +T. Mittan March, 1993 + +This function was adapted from the Van Der Grinten projection code +(FORTRAN) in the General Cartographic Transformation Package software +which is available from the U.S. Geological Survey National Mapping Division. + +ALGORITHM REFERENCES + +1. "New Equal-Area Map Projections for Noncircular Regions", John P. Snyder, + The American Cartographer, Vol 15, No. 4, October 1988, pp. 341-355. + +2. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological + Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United + State Government Printing Office, Washington D.C., 1987. + +3. "Software Documentation for GCTP General Cartographic Transformation + Package", U.S. Geological Survey National Mapping Division, May 1982. +*******************************************************************************/ + +package com.gradoservice.proj4as.proj +{ + import com.gradoservice.proj4as.ProjPoint; + import com.gradoservice.proj4as.ProjConstants; + import com.gradoservice.proj4as.Datum; + + public class ProjVandg extends AbstractProjProjection + { + + protected var R:Number; + + public function ProjVandg(data:ProjParams) + { + super(data); + } + + override public function init():void + { + this.R = 6370997.0; //Radius of earth + } + + override public function forward(p:ProjPoint):ProjPoint + { + var lon:Number=p.x; + var lat:Number=p.y; + + /* Forward equations + -----------------*/ + var dlon:Number = ProjConstants.adjust_lon(lon - this.long0); + var x:Number,y:Number; + + if (Math.abs(lat) <= ProjConstants.EPSLN) { + x = this.x0 + this.R * dlon; + y = this.y0; + } + var theta:Number = ProjConstants.asinz(2.0 * Math.abs(lat / ProjConstants.PI)); + if ((Math.abs(dlon) <= ProjConstants.EPSLN) || (Math.abs(Math.abs(lat) - ProjConstants.HALF_PI) <= ProjConstants.EPSLN)) { + x = this.x0; + if (lat >= 0) { + y = this.y0 + ProjConstants.PI * this.R * Math.tan(.5 * theta); + } else { + y = this.y0 + ProjConstants.PI * this.R * - Math.tan(.5 * theta); + } + // return(OK); + } + var al:Number = .5 * Math.abs((ProjConstants.PI / dlon) - (dlon / ProjConstants.PI)); + var asq:Number = al * al; + var sinth:Number = Math.sin(theta); + var costh:Number = Math.cos(theta); + + var g :Number= costh / (sinth + costh - 1.0); + var gsq:Number = g * g; + var m:Number = g * (2.0 / sinth - 1.0); + var msq:Number = m * m; + var con:Number = ProjConstants.PI * this.R * (al * (g - msq) + Math.sqrt(asq * (g - msq) * (g - msq) - (msq + asq) * (gsq - msq))) / (msq + asq); + if (dlon < 0) { + con = -con; + } + x = this.x0 + con; + con = Math.abs(con / (ProjConstants.PI * this.R)); + if (lat >= 0) { + y = this.y0 + ProjConstants.PI * this.R * Math.sqrt(1.0 - con * con - 2.0 * al * con); + } else { + y = this.y0 - ProjConstants.PI * this.R * Math.sqrt(1.0 - con * con - 2.0 * al * con); + } + p.x = x; + p.y = y; + return p; + } + +/* Van Der Grinten inverse equations--mapping x,y to lat/long + ---------------------------------------------------------*/ + override public function inverse(p:ProjPoint):ProjPoint + { + var dlon:Number,lat:Number,lon:Number; + var xx:Number,yy:Number,xys:Number,c1:Number,c2:Number,c3:Number; + var al:Number,asq:Number; + var a1:Number; + var m1:Number; + var con:Number; + var th1:Number; + var d:Number; + + /* inverse equations + -----------------*/ + p.x -= this.x0; + p.y -= this.y0; + con = ProjConstants.PI * this.R; + xx = p.x / con; + yy =p.y / con; + xys = xx * xx + yy * yy; + c1 = -Math.abs(yy) * (1.0 + xys); + c2 = c1 - 2.0 * yy * yy + xx * xx; + c3 = -2.0 * c1 + 1.0 + 2.0 * yy * yy + xys * xys; + d = yy * yy / c3 + (2.0 * c2 * c2 * c2 / c3 / c3 / c3 - 9.0 * c1 * c2 / c3 /c3) / 27.0; + a1 = (c1 - c2 * c2 / 3.0 / c3) / c3; + m1 = 2.0 * Math.sqrt( -a1 / 3.0); + con = ((3.0 * d) / a1) / m1; + if (Math.abs(con) > 1.0) { + if (con >= 0.0) { + con = 1.0; + } else { + con = -1.0; + } + } + th1 = Math.acos(con) / 3.0; + if (p.y >= 0) { + lat = (-m1 *Math.cos(th1 + ProjConstants.PI / 3.0) - c2 / 3.0 / c3) * ProjConstants.PI; + } else { + lat = -(-m1 * Math.cos(th1 + Math.PI / 3.0) - c2 / 3.0 / c3) * ProjConstants.PI; + } + + if (Math.abs(xx) < ProjConstants.EPSLN) { + lon = this.long0; + } + lon = ProjConstants.adjust_lon(this.long0 + ProjConstants.PI * (xys - 1.0 + Math.sqrt(1.0 + 2.0 * (xx * xx - yy * yy) + xys * xys)) / 2.0 / xx); + + p.x=lon; + p.y=lat; + return p; + } + + + } +} \ No newline at end of file diff --git a/net/systemeD/potlatch2/VectorSourceDialog.mxml b/net/systemeD/potlatch2/VectorSourceDialog.mxml index 754d19c4..f2ee64c5 100644 --- a/net/systemeD/potlatch2/VectorSourceDialog.mxml +++ b/net/systemeD/potlatch2/VectorSourceDialog.mxml @@ -33,7 +33,7 @@ - + @@ -44,12 +44,22 @@ + + + + + + + + + + - + @@ -104,9 +114,7 @@ private function get vectorLayers():Array { var v:Array=[]; for each (var a:MapPaint in map.getLayers() ) { - if (a.isBackground) { - v.push( { name:a.connection.name, visible:a.visible, url:a.connection.apiBase, style:a.style } ); - } + v.push( { name:a.connection.name, visible:a.visible, url:a.connection.apiBase, style:a.style, isBackground:a.isBackground } ); } return v; } @@ -138,7 +146,7 @@ PopUpManager.removePopUp(this); } - private function loadFiles(url:String,type:String,simplify:Boolean):void { + private function loadFiles(url:String,type:String,simplify:Boolean,projection:String=""):void { var names:Array=url.split('/'); var name:String=names[names.length-1]; var stylesheet:String="stylesheets/potlatch.css"; if (type=='gpx') { stylesheet="stylesheets/gpx.css"; } @@ -162,10 +170,16 @@ } else if (type=='osm') { var osm:OsmImporter=new OsmImporter(connection, map, [url], filesLoaded, simplify); } else { + /* FIXME: + we're currently hardcoding the projection values. We could populate this directly from + proj4as, or better still, parse the WKT in the .PRJ file: + http://trac.osgeo.org/proj4js/ticket/47 + http://trac.osgeo.org/proj4js/changeset/1873 + */ var re:RegExp=/.shp$/i; url=url.replace(re,''); var shp:ShpImporter=new ShpImporter(connection, map, - [url+".shp",url+".shx",url+".dbf"], filesLoaded, simplify); + [url+".shp",url+".shx",url+".dbf"], filesLoaded, simplify, projection); } } diff --git a/net/systemeD/potlatch2/utils/ShpImporter.as b/net/systemeD/potlatch2/utils/ShpImporter.as index 9f5cd9ce..70ded7e2 100644 --- a/net/systemeD/potlatch2/utils/ShpImporter.as +++ b/net/systemeD/potlatch2/utils/ShpImporter.as @@ -2,6 +2,7 @@ package net.systemeD.potlatch2.utils { import org.vanrijkom.shp.*; import org.vanrijkom.dbf.*; + import com.gradoservice.proj4as.*; import net.systemeD.halcyon.Map; import net.systemeD.halcyon.connection.Connection; import net.systemeD.halcyon.connection.Node; @@ -10,7 +11,10 @@ package net.systemeD.potlatch2.utils { public class ShpImporter extends Importer { - public function ShpImporter(connection:Connection, map:Map, filenames:Array, callback:Function=null, simplify:Boolean=false) { + private var projection:String; + + public function ShpImporter(connection:Connection, map:Map, filenames:Array, callback:Function=null, simplify:Boolean=false, projection:String="") { + if (projection!='') this.projection=projection; super(connection,map,filenames,callback,simplify); } @@ -19,6 +23,14 @@ package net.systemeD.potlatch2.utils { var shp:ShpHeader=new ShpHeader(files[0]); var dbf:DbfHeader=new DbfHeader(files[2]); + if (projection) { + var proj:Proj4as=new Proj4as(); + var toProj:ProjProjection=new ProjProjection('EPSG:4326'); + var fromProj:ProjProjection=new ProjProjection('EPSG:27700'); + } + + var nodemap:Object={}; + if (shp.shapeType==ShpType.SHAPE_POLYGON || shp.shapeType==ShpType.SHAPE_POLYLINE) { // Loop through all polylines in the shape @@ -30,14 +42,28 @@ package net.systemeD.potlatch2.utils { // var xsID:String = dr.values[idFieldName]; // Do each ring in turn, then each point in the ring + var way:Way; + var node:Node; + var x:Number, y:Number; for (var j:int=0; j < polyArray[i].shape.rings.length; j++) { - var way:Way; var nodestring:Array=[]; var points:Array = polyArray[i].shape.rings[j]; if (points!=null) { for (var k:int=0; k < points.length; k++) { var p:ShpPoint = ShpPoint(points[k]); - nodestring.push(connection.createNode({}, p.y, p.x, push)); + + if (projection) { + var r:ProjPoint = new ProjPoint(p.x,p.y,0); + r=proj.transform(fromProj,toProj,r); + x=r.x; y=r.y; + } else { + x=p.x; x=p.y; + } + + var key:String=x+","+y; + if (nodemap[key]) { node=nodemap[key]; } + else { node=connection.createNode({}, y, x, push); nodemap[key]=node; } + nodestring.push(node); } } if (nodestring.length>0) { From 0341638264bab9f402593afb81407f5fb27e858c Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Fri, 10 Jun 2011 10:09:04 +0100 Subject: [PATCH 52/89] Handle 'tags' in shapefiles, and don't create dupes on pull-through. Also, we really need TagTransform for this. ;) --- net/systemeD/halcyon/MapPaint.as | 14 ++++++++------ net/systemeD/halcyon/connection/Connection.as | 7 +++++++ net/systemeD/halcyon/connection/Entity.as | 10 ++++++++++ net/systemeD/potlatch2/utils/ShpImporter.as | 17 ++++++++++++----- 4 files changed, 37 insertions(+), 11 deletions(-) diff --git a/net/systemeD/halcyon/MapPaint.as b/net/systemeD/halcyon/MapPaint.as index 22a16dcc..31b4808e 100644 --- a/net/systemeD/halcyon/MapPaint.as +++ b/net/systemeD/halcyon/MapPaint.as @@ -462,16 +462,18 @@ package net.systemeD.halcyon { var action:CompositeUndoableAction = new CompositeUndoableAction("pull through"); if (entity is Way) { // copy way through to main layer - // ** shouldn't do this if the nodes are already in the main layer - // (or maybe we should just match on lat/long to avoid ways in background having nodes in foreground) var oldWay:Way=Way(entity); var nodemap:Object={}; var nodes:Array=[]; + var oldNode:Node, newNode:Node; for (var i:uint=0; i0) { - way=connection.createWay({}, nodestring, push); + way=connection.createWay(tags, nodestring, push); if (simplify) { Simplify.simplify(way, map, false); } } } From bc6a99cc44f856b77b0f19747bcc7b90ff7dde36 Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Fri, 10 Jun 2011 15:51:45 +0100 Subject: [PATCH 53/89] Beginnings of status API support, including WTFE and dedicated UI for selecting it --- net/systemeD/halcyon/EntityUI.as | 7 ++ net/systemeD/halcyon/NodeUI.as | 1 + net/systemeD/halcyon/WayUI.as | 1 + net/systemeD/halcyon/connection/Connection.as | 12 ++- net/systemeD/halcyon/connection/Entity.as | 12 ++- .../halcyon/connection/StatusFetcher.as | 85 +++++++++++++++++++ .../halcyon/connection/XMLBaseConnection.as | 22 +++-- .../potlatch2/options/OptionsDialog.mxml | 19 +++++ resources/stylesheets/potlatch.css | 8 ++ 9 files changed, 158 insertions(+), 9 deletions(-) create mode 100644 net/systemeD/halcyon/connection/StatusFetcher.as diff --git a/net/systemeD/halcyon/EntityUI.as b/net/systemeD/halcyon/EntityUI.as index d5fb8f4c..4a2c62d1 100644 --- a/net/systemeD/halcyon/EntityUI.as +++ b/net/systemeD/halcyon/EntityUI.as @@ -55,6 +55,7 @@ package net.systemeD.halcyon { this.entity=entity; this.paint=paint; entity.addEventListener(Connection.TAG_CHANGED, tagChanged, false, 0, true); + entity.addEventListener(Connection.STATUS_CHANGED, statusChanged, false, 0, true); entity.addEventListener(Connection.ADDED_TO_RELATION, relationAdded, false, 0, true); entity.addEventListener(Connection.REMOVED_FROM_RELATION, relationRemoved, false, 0, true); entity.addEventListener(Connection.SUSPEND_REDRAW, suspendRedraw, false, 0, true); @@ -71,6 +72,7 @@ package net.systemeD.halcyon { /** Remove the default event listeners. */ protected function removeGenericEventListeners():void { entity.removeEventListener(Connection.TAG_CHANGED, tagChanged); + entity.removeEventListener(Connection.STATUS_CHANGED, statusChanged); entity.removeEventListener(Connection.ADDED_TO_RELATION, relationAdded); entity.removeEventListener(Connection.REMOVED_FROM_RELATION, relationRemoved); entity.removeEventListener(Connection.SUSPEND_REDRAW, suspendRedraw); @@ -123,6 +125,11 @@ package net.systemeD.halcyon { redraw(); } + protected function statusChanged(event:EntityEvent):void { + invalidateStyleList(); + redraw(); + } + protected function mouseEvent(event:MouseEvent):void { paint.map.entityMouseEvent(event, entity); } diff --git a/net/systemeD/halcyon/NodeUI.as b/net/systemeD/halcyon/NodeUI.as index 204c14f8..4f8431f2 100644 --- a/net/systemeD/halcyon/NodeUI.as +++ b/net/systemeD/halcyon/NodeUI.as @@ -74,6 +74,7 @@ package net.systemeD.halcyon { setStateClass('hasTags', entity.hasInterestingTags()); setStateClass('dupe', Node(entity).isDupe()); tags=applyStateClasses(tags); + if (entity.status) { tags['_status']=entity.status; } if (!styleList || !styleList.isValidAt(paint.map.scale)) { styleList=paint.ruleset.getStyles(entity,tags,paint.map.scale); } diff --git a/net/systemeD/halcyon/WayUI.as b/net/systemeD/halcyon/WayUI.as index 00007f0c..0f5ebdd4 100644 --- a/net/systemeD/halcyon/WayUI.as +++ b/net/systemeD/halcyon/WayUI.as @@ -233,6 +233,7 @@ package net.systemeD.halcyon { setStateClass('area', Way(entity).isArea()); setStateClass('tiger', (entity.isUneditedTiger() && Globals.vars.highlightTiger)); tags=applyStateClasses(tags); + if (entity.status) { tags['_status']=entity.status; } // Keep track of maximum stroke width for hitzone var maxwidth:Number=4; diff --git a/net/systemeD/halcyon/connection/Connection.as b/net/systemeD/halcyon/connection/Connection.as index 1c579066..56f474e0 100644 --- a/net/systemeD/halcyon/connection/Connection.as +++ b/net/systemeD/halcyon/connection/Connection.as @@ -12,6 +12,7 @@ package net.systemeD.halcyon.connection { public class Connection extends EventDispatcher { public var name:String; + public var statusFetcher:StatusFetcher; protected var apiBaseURL:String; protected var policyURL:String; protected var params:Object; @@ -57,7 +58,8 @@ package net.systemeD.halcyon.connection { public static var NODE_RENUMBERED:String = "node_renumbered"; public static var WAY_RENUMBERED:String = "way_renumbered"; public static var RELATION_RENUMBERED:String = "relation_renumbered"; - public static var TAG_CHANGED:String = "tag_change"; + public static var TAG_CHANGED:String = "tag_changed"; + public static var STATUS_CHANGED:String = "status_changed"; public static var NODE_MOVED:String = "node_moved"; public static var NODE_ALTERED:String = "node_altered"; public static var WAY_NODE_ADDED:String = "way_node_added"; @@ -320,6 +322,14 @@ package net.systemeD.halcyon.connection { return list; } + public function getAllLoadedEntities():Array { + var list:Array = []; var entity:Entity; + for each (entity in relations) { if (entity.loaded && !entity.deleted) list.push(entity); } + for each (entity in ways ) { if (entity.loaded && !entity.deleted) list.push(entity); } + for each (entity in nodes ) { if (entity.loaded && !entity.deleted) list.push(entity); } + return list; + } + /** Returns all available relations that match all of {k1: [v1,v2,...], k2: [v1...] ...} * where p1 is an array [v1, v2, v3...] */ public function getMatchingRelationIDs(match:Object):Array { diff --git a/net/systemeD/halcyon/connection/Entity.as b/net/systemeD/halcyon/connection/Entity.as index c975324d..2837f398 100644 --- a/net/systemeD/halcyon/connection/Entity.as +++ b/net/systemeD/halcyon/connection/Entity.as @@ -1,5 +1,6 @@ package net.systemeD.halcyon.connection { + import flash.events.Event; import flash.events.EventDispatcher; import flash.utils.Dictionary; @@ -17,6 +18,7 @@ package net.systemeD.halcyon.connection { private var modified:Boolean = false; private var _loaded:Boolean = true; private var parents:Dictionary = new Dictionary(); + public var status:String; /** Lock against purging when off-screen */ public var locked:Boolean = false; public var deleted:Boolean = false; @@ -178,6 +180,14 @@ package net.systemeD.halcyon.connection { return copy; } + /** Change entity status. */ + public function setStatus(s:String):void { + if (s=='') s=null; + if (s==status) return; + status=s; + dispatchEvent(new EntityEvent(Connection.STATUS_CHANGED,this)); + } + // Clean/dirty methods /** Check if entity is modified since last markClean(). */ @@ -394,7 +404,7 @@ package net.systemeD.halcyon.connection { } - /** Basic description of Entity - should be overriden by subclass. */ + /** Basic description of Entity - should be overriden by subclass. */ public function getDescription():String { var basic:String=this.getType()+" "+_id; if (tags['ref'] && tags['name']) { return tags['ref']+' '+tags['name']+' ('+basic+')'; } diff --git a/net/systemeD/halcyon/connection/StatusFetcher.as b/net/systemeD/halcyon/connection/StatusFetcher.as new file mode 100644 index 00000000..25cf8ca4 --- /dev/null +++ b/net/systemeD/halcyon/connection/StatusFetcher.as @@ -0,0 +1,85 @@ +package net.systemeD.halcyon.connection { + + import flash.net.*; + import flash.events.*; + import net.systemeD.halcyon.AttentionEvent; + + public class StatusFetcher { + + /* Class to fetch the status for newly loaded objects. + At present this is rather specialised to WTFE (wtfe.gryph.de). + */ + + public var _url:String; + public var conn:Connection; + + private static var STATUSES:Array=["no","partial","unsure",'']; + + public function StatusFetcher(url:String, connection:Connection) { + _url=url; + conn=connection; + } + + public function fetch(entities:Array):void { + if (entities.length==0) return; + // Create URL request + var vars:URLVariables = new URLVariables(); + vars.nodes=''; + vars.ways=''; + vars.relations=''; + for each (var entity:Entity in entities) { + if (entity is Node) vars.nodes+=entity.id+","; + else if (entity is Way) vars.ways+=entity.id+","; + else if (entity is Relation) vars.relations+=entity.id+","; + } + if (vars.ways.substr(vars.ways.length-1,1)==',') vars.ways=vars.ways.substr(0,vars.ways.length-1); + if (vars.nodes.substr(vars.nodes.length-1,1)==',') vars.nodes=vars.nodes.substr(0,vars.nodes.length-1); + if (vars.relations.substr(vars.relations.length-1,1)==',') vars.relations=vars.relations.substr(0,vars.relations.length-1); + var request:URLRequest = new URLRequest(_url); + request.data = vars; + request.method = "POST"; + + // Make request + var loader:URLLoader = new URLLoader(); + loader.addEventListener(Event.COMPLETE, loadedFetch); + loader.addEventListener(IOErrorEvent.IO_ERROR, errorOnFetchLoad); + loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, fetchLoadStatus); + loader.load(request); + } + + private function loadedFetch(event:Event):void { + var xml:XML=new XML(URLLoader(event.target).data); + var entity:Entity, status:String; + + for each (var exml:XML in xml.*) { + switch (exml.name().localName) { + case "way": entity=conn.getWay(exml.@id); break; + case "relation":entity=conn.getRelation(exml.@id); break; + case "node": entity=conn.getNode(exml.@id); break; + } + + // **** Specific WTFE-parsing code starts here + // FIXME: should be generalised + // if all users are "yes" or "auto", status is 'ok' (green) + // if first user is "no", status is 'no' (red) + // if any other users are no, status is 'partial' (softer red) + // otherwise, status is 'unsure' (yellow) + var s:uint=3; // ok + for each (var user:XML in exml.user) { + if (user.@decision=='no' && user.@version=='first') { s=0; } // no from v1 + else if (user.@decision=='no') { s=Math.min(s,1); } // no from later version + else if (user.@decision=='undecided' || user.@decision=='anonymous') { s=Math.min(s,2); } // unsure + } + status=STATUSES[s]; + // **** Specific WTFE-parsing code ends here + entity.setStatus(status); + } + } + + private function errorOnFetchLoad(event:Event):void { + conn.dispatchEvent(new AttentionEvent(AttentionEvent.ALERT, null, "Couldn't load status information")); + } + private function fetchLoadStatus(event:HTTPStatusEvent):void { } + + } +} diff --git a/net/systemeD/halcyon/connection/XMLBaseConnection.as b/net/systemeD/halcyon/connection/XMLBaseConnection.as index 65b9f258..d2e5164e 100644 --- a/net/systemeD/halcyon/connection/XMLBaseConnection.as +++ b/net/systemeD/halcyon/connection/XMLBaseConnection.as @@ -26,6 +26,7 @@ package net.systemeD.halcyon.connection { var tags:Object; var node:Node, newNode:Node; var unusedNodes:Object={}; + var createdEntities:Array=[]; var minlon:Number, maxlon:Number, minlat:Number, maxlat:Number; var singleEntityRequest:Boolean=true; @@ -78,9 +79,11 @@ package net.systemeD.halcyon.connection { members.push(new RelationMember(member, role)); } - if ( rel == null ) - setRelation(new Relation(this, id, version, tags, true, members, uid, timestamp), false); - else { + if ( rel == null ) { + rel=new Relation(this, id, version, tags, true, members, uid, timestamp); + setRelation(rel, false); + createdEntities.push(rel); + } else { rel.update(version, tags, true, false, members, uid, timestamp); sendEvent(new EntityEvent(NEW_RELATION, rel), false); } @@ -107,6 +110,7 @@ package net.systemeD.halcyon.connection { // the node didn't exist before, so create/update it newNode.parentsLoaded=newNode.within(minlon,maxlon,minlat,maxlat); setOrUpdateNode(newNode, true); + createdEntities.push(newNode); } else { // the node's already in memory, but store it in case one of the new ways needs it if (newNode.within(minlon,maxlon,minlat,maxlat)) newNode.parentsLoaded=true; @@ -122,20 +126,22 @@ package net.systemeD.halcyon.connection { var way:Way = getWay(id); if ( way == null || !way.loaded || singleEntityRequest) { - var nodes:Array = []; + var nodelist:Array = []; for each(var nd:XML in data.nd) { var nodeid:Number=Number(nd.@ref) if (getNode(nodeid).isDeleted() && unusedNodes[nodeid]) { setOrUpdateNode(unusedNodes[nodeid], true); } - nodes.push(getNode(nodeid)); + nodelist.push(getNode(nodeid)); } tags = parseTags(data.tag); if ( way == null ) { - setWay(new Way(this, id, version, tags, true, nodes, uid, timestamp),false); + way=new Way(this, id, version, tags, true, nodelist, uid, timestamp) + setWay(way,false); + createdEntities.push(way); } else { waycount++; - way.update(version, tags, true, true, nodes, uid, timestamp); + way.update(version, tags, true, true, nodelist, uid, timestamp); sendEvent(new EntityEvent(NEW_WAY, way), false); } } @@ -144,6 +150,8 @@ package net.systemeD.halcyon.connection { markBboxLoaded(minlon,maxlon,maxlat,minlat); registerPOINodes(); dispatchEvent(new Event(LOAD_COMPLETED)); + + if (statusFetcher) statusFetcher.fetch(createdEntities); } protected function registerPOINodes():void { diff --git a/net/systemeD/potlatch2/options/OptionsDialog.mxml b/net/systemeD/potlatch2/options/OptionsDialog.mxml index 8771576c..c98cab8d 100644 --- a/net/systemeD/potlatch2/options/OptionsDialog.mxml +++ b/net/systemeD/potlatch2/options/OptionsDialog.mxml @@ -9,6 +9,9 @@ import mx.events.CloseEvent; import mx.core.Application; import net.systemeD.halcyon.Globals; + import net.systemeD.halcyon.Map; + import net.systemeD.halcyon.connection.Connection; + import net.systemeD.halcyon.connection.StatusFetcher; public function init():void { PopUpManager.addPopUp(this, Application(Application.application), true); @@ -21,6 +24,7 @@ cursorcheck.selected = Application.application.theController.cursorsEnabled; tigercheck.selected = obj.data['tiger_highlighted']; latlongcheck.selected = Application.application.coordsbox.visible; + licencecheck.selected = Map(Globals.vars.root).editableLayer.connection.statusFetcher!=null; } private function optionsDialog_close(evt:CloseEvent):void { @@ -36,6 +40,18 @@ obj.flush(); } + private function licenceToggle():void { + // ** FIXME: this is an inelegant patch for the short-term issue of highlighting licensing status + var conn:Connection=Map(Globals.vars.root).editableLayer.connection; + if (conn.statusFetcher) { + conn.statusFetcher=null; + } else { + conn.statusFetcher=new StatusFetcher("http://wtfe.gryph.de/api/0.6/userlist",conn); + conn.statusFetcher.fetch(conn.getAllLoadedEntities()); + // ** FIXME: needs to also switch map style + } + } + ]]> + + diff --git a/resources/stylesheets/potlatch.css b/resources/stylesheets/potlatch.css index 625d5462..08864f66 100644 --- a/resources/stylesheets/potlatch.css +++ b/resources/stylesheets/potlatch.css @@ -18,3 +18,11 @@ way .area_small_name {text-color: black; font-size: 9; text: name; text-halo: #ffffaa; text-halo-radius: 2; text-position: center;} @import("stylesheets/core_interactive.css"); +/* Test rendering for licence status */ + +way[_status=no] { z-index: 0; width: 20; color: red; } +way[_status=partial] { z-index: 0; width: 20; color: red; opacity: 0.4; } +way[_status=maybe] { z-index: 0; width: 20; color: orange; opacity: 0.3; } +node[_status=no] { z-index: 0; icon-image: square; icon-width: 15; color: red; } +node[_status=partial] { z-index: 0; icon-image: square; icon-width: 15; color: red; opacity: 0.4; } +node[_status=maybe] { z-index: 0; icon-image: square; icon-width: 15; color: orange; opacity: 0.3; } From 6f3e5f3c8537be37954ddc00c3b16970bca0d592 Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Fri, 10 Jun 2011 16:09:28 +0100 Subject: [PATCH 54/89] Correct the _status value --- resources/stylesheets/potlatch.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/stylesheets/potlatch.css b/resources/stylesheets/potlatch.css index 08864f66..39cc22ce 100644 --- a/resources/stylesheets/potlatch.css +++ b/resources/stylesheets/potlatch.css @@ -22,7 +22,7 @@ way .area_small_name {text-color: black; font-size: 9; text: name; text-halo: #f way[_status=no] { z-index: 0; width: 20; color: red; } way[_status=partial] { z-index: 0; width: 20; color: red; opacity: 0.4; } -way[_status=maybe] { z-index: 0; width: 20; color: orange; opacity: 0.3; } +way[_status=unsure] { z-index: 0; width: 20; color: orange; opacity: 0.4; } node[_status=no] { z-index: 0; icon-image: square; icon-width: 15; color: red; } node[_status=partial] { z-index: 0; icon-image: square; icon-width: 15; color: red; opacity: 0.4; } -node[_status=maybe] { z-index: 0; icon-image: square; icon-width: 15; color: orange; opacity: 0.3; } +node[_status=unsure] { z-index: 0; icon-image: square; icon-width: 15; color: orange; opacity: 0.4; } From 09b169bfe0448b970d3d6cdec850895003521f60 Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Fri, 10 Jun 2011 17:54:55 +0100 Subject: [PATCH 55/89] selected background node --- .../potlatch2/controller/ControllerState.as | 2 +- .../controller/SelectedBackgroundNode.as | 69 +++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 net/systemeD/potlatch2/controller/SelectedBackgroundNode.as diff --git a/net/systemeD/potlatch2/controller/ControllerState.as b/net/systemeD/potlatch2/controller/ControllerState.as index 0aeddaa6..e7641c3f 100644 --- a/net/systemeD/potlatch2/controller/ControllerState.as +++ b/net/systemeD/potlatch2/controller/ControllerState.as @@ -96,7 +96,7 @@ package net.systemeD.potlatch2.controller { if ( paint && paint.isBackground ) { if ( event.type == MouseEvent.MOUSE_DOWN && entity.connection is SnapshotConnection) { if (entity is Way) { return new SelectedBackgroundWay(entity as Way); } - else if (entity is Node) { return new SelectedPOINode(entity as Node); } + else if (entity is Node) { return new SelectedBackgroundNode(entity as Node, paint); } } else if ( event.type == MouseEvent.MOUSE_DOWN && ((event.shiftKey && event.ctrlKey) || event.altKey) ) { // alt-click to pull data out of vector background layer var newEntity:Entity=paint.pullThrough(entity,editableLayer); diff --git a/net/systemeD/potlatch2/controller/SelectedBackgroundNode.as b/net/systemeD/potlatch2/controller/SelectedBackgroundNode.as new file mode 100644 index 00000000..a125a7b9 --- /dev/null +++ b/net/systemeD/potlatch2/controller/SelectedBackgroundNode.as @@ -0,0 +1,69 @@ +package net.systemeD.potlatch2.controller { + import flash.events.*; + import flash.ui.Keyboard; + import net.systemeD.potlatch2.EditController; + import net.systemeD.halcyon.connection.*; + import net.systemeD.halcyon.MapPaint; + + public class SelectedBackgroundNode extends ControllerState { + protected var initNode:Node; + protected var layer:MapPaint; + + public function SelectedBackgroundNode(node:Node, layer:MapPaint) { + initNode = node; + this.layer = layer; + } + + protected function selectNode(node:Node):void { + if ( firstSelected is Node && Node(firstSelected)==node ) + return; + + clearSelection(this); + editableLayer.setHighlight(node, { selected: true }); + selection = [node]; + controller.updateSelectionUI(layer); + initNode = node; + } + + protected function clearSelection(newState:ControllerState):void { + if ( selectCount ) { + editableLayer.setHighlight(firstSelected, { selected: false }); + selection = []; + if (!newState.isSelectionState()) { controller.updateSelectionUI(); } + } + } + + override public function processMouseEvent(event:MouseEvent, entity:Entity):ControllerState { + if (event.type==MouseEvent.MOUSE_MOVE) { return this; } + if (event.type==MouseEvent.MOUSE_UP) { return this; } + var cs:ControllerState = sharedMouseEvents(event, entity); + return cs ? cs : this; + } + + override public function processKeyboardEvent(event:KeyboardEvent):ControllerState { + switch (event.keyCode) { + } + var cs:ControllerState = sharedKeyboardEvents(event); + return cs ? cs : this; + } + + public function deletePOI():ControllerState { + return new NoSelection(); + } + + override public function enterState():void { + selectNode(initNode); + editableLayer.setPurgable(selection,false); + } + + override public function exitState(newState:ControllerState):void { + editableLayer.setPurgable(selection,true); + clearSelection(newState); + } + + override public function toString():String { + return "SelectedBackgroundNode"; + } + + } +} From 68405b6581f937499f1fec5a481251008224393c Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Fri, 10 Jun 2011 17:55:35 +0100 Subject: [PATCH 56/89] work in progress for marking nodes as complete --- .../potlatch2/panels/BackgroundPanel.mxml | 8 ++++++ .../potlatch2/utils/SnapshotConnection.as | 26 +++++++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/net/systemeD/potlatch2/panels/BackgroundPanel.mxml b/net/systemeD/potlatch2/panels/BackgroundPanel.mxml index cd60f017..982feb24 100644 --- a/net/systemeD/potlatch2/panels/BackgroundPanel.mxml +++ b/net/systemeD/potlatch2/panels/BackgroundPanel.mxml @@ -12,10 +12,13 @@ + + \ No newline at end of file diff --git a/net/systemeD/potlatch2/utils/SnapshotConnection.as b/net/systemeD/potlatch2/utils/SnapshotConnection.as index 5159e095..4910cf5f 100644 --- a/net/systemeD/potlatch2/utils/SnapshotConnection.as +++ b/net/systemeD/potlatch2/utils/SnapshotConnection.as @@ -1,6 +1,8 @@ package net.systemeD.potlatch2.utils { - import net.systemeD.halcyon.connection.XMLConnection; + import net.systemeD.halcyon.connection.*; + import flash.events.Event; + import flash.net.*; public class SnapshotConnection extends XMLConnection { @@ -8,7 +10,27 @@ package net.systemeD.potlatch2.utils { super(cname,api,policy,initparams); } - /* todo - stuff about marking nodes/ways as complete */ + /** Send a "complete" call to the server, and remove it from the current layer */ + public function markComplete(entity:Entity):void { + if (entity is Node) { + var node:Node = Node(entity); + if (node == getNode(node.id)) { // confirm it's from this connection + var urlReq:URLRequest = new URLRequest(apiBaseURL+"node/"+node.id+"/complete"); + urlReq.method = "POST"; + urlReq.data = ' '; + urlReq.contentType = "application/xml"; + urlReq.requestHeaders = [ new URLRequestHeader("X_HTTP_METHOD_OVERRIDE", "PUT"), + new URLRequestHeader("X-Error-Format", "XML") ]; + var loader:URLLoader = new URLLoader(); + loader.addEventListener(Event.COMPLETE, function(e:Event):void { killNode(node.id) }); + loader.load(urlReq); + } + + } else if (entity is Way) { + var way:Way = Way(entity); + trace("not implemented"); + } + } } } \ No newline at end of file From 1490fa466d8f029303ed8837972a648a1c024988 Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Fri, 10 Jun 2011 21:14:09 +0100 Subject: [PATCH 57/89] Fix issue where removing node B from an ABA way would leave two As. Needs reasonably thorough testing please ;) --- .../actions/RemoveNodeByIndexAction.as | 49 +++++++++++-------- .../actions/RemoveNodeFromWayAction.as | 22 ++++++--- 2 files changed, 45 insertions(+), 26 deletions(-) diff --git a/net/systemeD/halcyon/connection/actions/RemoveNodeByIndexAction.as b/net/systemeD/halcyon/connection/actions/RemoveNodeByIndexAction.as index 2e623aec..f62e57c0 100644 --- a/net/systemeD/halcyon/connection/actions/RemoveNodeByIndexAction.as +++ b/net/systemeD/halcyon/connection/actions/RemoveNodeByIndexAction.as @@ -18,26 +18,35 @@ package net.systemeD.halcyon.connection.actions { this.fireEvent = fireEvent; } - public override function doAction():uint { - removed = nodeList.splice(index, 1); - if (nodeList.indexOf(removed[0])==-1) { removed[0].removeParent(way); } - way.deleted = nodeList.length == 0; - markDirty(); - if (fireEvent) { - entity.dispatchEvent(new WayNodeEvent(Connection.WAY_NODE_REMOVED, removed[0], way, index)); - } - return SUCCESS; - } - - public override function undoAction():uint { - nodeList.splice(index, 0, removed[0]); - removed[0].addParent(way); - way.deleted = nodeList.length == 0; - markClean(); - if (fireEvent) { - entity.dispatchEvent(new WayNodeEvent(Connection.WAY_NODE_ADDED, removed[0], way, index)); - } - return SUCCESS; + public override function doAction():uint { + var preceding:Node=(index>1) ? nodeList[index-1] : null; + var node:Node=nodeList[index]; + removed=[]; + + while (nodeList[index]==node || nodeList[index]==preceding) { + var removedNode:Node=nodeList.splice(index, 1)[0]; + removed.push(removedNode); + if (nodeList.indexOf(removedNode)==-1) { removedNode.removeParent(way); } + if (fireEvent) { + entity.dispatchEvent(new WayNodeEvent(Connection.WAY_NODE_REMOVED, removedNode, way, index)); + } + } + way.deleted = nodeList.length == 0; + markDirty(); + return SUCCESS; + } + + public override function undoAction():uint { + for (var i:uint=removed.length-1; i>=0; i--) { + nodeList.splice(index, 0, removed[i]); + removed[i].addParent(way); + if (fireEvent) { + entity.dispatchEvent(new WayNodeEvent(Connection.WAY_NODE_ADDED, removed[i], way, index)); + } + } + way.deleted = nodeList.length == 0; + markClean(); + return SUCCESS; } } } \ No newline at end of file diff --git a/net/systemeD/halcyon/connection/actions/RemoveNodeFromWayAction.as b/net/systemeD/halcyon/connection/actions/RemoveNodeFromWayAction.as index 760866ac..cd3007b6 100644 --- a/net/systemeD/halcyon/connection/actions/RemoveNodeFromWayAction.as +++ b/net/systemeD/halcyon/connection/actions/RemoveNodeFromWayAction.as @@ -15,11 +15,19 @@ package net.systemeD.halcyon.connection.actions { public override function doAction():uint { nodeRemovedFrom = []; - var i:int; + var i:int, node2:Node; while ((i=nodeList.indexOf(node))>-1) { + // remove the node from the way nodeList.splice(i,1); - nodeRemovedFrom.push(i); - entity.dispatchEvent(new WayNodeEvent(Connection.WAY_NODE_REMOVED, node, Way(entity), i)); + nodeRemovedFrom.push([node,i]); + entity.dispatchEvent(new WayNodeEvent(Connection.WAY_NODE_REMOVED, node, Way(entity), i)); + + // remove any repeated nodes that have occurred as a result (i.e. removing B from ABA) + while (i>0 && nodeList[i-1]==nodeList[i]) { + node2=nodeList.splice(i,1)[0]; + nodeRemovedFrom.push([node2,i]); + entity.dispatchEvent(new WayNodeEvent(Connection.WAY_NODE_REMOVED, node2, Way(entity), i)); + } } if ( nodeRemovedFrom.length > 0 ) { @@ -36,9 +44,11 @@ package net.systemeD.halcyon.connection.actions { node.addParent(entity); for (var i:int = nodeRemovedFrom.length - 1; i >= 0; i--) { - var index:int = nodeRemovedFrom[i]; - nodeList.splice(index, 0, node); - entity.dispatchEvent(new WayNodeEvent(Connection.WAY_NODE_ADDED, node, Way(entity), index)); + var removal:Array = nodeRemovedFrom[i]; + var reinstate:Node = removal[0]; + var index:int = removal[1]; + nodeList.splice(index, 0, reinstate); + entity.dispatchEvent(new WayNodeEvent(Connection.WAY_NODE_ADDED, reinstate, Way(entity), index)); } entity.deleted = nodeList.length == 0; From e83536cf61ba16ff9415d38207836a1360a7ed6e Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Fri, 10 Jun 2011 21:25:51 +0100 Subject: [PATCH 58/89] Fix undo --- .../halcyon/connection/actions/RemoveNodeByIndexAction.as | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/systemeD/halcyon/connection/actions/RemoveNodeByIndexAction.as b/net/systemeD/halcyon/connection/actions/RemoveNodeByIndexAction.as index f62e57c0..7021379c 100644 --- a/net/systemeD/halcyon/connection/actions/RemoveNodeByIndexAction.as +++ b/net/systemeD/halcyon/connection/actions/RemoveNodeByIndexAction.as @@ -37,7 +37,7 @@ package net.systemeD.halcyon.connection.actions { } public override function undoAction():uint { - for (var i:uint=removed.length-1; i>=0; i--) { + for (var i:int=removed.length-1; i>=0; i--) { nodeList.splice(index, 0, removed[i]); removed[i].addParent(way); if (fireEvent) { From 45c4335fd0f876733f2b61616862e585a1312a5f Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Sat, 11 Jun 2011 10:38:02 +0100 Subject: [PATCH 59/89] Make 'delete' work on (new tag)=(new value) --- net/systemeD/halcyon/connection/actions/SetTagAction.as | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/systemeD/halcyon/connection/actions/SetTagAction.as b/net/systemeD/halcyon/connection/actions/SetTagAction.as index 9f1b90ce..c8b3bc61 100644 --- a/net/systemeD/halcyon/connection/actions/SetTagAction.as +++ b/net/systemeD/halcyon/connection/actions/SetTagAction.as @@ -17,8 +17,8 @@ package net.systemeD.halcyon.connection.actions { public override function doAction():uint { var tags:Object = entity.getTagsHash(); oldValue = tags[key]; - if ( oldValue != value || key == '' ) { - if ( value == null || value == "" || key == '' ) + if ( value == null || key == '' || oldValue != value ) { + if ( value == null || key == '' || value == '' ) delete tags[key]; else tags[key] = value; From f63f7f7371d0ac2fae68fa8fec637a19964a62e6 Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Sat, 11 Jun 2011 11:18:58 +0100 Subject: [PATCH 60/89] Provide a new 'View data' button in the upload dialogue. If the upload freaks out and refuses to save, the user can at least copy and paste the raw XML for later use. --- net/systemeD/halcyon/connection/Connection.as | 2 +- net/systemeD/halcyon/connection/XMLConnection.as | 8 ++++++-- net/systemeD/potlatch2/save/SaveDialog.mxml | 15 ++++++++++++--- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/net/systemeD/halcyon/connection/Connection.as b/net/systemeD/halcyon/connection/Connection.as index 56f474e0..4b2dbe41 100644 --- a/net/systemeD/halcyon/connection/Connection.as +++ b/net/systemeD/halcyon/connection/Connection.as @@ -582,7 +582,7 @@ package net.systemeD.halcyon.connection { public function setAccessToken(key:String, secret:String):void {} public function createChangeset(tags:Object):void {} public function closeChangeset():void {} - public function uploadChanges():void {} + public function uploadChanges():* {} public function fetchUserTraces(refresh:Boolean=false):void {} public function fetchTrace(id:Number, callback:Function):void {} public function hasAccessToken():Boolean { return false; } diff --git a/net/systemeD/halcyon/connection/XMLConnection.as b/net/systemeD/halcyon/connection/XMLConnection.as index 0e6bb844..d87d87ee 100644 --- a/net/systemeD/halcyon/connection/XMLConnection.as +++ b/net/systemeD/halcyon/connection/XMLConnection.as @@ -197,7 +197,10 @@ package net.systemeD.halcyon.connection { loader.load(urlReq); } - override public function uploadChanges():void { + /** Create XML changeset and send it to the server. Returns the XML string for use in the 'Show data' button. + (We don't mind what's returned as long as it implements .toString() ) */ + + override public function uploadChanges():* { var changeset:Changeset = getActiveChangeset(); var upload:XML = upload.appendChild(addCreated(changeset, getAllNodeIDs, getNode, serialiseNode)); @@ -230,7 +233,8 @@ package net.systemeD.halcyon.connection { serv.addEventListener(FaultEvent.FAULT, diffUploadIOError); serv.send(upload); - dispatchEvent(new Event(SAVE_STARTED)); + dispatchEvent(new Event(SAVE_STARTED)); + return upload; } private function diffUploadComplete(event:ResultEvent):void { diff --git a/net/systemeD/potlatch2/save/SaveDialog.mxml b/net/systemeD/potlatch2/save/SaveDialog.mxml index 4d87dd13..676c446c 100644 --- a/net/systemeD/potlatch2/save/SaveDialog.mxml +++ b/net/systemeD/potlatch2/save/SaveDialog.mxml @@ -64,9 +64,14 @@ + + + + + @@ -168,7 +173,11 @@ saveProgress.label = "Uploading changes"; _connection.addEventListener(Connection.SAVE_COMPLETED, saveCompleted); - _connection.uploadChanges(); + var rawData:*=_connection.uploadChanges(); + if (rawData) { + dataText.text=rawData.toString(); + dataButton.visible=true; + } } private function changesetError(event:Event):void { @@ -178,7 +187,7 @@ private function saveCompleted(event:SaveCompleteEvent):void { if ( event.saveOK ) { _connection.dispatchEvent(new AttentionEvent(AttentionEvent.ALERT, null, "Changes successfully saved")); - close(); + if (processSequence.selectedChild!=dataTab) close(); } else { fail("Failure when uploading data"); } @@ -197,7 +206,7 @@ processSequence.selectedChild = failureTab; failureText = text; } - + private function close():void { _connection.removeEventListener(Connection.NEW_CHANGESET, changesetCreated); _connection.removeEventListener(Connection.NEW_CHANGESET_ERROR, changesetError); From fa70f8c582f512cf47555904cbc8d183453bb2c5 Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Sat, 11 Jun 2011 11:26:59 +0100 Subject: [PATCH 61/89] Don't freak out when backspacing a value then deleting the whole tag --- net/systemeD/controls/AutoComplete.as | 1 + 1 file changed, 1 insertion(+) diff --git a/net/systemeD/controls/AutoComplete.as b/net/systemeD/controls/AutoComplete.as index 527b8049..833e6274 100644 --- a/net/systemeD/controls/AutoComplete.as +++ b/net/systemeD/controls/AutoComplete.as @@ -355,6 +355,7 @@ package net.systemeD.controls { } private function defaultFilterFunction(element:*, text:String):Boolean { + if (!text || text=='') return false; var label:String = itemToLabel(element); return (label.toLowerCase().substring(0,text.length) == text.toLowerCase()); } From 134f37ce74d58cb06770129cd9674e73f1e62956 Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Sun, 12 Jun 2011 07:59:00 +0100 Subject: [PATCH 62/89] Control-drag for selection by area --- net/systemeD/halcyon/connection/Way.as | 48 ++++++++++++- .../potlatch2/controller/ControllerState.as | 12 ++-- .../potlatch2/controller/SelectArea.as | 69 +++++++++++++++++++ 3 files changed, 123 insertions(+), 6 deletions(-) create mode 100644 net/systemeD/potlatch2/controller/SelectArea.as diff --git a/net/systemeD/halcyon/connection/Way.as b/net/systemeD/halcyon/connection/Way.as index 8cefcf1a..d5f991cf 100644 --- a/net/systemeD/halcyon/connection/Way.as +++ b/net/systemeD/halcyon/connection/Way.as @@ -51,7 +51,7 @@ package net.systemeD.halcyon.connection { (edge_b>top && edge_b>top ) || deleted) { return false; } return true; } - + public function getNode(index:uint):Node { return nodes[index]; } @@ -291,5 +291,51 @@ package net.systemeD.halcyon.connection { } return null; } + + public function intersects(left:Number,right:Number,top:Number,bottom:Number):Boolean { + // simple test first: are any nodes contained? + for (var i:uint=0; i0) { + top_intersection = (m*l + c); + bottom_intersection = (m*r + c); + } else { + top_intersection = (m*r + c); + bottom_intersection = (m*l + c); + } + + if (y0toptrianglepoint ? top_intersection : toptrianglepoint; + var botoverlap:Number = bottom_intersectionb))); + } + + } } diff --git a/net/systemeD/potlatch2/controller/ControllerState.as b/net/systemeD/potlatch2/controller/ControllerState.as index e7641c3f..c9645aeb 100644 --- a/net/systemeD/potlatch2/controller/ControllerState.as +++ b/net/systemeD/potlatch2/controller/ControllerState.as @@ -94,14 +94,14 @@ package net.systemeD.potlatch2.controller { var focus:Entity = getTopLevelFocusEntity(entity); if ( paint && paint.isBackground ) { - if ( event.type == MouseEvent.MOUSE_DOWN && entity.connection is SnapshotConnection) { - if (entity is Way) { return new SelectedBackgroundWay(entity as Way); } - else if (entity is Node) { return new SelectedBackgroundNode(entity as Node, paint); } - } else if ( event.type == MouseEvent.MOUSE_DOWN && ((event.shiftKey && event.ctrlKey) || event.altKey) ) { + if (event.type == MouseEvent.MOUSE_DOWN && ((event.shiftKey && event.ctrlKey) || event.altKey) ) { // alt-click to pull data out of vector background layer var newEntity:Entity=paint.pullThrough(entity,editableLayer); - if (entity is Way) { return new SelectedWay(newEntity as Way); } + if (entity is Way ) { return new SelectedWay(newEntity as Way); } else if (entity is Node) { return new SelectedPOINode(newEntity as Node); } + } else if (event.type == MouseEvent.MOUSE_DOWN) { + if (entity is Way ) { return new SelectedBackgroundWay(entity as Way); } + else if (entity is Node) { return new SelectedBackgroundNode(entity as Node, paint); } } else if (event.type == MouseEvent.MOUSE_DOWN && entity is Marker) { return new SelectedMarker(entity as Marker, paint); } else if ( event.type == MouseEvent.MOUSE_UP ) { @@ -123,6 +123,8 @@ package net.systemeD.potlatch2.controller { return new DragSelection(selection, event); } else if (entity) { return new DragSelection([entity], event); + } else if (event.ctrlKey) { + return new SelectArea(event.localX,event.localY); } } else if ( event.type == MouseEvent.CLICK && focus == null && map.dragstate!=map.DRAGGING && this is SelectedMarker) { // this is identical to the below, but needed for unselecting markers on vector background layers. diff --git a/net/systemeD/potlatch2/controller/SelectArea.as b/net/systemeD/potlatch2/controller/SelectArea.as new file mode 100644 index 00000000..73cb2fc5 --- /dev/null +++ b/net/systemeD/potlatch2/controller/SelectArea.as @@ -0,0 +1,69 @@ +package net.systemeD.potlatch2.controller { + + import flash.display.*; + import flash.events.*; + import net.systemeD.halcyon.connection.*; + + public class SelectArea extends ControllerState { + + private var startX:Number; + private var startY:Number; + private var endX:Number; + private var endY:Number; + private var box:Shape; + private const TOLERANCE:uint=4; + + public function SelectArea(x:Number,y:Number) { + startX=endX=x; + startY=endY=y; + } + + override public function processMouseEvent(event:MouseEvent, entity:Entity):ControllerState { + if (event.type==MouseEvent.MOUSE_MOVE) { + // ** FIXME: weird things happen if you mouse-over the drag-and-drop panel + endX=event.localX; + endY=event.localY; + drawSelectionBox(); + } else if (event.type==MouseEvent.MOUSE_UP) { + // select everything within boundary + var a:Number; + if (startX>endX) { a=startX; startX=endX; endX=a; } + if (startY>endY) { a=startY; startY=endY; endY=a; } + if (endX-startX Date: Sun, 12 Jun 2011 14:42:04 +0100 Subject: [PATCH 63/89] New RuleChain object to replace previous nested array within StyleChooser --- net/systemeD/halcyon/styleparser/RuleChain.as | 65 +++++++++++++++++ net/systemeD/halcyon/styleparser/RuleSet.as | 18 ++--- .../halcyon/styleparser/StyleChooser.as | 70 ++++++------------- 3 files changed, 95 insertions(+), 58 deletions(-) create mode 100644 net/systemeD/halcyon/styleparser/RuleChain.as diff --git a/net/systemeD/halcyon/styleparser/RuleChain.as b/net/systemeD/halcyon/styleparser/RuleChain.as new file mode 100644 index 00000000..cd6c5b43 --- /dev/null +++ b/net/systemeD/halcyon/styleparser/RuleChain.as @@ -0,0 +1,65 @@ +package net.systemeD.halcyon.styleparser { + + import net.systemeD.halcyon.connection.*; + + /** A descendant list of MapCSS selectors (Rules). + + For example, + relation[type=route] way[highway=primary] + ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ + first Rule second Rule + |------------|---------| + | + one RuleChain + + */ + + public class RuleChain { + public var rules:Array=[]; // should eventually become a Vector of Rules + public var subpart:String=''; // subpart name, as in way[highway=primary]::centreline + + // Test a ruleChain + // - run a set of tests in the chain + // works backwards from at position "pos" in array, or -1 for the last + // separate tags object is required in case they've been dynamically retagged + // - if they fail, return false + // - if they succeed, and it's the last in the chain, return happily + // - if they succeed, and there's more in the chain, rerun this for each parent until success + + public function test(pos:int, obj:Entity, tags:Object, zoom:uint):Boolean { + if (pos==-1) { pos=rules.length-1; } + + var r:Rule=rules[pos]; + if (!r.test(obj, tags, zoom)) { return false; } + if (pos==0) { return true; } + + var o:Array=obj.parentObjects; + for each (var p:Entity in o) { + if (test(pos-1, p, p.getTagsHash(), zoom)) { return true; } + } + return false; + } + + public function get length():int { + return rules.length; + } + + // --------------------------------------------------------------------------------------------- + // Methods to add properties (used by parsers such as MapCSS) + + public function addRule(e:String=''):void { + rules.push(new Rule(e)); + } + + public function addConditionToLast(c:Condition):void { + rules[rules.length-1].conditions.push(c); + } + + public function addZoomToLast(z1:uint,z2:uint):void { + rules[rules.length-1].minZoom=z1; + rules[rules.length-1].maxZoom=z2; + } + + + } +} diff --git a/net/systemeD/halcyon/styleparser/RuleSet.as b/net/systemeD/halcyon/styleparser/RuleSet.as index 33c20b9c..0bf9923a 100644 --- a/net/systemeD/halcyon/styleparser/RuleSet.as +++ b/net/systemeD/halcyon/styleparser/RuleSet.as @@ -43,6 +43,7 @@ package net.systemeD.halcyon.styleparser { private static const CONDITION:RegExp =/^ \[(.+?)\] \s* /sx; private static const OBJECT:RegExp =/^ (\w+) \s* /sx; private static const DECLARATION:RegExp =/^ \{(.+?)\} \s* /sx; + private static const SUBPART:RegExp =/^ ::(\S+) \s* /sx; private static const UNKNOWN:RegExp =/^ (\S+) \s* /sx; private static const ZOOM_MINMAX:RegExp =/^ (\d+)\-(\d+) $/sx; @@ -366,7 +367,7 @@ package net.systemeD.halcyon.styleparser { if (previous==oDECLARATION) { saveChooser(sc); sc=new StyleChooser(); } css=css.replace(CLASS,''); - sc.addCondition(new Condition('set',o[1])); + sc.currentChain.addConditionToLast(new Condition('set',o[1])); previous=oCONDITION; // Not class - !.motorway, !.builtup, !:hover @@ -374,30 +375,31 @@ package net.systemeD.halcyon.styleparser { if (previous==oDECLARATION) { saveChooser(sc); sc=new StyleChooser(); } css=css.replace(NOT_CLASS,''); - sc.addCondition(new Condition('unset',o[1])); + sc.currentChain.addConditionToLast(new Condition('unset',o[1])); previous=oCONDITION; // Zoom } else if ((o=ZOOM.exec(css))) { - if (previous!=oOBJECT && previous!=oCONDITION) { sc.newObject(); } + if (previous!=oOBJECT && previous!=oCONDITION) { sc.currentChain.addRule(); } css=css.replace(ZOOM,''); var z:Array=parseZoom(o[1]); - sc.addZoom(z[0],z[1]); + sc.currentChain.addZoomToLast(z[0],z[1]); + sc.zoomSpecific=true; previous=oZOOM; // Grouping - just a comma } else if ((o=GROUP.exec(css))) { css=css.replace(GROUP,''); - sc.newGroup(); + sc.newRuleChain(); previous=oGROUP; // Condition - [highway=primary] } else if ((o=CONDITION.exec(css))) { if (previous==oDECLARATION) { saveChooser(sc); sc=new StyleChooser(); } - if (previous!=oOBJECT && previous!=oZOOM && previous!=oCONDITION) { sc.newObject(); } + if (previous!=oOBJECT && previous!=oZOOM && previous!=oCONDITION) { sc.currentChain.addRule(); } css=css.replace(CONDITION,''); - sc.addCondition(parseCondition(o[1]) as Condition); + sc.currentChain.addConditionToLast(parseCondition(o[1]) as Condition); previous=oCONDITION; // Object - way, node, relation @@ -405,7 +407,7 @@ package net.systemeD.halcyon.styleparser { if (previous==oDECLARATION) { saveChooser(sc); sc=new StyleChooser(); } css=css.replace(OBJECT,''); - sc.newObject(o[1]); + sc.currentChain.addRule(o[1]); previous=oOBJECT; // Declaration - {...} diff --git a/net/systemeD/halcyon/styleparser/StyleChooser.as b/net/systemeD/halcyon/styleparser/StyleChooser.as index 05b71b88..1a3f86fa 100644 --- a/net/systemeD/halcyon/styleparser/StyleChooser.as +++ b/net/systemeD/halcyon/styleparser/StyleChooser.as @@ -10,25 +10,35 @@ package net.systemeD.halcyon.styleparser { Its ruleChains property is an array of all the selectors, which would traditionally be comma-separated. For example: h1, h2, h3 em - is three ruleChains. + is three RuleChains. - Each ruleChain is itself an array of nested selectors. So the above + Each RuleChain is itself an array of nested selectors. So the above example would roughly be encoded as: [[h1],[h2],[h3,em]] ^^ ^^ ^^ ^^ each of these is a Rule - + ^^^^ ^^^^ ^^^^^^^ each of these is a RuleChain + The styles property is an array of all the style objects to be drawn if any of the ruleChains evaluate to true. */ - public var ruleChains:Array=[[]]; // array of array of Rules + public var ruleChains:Array; // array of RuleChains (each one an array of Rules) public var styles:Array=[]; // array of ShapeStyle/ShieldStyle/TextStyle/PointStyle public var zoomSpecific:Boolean=false; // are any of the rules zoom-specific? - private var rcpos:uint=0; + private var rcpos:uint; private var stylepos:uint=0; + public function StyleChooser():void { + ruleChains=[new RuleChain()]; + rcpos=0; + } + + public function get currentChain():RuleChain { + return ruleChains[rcpos]; + } + // Update the current StyleList from this StyleChooser public function updateStyles(obj:Entity, tags:Object, sl:StyleList, imageWidths:Object, zoom:uint):void { @@ -37,8 +47,8 @@ package net.systemeD.halcyon.styleparser { // Are any of the ruleChains fulfilled? var w:Number; var fulfilled:Boolean=false; - for each (var c:Array in ruleChains) { - if (testChain(c,-1,obj,tags,zoom)) { + for each (var c:RuleChain in ruleChains) { + if (c.test(-1,obj,tags,zoom)) { fulfilled=true; break; } } @@ -86,58 +96,18 @@ package net.systemeD.halcyon.styleparser { } } } - - - // Test a ruleChain - // - run a set of tests in the chain - // works backwards from at position "pos" in array, or -1 for the last - // separate tags object is required in case they've been dynamically retagged - // - if they fail, return false - // - if they succeed, and it's the last in the chain, return happily - // - if they succeed, and there's more in the chain, rerun this for each parent until success - - private function testChain(chain:Array,pos:int,obj:Entity,tags:Object,zoom:uint):Boolean { - if (pos==-1) { pos=chain.length-1; } - - var r:Rule=chain[pos]; - if (!r.test(obj, tags, zoom)) { return false; } - if (pos==0) { return true; } - - var o:Array=obj.parentObjects; - for each (var p:Entity in o) { - if (testChain(chain, pos-1, p, p.getTagsHash(), zoom )) { return true; } - } - return false; - } // --------------------------------------------------------------------------------------------- // Methods to add properties (used by parsers such as MapCSS) - // newGroup <- starts a new ruleChain in this.ruleChains - public function newGroup():void { + // newRuleChain <- starts a new ruleChain in this.ruleChains + public function newRuleChain():void { if (ruleChains[rcpos].length>0) { - ruleChains[++rcpos]=[]; + ruleChains[++rcpos]=new RuleChain(); } } - // newObject <- adds into the current ruleChain (starting a new Rule) - public function newObject(e:String=''):void { - ruleChains[rcpos].push(new Rule(e)); - } - - // addZoom <- adds into the current ruleChain (existing Rule) - public function addZoom(z1:uint,z2:uint):void { - ruleChains[rcpos][ruleChains[rcpos].length-1].minZoom=z1; - ruleChains[rcpos][ruleChains[rcpos].length-1].maxZoom=z2; - zoomSpecific=true; - } - - // addCondition <- adds into the current ruleChain (existing Rule) - public function addCondition(c:Condition):void { - ruleChains[rcpos][ruleChains[rcpos].length-1].conditions.push(c); - } - // addStyles <- adds to this.styles public function addStyles(a:Array):void { styles=styles.concat(a); From 3136f14c242c551e2edc95abd470ca2382948d9b Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Sun, 12 Jun 2011 19:55:39 +0100 Subject: [PATCH 64/89] Better support for MapCSS 0.2, including subparts --- net/systemeD/halcyon/EntityUI.as | 7 +- net/systemeD/halcyon/MapPaint.as | 12 +-- net/systemeD/halcyon/MarkerUI.as | 38 ++++---- net/systemeD/halcyon/NodeUI.as | 38 ++++---- net/systemeD/halcyon/WayUI.as | 16 ++-- net/systemeD/halcyon/styleparser/RuleChain.as | 12 ++- net/systemeD/halcyon/styleparser/RuleSet.as | 12 ++- .../halcyon/styleparser/ShapeStyle.as | 2 +- .../halcyon/styleparser/StyleChooser.as | 88 +++++++++---------- net/systemeD/halcyon/styleparser/StyleList.as | 10 +-- .../potlatch2/controller/ControllerState.as | 4 +- .../potlatch2/controller/SelectedPOINode.as | 1 + resources/stylesheets/core_interactive.css | 4 +- resources/stylesheets/core_relations.css | 10 +-- resources/stylesheets/core_ways.css | 14 ++- 15 files changed, 138 insertions(+), 130 deletions(-) diff --git a/net/systemeD/halcyon/EntityUI.as b/net/systemeD/halcyon/EntityUI.as index 4a2c62d1..bca513b3 100644 --- a/net/systemeD/halcyon/EntityUI.as +++ b/net/systemeD/halcyon/EntityUI.as @@ -139,13 +139,13 @@ package net.systemeD.halcyon { /** Add object (stroke/fill/roadname) to layer sprite*/ - protected function addToLayer(s:DisplayObject,t:uint,sublayer:int=-1):void { + protected function addToLayer(s:DisplayObject,spritetype:uint,sublayer:int=-1):void { var l:Sprite, o:Sprite; if (sublayer!=-1) { - o=paint.sublayer(layer,sublayer); + o=paint.sublayer(layer,spritetype,sublayer); } else { l=paint.getPaintSpriteAt(layer); - o=l.getChildAt(t) as Sprite; + o=l.getChildAt(spritetype) as Sprite; } o.addChild(s); if (sprites.indexOf(s)==-1) { sprites.push(s); } @@ -155,7 +155,6 @@ package net.systemeD.halcyon { } } - // What does this do, could someone please document? protected function setListenSprite():void { var l:Sprite=paint.getHitSpriteAt(layer); var s:Sprite; diff --git a/net/systemeD/halcyon/MapPaint.as b/net/systemeD/halcyon/MapPaint.as index 31b4808e..8206aefe 100644 --- a/net/systemeD/halcyon/MapPaint.as +++ b/net/systemeD/halcyon/MapPaint.as @@ -75,7 +75,9 @@ package net.systemeD.halcyon { // Add paint sprites for (l=minlayer; l<=maxlayer; l++) { // each layer (10 is +5, 0 is -5) s = getPaintSprite(); // | - s.addChild(getPaintSprite()); // | 0 fill + var q:Sprite = getPaintSprite(); // | 0 fill + q.addChild(getPaintSprite()); // | | sublayer + s.addChild(q); // | | s.addChild(getPaintSprite()); // | 1 casing var t:Sprite = getPaintSprite(); // | 2 stroke t.addChild(getPaintSprite()); // | | sublayer @@ -110,7 +112,7 @@ package net.systemeD.halcyon { return true; } - public function sublayer(layer:int,sublayer:Number):Sprite { + public function sublayer(layer:int,spritetype:uint,sublayer:Number):Sprite { var l:DisplayObject; var o:DisplayObject; var index:String, ix:Number; @@ -132,8 +134,8 @@ package net.systemeD.halcyon { // add sprites for (var i:int=minlayer; i<=maxlayer; i++) { l=getChildAt(i-minlayer); - o=(l as Sprite).getChildAt(2); - (o as Sprite).addChildAt(getPaintSprite(),lowestAbovePos); + o=(l as Sprite).getChildAt(0); (o as Sprite).addChildAt(getPaintSprite(),lowestAbovePos); // fillsprite + o=(l as Sprite).getChildAt(2); (o as Sprite).addChildAt(getPaintSprite(),lowestAbovePos); // strokesprite } // update index @@ -149,7 +151,7 @@ package net.systemeD.halcyon { } l=getChildAt(layer-minlayer); - o=(l as Sprite).getChildAt(2); + o=(l as Sprite).getChildAt(spritetype); return ((o as Sprite).getChildAt(sublayerIndex[sublayer]) as Sprite); } diff --git a/net/systemeD/halcyon/MarkerUI.as b/net/systemeD/halcyon/MarkerUI.as index e2b9f20a..536a2085 100644 --- a/net/systemeD/halcyon/MarkerUI.as +++ b/net/systemeD/halcyon/MarkerUI.as @@ -14,7 +14,7 @@ package net.systemeD.halcyon { public class MarkerUI extends EntityUI { public var loaded:Boolean=false; - private var iconnames:Object={}; // name of icon on each sublayer + private var iconnames:Object={}; // name of icon on each subpart private var heading:Number=0; // heading within way private var rotation:Number=0; // rotation applied to this POI private static const NO_LAYER:int=-99999; @@ -76,47 +76,47 @@ package net.systemeD.halcyon { var w:Number; var icon:Sprite; interactive=false; - for each (var sublayer:Number in styleList.sublayers) { + for each (var subpart:String in styleList.subparts) { - if (styleList.pointStyles[sublayer]) { - var s:PointStyle=styleList.pointStyles[sublayer]; + if (styleList.pointStyles[subpart]) { + var s:PointStyle=styleList.pointStyles[subpart]; interactive||=s.interactive; r=true; if (s.rotation) { rotation=s.rotation; } - if (s.icon_image!=iconnames[sublayer]) { + if (s.icon_image!=iconnames[subpart]) { if (s.icon_image=='square') { // draw square icon=new Sprite(); - addToLayer(icon,STROKESPRITE,sublayer); - w=styleIcon(icon,sublayer); + addToLayer(icon,STROKESPRITE,s.sublayer); + w=styleIcon(icon,subpart); icon.graphics.drawRect(0,0,w,w); if (s.interactive) { maxwidth=Math.max(w,maxwidth); } - iconnames[sublayer]='_square'; + iconnames[subpart]='_square'; } else if (s.icon_image=='circle') { // draw circle icon=new Sprite(); - addToLayer(icon,STROKESPRITE,sublayer); - w=styleIcon(icon,sublayer); + addToLayer(icon,STROKESPRITE,s.sublayer); + w=styleIcon(icon,subpart); icon.graphics.drawCircle(w,w,w); if (s.interactive) { maxwidth=Math.max(w,maxwidth); } - iconnames[sublayer]='_circle'; + iconnames[subpart]='_circle'; } else if (paint.ruleset.images[s.icon_image]) { // 'load' icon (actually just from library) var loader:ExtendedLoader = new ExtendedLoader(); - loader.info['sublayer']=sublayer; + loader.info['sublayer']=s.sublayer; loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadedIcon, false, 0, true); loader.loadBytes(paint.ruleset.images[s.icon_image]); - iconnames[sublayer]=s.icon_image; + iconnames[subpart]=s.icon_image; } } } // name sprite var a:String='', t:TextStyle; - if (styleList.textStyles[sublayer]) { - t=styleList.textStyles[sublayer]; + if (styleList.textStyles[subpart]) { + t=styleList.textStyles[subpart]; interactive||=t.interactive; a=tags[t.text]; } @@ -135,12 +135,12 @@ package net.systemeD.halcyon { } - private function styleIcon(icon:Sprite, sublayer:Number):Number { + private function styleIcon(icon:Sprite, subpart:String):Number { loaded=true; // get colours - if (styleList.shapeStyles[sublayer]) { - var s:ShapeStyle=styleList.shapeStyles[sublayer]; + if (styleList.shapeStyles[subpart]) { + var s:ShapeStyle=styleList.shapeStyles[subpart]; if (!isNaN(s.color)) { icon.graphics.beginFill(s.color); } if (s.casing_width || !isNaN(s.casing_color)) { @@ -151,7 +151,7 @@ package net.systemeD.halcyon { } // return width - return styleList.pointStyles[sublayer].icon_width; + return styleList.pointStyles[subpart].icon_width; } private function addHitSprite(w:uint):void { diff --git a/net/systemeD/halcyon/NodeUI.as b/net/systemeD/halcyon/NodeUI.as index 4f8431f2..cf58a14b 100644 --- a/net/systemeD/halcyon/NodeUI.as +++ b/net/systemeD/halcyon/NodeUI.as @@ -15,7 +15,7 @@ package net.systemeD.halcyon { public class NodeUI extends EntityUI { public var loaded:Boolean=false; - private var iconnames:Object={}; // name of icon on each sublayer + private var iconnames:Object={}; // name of icon on each subpart private var heading:Number=0; // heading within way private var rotation:Number=0; // rotation applied to this POI private static const NO_LAYER:int=-99999; @@ -96,47 +96,47 @@ package net.systemeD.halcyon { var w:Number; var icon:Sprite; interactive=false; - for each (var sublayer:Number in styleList.sublayers) { + for each (var subpart:String in styleList.subparts) { - if (styleList.pointStyles[sublayer]) { - var s:PointStyle=styleList.pointStyles[sublayer]; + if (styleList.pointStyles[subpart]) { + var s:PointStyle=styleList.pointStyles[subpart]; interactive||=s.interactive; r=true; if (s.rotation) { rotation=s.rotation; } - if (s.icon_image!=iconnames[sublayer]) { + if (s.icon_image!=iconnames[subpart]) { if (s.icon_image=='square') { // draw square icon=new Sprite(); - addToLayer(icon,STROKESPRITE,sublayer); - w=styleIcon(icon,sublayer); + addToLayer(icon,STROKESPRITE,s.sublayer); + w=styleIcon(icon,subpart); icon.graphics.drawRect(0,0,w,w); if (s.interactive) { maxwidth=Math.max(w,maxwidth); } - iconnames[sublayer]='_square'; + iconnames[subpart]='_square'; } else if (s.icon_image=='circle') { // draw circle icon=new Sprite(); - addToLayer(icon,STROKESPRITE,sublayer); - w=styleIcon(icon,sublayer); + addToLayer(icon,STROKESPRITE,s.sublayer); + w=styleIcon(icon,subpart); icon.graphics.drawCircle(w,w,w); if (s.interactive) { maxwidth=Math.max(w,maxwidth); } - iconnames[sublayer]='_circle'; + iconnames[subpart]='_circle'; } else if (paint.ruleset.images[s.icon_image]) { // 'load' icon (actually just from library) var loader:ExtendedLoader = new ExtendedLoader(); - loader.info['sublayer']=sublayer; + loader.info['sublayer']=s.sublayer; loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadedIcon, false, 0, true); loader.loadBytes(paint.ruleset.images[s.icon_image]); - iconnames[sublayer]=s.icon_image; + iconnames[subpart]=s.icon_image; } } } // name sprite var a:String='', t:TextStyle; - if (styleList.textStyles[sublayer]) { - t=styleList.textStyles[sublayer]; + if (styleList.textStyles[subpart]) { + t=styleList.textStyles[subpart]; interactive||=t.interactive; a=tags[t.text]; } @@ -155,12 +155,12 @@ package net.systemeD.halcyon { } - private function styleIcon(icon:Sprite, sublayer:Number):Number { + private function styleIcon(icon:Sprite, subpart:String):Number { loaded=true; // get colours - if (styleList.shapeStyles[sublayer]) { - var s:ShapeStyle=styleList.shapeStyles[sublayer]; + if (styleList.shapeStyles[subpart]) { + var s:ShapeStyle=styleList.shapeStyles[subpart]; if (!isNaN(s.color)) { icon.graphics.beginFill(s.color, s.opacity ? s.opacity : 1); } if (s.casing_width || !isNaN(s.casing_color)) { @@ -171,7 +171,7 @@ package net.systemeD.halcyon { } // return width - return styleList.pointStyles[sublayer].icon_width; + return styleList.pointStyles[subpart].icon_width; } private function addHitSprite(w:uint):void { diff --git a/net/systemeD/halcyon/WayUI.as b/net/systemeD/halcyon/WayUI.as index 0f5ebdd4..fdec4d40 100644 --- a/net/systemeD/halcyon/WayUI.as +++ b/net/systemeD/halcyon/WayUI.as @@ -259,7 +259,7 @@ package net.systemeD.halcyon { indexEnd =Math.min(drawOnly+2,Way(entity).length); } - // Iterate through each sublayer, drawing any styles on that layer + // Iterate through each subpart, drawing any styles on that layer var drawn:Boolean; var multis:Array=entity.findParentRelationsOfType('multipolygon','outer'); var inners:Array=[]; @@ -267,9 +267,9 @@ package net.systemeD.halcyon { inners=inners.concat(m.findMembersByRole('inner',Way)); } - for each (var sublayer:Number in styleList.sublayers) { - if (styleList.shapeStyles[sublayer]) { - var s:ShapeStyle=styleList.shapeStyles[sublayer]; + for each (var subpart:String in styleList.subparts) { + if (styleList.shapeStyles[subpart]) { + var s:ShapeStyle=styleList.shapeStyles[subpart]; var stroke:Shape, fill:Shape, casing:Shape, roadname:Sprite; var x0:Number=paint.map.lon2coord(Way(entity).getNode(0).lon); var y0:Number=paint.map.latp2coord(Way(entity).getNode(0).latp); @@ -277,7 +277,7 @@ package net.systemeD.halcyon { // Stroke if (s.width) { - stroke=new Shape(); addToLayer(stroke,STROKESPRITE,sublayer); + stroke=new Shape(); addToLayer(stroke,STROKESPRITE,s.sublayer); stroke.graphics.moveTo(x0,y0); s.applyStrokeStyle(stroke.graphics); if (s.dashes && s.dashes.length>0) { @@ -290,7 +290,7 @@ package net.systemeD.halcyon { // Fill if ((!isNaN(s.fill_color) || s.fill_image) && entity.findParentRelationsOfType('multipolygon','inner').length==0 && isNaN(drawExcept)) { - fill=new Shape(); addToLayer(fill,FILLSPRITE); + fill=new Shape(); addToLayer(fill,FILLSPRITE,s.sublayer); fill.graphics.moveTo(x0,y0); if (s.fill_image) { new WayBitmapFiller(this,fill.graphics,s); } else { s.applyFill(fill.graphics); } @@ -311,8 +311,8 @@ package net.systemeD.halcyon { } } - if (styleList.textStyles[sublayer] && isNaN(drawExcept)) { - var t:TextStyle=styleList.textStyles[sublayer]; + if (styleList.textStyles[subpart] && isNaN(drawExcept)) { + var t:TextStyle=styleList.textStyles[subpart]; interactive||=t.interactive; roadname=new Sprite(); addToLayer(roadname,NAMESPRITE); nameformat = t.getTextFormat(); diff --git a/net/systemeD/halcyon/styleparser/RuleChain.as b/net/systemeD/halcyon/styleparser/RuleChain.as index cd6c5b43..61bca340 100644 --- a/net/systemeD/halcyon/styleparser/RuleChain.as +++ b/net/systemeD/halcyon/styleparser/RuleChain.as @@ -15,8 +15,8 @@ package net.systemeD.halcyon.styleparser { */ public class RuleChain { - public var rules:Array=[]; // should eventually become a Vector of Rules - public var subpart:String=''; // subpart name, as in way[highway=primary]::centreline + public var rules:Array=[]; // should eventually become a Vector of Rules + public var subpart:String='default'; // subpart name, as in way[highway=primary]::centreline // Test a ruleChain // - run a set of tests in the chain @@ -27,8 +27,9 @@ package net.systemeD.halcyon.styleparser { // - if they succeed, and there's more in the chain, rerun this for each parent until success public function test(pos:int, obj:Entity, tags:Object, zoom:uint):Boolean { + if (length==0) { return false; } if (pos==-1) { pos=rules.length-1; } - + var r:Rule=rules[pos]; if (!r.test(obj, tags, zoom)) { return false; } if (pos==0) { return true; } @@ -44,6 +45,10 @@ package net.systemeD.halcyon.styleparser { return rules.length; } + public function setSubpart(s:String):void { + subpart = s=='' ? 'default' : s; + } + // --------------------------------------------------------------------------------------------- // Methods to add properties (used by parsers such as MapCSS) @@ -60,6 +65,5 @@ package net.systemeD.halcyon.styleparser { rules[rules.length-1].maxZoom=z2; } - } } diff --git a/net/systemeD/halcyon/styleparser/RuleSet.as b/net/systemeD/halcyon/styleparser/RuleSet.as index 0bf9923a..1c9f6be8 100644 --- a/net/systemeD/halcyon/styleparser/RuleSet.as +++ b/net/systemeD/halcyon/styleparser/RuleSet.as @@ -43,7 +43,7 @@ package net.systemeD.halcyon.styleparser { private static const CONDITION:RegExp =/^ \[(.+?)\] \s* /sx; private static const OBJECT:RegExp =/^ (\w+) \s* /sx; private static const DECLARATION:RegExp =/^ \{(.+?)\} \s* /sx; - private static const SUBPART:RegExp =/^ ::(\S+) \s* /sx; + private static const SUBPART:RegExp =/^ ::(\w+) \s* /sx; private static const UNKNOWN:RegExp =/^ (\S+) \s* /sx; private static const ZOOM_MINMAX:RegExp =/^ (\d+)\-(\d+) $/sx; @@ -75,6 +75,7 @@ package net.systemeD.halcyon.styleparser { private static const oCONDITION:uint=4; private static const oOBJECT:uint=5; private static const oDECLARATION:uint=6; + private static const oSUBPART:uint=7; private static const DASH:RegExp=/\-/g; private static const COLOR:RegExp=/color$/; @@ -288,7 +289,7 @@ package net.systemeD.halcyon.styleparser { else if (style is ShieldStyle && ShieldStyle(style).shield_image) { filename=ShieldStyle(style).shield_image; } else { continue; } if (filename=='square' || filename=='circle') { continue; } - + iconsToLoad++; var request:DebugURLRequest=new DebugURLRequest(filename); var loader:ExtendedURLLoader=new ExtendedURLLoader(); @@ -410,6 +411,13 @@ package net.systemeD.halcyon.styleparser { sc.currentChain.addRule(o[1]); previous=oOBJECT; + // Subpart - ::centreline + } else if ((o=SUBPART.exec(css))) { + if (previous==oDECLARATION) { saveChooser(sc); sc=new StyleChooser(); } + css=css.replace(SUBPART,''); + sc.currentChain.setSubpart(o[1]); + previous=oSUBPART; + // Declaration - {...} } else if ((o=DECLARATION.exec(css))) { css=css.replace(DECLARATION,''); diff --git a/net/systemeD/halcyon/styleparser/ShapeStyle.as b/net/systemeD/halcyon/styleparser/ShapeStyle.as index 03411fc0..1ec99967 100644 --- a/net/systemeD/halcyon/styleparser/ShapeStyle.as +++ b/net/systemeD/halcyon/styleparser/ShapeStyle.as @@ -45,7 +45,7 @@ package net.systemeD.halcyon.styleparser { } public function applyCasingStyle(g:Graphics):void { - g.lineStyle(casing_width, + g.lineStyle(width + casing_width, casing_color ? casing_color : 0, casing_opacity ? casing_opacity : 1, false, "normal", diff --git a/net/systemeD/halcyon/styleparser/StyleChooser.as b/net/systemeD/halcyon/styleparser/StyleChooser.as index 1a3f86fa..c2d29809 100644 --- a/net/systemeD/halcyon/styleparser/StyleChooser.as +++ b/net/systemeD/halcyon/styleparser/StyleChooser.as @@ -38,7 +38,7 @@ package net.systemeD.halcyon.styleparser { public function get currentChain():RuleChain { return ruleChains[rcpos]; } - + // Update the current StyleList from this StyleChooser public function updateStyles(obj:Entity, tags:Object, sl:StyleList, imageWidths:Object, zoom:uint):void { @@ -46,53 +46,50 @@ package net.systemeD.halcyon.styleparser { // Are any of the ruleChains fulfilled? var w:Number; - var fulfilled:Boolean=false; for each (var c:RuleChain in ruleChains) { if (c.test(-1,obj,tags,zoom)) { - fulfilled=true; break; - } - } - if (!fulfilled) { return; } + sl.addSubpart(c.subpart); - // Update StyleList - for each (var r:Style in styles) { - var a:*; - if (r is ShapeStyle) { - a=sl.shapeStyles; - if (ShapeStyle(r).width>sl.maxwidth && !r.evals['width']) { sl.maxwidth=ShapeStyle(r).width; } - } else if (r is ShieldStyle) { - a=sl.shieldStyles; - } else if (r is TextStyle) { - a=sl.textStyles; - } else if (r is PointStyle) { - a=sl.pointStyles; - w=0; - if (PointStyle(r).icon_width && !PointStyle(r).evals['icon_width']) { - w=PointStyle(r).icon_width; - } else if (PointStyle(r).icon_image && imageWidths[PointStyle(r).icon_image]) { - w=imageWidths[PointStyle(r).icon_image]; - } - if (w>sl.maxwidth) { sl.maxwidth=w; } - } else if (r is InstructionStyle) { - if (InstructionStyle(r).breaker) { return; } - if (InstructionStyle(r).set_tags) { - for (var k:String in InstructionStyle(r).set_tags) { tags[k]=InstructionStyle(r).set_tags[k]; } - } - continue; - } - if (r.drawn) { tags[':drawn']='yes'; } - tags['_width']=sl.maxwidth; + // Update StyleList + for each (var r:Style in styles) { + var a:Object; + if (r is ShapeStyle) { + a=sl.shapeStyles; + if (ShapeStyle(r).width>sl.maxwidth && !r.evals['width']) { sl.maxwidth=ShapeStyle(r).width; } + } else if (r is ShieldStyle) { + a=sl.shieldStyles; + } else if (r is TextStyle) { + a=sl.textStyles; + } else if (r is PointStyle) { + a=sl.pointStyles; + w=0; + if (PointStyle(r).icon_width && !PointStyle(r).evals['icon_width']) { + w=PointStyle(r).icon_width; + } else if (PointStyle(r).icon_image && imageWidths[PointStyle(r).icon_image]) { + w=imageWidths[PointStyle(r).icon_image]; + } + if (w>sl.maxwidth) { sl.maxwidth=w; } + } else if (r is InstructionStyle) { + if (InstructionStyle(r).breaker) { return; } + if (InstructionStyle(r).set_tags) { + for (var k:String in InstructionStyle(r).set_tags) { tags[k]=InstructionStyle(r).set_tags[k]; } + } + continue; + } + if (r.drawn) { tags[':drawn']='yes'; } + tags['_width']=sl.maxwidth; - r.runEvals(tags); - sl.addSublayer(r.sublayer); - if (a[r.sublayer]) { - // If there's already a style on this sublayer, then merge them - // (making a deep copy if necessary to avoid altering the root style) - if (!a[r.sublayer].merged) { a[r.sublayer]=a[r.sublayer].deepCopy(); } - a[r.sublayer].mergeWith(r); - } else { - // Otherwise, just assign it - a[r.sublayer]=r; + r.runEvals(tags); + if (a[c.subpart]) { + // If there's already a style on this sublayer, then merge them + // (making a deep copy if necessary to avoid altering the root style) + if (!a[c.subpart].merged) { a[c.subpart]=a[c.subpart].deepCopy(); } + a[c.subpart].mergeWith(r); + } else { + // Otherwise, just assign it + a[c.subpart]=r; + } + } } } } @@ -108,10 +105,9 @@ package net.systemeD.halcyon.styleparser { } } - // addStyles <- adds to this.styles public function addStyles(a:Array):void { styles=styles.concat(a); } - + } } diff --git a/net/systemeD/halcyon/styleparser/StyleList.as b/net/systemeD/halcyon/styleparser/StyleList.as index c2fd02bd..97bcd1ad 100644 --- a/net/systemeD/halcyon/styleparser/StyleList.as +++ b/net/systemeD/halcyon/styleparser/StyleList.as @@ -19,8 +19,8 @@ package net.systemeD.halcyon.styleparser { public var shieldStyles:Object={}; public var maxwidth:Number=0; - /** List of sublayers used in this StyleList. */ - public var sublayers:Array=[]; + /** List of subparts used in this StyleList. */ + public var subparts:Array=[]; /** Zoom level this StyleList is valid at. If -1, valid at all styles (i.e. doesn't need to be recomputed on zoom in/out); otherwise, specifies a single zoom level. */ @@ -47,9 +47,9 @@ package net.systemeD.halcyon.styleparser { return NaN; } - /** Record that a sublayer is used in this StyleList. */ - public function addSublayer(s:Number):void { - if (sublayers.indexOf(s)==-1) { sublayers.push(s); } + /** Record that a subpart is used in this StyleList. */ + public function addSubpart(s:String):void { + if (subparts.indexOf(s)==-1) { subparts.push(s); } } /** Summarise StyleList as String - for debugging. */ diff --git a/net/systemeD/potlatch2/controller/ControllerState.as b/net/systemeD/potlatch2/controller/ControllerState.as index c9645aeb..f6f00a9c 100644 --- a/net/systemeD/potlatch2/controller/ControllerState.as +++ b/net/systemeD/potlatch2/controller/ControllerState.as @@ -99,11 +99,11 @@ package net.systemeD.potlatch2.controller { var newEntity:Entity=paint.pullThrough(entity,editableLayer); if (entity is Way ) { return new SelectedWay(newEntity as Way); } else if (entity is Node) { return new SelectedPOINode(newEntity as Node); } + } else if (event.type == MouseEvent.MOUSE_DOWN && entity is Marker) { + return new SelectedMarker(entity as Marker, paint); } else if (event.type == MouseEvent.MOUSE_DOWN) { if (entity is Way ) { return new SelectedBackgroundWay(entity as Way); } else if (entity is Node) { return new SelectedBackgroundNode(entity as Node, paint); } - } else if (event.type == MouseEvent.MOUSE_DOWN && entity is Marker) { - return new SelectedMarker(entity as Marker, paint); } else if ( event.type == MouseEvent.MOUSE_UP ) { return (this is NoSelection) ? null : new NoSelection(); } else { return null; } diff --git a/net/systemeD/potlatch2/controller/SelectedPOINode.as b/net/systemeD/potlatch2/controller/SelectedPOINode.as index 2710dc99..9b893cb2 100644 --- a/net/systemeD/potlatch2/controller/SelectedPOINode.as +++ b/net/systemeD/potlatch2/controller/SelectedPOINode.as @@ -63,6 +63,7 @@ package net.systemeD.potlatch2.controller { editableLayer.setPurgable(selection,false); } override public function exitState(newState:ControllerState):void { +trace("firstSelected is "+firstSelected); if(firstSelected.hasTags()) { controller.clipboards['node']=firstSelected.getTagsCopy(); } diff --git a/resources/stylesheets/core_interactive.css b/resources/stylesheets/core_interactive.css index 0e4ae871..402d86d9 100644 --- a/resources/stylesheets/core_interactive.css +++ b/resources/stylesheets/core_interactive.css @@ -20,5 +20,5 @@ node !:drawn :poi { z-index: 2; icon-image: circle; icon-width: 4; color: green; node !:drawn :hasTags { z-index: 9; icon-image: circle; icon-width: 4; color: black; } node :hasTags :selectedway { z-index: 9; icon-image: square; icon-width: 8; color: black; layer: 5; } node !:drawn :selectedway { z-index: 9; icon-image: square; icon-width: 8; color: red; casing-color: #cc0000; casing-width: 1; layer: 5; } -node :selected { z-index: 1; icon-image: square; icon-width: eval('_width+10'); color: yellow; interactive: no; layer: 5; } -node :junction :selectedway { z-index: 8; icon-image: square; icon-width: 12; casing-color: black; casing-width: 1; layer: 5; } +node::selectedNode :selected { z-index: 1; icon-image: square; icon-width: eval('_width+10'); color: yellow; interactive: no; layer: 5; } +node::junctionNode :junction :selectedway { z-index: 8; icon-image: square; icon-width: 12; casing-color: black; casing-width: 1; layer: 5; } diff --git a/resources/stylesheets/core_relations.css b/resources/stylesheets/core_relations.css index d1b2d5f6..7756abe6 100644 --- a/resources/stylesheets/core_relations.css +++ b/resources/stylesheets/core_relations.css @@ -1,7 +1,7 @@ /* Route relations */ -relation[type=route] way { z-index: 1; width: 13; color: blue; opacity: 0.3; } -relation[type=route][route=bicycle][network=ncn] way { z-index: 1; width: 12; color: red; opacity: 0.3; } -relation[type=route][route=bicycle][network=rcn] way { z-index: 1; width: 12; color: cyan; opacity: 0.3; } -relation[type=route][route=bicycle][network=lcn] way { z-index: 1; width: 12; color: blue; opacity: 0.3; } -relation[type=route][route=foot] way { z-index: 1; width: 10; color: #80ff80; opacity: 0.6; } +relation[type=route] way::route { z-index: 1; width: 13; color: blue; opacity: 0.3; } +relation[type=route][route=bicycle][network=ncn] way::route { z-index: 1; width: 12; color: red; opacity: 0.3; } +relation[type=route][route=bicycle][network=rcn] way::route { z-index: 1; width: 12; color: cyan; opacity: 0.3; } +relation[type=route][route=bicycle][network=lcn] way::route { z-index: 1; width: 12; color: blue; opacity: 0.3; } +relation[type=route][route=foot] way::route { z-index: 1; width: 10; color: #80ff80; opacity: 0.6; } diff --git a/resources/stylesheets/core_ways.css b/resources/stylesheets/core_ways.css index 9e087f59..876c5b56 100644 --- a/resources/stylesheets/core_ways.css +++ b/resources/stylesheets/core_ways.css @@ -112,14 +112,12 @@ way[leisure=sports_centre] :area { color: #66ddcc; fill-color: #66ddcc; set .are /* Physical decoration */ -way[bridge=yes], way[bridge=viaduct], way[bridge=suspension] - { z-index: 4; color: white; width: eval('_width+3'); } - { z-index: 3; color: black; width: eval('_width+6'); } -way[tunnel=yes][!waterway] - { z-index: 4; color: white; width: eval('_width+2'); } - { z-index: 3; color: black; width: eval('_width+6'); dashes: 4,4; } +way[bridge=yes]::bridge1, way[bridge=viaduct]::bridge1, way[bridge=suspension]::bridge1 { z-index: 4; color: white; width: eval('_width+3'); } +way[bridge=yes]::bridge2, way[bridge=viaduct]::bridge2, way[bridge=suspension]::bridge2 { z-index: 3; color: black; width: eval('_width+6'); } +way[tunnel=yes][!waterway]::bridge1 { z-index: 4; color: white; width: eval('_width+2'); } +way[tunnel=yes][!waterway]::bridge2 { z-index: 3; color: black; width: eval('_width+6'); dashes: 4,4; } /* Attribute decoration */ -way[oneway=yes], way[junction=roundabout] { z-index: 15; color: #444444; width: 2; dashes: 15,35; line-style: arrows; } -way[oneway=-1] { z-index: 15; color: #444444; width: 2; dashes: 15,35; line-style: arrows-reversed; } +way[oneway=yes]::arrows, way[junction=roundabout]::arrows { z-index: 15; color: #444444; width: 2; dashes: 15,35; line-style: arrows; } +way[oneway=-1]::arrows { z-index: 15; color: #444444; width: 2; dashes: 15,35; line-style: arrows-reversed; } From cea362ec3b287632b3443741b586ce347400c850 Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Sun, 12 Jun 2011 19:58:25 +0100 Subject: [PATCH 65/89] Remove trace statement --- net/systemeD/potlatch2/controller/SelectedPOINode.as | 1 - 1 file changed, 1 deletion(-) diff --git a/net/systemeD/potlatch2/controller/SelectedPOINode.as b/net/systemeD/potlatch2/controller/SelectedPOINode.as index 9b893cb2..2710dc99 100644 --- a/net/systemeD/potlatch2/controller/SelectedPOINode.as +++ b/net/systemeD/potlatch2/controller/SelectedPOINode.as @@ -63,7 +63,6 @@ package net.systemeD.potlatch2.controller { editableLayer.setPurgable(selection,false); } override public function exitState(newState:ControllerState):void { -trace("firstSelected is "+firstSelected); if(firstSelected.hasTags()) { controller.clipboards['node']=firstSelected.getTagsCopy(); } From 1fac4e85c46d5003e1ba0ff6823fb126cd0bfd83 Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Wed, 15 Jun 2011 11:43:15 +0100 Subject: [PATCH 66/89] Fix casing widths in a not-completely-scientific way. I suspect in most cases ~1 was what was intended anyway --- resources/stylesheets/core_landuse.css | 4 +-- resources/stylesheets/core_ways.css | 44 +++++++++++++------------- resources/stylesheets/opencyclemap.css | 16 +++++----- 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/resources/stylesheets/core_landuse.css b/resources/stylesheets/core_landuse.css index 7eeb1173..a113cc7e 100644 --- a/resources/stylesheets/core_landuse.css +++ b/resources/stylesheets/core_landuse.css @@ -28,10 +28,10 @@ way[leisure=pitch] :area { z-index: 6; color: #88bb44; width: 2; fill-color: way[landuse=recreation_ground] :area { color: green; fill-color: green; set .area_small_name;} way[amenity=parking] :area { color: #bbaa66; width: 1; fill-color: #bbaa66; fill-opacity: 0.2; } way[public_transport=pay_scale_area] :area { color: gray; width: 1; fill-color: gray; fill-opacity: 0.1; } -way[man_made=pier] { z-index: 4; color: #777; width: 3; casing-color: black; casing-width: 5;} +way[man_made=pier] { z-index: 4; color: #777; width: 3; casing-color: black; casing-width: 1;} way[man_made=pier][floating=yes] { dashes: 4,2; casing-color: #444;} way[leisure=marina] :area { color: pink; fill-color: pink; fill-opacity: 0.4; set .area_small_name;} -way[leisure=slipway] { color: grey; width: 3; casing-color: blue; casing-width: 7; } +way[leisure=slipway] { color: grey; width: 3; casing-color: blue; casing-width: 2; } way[leisure=golf_course] :area { color: #44ee22; width: 2; fill-color: #44ee22; fill-opacity: 0.2; set .area_small_name;} way[boundary] { color: #000066; width: 2; opacity: 0.6; dashes: 24,4, 4, 4; z-index: 4;} /* Perhaps should be filled, on lower zooms. */ diff --git a/resources/stylesheets/core_ways.css b/resources/stylesheets/core_ways.css index 876c5b56..ccb9dbe6 100644 --- a/resources/stylesheets/core_ways.css +++ b/resources/stylesheets/core_ways.css @@ -7,23 +7,23 @@ way[highway=primary],way[highway=primary_link], way[highway=secondary],way[highway=secondary_link], way[highway=tertiary],way[highway=tertiary_link], way[highway=residential],way[highway=unclassified] { text: name; text-color: black; font-size: 10; text-position: line; text-halo-color: white; text-halo-radius: 2; } -way[highway=motorway],way[highway=motorway_link] { z-index: 9; color: #809BC0; width: 7; casing-color: black; casing-width: 8; } -way[highway=trunk],way[highway=trunk_link] { z-index: 9; color: #7FC97F; width: 7; casing-color: black; casing-width: 8; } -way[highway=primary],way[highway=primary_link] { z-index: 8; color: #E46D71; width: 7; casing-color: black; casing-width: 8; } -way[highway=secondary],way[highway=secondary_link] { z-index: 7; color: #FDBF6F; width: 7; casing-width: 8; } -way[highway=tertiary] { z-index: 6; color: #FEFECB; width: 5; casing-width: 7; } -way[highway=unclassified] { z-index: 6; color: #D0D0D0; width: 5; casing-width: 7; } -way[highway=tertiary_link] { z-index: 5; color: #FEFECB; width: 4; casing-width: 5; } -way[highway=residential] { z-index: 5; color: #E8E8E8; width: 5; casing-color: gray; casing-width: 7; } -way[highway=service][service!=parking_aisle] { color: white; width: 3; casing-color: gray; casing-width: 5; } -way[highway=service][service=parking_aisle] { color: white; width: 1; casing-color: #aaaaaa; casing-width: 2; } -way[highway=service][service=alley] { color: white; width: 2; dashes: 6,2; casing-color: black; casing-width: 4; } -way[highway=road] { color: gray; width: 5; casing-color: white; casing-width: 7; } -way[highway=living_street] { z-index: 5; color: #ddffee; width: 3; casing-color: #555555; casing-width: 4; } +way[highway=motorway],way[highway=motorway_link] { z-index: 9; color: #809BC0; width: 7; casing-color: black; casing-width: 1; } +way[highway=trunk],way[highway=trunk_link] { z-index: 9; color: #7FC97F; width: 7; casing-color: black; casing-width: 1; } +way[highway=primary],way[highway=primary_link] { z-index: 8; color: #E46D71; width: 7; casing-color: black; casing-width: 1; } +way[highway=secondary],way[highway=secondary_link] { z-index: 7; color: #FDBF6F; width: 7; casing-width: 1; } +way[highway=tertiary] { z-index: 6; color: #FEFECB; width: 5; casing-width: 1; } +way[highway=unclassified] { z-index: 6; color: #D0D0D0; width: 5; casing-width: 1; } +way[highway=tertiary_link] { z-index: 5; color: #FEFECB; width: 4; casing-width: 1; } +way[highway=residential] { z-index: 5; color: #E8E8E8; width: 5; casing-color: gray; casing-width: 1; } +way[highway=service][service!=parking_aisle] { color: white; width: 3; casing-color: gray; casing-width: 1; } +way[highway=service][service=parking_aisle] { color: white; width: 1; casing-color: #aaaaaa; casing-width: 1; } +way[highway=service][service=alley] { color: white; width: 2; dashes: 6,2; casing-color: black; casing-width: 1; } +way[highway=road] { color: gray; width: 5; casing-color: white; casing-width: 1; } +way[highway=living_street] { z-index: 5; color: #ddffee; width: 3; casing-color: #555555; casing-width: 1; } /* Road areas */ -way[highway=pedestrian] !:area { color: #ddddee; width: 5; casing-color: #555555; casing-width: 6; casing-dashes: 2,4;} +way[highway=pedestrian] !:area { color: #ddddee; width: 5; casing-color: #555555; casing-width: 1; casing-dashes: 2,4;} way[highway=pedestrian] :area { color: #555555; width: 1; fill-color: #ddddee; fill-opacity: 0.8; } /* Paths */ @@ -35,13 +35,13 @@ way[highway=bridleway] { z-index:9; color: #996644; width: 2; dashes: 4, 2, 2, 2 way[highway=track] { color: #996644; width: 2; dashes: 4, 2; set .path;} way[highway=path] { color: brown; width: 2; dashes: 2, 2; set .path;} way[highway=cycleway] { color: blue; width: 2; dashes: 4, 2; set .path;} -way[railway=tram] { z-index: 11; color: #999999; width: 2; casing-color: black; casing-width: 6; } +way[railway=tram] { z-index: 11; color: #999999; width: 2; casing-color: black; casing-width: 2; } way .path { text:name; text-color: black; text-position: offset; text-offset: 5;} /* Under construction */ way[highway=proposed] { color: #88ffff; width: 6; dashes: 8, 4; } -way[highway=construction] { color: #ffffbb; width: 6; dashes: 8, 4; casing-color: #0000aa; casing-width: 8; casing-dashes: 8,4;} +way[highway=construction] { color: #ffffbb; width: 6; dashes: 8, 4; casing-color: #0000aa; casing-width: 1; casing-dashes: 8,4;} way[construction=rail] { z-index: 6; color: black; width: 5; dashes: 6, 6, 4, 8;} { z-index: 7; color: white; width: 3; dashes: 6,18; } @@ -70,13 +70,13 @@ way[waterway][tunnel=yes] {dashes: 8,4;} /* Aeroways */ way[aeroway=aerodrome] :area - { z-index: 3; color: #bb44bb; width: 3; casing-color: #66066; casing-width: 4; } + { z-index: 3; color: #bb44bb; width: 3; casing-color: #66066; casing-width: 1; } way|z-15[aeroway=aerodrome] :area { z-index: 3; fill-color: #bb99bb; fill-opacity: 0.5;} -way[aeroway=taxiway] !:area { z-index: 8; color: #999999; width: 3; casing-color: #aa66aa; casing-width: 6; } +way[aeroway=taxiway] !:area { z-index: 8; color: #999999; width: 3; casing-color: #aa66aa; casing-width: 2; } way[aeroway=taxiway] :area { z-index: 8; color: #bb99bb; width: 3; fill-color: #ccaacc; } way|z17-[aeroway=runway] !:area - { z-index: 9; color: black; width: 11; casing-color: #aa66aa; casing-width: 12; } + { z-index: 9; color: black; width: 11; casing-color: #aa66aa; casing-width: 1; } { z-index: 10; color: white; width: 9; dashes: 0, 20, 4, 76; } { z-index: 11; color: black; width: 7; } { z-index: 12; color: white; width: 5; dashes: 0, 20, 4, 76; } @@ -99,14 +99,14 @@ way[barrier=fence] {color: #000000; width: 1; dashes: 8,4,2,4; } /* Power */ -way[power=line] {color: darkgray; width: 3; dashes: 12,2; casing-color: black; casing-width: 8; casing-dashes: 4, 38;} -way[power=minor_line] {color: gray; width: 2; dashes: 2,4; casing-width: 8; casing-color: white; casing-dashes: 2,22;} +way[power=line] {color: darkgray; width: 3; dashes: 12,2; casing-color: black; casing-width: 2; casing-dashes: 4, 38;} +way[power=minor_line] {color: gray; width: 2; dashes: 2,4; casing-width: 3; casing-color: white; casing-dashes: 2,22;} way[power=station] :area { color: black; width: 2; fill-color: #666666; fill-opacity: 0.6; set .area_small_name;} way[power=generator] :area { color: black; width: 2; fill-color: #444444; fill-opacity: 0.6; set .area_small_name;} /* Leisure */ -way[golf=hole] {color: darkgreen; width: 5; casing-color: green; casing-width: 10; } +way[golf=hole] {color: darkgreen; width: 5; casing-color: green; casing-width: 2; } way[leisure=sports_centre] :area { color: #66ddcc; fill-color: #66ddcc; set .area_small_name; } diff --git a/resources/stylesheets/opencyclemap.css b/resources/stylesheets/opencyclemap.css index 194d9101..1a1e80fe 100644 --- a/resources/stylesheets/opencyclemap.css +++ b/resources/stylesheets/opencyclemap.css @@ -27,17 +27,17 @@ way[highway=primary],way[highway=primary_link], way[highway=secondary],way[highway=secondary_link], way[highway=tertiary],way[highway=tertiary_link], way[highway=residential] { text: name; text-color: black; font-size: 7; text-position: line;}*/ -way[highway=motorway],way[highway=motorway_link] { z-index: 9; color: #bfbfcf; width: 7; casing-color: #506077; casing-width: 9; } -way[highway=trunk],way[highway=trunk_link] { z-index: 9; color: #c8d8c8; width: 7; casing-color: #477147; casing-width: 9; } -way[highway=primary],way[highway=primary_link] { z-index: 8; color: #d8c8c8; width: 7; casing-color: #8d4346; casing-width: 9; } -way[highway=secondary],way[highway=secondary_link] { z-index: 7; color: #eeeec9; width: 7; casing-color: #a37b48; casing-width: 9; } -way[highway=tertiary],way[highway=unclassified] { z-index: 6; color: #eeeec9; width: 5; casing-color: #999999; casing-width: 7; } -way[highway=residential] { z-index: 5; color: white; width: 5; casing-color: #999; casing-width: 7; } -way[highway=service] { color: white; width: 3; casing-color: #999; casing-width: 5; } +way[highway=motorway],way[highway=motorway_link] { z-index: 9; color: #bfbfcf; width: 7; casing-color: #506077; casing-width: 1; } +way[highway=trunk],way[highway=trunk_link] { z-index: 9; color: #c8d8c8; width: 7; casing-color: #477147; casing-width: 1; } +way[highway=primary],way[highway=primary_link] { z-index: 8; color: #d8c8c8; width: 7; casing-color: #8d4346; casing-width: 1; } +way[highway=secondary],way[highway=secondary_link] { z-index: 7; color: #eeeec9; width: 7; casing-color: #a37b48; casing-width: 1; } +way[highway=tertiary],way[highway=unclassified] { z-index: 6; color: #eeeec9; width: 5; casing-color: #999999; casing-width: 1; } +way[highway=residential] { z-index: 5; color: white; width: 5; casing-color: #999; casing-width: 1; } +way[highway=service] { color: white; width: 3; casing-color: #999; casing-width: 1; } /* Pedestrian precincts need to be treated carefully. Only closed-loops with an explicit area=yes tag should be filled. The below doesn't yet work as intended. */ -way[highway=pedestrian] !:area { color: #ddddee; width: 5; casing-color: #555555; casing-width: 6; } +way[highway=pedestrian] !:area { color: #ddddee; width: 5; casing-color: #555555; casing-width: 1; } way[highway=pedestrian] :area { color: #555555; width: 1; fill-color: #ddddee; fill-opacity: 0.8; } way[highway=steps] { color: #be6c6c; width: 2; dashes: 4, 2; } From 43ed0cf8de3fdac31e23f51598fbcd5a6ab387d6 Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Wed, 15 Jun 2011 11:44:03 +0100 Subject: [PATCH 67/89] Fix railways to have a separate dashes layer --- resources/stylesheets/opencyclemap.css | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/resources/stylesheets/opencyclemap.css b/resources/stylesheets/opencyclemap.css index 1a1e80fe..ae0ac977 100644 --- a/resources/stylesheets/opencyclemap.css +++ b/resources/stylesheets/opencyclemap.css @@ -107,13 +107,11 @@ node[barrier=cattle_grid] { icon-image: icons/cattle_grid.png; }*/ /* We can stack styles at different z-index (depth) */ -way[railway=rail] - { z-index: 6; color: #444444; width: 5; } - { z-index: 7; color: white; width: 3; dashes: 12,12; } +way[railway=rail] { z-index: 6; color: #444444; width: 5; } +way[railway=rail]::dashes { z-index: 7; color: white; width: 3; dashes: 12,12; } way[railway=platform] { color:black; width: 2; } -way[railway=subway] - { z-index: 6; color: #444444; width: 5; } - { z-index: 7; color: white; width: 3; dashes: 8,8; } +way[railway=subway] { z-index: 6; color: #444444; width: 5; } +way[railway=subway]::dashes { z-index: 7; color: white; width: 3; dashes: 8,8; } /* Bridge */ way[bridge=yes], way[bridge=viaduct], way[bridge=suspension] From 4348438f1ae51441aa6c776dcd42378a70ca7184 Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Wed, 15 Jun 2011 11:45:05 +0100 Subject: [PATCH 68/89] use selectors for bridges, tunnels and arrows --- resources/stylesheets/opencyclemap.css | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/resources/stylesheets/opencyclemap.css b/resources/stylesheets/opencyclemap.css index ae0ac977..bbf65d0b 100644 --- a/resources/stylesheets/opencyclemap.css +++ b/resources/stylesheets/opencyclemap.css @@ -114,17 +114,15 @@ way[railway=subway] { z-index: 6; color: #444444; width: 5; } way[railway=subway]::dashes { z-index: 7; color: white; width: 3; dashes: 8,8; } /* Bridge */ -way[bridge=yes], way[bridge=viaduct], way[bridge=suspension] - { z-index: 4; color: white; width: eval('_width+3'); } - { z-index: 3; color: black; width: eval('_width+6'); } +way[bridge=yes]::bridge1, way[bridge=viaduct]::bridge1, way[bridge=suspension]::bridge1 { z-index: 4; color: white; width: eval('_width+3'); } +way[bridge=yes]::bridge2, way[bridge=viaduct]::bridge2, way[bridge=suspension]::bridge2 { z-index: 3; color: black; width: eval('_width+6'); } /* Tunnel */ -way[tunnel=yes] - { z-index: 4; color: white; width: eval('_width+2'); } - { z-index: 3; color: black; width: eval('_width+6'); dashes: 4,4; } +way[tunnel=yes]::tunnel1 { z-index: 4; color: white; width: eval('_width+2'); } +way[tunnel=yes]::tunnel2 { z-index: 3; color: black; width: eval('_width+6'); dashes: 4,4; } /* Oneway */ -way[oneway=yes] { z-index: 10; color: #6c70d5; width: 2; dashes: 10,30; line-style: arrows; } +way[oneway=yes]::arrows { z-index: 10; color: #6c70d5; width: 2; dashes: 10,30; line-style: arrows; } /* Change the road colour based on dynamically set "highlighted" tag (see earlier) */ From 9361524e24654c4608dd536d0ed3b7efc1228d48 Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Wed, 15 Jun 2011 11:45:17 +0100 Subject: [PATCH 69/89] Fix route highlighting --- resources/stylesheets/opencyclemap.css | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/resources/stylesheets/opencyclemap.css b/resources/stylesheets/opencyclemap.css index bbf65d0b..90af389b 100644 --- a/resources/stylesheets/opencyclemap.css +++ b/resources/stylesheets/opencyclemap.css @@ -145,11 +145,11 @@ node :junction :selectedway { z-index: 8; icon-image: square; icon-width: 12; ca /* Descendant selectors provide an easy way to style relations: this example means "any way which is part of a relation whose type=route". */ -relation[type=route] way { z-index: 1; width: 17; color: yellow; opacity: 0.3; } -relation[type=route][route=bicycle][network=ncn] way { z-index: 1; width: 12; color: red; opacity: 0.3; } -relation[type=route][route=bicycle][network=rcn] way { z-index: 1; width: 12; color: cyan; opacity: 0.3; } -relation[type=route][route=bicycle][network=lcn] way { z-index: 1; width: 12; color: blue; opacity: 0.3; } -relation[type=route][route=bicycle][network=mtb] way { z-index: 1; width: 12; color: #48a448; opacity: 0.3; } +relation[type=route] way::routeline { z-index: 1; width: 17; color: yellow; opacity: 0.3; } +relation[type=route][route=bicycle][network=ncn] way::routeline { z-index: 1; width: 12; color: red; opacity: 0.3; } +relation[type=route][route=bicycle][network=rcn] way::routeline { z-index: 1; width: 12; color: cyan; opacity: 0.3; } +relation[type=route][route=bicycle][network=lcn] way::routeline { z-index: 1; width: 12; color: blue; opacity: 0.3; } +relation[type=route][route=bicycle][network=mtb] way::routeline { z-index: 1; width: 12; color: #48a448; opacity: 0.3; } From 43d519482c77a6fd82c6c319ec617355c6fd4804 Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Wed, 15 Jun 2011 11:45:54 +0100 Subject: [PATCH 70/89] Choose whether layers are interactive (i.e. objects can be selected). After all, you don't want to be able to select a GPS track, you want to trace it by clicking along it. --- net/systemeD/halcyon/Map.as | 3 ++- net/systemeD/halcyon/MapPaint.as | 2 ++ .../potlatch2/VectorSourceDialog.mxml | 23 ++++++++++++++++--- .../potlatch2/controller/ControllerState.as | 9 ++++---- net/systemeD/potlatch2/utils/BugLoader.as | 2 +- 5 files changed, 29 insertions(+), 10 deletions(-) diff --git a/net/systemeD/halcyon/Map.as b/net/systemeD/halcyon/Map.as index 9dcb118a..5054ac16 100644 --- a/net/systemeD/halcyon/Map.as +++ b/net/systemeD/halcyon/Map.as @@ -245,10 +245,11 @@ package net.systemeD.halcyon { // ------------------------------------------------------------------------------------------ // Add layers - public function addLayer(connection:Connection, styleurl:String, backgroundlayer:Boolean=true):MapPaint { + public function addLayer(connection:Connection, styleurl:String, backgroundlayer:Boolean=true, interactive:Boolean=false):MapPaint { var paint:MapPaint=new MapPaint(this, connection, styleurl, -5, 5); paintContainer.addChild(paint); paint.isBackground=backgroundlayer; + paint.interactive=interactive; return paint; } diff --git a/net/systemeD/halcyon/MapPaint.as b/net/systemeD/halcyon/MapPaint.as index 8206aefe..c1fb5a6e 100644 --- a/net/systemeD/halcyon/MapPaint.as +++ b/net/systemeD/halcyon/MapPaint.as @@ -31,6 +31,8 @@ package net.systemeD.halcyon { private var markeruis:Object=new Object(); /** Is this a background layer or the core paint object? */ public var isBackground:Boolean = true; + /** Can the user select entities in this layer? */ + public var interactive:Boolean = false; /** Hash of index->position */ public var sublayerIndex:Object={}; diff --git a/net/systemeD/potlatch2/VectorSourceDialog.mxml b/net/systemeD/potlatch2/VectorSourceDialog.mxml index f2ee64c5..42a61d00 100644 --- a/net/systemeD/potlatch2/VectorSourceDialog.mxml +++ b/net/systemeD/potlatch2/VectorSourceDialog.mxml @@ -3,12 +3,12 @@ xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" showCloseButton="true" horizontalAlign="center" title="Load vector file" - width="400" height="350" verticalGap="0"> + width="500" height="350" verticalGap="0"> - + + + + + + + + + @@ -94,6 +106,7 @@ PopUpManager.centerPopUp(this); this.addEventListener(CloseEvent.CLOSE, vectorDialog_close); dataGrid.addEventListener("visibility_changed", toggleVisibility); + dataGrid.addEventListener("interactive_changed", toggleInteractive); map = Globals.vars.root; dispatchEvent(new Event("layers_changed")); } @@ -114,7 +127,7 @@ private function get vectorLayers():Array { var v:Array=[]; for each (var a:MapPaint in map.getLayers() ) { - v.push( { name:a.connection.name, visible:a.visible, url:a.connection.apiBase, style:a.style, isBackground:a.isBackground } ); + v.push( { name:a.connection.name, visible:a.visible, interactive:a.interactive, url:a.connection.apiBase, style:a.style, isBackground:a.isBackground } ); } return v; } @@ -122,6 +135,10 @@ private function toggleVisibility(event:Event):void { map.findLayer(dataGrid.selectedItem.name).visible = !map.findLayer(dataGrid.selectedItem.name).visible; } + + private function toggleInteractive(event:Event):void { + map.findLayer(dataGrid.selectedItem.name).interactive = !map.findLayer(dataGrid.selectedItem.name).interactive; + } private function dataEdited(event:DataGridEvent):void { if (event.dataField=='name') { diff --git a/net/systemeD/potlatch2/controller/ControllerState.as b/net/systemeD/potlatch2/controller/ControllerState.as index f6f00a9c..ad8ac7f4 100644 --- a/net/systemeD/potlatch2/controller/ControllerState.as +++ b/net/systemeD/potlatch2/controller/ControllerState.as @@ -99,11 +99,10 @@ package net.systemeD.potlatch2.controller { var newEntity:Entity=paint.pullThrough(entity,editableLayer); if (entity is Way ) { return new SelectedWay(newEntity as Way); } else if (entity is Node) { return new SelectedPOINode(newEntity as Node); } - } else if (event.type == MouseEvent.MOUSE_DOWN && entity is Marker) { - return new SelectedMarker(entity as Marker, paint); - } else if (event.type == MouseEvent.MOUSE_DOWN) { - if (entity is Way ) { return new SelectedBackgroundWay(entity as Way); } - else if (entity is Node) { return new SelectedBackgroundNode(entity as Node, paint); } + } else if (event.type == MouseEvent.MOUSE_DOWN && paint.interactive) { + if (entity is Way ) { return new SelectedBackgroundWay(entity as Way); } + else if (entity is Node ) { return new SelectedBackgroundNode(entity as Node, paint); } + else if (entity is Marker) { return new SelectedMarker(entity as Marker, paint); } } else if ( event.type == MouseEvent.MOUSE_UP ) { return (this is NoSelection) ? null : new NoSelection(); } else { return null; } diff --git a/net/systemeD/potlatch2/utils/BugLoader.as b/net/systemeD/potlatch2/utils/BugLoader.as index 7cb6bf40..4c6f08bb 100644 --- a/net/systemeD/potlatch2/utils/BugLoader.as +++ b/net/systemeD/potlatch2/utils/BugLoader.as @@ -31,7 +31,7 @@ package net.systemeD.potlatch2.utils { public function load():void { if (!_layer) { - _layer = map.addLayer(connection, STYLESHEET); + _layer = map.addLayer(connection, STYLESHEET, true, true); } connection.loadBbox(map.edge_l, map.edge_r, map.edge_t, map.edge_b); } From ea19b179b83d7e11b645029c4c47124172d191f7 Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Wed, 15 Jun 2011 11:55:18 +0100 Subject: [PATCH 71/89] Drop the interactive stuff from opencyclemap.css and use core_interactive instead --- resources/stylesheets/opencyclemap.css | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/resources/stylesheets/opencyclemap.css b/resources/stylesheets/opencyclemap.css index 90af389b..1270ba26 100644 --- a/resources/stylesheets/opencyclemap.css +++ b/resources/stylesheets/opencyclemap.css @@ -132,16 +132,8 @@ way .highlighted { color: pink; } /* Interactive editors may choose different behaviour when a user mouses-over or selects an object. Potlatch 2 supports these but the stand-alone Halcyon viewer does not */ -way :hover { z-index: 2; width: eval('_width+10'); color: #ffff99; } -way :selected { z-index: 2; width: eval('_width+10'); color: yellow; opacity: 0.7;} -way !:drawn { z-index:10; width: 0.5; color: gray; } - -node :selectedway { z-index: 9; icon-image: square; icon-width: 8; color: red; casing-color: #cc0000; casing-width: 1;} -node :hoverway { z-index: 9; icon-image: square; icon-width: 7; color: blue; } -node !:drawn :poi { z-index: 2; icon-image: circle; icon-width: 3; color: lightsteelblue; casing-color: black; casing-width: 1; } -node :selected { z-index: 1; icon-image: square; icon-width: eval('_width+10'); color: yellow; } -node :junction :selectedway { z-index: 8; icon-image: square; icon-width: 12; casing-color: black; casing-width: 1; } - +@import("stylesheets/core_interactive.css"); + /* Descendant selectors provide an easy way to style relations: this example means "any way which is part of a relation whose type=route". */ From 243ffecced8e66f575bcaa59f218d4b20fa0af5a Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Wed, 15 Jun 2011 12:01:10 +0100 Subject: [PATCH 72/89] Move the various way highlighting to their own subpart --- resources/stylesheets/core_interactive.css | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/resources/stylesheets/core_interactive.css b/resources/stylesheets/core_interactive.css index 402d86d9..6fec5f74 100644 --- a/resources/stylesheets/core_interactive.css +++ b/resources/stylesheets/core_interactive.css @@ -4,10 +4,10 @@ relation[type=restriction] node { z-index:11; icon-image: icons/restriction.png; /* Interactive way behaviour */ -way :hover { z-index: 2; width: eval('_width+10'); color: #ffff99; } -way :selected { z-index: 2; width: eval('_width+10'); color: yellow; opacity: 0.7;} -way :restrictfrom { z-index: -1; width: eval('_width+10'); color: red; opacity: 0.7;} -way :restrictto { z-index: -1; width: eval('_width+10'); color: blue; opacity: 0.7;} +way::highlight :hover { z-index: 2; width: eval('_width+10'); color: #ffff99; } +way::highlight :selected { z-index: 2; width: eval('_width+10'); color: yellow; opacity: 0.7;} +way::highlight :restrictfrom { z-index: -1; width: eval('_width+10'); color: red; opacity: 0.7;} +way::highlight :restrictto { z-index: -1; width: eval('_width+10'); color: blue; opacity: 0.7;} /*way !:drawn !:hasTags{ z-index:10; width: 0.5; color: red; }*/ way !:drawn { z-index:10; width: 1; color: #333333; } way :tiger { casing-color: #ff00ff;} From f0a3e8b311ac499a1a90aa86f08ef899295c91a3 Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Wed, 15 Jun 2011 12:46:54 +0100 Subject: [PATCH 73/89] Make the license highlighting use a 'status' subpart --- resources/stylesheets/potlatch.css | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/resources/stylesheets/potlatch.css b/resources/stylesheets/potlatch.css index 39cc22ce..34fd3bc4 100644 --- a/resources/stylesheets/potlatch.css +++ b/resources/stylesheets/potlatch.css @@ -20,9 +20,9 @@ way .area_small_name {text-color: black; font-size: 9; text: name; text-halo: #f /* Test rendering for licence status */ -way[_status=no] { z-index: 0; width: 20; color: red; } -way[_status=partial] { z-index: 0; width: 20; color: red; opacity: 0.4; } -way[_status=unsure] { z-index: 0; width: 20; color: orange; opacity: 0.4; } -node[_status=no] { z-index: 0; icon-image: square; icon-width: 15; color: red; } -node[_status=partial] { z-index: 0; icon-image: square; icon-width: 15; color: red; opacity: 0.4; } -node[_status=unsure] { z-index: 0; icon-image: square; icon-width: 15; color: orange; opacity: 0.4; } +way[_status=no]::status { z-index: 0; width: 20; color: red; } +way[_status=partial]::status { z-index: 0; width: 20; color: red; opacity: 0.4; } +way[_status=unsure]::status { z-index: 0; width: 20; color: orange; opacity: 0.4; } +node[_status=no]::status { z-index: 0; icon-image: square; icon-width: 15; color: red; } +node[_status=partial]::status { z-index: 0; icon-image: square; icon-width: 15; color: red; opacity: 0.4; } +node[_status=unsure]::status { z-index: 0; icon-image: square; icon-width: 15; color: orange; opacity: 0.4; } From eb3b73a548e72d3b9dea5734d2a81491c64b0aa1 Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Wed, 15 Jun 2011 12:47:17 +0100 Subject: [PATCH 74/89] Fix railways to use subparts on the main style too --- resources/stylesheets/core_ways.css | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/resources/stylesheets/core_ways.css b/resources/stylesheets/core_ways.css index ccb9dbe6..6fbbe59e 100644 --- a/resources/stylesheets/core_ways.css +++ b/resources/stylesheets/core_ways.css @@ -42,22 +42,21 @@ way .path { text:name; text-color: black; text-position: offset; te way[highway=proposed] { color: #88ffff; width: 6; dashes: 8, 4; } way[highway=construction] { color: #ffffbb; width: 6; dashes: 8, 4; casing-color: #0000aa; casing-width: 1; casing-dashes: 8,4;} -way[construction=rail] - { z-index: 6; color: black; width: 5; dashes: 6, 6, 4, 8;} - { z-index: 7; color: white; width: 3; dashes: 6,18; } +way[construction=rail] { z-index: 6; color: black; width: 5; dashes: 6, 6, 4, 8;} +way[construction=rail]::inner { z-index: 7; color: white; width: 3; dashes: 6,18; } /* Railways */ -way[railway=rail] - { z-index: 6; color: black; width: 5; } - { z-index: 7; color: white; width: 3; dashes: 12,12; } +way[railway=rail] { z-index: 6; color: black; width: 5; } +way[railway=rail]::dashes { z-index: 7; color: white; width: 3; dashes: 12,12; } + way[railway=platform] { color:black; width: 2; } -way[railway=subway] - { z-index: 6; color: #444444; width: 5; } - { z-index: 7; color: white; width: 3; dashes: 8,8; } -way[railway=disused],way[railway=abandoned] - { z-index: 6; color: #444400; width: 3; dashes: 17, 2, 5, 0; } - { z-index: 7; color: #999999; width: 2; dashes: 12,12; } + +way[railway=subway] { z-index: 6; color: #444444; width: 5; } +way[railway=subway]::dashes { z-index: 7; color: white; width: 3; dashes: 8,8; } + +way[railway=disused],way[railway=abandoned] { z-index: 6; color: #444400; width: 3; dashes: 17, 2, 5, 0; } +way[railway=disused]::dashes,way[railway=abandoned]::dashes { z-index: 7; color: #999999; width: 2; dashes: 12,12; } /* Waterways */ From 8a6e1d4d3d97c575675345ea0d81ed209990231e Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Wed, 15 Jun 2011 13:43:22 +0100 Subject: [PATCH 75/89] Fix refactoring issues in potlatch2.mxml --- net/systemeD/halcyon/Map.as | 8 ---- net/systemeD/halcyon/TileSet.as | 4 +- .../potlatch2/collections/CollectionEvent.as | 17 ++++++++ net/systemeD/potlatch2/collections/Imagery.as | 40 ++++++++++--------- .../potlatch2/collections/Stylesheets.as | 29 +++++++++----- potlatch2.mxml | 28 +++++++------ 6 files changed, 74 insertions(+), 52 deletions(-) create mode 100644 net/systemeD/potlatch2/collections/CollectionEvent.as diff --git a/net/systemeD/halcyon/Map.as b/net/systemeD/halcyon/Map.as index 5054ac16..b65ac7ac 100644 --- a/net/systemeD/halcyon/Map.as +++ b/net/systemeD/halcyon/Map.as @@ -74,8 +74,6 @@ package net.systemeD.halcyon { public var backdrop:Object; /** background tile object */ public var tileset:TileSet; - /** background tile URL, name and scheme */ - public var tileparams:Object={ url:'' }; /** show all objects, even if unstyled? */ public var showall:Boolean=true; @@ -327,12 +325,6 @@ package net.systemeD.halcyon { download(); } - /** Select a new background imagery. */ - public function setBackground(bg:Object):void { - tileparams=bg; - if (tileset) { tileset.init(bg, bg.url!=''); } - } - /** Set background dimming on/off. */ public function setDimming(dim:Boolean):void { if (tileset) { tileset.setDimming(dim); } diff --git a/net/systemeD/halcyon/TileSet.as b/net/systemeD/halcyon/TileSet.as index b5469555..5d2e1eac 100644 --- a/net/systemeD/halcyon/TileSet.as +++ b/net/systemeD/halcyon/TileSet.as @@ -47,9 +47,7 @@ package net.systemeD.halcyon { * @param dim Start with imagery faded? * @param sharpen Start with sharpen filter applied? */ - public function init(params:Object, update:Boolean=false, dim:Boolean=true, sharpen:Boolean=false):void { - setDimming(dim); - sharpening=sharpen; + public function init(params:Object, update:Boolean=false):void { baseurl=params.url; scheme =params.scheme ? params.scheme : '900913'; tiles={}; diff --git a/net/systemeD/potlatch2/collections/CollectionEvent.as b/net/systemeD/potlatch2/collections/CollectionEvent.as new file mode 100644 index 00000000..bab3ee38 --- /dev/null +++ b/net/systemeD/potlatch2/collections/CollectionEvent.as @@ -0,0 +1,17 @@ +package net.systemeD.potlatch2.collections { + + import flash.events.Event; + + public class CollectionEvent extends Event { + + public static const SELECT:String = "select"; + + public var data:Object; + + public function CollectionEvent(eventname:String, data:Object) { + super(eventname); + this.data=data; + } + } + +} diff --git a/net/systemeD/potlatch2/collections/Imagery.as b/net/systemeD/potlatch2/collections/Imagery.as index d0443c55..580017bd 100644 --- a/net/systemeD/potlatch2/collections/Imagery.as +++ b/net/systemeD/potlatch2/collections/Imagery.as @@ -24,7 +24,7 @@ package net.systemeD.potlatch2.collections { public static function instance():Imagery { return GLOBAL_INSTANCE; } public var collection:Array=[]; - public var selected:Object={}; + private var _selected:Object={}; private var _map:Map; private var _overlay:Sprite; @@ -157,9 +157,9 @@ package net.systemeD.potlatch2.collections { public function setBackground(bg:Object):void { // set background - selected=bg; - if (bg.url=='yahoo') { _map.setBackground({url:''}); _yahoo.show(); } - else { _map.setBackground(bg ); _yahoo.hide(); } + _selected=bg; + if (bg.url=='yahoo') { dispatchEvent(new CollectionEvent(CollectionEvent.SELECT, {url:''})); _yahoo.show(); } + else { dispatchEvent(new CollectionEvent(CollectionEvent.SELECT, bg )); _yahoo.hide(); } // update attribution and logo _overlay.visible=bg.attribution || bg.logo || bg.terms_url; setLogo(); setAttribution(); setTerms(); @@ -170,6 +170,8 @@ package net.systemeD.potlatch2.collections { obj.flush(); } + public function get selected():Object { return _selected; } + private function findBackgroundWithName(name:String):Object { for each (var bg:Object in collection) { if (bg.name==name) { return bg; } @@ -184,10 +186,10 @@ package net.systemeD.potlatch2.collections { private function setAttribution():void { var tf:TextField=TextField(_overlay.getChildAt(0)); tf.text=''; - if (!selected.attribution) return; + if (!_selected.attribution) return; var attr:Array=[]; - for (var provider:String in selected.attribution) { - for each (var bounds:Array in selected.attribution[provider]) { + for (var provider:String in _selected.attribution) { + for each (var bounds:Array in _selected.attribution[provider]) { if (_map.scale>=bounds[0] && _map.scale<=bounds[1] && ((_map.edge_l>bounds[3] && _map.edge_lbounds[3] && _map.edge_r2) { _overlay.removeChildAt(2); } - if (!selected.logoData) return; + if (!_selected.logoData) return; var logo:Sprite=new Sprite(); - logo.addChild(new Bitmap(selected.logoData)); - if (selected.logo_url) { logo.buttonMode=true; logo.addEventListener(MouseEvent.CLICK, launchLogoLink, false, 0, true); } + logo.addChild(new Bitmap(_selected.logoData)); + if (_selected.logo_url) { logo.buttonMode=true; logo.addEventListener(MouseEvent.CLICK, launchLogoLink, false, 0, true); } _overlay.addChild(logo); positionLogo(); } private function positionLogo():void { _overlay.getChildAt(2).x=5; - _overlay.getChildAt(2).y=_map.mapheight - 5 - selected.logoHeight - (selected.terms_url ? 10 : 0); + _overlay.getChildAt(2).y=_map.mapheight - 5 - _selected.logoHeight - (_selected.terms_url ? 10 : 0); } private function launchLogoLink(e:Event):void { - if (!selected.logo_url) return; - navigateToURL(new URLRequest(selected.logo_url), '_blank'); + if (!_selected.logo_url) return; + navigateToURL(new URLRequest(_selected.logo_url), '_blank'); } private function setTerms():void { var terms:TextField=TextField(_overlay.getChildAt(1)); - if (!selected.terms_url) { terms.text=''; return; } + if (!_selected.terms_url) { terms.text=''; return; } terms.text="Background terms of use"; positionTerms(); terms.addEventListener(MouseEvent.CLICK, launchTermsLink, false, 0, true); @@ -239,14 +241,14 @@ package net.systemeD.potlatch2.collections { _overlay.getChildAt(1).y=_map.mapheight - 15; } private function launchTermsLink(e:Event):void { - if (!selected.terms_url) return; - navigateToURL(new URLRequest(selected.terms_url), '_blank'); + if (!_selected.terms_url) return; + navigateToURL(new URLRequest(_selected.terms_url), '_blank'); } private function resizeHandler(event:MapEvent):void { - if (selected.logoData) positionLogo(); - if (selected.terms_url) positionTerms(); - if (selected.attribution) positionAttribution(); + if (_selected.logoData) positionLogo(); + if (_selected.terms_url) positionTerms(); + if (_selected.attribution) positionAttribution(); } [Bindable(event="collection_changed")] diff --git a/net/systemeD/potlatch2/collections/Stylesheets.as b/net/systemeD/potlatch2/collections/Stylesheets.as index f10d079f..1ac3f63d 100644 --- a/net/systemeD/potlatch2/collections/Stylesheets.as +++ b/net/systemeD/potlatch2/collections/Stylesheets.as @@ -14,24 +14,31 @@ package net.systemeD.potlatch2.collections { private static const GLOBAL_INSTANCE:Stylesheets = new Stylesheets(); public static function instance():Stylesheets { return GLOBAL_INSTANCE; } + private static const DEFAULT:String = 'stylesheets/potlatch.css'; + public var collection:Array=[]; - public var selected:Object={}; - private var _map:Map; + private var _selected:String; /* Load catalogue file */ - public function init(map:Map):void { - _map=map; + public function init(request_url:String=null):void { + // First, we set _selected in case it's needed before the stylesheet catalogue loads + _selected=request_url; + _selected=_selected ? _selected : SharedObject.getLocal("user_state").data['stylesheet_url']; + _selected=_selected ? _selected : DEFAULT; + + // Load the stylesheet catalogue var request:DebugURLRequest = new DebugURLRequest("stylesheets.xml"); var loader:URLLoader = new URLLoader(); - loader.addEventListener(Event.COMPLETE, onStylesheetsLoad); + loader.addEventListener(Event.COMPLETE, function(e:Event):void { onStylesheetsLoad(e,request_url); }); loader.load(request.request); } - private function onStylesheetsLoad(event:Event):void { + private function onStylesheetsLoad(event:Event, request_url:String=null):void { var xml:XML = new XML(URLLoader(event.target).data); var saved_url:String = SharedObject.getLocal("user_state").data['stylesheet_url']; var saved_name:String= SharedObject.getLocal("user_state").data['stylesheet_name']; + if (request_url && request_url!=saved_url) { saved_url=request_url; saved_name='Custom'; } var isInMenu:Boolean=false, isSet:Boolean=false; // first, build the menu from the stylesheet list. @@ -64,8 +71,8 @@ package net.systemeD.potlatch2.collections { setStylesheet(s.name, s.url); } else { //hit and hope. FIXME should this be an error state? - collection.push({ name:'Potlatch', url:'stylesheets/potlatch.css'}); - setStylesheet('Potlatch','stylesheets/potlatch.css'); + collection.push({ name:'Potlatch', url:DEFAULT}); + setStylesheet('Potlatch',DEFAULT); } } FunctionKeyManager.instance().registerListener('Map style', @@ -74,13 +81,15 @@ package net.systemeD.potlatch2.collections { } public function setStylesheet(name:String,url:String):void { - _map.editableLayer.setStyle(url); - // >>>> REFACTOR: not great to have a reference to editableLayer in here + _selected=url; + dispatchEvent(new CollectionEvent(CollectionEvent.SELECT, url)); var obj:SharedObject = SharedObject.getLocal("user_state"); obj.setProperty("stylesheet_url",url); obj.setProperty("stylesheet_name",name); obj.flush(); } + + public function get selected():String { return _selected; } private function findStylesheetURLWithName(name:String):String { for each (var ss:Object in collection) { diff --git a/potlatch2.mxml b/potlatch2.mxml index 9ad70000..055f0a6f 100644 --- a/potlatch2.mxml +++ b/potlatch2.mxml @@ -190,15 +190,13 @@ _root.addChild(yahoo); _root.addChild(theMap); - // Initialise 900913 background - // >>>> REFACTOR: something odd about accessing map.tileparams here... - theMap.tileset.blocks=[new RegExp("google","i")]; // hard-coded block on Google tiles - theMap.tileset.init(theMap.tileparams, false, - params['background_dim'] ==null ? true : params['background_dim'], - params['background_sharpen']==null ? false : params['background_sharpen']); + // Initialise stylesheets + Stylesheets.instance().init(); + Stylesheets.instance().addEventListener(CollectionEvent.SELECT, + function(e:CollectionEvent):void { theMap.editableLayer.setStyle(String(e.data)); } + ); // Add core data layer - // >>>> REFACTOR: shouldn't be hardcoded to XMLConnection var conn:Connection = new XMLConnection("Main", params['api'], params['policy'], params); conn.addEventListener(Connection.LOAD_STARTED, onDataStart); conn.addEventListener(Connection.LOAD_COMPLETED, onDataComplete); @@ -209,14 +207,14 @@ conn.addEventListener(MapEvent.ERROR, onMapError); conn.addEventListener(AttentionEvent.ATTENTION, onAttention); conn.addEventListener(AttentionEvent.ALERT, onAlert); - // >>>> REFACTOR: shouldn't be trying to find out stylesheet from here - theMap.addLayer(conn,params['styleurl'] ? params['styleurl'] : 'stylesheets/potlatch.css',false); + theMap.addLayer(conn, Stylesheets.instance().selected, false, true); // Auto-load vector backgrounds from config theMap.addEventListener(MapEvent.INITIALISED, function(e:Event):void { VectorBackgrounds.instance().init(theMap); }); // Set start position of map - // >>>> REFACTOR: what happens if lat/lon/zoom not supplied? (Hurleston GPX case) + // ** FIXME: if lat/lon/zoom aren't supplied, we need to keep the map in a non-loading state + // until the user has decided where to start editing (e.g. when the first GPX loads) theMap.init(params['lat'], params['lon'], params['zoom']); // add attribution/logo sprite @@ -240,10 +238,15 @@ Globals.vars.map_area.addEventListener(MouseEvent.MOUSE_MOVE, theMap.mouseMoveHandler); Globals.vars.map_area.addEventListener(MouseEvent.MOUSE_DOWN, theMap.mouseDownHandler); - // initialise imagery and stylesheets + // initialise imagery + theMap.tileset.blocks=[new RegExp("google","i")]; // hard-coded block on Google tiles + theMap.tileset.setDimming(params['background_dim'] ==null ? true : params['background_dim']); + theMap.tileset.setSharpen(params['background_sharpen']==null ? false : params['background_sharpen']); Imagery.instance().init(theMap, overlay, yahoo); - Stylesheets.instance().init(theMap); Imagery.instance().addEventListener(MapEvent.BUMP, bumpHandler); + Imagery.instance().addEventListener(CollectionEvent.SELECT, + function(e:CollectionEvent):void { theMap.tileset.init(e.data, e.data!=''); } + ); // keyboard event attached to stage stage.addEventListener(KeyboardEvent.KEY_UP, theMap.keyUpHandler); @@ -266,6 +269,7 @@ t.visible = loaderInfo.parameters["show_debug"] == 'true'; Globals.vars.root=theMap; // just for the addDebug function + // create controller theController = new EditController(theMap, tagViewer, toolbox); theController.setActive(); theController.addEventListener(AttentionEvent.ATTENTION, onAttention); From 881fdbf29136830760356071c5013a8458778f24 Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Wed, 15 Jun 2011 14:28:47 +0100 Subject: [PATCH 76/89] Use a plain old URLRequest for importing --- net/systemeD/potlatch2/utils/Importer.as | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/net/systemeD/potlatch2/utils/Importer.as b/net/systemeD/potlatch2/utils/Importer.as index e53355de..263dacb7 100644 --- a/net/systemeD/potlatch2/utils/Importer.as +++ b/net/systemeD/potlatch2/utils/Importer.as @@ -2,7 +2,6 @@ package net.systemeD.potlatch2.utils { import net.systemeD.halcyon.Map; import net.systemeD.halcyon.ExtendedURLLoader; - import net.systemeD.halcyon.DebugURLRequest; import net.systemeD.halcyon.connection.*; import flash.net.URLLoader; import flash.display.LoaderInfo; @@ -30,7 +29,7 @@ package net.systemeD.potlatch2.utils { // Use forEach to avoid closure problem (http://stackoverflow.com/questions/422784/how-to-fix-closure-problem-in-actionscript-3-as3#3971784) filenames.forEach(function(fn:String, index:int, array:Array):void { trace("requesting file "+index); - var request:DebugURLRequest = new DebugURLRequest(fn); + var request:URLRequest = new URLRequest(fn); var loader:URLLoader = new URLLoader(); loader.dataFormat=URLLoaderDataFormat.BINARY; loader.addEventListener(Event.COMPLETE,function(e:Event):void { fileLoaded(e,index); }); @@ -38,7 +37,7 @@ package net.systemeD.potlatch2.utils { loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler); loader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler); } - loader.load(request.request); + loader.load(request); }); } From 42227c937938f3e0badeb785ccade1547c83caff Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Wed, 15 Jun 2011 14:57:58 +0100 Subject: [PATCH 77/89] Fix up the (legendary) runway rendering --- resources/stylesheets/core_ways.css | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/resources/stylesheets/core_ways.css b/resources/stylesheets/core_ways.css index 6fbbe59e..b7c28233 100644 --- a/resources/stylesheets/core_ways.css +++ b/resources/stylesheets/core_ways.css @@ -74,20 +74,21 @@ way|z-15[aeroway=aerodrome] :area { z-index: 3; fill-color: #bb99bb; fill-opacity: 0.5;} way[aeroway=taxiway] !:area { z-index: 8; color: #999999; width: 3; casing-color: #aa66aa; casing-width: 2; } way[aeroway=taxiway] :area { z-index: 8; color: #bb99bb; width: 3; fill-color: #ccaacc; } -way|z17-[aeroway=runway] !:area - { z-index: 9; color: black; width: 11; casing-color: #aa66aa; casing-width: 1; } - { z-index: 10; color: white; width: 9; dashes: 0, 20, 4, 76; } - { z-index: 11; color: black; width: 7; } - { z-index: 12; color: white; width: 5; dashes: 0, 20, 4, 76; } - { z-index: 13; color: black; width: 3; } - { z-index: 14; color: white; width: 1; dashes: 4, 16; } -way|z15-16[aeroway=runway] !:area - { z-index: 9; color: black; width: 5; } - { z-index: 12; color: white; width: 5; dashes: 0, 20, 4, 76; } - { z-index: 13; color: black; width: 3; } - { z-index: 14; color: white; width: 1; dashes: 4, 16; } -way|z-14[aeroway=runway] !:area - { z-index: 9; color: #444444; width: 3; } + +way|z17-[aeroway=runway] !:area { z-index: 9; color: black; width: 11; casing-color: #aa66aa; casing-width: 1; } +way|z17-[aeroway=runway]::aa !:area { z-index: 10; color: white; width: 9; dashes: 0, 20, 4, 76; } +way|z17-[aeroway=runway]::bb !:area { z-index: 11; color: black; width: 7; } +way|z17-[aeroway=runway]::cc !:area { z-index: 12; color: white; width: 5; dashes: 0, 20, 4, 76; } +way|z17-[aeroway=runway]::dd !:area { z-index: 13; color: black; width: 3; } +way|z17-[aeroway=runway]::ee !:area { z-index: 14; color: white; width: 1; dashes: 4, 16; } + +way|z15-16[aeroway=runway] !:area { z-index: 9; color: black; width: 5; } +way|z15-16[aeroway=runway]::aa !:area { z-index: 12; color: white; width: 5; dashes: 0, 20, 4, 76; } +way|z15-16[aeroway=runway]::bb !:area { z-index: 13; color: black; width: 3; } +way|z15-16[aeroway=runway]::cc !:area { z-index: 14; color: white; width: 1; dashes: 4, 16; } + +way|z-14[aeroway=runway] !:area { z-index: 9; color: #444444; width: 3; } + way[aeroway=runway] :area { z-index: 9; color: black; width: 3; fill-color: #775577; } way[aeroway=apron] :area { z-index: 4; color: #cc66cc; width: 1; fill-color: #ddaadd; fill-opacity: 0.5;} From d7f92ee659c4e997b452ab742f5de6f72791e03d Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Wed, 15 Jun 2011 14:58:29 +0100 Subject: [PATCH 78/89] Direction arrows on network and enhanced styles --- resources/stylesheets/enhanced.css | 8 ++++---- resources/stylesheets/network.css | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/resources/stylesheets/enhanced.css b/resources/stylesheets/enhanced.css index 61315b39..52fb9ee1 100644 --- a/resources/stylesheets/enhanced.css +++ b/resources/stylesheets/enhanced.css @@ -28,8 +28,8 @@ way .area_small_name {text-color: black; font-size: 9; text: name; text-halo: #f /* Direction on selected ways */ -way[highway][!oneway][junction!=roundabout]:selected, -way[aerial_way]:selected { z-index: 14; color: #999922; width: 2; dashes: 3,60; line-style: arrows; } -way[waterway]:selected { z-index: 14; color: #4444CC; width: 2; dashes: 5,60; line-style: arrows; } -way[railway] :selected{ z-index: 14; color: #999999; width: 3; dashes: 4,92; line-style: arrows; } +way[highway][!oneway][junction!=roundabout]::direction :selected, +way[aerial_way]::direction :selected { z-index: 14; color: #999922; width: 2; dashes: 3,60; line-style: arrows; } +way[waterway]::direction :selected { z-index: 14; color: #4444CC; width: 2; dashes: 5,60; line-style: arrows; } +way[railway]::direction :selected{ z-index: 14; color: #999999; width: 3; dashes: 4,92; line-style: arrows; } diff --git a/resources/stylesheets/network.css b/resources/stylesheets/network.css index a8f72a6c..5d4cb5b2 100644 --- a/resources/stylesheets/network.css +++ b/resources/stylesheets/network.css @@ -28,8 +28,8 @@ way .area_small_name {text-color: black; font-size: 9; text: name; text-halo: #f /* Direction on selected ways */ -way[highway][!oneway][junction!=roundabout]:selected, -way[aerial_way]:selected { z-index: 14; color: #999922; width: 2; dashes: 3,60; line-style: arrows; } -way[waterway]:selected { z-index: 14; color: #4444CC; width: 2; dashes: 5,60; line-style: arrows; } -way[railway] :selected{ z-index: 14; color: #999999; width: 3; dashes: 4,92; line-style: arrows; } +way[highway][!oneway][junction!=roundabout]::direction :selected, +way[aerial_way]::direction :selected { z-index: 14; color: #999922; width: 2; dashes: 3,60; line-style: arrows; } +way[waterway]::direction :selected { z-index: 14; color: #4444CC; width: 2; dashes: 5,60; line-style: arrows; } +way[railway]::direction :selected{ z-index: 14; color: #999999; width: 3; dashes: 4,92; line-style: arrows; } From 0692c6a524881cb1618dfd81e6a17bf53ab61d05 Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Wed, 15 Jun 2011 15:02:37 +0100 Subject: [PATCH 79/89] More subparts for network and enhanced stylesheets --- resources/stylesheets/enhanced.css | 6 +++--- resources/stylesheets/network.css | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/resources/stylesheets/enhanced.css b/resources/stylesheets/enhanced.css index 52fb9ee1..23966e00 100644 --- a/resources/stylesheets/enhanced.css +++ b/resources/stylesheets/enhanced.css @@ -12,12 +12,12 @@ /* Access */ -way[access=private],way[access=no] { z-index: 10; color: red; width: eval('_width+2'); dashes: 2,5;} -way[access=permissive] { z-index: 10; color: green; width: eval('_width+2'); dashes: 1,3;} +way[access=private]::access,way[access=no]::access { z-index: 10; color: red; width: eval('_width+2'); dashes: 2,5;} +way[access=permissive]::access { z-index: 10; color: green; width: eval('_width+2'); dashes: 1,3;} /* Physical */ -way[embankment=yes], way[cutting=yes] +way[embankment=yes]::hatches, way[cutting=yes]::hatches { z-index: 3; opacity: 0.5; color: grey; width: eval('_width+5'); dashes: 2, 2; } /* Interactive behaviour */ diff --git a/resources/stylesheets/network.css b/resources/stylesheets/network.css index 5d4cb5b2..d2a60a9f 100644 --- a/resources/stylesheets/network.css +++ b/resources/stylesheets/network.css @@ -12,12 +12,12 @@ /* Access */ -way[access=private],way[access=no] { z-index: 10; color: red; width: eval('_width+2'); dashes: 2,5;} -way[access=permissive] { z-index: 10; color: green; width: eval('_width+2'); dashes: 1,3;} +way[access=private]::access,way[access=no]::access { z-index: 10; color: red; width: eval('_width+2'); dashes: 2,5;} +way[access=permissive]::access { z-index: 10; color: green; width: eval('_width+2'); dashes: 1,3;} /* Physical */ -way[embankment=yes], way[cutting=yes] +way[embankment=yes]::hatches, way[cutting=yes]::hatches { z-index: 3; opacity: 0.5; color: grey; width: eval('_width+5'); dashes: 2, 2; } /* Interactive behaviour */ From 1d3d02071aed786cd9f47d449989ebd08281d640 Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Wed, 15 Jun 2011 15:48:29 +0100 Subject: [PATCH 80/89] Whoops --- net/systemeD/potlatch2/utils/ShpImporter.as | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/systemeD/potlatch2/utils/ShpImporter.as b/net/systemeD/potlatch2/utils/ShpImporter.as index 95386cff..45d020c0 100644 --- a/net/systemeD/potlatch2/utils/ShpImporter.as +++ b/net/systemeD/potlatch2/utils/ShpImporter.as @@ -64,7 +64,7 @@ package net.systemeD.potlatch2.utils { r=proj.transform(fromProj,toProj,r); x=r.x; y=r.y; } else { - x=p.x; x=p.y; + x=p.x; y=p.y; } key=x+","+y; From e641958d6d2fd2de39cdf80e73e742e6338850e3 Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Wed, 15 Jun 2011 17:12:20 +0100 Subject: [PATCH 81/89] Auto-detect filetype based on extension --- net/systemeD/potlatch2/VectorSourceDialog.mxml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/net/systemeD/potlatch2/VectorSourceDialog.mxml b/net/systemeD/potlatch2/VectorSourceDialog.mxml index 42a61d00..e17c8837 100644 --- a/net/systemeD/potlatch2/VectorSourceDialog.mxml +++ b/net/systemeD/potlatch2/VectorSourceDialog.mxml @@ -70,7 +70,7 @@ - + @@ -159,6 +159,13 @@ dispatchEvent(new Event("layers_changed")); } + private function selectByExtension():void { + if (src.text.match(/\.shp$/i)) filetype.selectedValue='shp' + else if (src.text.match(/\.osm$/i)) filetype.selectedValue='osm' + else if (src.text.match(/\.gpx$/i)) filetype.selectedValue='gpx' + else if (src.text.match(/\.kml$/i)) filetype.selectedValue='kml' + } + private function vectorDialog_close(evt:CloseEvent):void { PopUpManager.removePopUp(this); } From 0944e7343a97770fdbc9eb638fde2eb9728802f1 Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Wed, 15 Jun 2011 21:29:43 +0100 Subject: [PATCH 82/89] Improve selection for background objects and tidy ControllerState layer handling --- net/systemeD/halcyon/Map.as | 2 +- net/systemeD/halcyon/WayUI.as | 1 + .../potlatch2/controller/ControllerState.as | 66 +++++++++---------- .../potlatch2/controller/DragSelection.as | 4 +- .../potlatch2/controller/DragWayNode.as | 20 +++--- net/systemeD/potlatch2/controller/DrawWay.as | 30 ++++----- .../potlatch2/controller/NoSelection.as | 2 +- .../potlatch2/controller/SelectArea.as | 4 +- .../controller/SelectedBackgroundNode.as | 9 ++- .../controller/SelectedBackgroundWay.as | 18 ++--- .../potlatch2/controller/SelectedMarker.as | 9 ++- .../potlatch2/controller/SelectedMultiple.as | 10 +-- .../potlatch2/controller/SelectedPOINode.as | 8 +-- .../controller/SelectedParallelWay.as | 2 +- .../potlatch2/controller/SelectedWay.as | 16 ++--- .../potlatch2/controller/SelectedWayNode.as | 26 ++++---- net/systemeD/potlatch2/utils/ShpImporter.as | 1 + resources/stylesheets/core_interactive.css | 3 + 18 files changed, 115 insertions(+), 116 deletions(-) diff --git a/net/systemeD/halcyon/Map.as b/net/systemeD/halcyon/Map.as index b65ac7ac..1377d446 100644 --- a/net/systemeD/halcyon/Map.as +++ b/net/systemeD/halcyon/Map.as @@ -245,7 +245,7 @@ package net.systemeD.halcyon { public function addLayer(connection:Connection, styleurl:String, backgroundlayer:Boolean=true, interactive:Boolean=false):MapPaint { var paint:MapPaint=new MapPaint(this, connection, styleurl, -5, 5); - paintContainer.addChild(paint); + paintContainer.addChildAt(paint,0); paint.isBackground=backgroundlayer; paint.interactive=interactive; return paint; diff --git a/net/systemeD/halcyon/WayUI.as b/net/systemeD/halcyon/WayUI.as index fdec4d40..787385f4 100644 --- a/net/systemeD/halcyon/WayUI.as +++ b/net/systemeD/halcyon/WayUI.as @@ -231,6 +231,7 @@ package net.systemeD.halcyon { // Copy tags object, and add states var tags:Object = entity.getTagsCopy(); setStateClass('area', Way(entity).isArea()); + setStateClass('background', paint.isBackground); setStateClass('tiger', (entity.isUneditedTiger() && Globals.vars.highlightTiger)); tags=applyStateClasses(tags); if (entity.status) { tags['_status']=entity.status; } diff --git a/net/systemeD/potlatch2/controller/ControllerState.as b/net/systemeD/potlatch2/controller/ControllerState.as index ad8ac7f4..3c02e1b4 100644 --- a/net/systemeD/potlatch2/controller/ControllerState.as +++ b/net/systemeD/potlatch2/controller/ControllerState.as @@ -20,7 +20,7 @@ package net.systemeD.potlatch2.controller { public class ControllerState { protected var controller:EditController; - protected var editableLayer:MapPaint; + public var layer:MapPaint; protected var previousState:ControllerState; protected var _selection:Array=[]; @@ -28,8 +28,8 @@ package net.systemeD.potlatch2.controller { public function ControllerState() {} public function setController(controller:EditController):void { - this.controller = controller; - editableLayer = controller.map.editableLayer; + this.controller=controller; + if (!layer) layer=controller.map.editableLayer; } public function setPreviousState(previousState:ControllerState):void { @@ -72,6 +72,7 @@ package net.systemeD.potlatch2.controller { } /** Default behaviour for the current state that should be called if state-specific action has been taken care of or ruled out. */ protected function sharedKeyboardEvents(event:KeyboardEvent):ControllerState { + var editableLayer:MapPaint=controller.map.editableLayer; // shorthand for this method switch (event.keyCode) { case 66: setSourceTag(); break; // B - set source tag for current object case 67: editableLayer.connection.closeChangeset(); break; // C - close changeset @@ -93,22 +94,38 @@ package net.systemeD.potlatch2.controller { var paint:MapPaint = getMapPaint(DisplayObject(event.target)); var focus:Entity = getTopLevelFocusEntity(entity); + if ( event.type == MouseEvent.MOUSE_UP && focus && map.dragstate!=map.NOT_DRAGGING) { + map.mouseUpHandler(); // in case the end-drag is over an EntityUI + } else if ( event.type == MouseEvent.ROLL_OVER && paint && paint.interactive ) { + paint.setHighlight(focus, { hover: true }); + } else if ( event.type == MouseEvent.MOUSE_OUT && paint && paint.interactive ) { + paint.setHighlight(focus, { hover: false }); + } else if ( event.type == MouseEvent.MOUSE_WHEEL ) { + if (event.delta > 0) { map.zoomIn(); } + else if (event.delta < 0) { map.zoomOut(); } + } + if ( paint && paint.isBackground ) { if (event.type == MouseEvent.MOUSE_DOWN && ((event.shiftKey && event.ctrlKey) || event.altKey) ) { // alt-click to pull data out of vector background layer - var newEntity:Entity=paint.pullThrough(entity,editableLayer); + paint.setHighlight(entity, { hover:false, selected: false }); + if (entity is Way) paint.setHighlightOnNodes(Way(entity), { selectedway: false }); + var newEntity:Entity=paint.pullThrough(entity,controller.map.editableLayer); if (entity is Way ) { return new SelectedWay(newEntity as Way); } else if (entity is Node) { return new SelectedPOINode(newEntity as Node); } - } else if (event.type == MouseEvent.MOUSE_DOWN && paint.interactive) { - if (entity is Way ) { return new SelectedBackgroundWay(entity as Way); } - else if (entity is Node ) { return new SelectedBackgroundNode(entity as Node, paint); } + } else if (!paint.interactive) { + return null; + } else if (event.type == MouseEvent.MOUSE_DOWN && paint.interactive) { + if (entity is Way ) { return new SelectedBackgroundWay(entity as Way, paint); } + else if (entity is Node ) { return new SelectedBackgroundNode(entity as Node, paint); } else if (entity is Marker) { return new SelectedMarker(entity as Marker, paint); } - } else if ( event.type == MouseEvent.MOUSE_UP ) { + } else if ( event.type == MouseEvent.MOUSE_UP) { return (this is NoSelection) ? null : new NoSelection(); - } else { return null; } - } - - if ( event.type == MouseEvent.MOUSE_DOWN ) { + } else if ( event.type == MouseEvent.CLICK && focus == null && map.dragstate!=map.DRAGGING) { + return (this is NoSelection) ? null : new NoSelection(); + } + + } else if ( event.type == MouseEvent.MOUSE_DOWN ) { if ( entity is Node && selectedWay && entity.hasParent(selectedWay) ) { // select node within this way return new DragWayNode(selectedWay, getNodeIndex(selectedWay,entity as Node), event, false); @@ -125,30 +142,9 @@ package net.systemeD.potlatch2.controller { } else if (event.ctrlKey) { return new SelectArea(event.localX,event.localY); } - } else if ( event.type == MouseEvent.CLICK && focus == null && map.dragstate!=map.DRAGGING && this is SelectedMarker) { - // this is identical to the below, but needed for unselecting markers on vector background layers. - // Deselecting a POI or way on the main layer emits both CLICK and MOUSE_UP, but markers only CLICK - // I'll leave it to someone who understands to decide whether they are the same thing and should be - // combined with a (CLICK || MOUSE_UP) - - // "&& this is SelectedMarker" added by Steve Bennett. The CLICK event being processed for SelectedWay state - // causes way to get unselected...so restrict the double processing as much as possible. - + + } else if ( (event.type==MouseEvent.CLICK || event.type==MouseEvent.MOUSE_UP) && focus == null && map.dragstate!=map.DRAGGING) { return (this is NoSelection) ? null : new NoSelection(); - } else if ( event.type == MouseEvent.MOUSE_UP && focus == null && map.dragstate!=map.DRAGGING) { - return (this is NoSelection) ? null : new NoSelection(); - } else if ( event.type == MouseEvent.MOUSE_UP && focus && map.dragstate!=map.NOT_DRAGGING) { - map.mouseUpHandler(); // in case the end-drag is over an EntityUI - } else if ( event.type == MouseEvent.ROLL_OVER ) { - editableLayer.setHighlight(focus, { hover: true }); - } else if ( event.type == MouseEvent.MOUSE_OUT ) { - editableLayer.setHighlight(focus, { hover: false }); - } else if ( event.type == MouseEvent.MOUSE_WHEEL ) { - if (event.delta > 0) { - map.zoomIn(); - } else if (event.delta < 0) { - map.zoomOut(); - } } return null; } diff --git a/net/systemeD/potlatch2/controller/DragSelection.as b/net/systemeD/potlatch2/controller/DragSelection.as index 739180e5..6f583f60 100644 --- a/net/systemeD/potlatch2/controller/DragSelection.as +++ b/net/systemeD/potlatch2/controller/DragSelection.as @@ -95,14 +95,14 @@ package net.systemeD.potlatch2.controller { /** Highlight the dragged selection. */ override public function enterState():void { for each (var entity:Entity in selection) { - editableLayer.setHighlight(entity, { selected: true }); + layer.setHighlight(entity, { selected: true }); } } /** Un-highlight the dragged selection. */ override public function exitState(newState:ControllerState):void { for each (var entity:Entity in selection) { - editableLayer.setHighlight(entity, { selected: false }); + layer.setHighlight(entity, { selected: false }); } } /** "DragSelection" */ diff --git a/net/systemeD/potlatch2/controller/DragWayNode.as b/net/systemeD/potlatch2/controller/DragWayNode.as index 3625b17c..b8c7911e 100644 --- a/net/systemeD/potlatch2/controller/DragWayNode.as +++ b/net/systemeD/potlatch2/controller/DragWayNode.as @@ -33,7 +33,7 @@ package net.systemeD.potlatch2.controller { } private function addNode(selectedWay:Way,event:MouseEvent):int { - var ways:Array = editableLayer.findWaysAtPoint(event.stageX, event.stageY, selectedWay); + var ways:Array = layer.findWaysAtPoint(event.stageX, event.stageY, selectedWay); var lat:Number = controller.map.coord2lat(event.localY); var lon:Number = controller.map.coord2lon(event.localX); var undo:CompositeUndoableAction = new CompositeUndoableAction("Insert node"); @@ -109,17 +109,17 @@ package net.systemeD.potlatch2.controller { originalLat = draggingNode.lat; originalLon = draggingNode.lon; - editableLayer.setHighlightOnNodes(parentWay, { selectedway: true } ); - editableLayer.limitWayDrawing(parentWay, draggingIndex); - editableLayer.setHighlight(draggingNode, { selected: true } ); - editableLayer.protectWay(parentWay); - editableLayer.limitWayDrawing(parentWay, NaN, draggingIndex); + layer.setHighlightOnNodes(parentWay, { selectedway: true } ); + layer.limitWayDrawing(parentWay, draggingIndex); + layer.setHighlight(draggingNode, { selected: true } ); + layer.protectWay(parentWay); + layer.limitWayDrawing(parentWay, NaN, draggingIndex); } override public function exitState(newState:ControllerState):void { - editableLayer.unprotectWay(parentWay); - editableLayer.limitWayDrawing(parentWay); - editableLayer.setHighlightOnNodes(parentWay, { selectedway: false } ); - editableLayer.setHighlight(draggingNode, { selected: false } ); + layer.unprotectWay(parentWay); + layer.limitWayDrawing(parentWay); + layer.setHighlightOnNodes(parentWay, { selectedway: false } ); + layer.setHighlight(draggingNode, { selected: false } ); } override public function toString():String { return "DragWayNode"; diff --git a/net/systemeD/potlatch2/controller/DrawWay.as b/net/systemeD/potlatch2/controller/DrawWay.as index 84a95497..1984ecef 100644 --- a/net/systemeD/potlatch2/controller/DrawWay.as +++ b/net/systemeD/potlatch2/controller/DrawWay.as @@ -43,8 +43,8 @@ package net.systemeD.potlatch2.controller { controller.map.mouseUpHandler(); // in case you're still in the drag-tolerance zone, and mouse up over something. if ( entity == null || isBackground ) { // didn't hit anything: extend the way by one node. node = createAndAddNode(event, MainUndoStack.getGlobalStack().addAction); - editableLayer.setHighlight(node, { selectedway: true }); - editableLayer.setPurgable([node], false); + layer.setHighlight(node, { selectedway: true }); + layer.setPurgable([node], false); resetElastic(node); lastClick=node; controller.updateSelectionUIWithoutTagChange(); @@ -56,7 +56,7 @@ package net.systemeD.potlatch2.controller { MainUndoStack.getGlobalStack().undo(); // undo the BeginWayAction that (presumably?) just happened var newPoiAction:CreatePOIAction = new CreatePOIAction( - editableLayer.connection, + layer.connection, {}, controller.map.coord2lat(event.localY), controller.map.coord2lon(event.localX)); @@ -76,9 +76,9 @@ package net.systemeD.potlatch2.controller { // hit a node, add it to this way and carry on appendNode(entity as Node, MainUndoStack.getGlobalStack().addAction); if (focus is Way) { - editableLayer.setHighlightOnNodes(focus as Way, { hoverway: false }); + layer.setHighlightOnNodes(focus as Way, { hoverway: false }); } - editableLayer.setHighlight(entity, { selectedway: true }); + layer.setHighlight(entity, { selectedway: true }); resetElastic(entity as Node); lastClick=entity; if (Way(firstSelected).getNode(0)==Way(firstSelected).getLastNode()) { @@ -102,13 +102,13 @@ package net.systemeD.potlatch2.controller { node = createAndAddNode(event, jnct.push); Way(entity).insertNodeAtClosestPosition(node, true, jnct.push); MainUndoStack.getGlobalStack().addAction(jnct); - editableLayer.setHighlight(node, { selectedway: true }); - editableLayer.setPurgable([node], false); + layer.setHighlight(node, { selectedway: true }); + layer.setPurgable([node], false); } resetElastic(node); lastClick=node; - editableLayer.setHighlightOnNodes(entity as Way, { hoverway: false }); - editableLayer.setHighlightOnNodes(firstSelected as Way, { selectedway: true }); + layer.setHighlightOnNodes(entity as Way, { hoverway: false }); + layer.setHighlightOnNodes(firstSelected as Way, { selectedway: true }); } lastClickTime=new Date(); } else if ( event.type == MouseEvent.MOUSE_MOVE && elastic ) { @@ -122,7 +122,7 @@ package net.systemeD.potlatch2.controller { if (focus is Way && focus!=firstSelected) { // floating over another way, highlight its nodes hoverEntity=focus; - editableLayer.setHighlightOnNodes(focus as Way, { hoverway: true }); + layer.setHighlightOnNodes(focus as Way, { hoverway: true }); } // set cursor depending on whether we're floating over the start of this way, // another random node, a possible junction... @@ -137,7 +137,7 @@ package net.systemeD.potlatch2.controller { } else if ( event.type == MouseEvent.MOUSE_OUT && !isBackground ) { if (focus is Way && entity!=firstSelected) { hoverEntity=null; - editableLayer.setHighlightOnNodes(focus as Way, { hoverway: false }); + layer.setHighlightOnNodes(focus as Way, { hoverway: false }); // ** We could do with an optional way of calling WayUI.redraw to only do the nodes, which would be a // useful optimisation. } @@ -195,7 +195,7 @@ package net.systemeD.potlatch2.controller { protected function stopDrawing():ControllerState { if ( hoverEntity ) { - editableLayer.setHighlightOnNodes(hoverEntity as Way, { hoverway: false }); + layer.setHighlightOnNodes(hoverEntity as Way, { hoverway: false }); hoverEntity = null; } @@ -244,7 +244,7 @@ package net.systemeD.potlatch2.controller { } // Only actually delete the node if it has no other tags, and is not part of other ways (or part of this way twice) if (node.numParentWays==1 && Way(firstSelected).hasOnceOnly(node) && !node.hasInterestingTags()) { - editableLayer.setPurgable([node], true); + layer.setPurgable([node], true); node.connection.unregisterPOI(node); node.remove(undo.push); } @@ -261,7 +261,7 @@ package net.systemeD.potlatch2.controller { performAction(undo); if(!node.isDeleted()) { // i.e. was junction with another way (or is now POI) - editableLayer.setHighlight(node, {selectedway: false}); + layer.setHighlight(node, {selectedway: false}); } return state; } @@ -310,7 +310,7 @@ package net.systemeD.potlatch2.controller { appendNode(nextNode as Node, MainUndoStack.getGlobalStack().addAction); resetElastic(nextNode as Node); lastClick=nextNode; - editableLayer.setHighlight(nextNode, { selectedway: true }); + layer.setHighlight(nextNode, { selectedway: true }); // recentre the map if the new lat/lon is offscreen controller.map.scrollIfNeeded(nextNode.lat,nextNode.lon); diff --git a/net/systemeD/potlatch2/controller/NoSelection.as b/net/systemeD/potlatch2/controller/NoSelection.as index 5c5f8800..5c5072d2 100644 --- a/net/systemeD/potlatch2/controller/NoSelection.as +++ b/net/systemeD/potlatch2/controller/NoSelection.as @@ -26,7 +26,7 @@ package net.systemeD.potlatch2.controller { if (event.type==MouseEvent.MOUSE_UP && (focus==null || (paint && paint.isBackground)) && map.dragstate!=map.DRAGGING) { map.dragstate=map.NOT_DRAGGING; var undo:CompositeUndoableAction = new BeginWayAction(); - var conn:Connection = editableLayer.connection; + var conn:Connection = layer.connection; var startNode:Node = conn.createNode( {}, controller.map.coord2lat(event.localY), diff --git a/net/systemeD/potlatch2/controller/SelectArea.as b/net/systemeD/potlatch2/controller/SelectArea.as index 73cb2fc5..1a0ad60b 100644 --- a/net/systemeD/potlatch2/controller/SelectArea.as +++ b/net/systemeD/potlatch2/controller/SelectArea.as @@ -34,7 +34,7 @@ package net.systemeD.potlatch2.controller { var right:Number=controller.map.coord2lon(endX); var top:Number=controller.map.coord2lat(startY); var bottom:Number=controller.map.coord2lat(endY); - var entities:Object=editableLayer.connection.getObjectsByBbox(left,right,top,bottom); + var entities:Object=layer.connection.getObjectsByBbox(left,right,top,bottom); for each (var way:Way in entities.waysInside) { if (way.intersects(left,right,top,bottom)) toggleSelection(way); } for each (var poi:Node in entities.poisInside) { toggleSelection(poi); } return controller.findStateForSelection(selection); @@ -51,7 +51,7 @@ package net.systemeD.potlatch2.controller { override public function enterState():void { box=new Shape(); - var l:DisplayObject=editableLayer.getPaintSpriteAt(editableLayer.maxlayer); + var l:DisplayObject=layer.getPaintSpriteAt(layer.maxlayer); var o:DisplayObject=Sprite(l).getChildAt(3); (o as Sprite).addChild(box); controller.map.draggable=false; diff --git a/net/systemeD/potlatch2/controller/SelectedBackgroundNode.as b/net/systemeD/potlatch2/controller/SelectedBackgroundNode.as index a125a7b9..33ab41ca 100644 --- a/net/systemeD/potlatch2/controller/SelectedBackgroundNode.as +++ b/net/systemeD/potlatch2/controller/SelectedBackgroundNode.as @@ -7,7 +7,6 @@ package net.systemeD.potlatch2.controller { public class SelectedBackgroundNode extends ControllerState { protected var initNode:Node; - protected var layer:MapPaint; public function SelectedBackgroundNode(node:Node, layer:MapPaint) { initNode = node; @@ -19,7 +18,7 @@ package net.systemeD.potlatch2.controller { return; clearSelection(this); - editableLayer.setHighlight(node, { selected: true }); + layer.setHighlight(node, { selected: true }); selection = [node]; controller.updateSelectionUI(layer); initNode = node; @@ -27,7 +26,7 @@ package net.systemeD.potlatch2.controller { protected function clearSelection(newState:ControllerState):void { if ( selectCount ) { - editableLayer.setHighlight(firstSelected, { selected: false }); + layer.setHighlight(firstSelected, { selected: false }); selection = []; if (!newState.isSelectionState()) { controller.updateSelectionUI(); } } @@ -53,11 +52,11 @@ package net.systemeD.potlatch2.controller { override public function enterState():void { selectNode(initNode); - editableLayer.setPurgable(selection,false); + layer.setPurgable(selection,false); } override public function exitState(newState:ControllerState):void { - editableLayer.setPurgable(selection,true); + layer.setPurgable(selection,true); clearSelection(newState); } diff --git a/net/systemeD/potlatch2/controller/SelectedBackgroundWay.as b/net/systemeD/potlatch2/controller/SelectedBackgroundWay.as index 934010c4..6ce097fe 100644 --- a/net/systemeD/potlatch2/controller/SelectedBackgroundWay.as +++ b/net/systemeD/potlatch2/controller/SelectedBackgroundWay.as @@ -5,8 +5,7 @@ package net.systemeD.potlatch2.controller { import net.systemeD.halcyon.WayUI; import net.systemeD.halcyon.connection.*; - import net.systemeD.potlatch2.tools.Quadrilateralise; - import net.systemeD.potlatch2.tools.Simplify; + import net.systemeD.halcyon.MapPaint; /** Behaviour that takes place while a way is selected includes: adding a node to the way, straightening/reshaping the way, dragging it. */ public class SelectedBackgroundWay extends ControllerState { @@ -20,11 +19,12 @@ package net.systemeD.potlatch2.controller { * @param way The way that is now selected. * @param point The location that was clicked. * @param ways An ordered list of ways sharing a node, to make "way cycling" work. */ - public function SelectedBackgroundWay(way:Way, point:Point=null, ways:Array=null, index:int=0) { + public function SelectedBackgroundWay(way:Way, layer:MapPaint, point:Point=null, ways:Array=null, index:int=0) { initWay = way; clicked = point; wayList = ways; initIndex=index; + this.layer = layer; } private function updateSelectionUI(e:Event):void { @@ -34,8 +34,8 @@ package net.systemeD.potlatch2.controller { /** Tidy up UI as we transition to a new state without the current selection. */ protected function clearSelection(newState:ControllerState):void { if ( selectCount ) { - editableLayer.setHighlight(firstSelected, { selected: false, hover: false }); - editableLayer.setHighlightOnNodes(firstSelected as Way, { selectedway: false }); + layer.setHighlight(firstSelected, { selected: false, hover: false }); + layer.setHighlightOnNodes(firstSelected as Way, { selectedway: false }); selection = []; if (!newState.isSelectionState()) { controller.updateSelectionUI(); } } @@ -63,17 +63,17 @@ package net.systemeD.potlatch2.controller { override public function enterState():void { if (firstSelected!=initWay) { clearSelection(this); - editableLayer.setHighlight(initWay, { selected: true, hover: false }); - editableLayer.setHighlightOnNodes(initWay, { selectedway: true }); + layer.setHighlight(initWay, { selected: true, hover: false }); + layer.setHighlightOnNodes(initWay, { selectedway: true }); selection = [initWay]; controller.updateSelectionUI(); } - editableLayer.setPurgable(selection,false); + layer.setPurgable(selection,false); } /** Officially leave the state */ override public function exitState(newState:ControllerState):void { - editableLayer.setPurgable(selection,true); + layer.setPurgable(selection,true); clearSelection(newState); } diff --git a/net/systemeD/potlatch2/controller/SelectedMarker.as b/net/systemeD/potlatch2/controller/SelectedMarker.as index 9f9aeca8..2af2441f 100644 --- a/net/systemeD/potlatch2/controller/SelectedMarker.as +++ b/net/systemeD/potlatch2/controller/SelectedMarker.as @@ -7,7 +7,6 @@ package net.systemeD.potlatch2.controller { public class SelectedMarker extends ControllerState { protected var initMarker:Marker; - protected var layer:MapPaint; public function SelectedMarker(marker:Marker, layer:MapPaint) { initMarker = marker; @@ -19,7 +18,7 @@ package net.systemeD.potlatch2.controller { return; clearSelection(this); - editableLayer.setHighlight(marker, { selected: true }); + layer.setHighlight(marker, { selected: true }); selection = [marker]; controller.updateSelectionUI(layer); initMarker = marker; @@ -27,7 +26,7 @@ package net.systemeD.potlatch2.controller { protected function clearSelection(newState:ControllerState):void { if ( selectCount ) { - editableLayer.setHighlight(firstSelected, { selected: false }); + layer.setHighlight(firstSelected, { selected: false }); selection = []; if (!newState.isSelectionState()) { controller.updateSelectionUI(); } } @@ -53,11 +52,11 @@ package net.systemeD.potlatch2.controller { override public function enterState():void { selectMarker(initMarker); - editableLayer.setPurgable(selection,false); + layer.setPurgable(selection,false); } override public function exitState(newState:ControllerState):void { - editableLayer.setPurgable(selection,true); + layer.setPurgable(selection,true); clearSelection(newState); } diff --git a/net/systemeD/potlatch2/controller/SelectedMultiple.as b/net/systemeD/potlatch2/controller/SelectedMultiple.as index aa895515..3b0a0122 100644 --- a/net/systemeD/potlatch2/controller/SelectedMultiple.as +++ b/net/systemeD/potlatch2/controller/SelectedMultiple.as @@ -19,7 +19,7 @@ package net.systemeD.potlatch2.controller { if ( event.type == MouseEvent.MOUSE_DOWN && entity && event.ctrlKey ) { // modify selection - editableLayer.setHighlight(entity, { selected: toggleSelection(entity) }); + layer.setHighlight(entity, { selected: toggleSelection(entity) }); controller.updateSelectionUI(); if (selectCount>1) { return this; } @@ -110,16 +110,16 @@ package net.systemeD.potlatch2.controller { override public function enterState():void { selection=initSelection.concat(); for each (var entity:Entity in selection) { - editableLayer.setHighlight(entity, { selected: true, hover: false }); + layer.setHighlight(entity, { selected: true, hover: false }); } controller.updateSelectionUI(); - editableLayer.setPurgable(selection,false); + layer.setPurgable(selection,false); } override public function exitState(newState:ControllerState):void { - editableLayer.setPurgable(selection,true); + layer.setPurgable(selection,true); for each (var entity:Entity in selection) { - editableLayer.setHighlight(entity, { selected: false, hover: false }); + layer.setHighlight(entity, { selected: false, hover: false }); } selection = []; if (!newState.isSelectionState()) { controller.updateSelectionUI(); } diff --git a/net/systemeD/potlatch2/controller/SelectedPOINode.as b/net/systemeD/potlatch2/controller/SelectedPOINode.as index 2710dc99..2e6af17c 100644 --- a/net/systemeD/potlatch2/controller/SelectedPOINode.as +++ b/net/systemeD/potlatch2/controller/SelectedPOINode.as @@ -16,7 +16,7 @@ package net.systemeD.potlatch2.controller { return; clearSelection(this); - editableLayer.setHighlight(node, { selected: true }); + layer.setHighlight(node, { selected: true }); selection = [node]; controller.updateSelectionUI(); initNode = node; @@ -24,7 +24,7 @@ package net.systemeD.potlatch2.controller { protected function clearSelection(newState:ControllerState):void { if ( selectCount ) { - editableLayer.setHighlight(firstSelected, { selected: false }); + layer.setHighlight(firstSelected, { selected: false }); selection = []; if (!newState.isSelectionState()) { controller.updateSelectionUI(); } } @@ -60,13 +60,13 @@ package net.systemeD.potlatch2.controller { override public function enterState():void { selectNode(initNode); - editableLayer.setPurgable(selection,false); + layer.setPurgable(selection,false); } override public function exitState(newState:ControllerState):void { if(firstSelected.hasTags()) { controller.clipboards['node']=firstSelected.getTagsCopy(); } - editableLayer.setPurgable(selection,true); + layer.setPurgable(selection,true); clearSelection(newState); } diff --git a/net/systemeD/potlatch2/controller/SelectedParallelWay.as b/net/systemeD/potlatch2/controller/SelectedParallelWay.as index 1324af13..dc35494e 100644 --- a/net/systemeD/potlatch2/controller/SelectedParallelWay.as +++ b/net/systemeD/potlatch2/controller/SelectedParallelWay.as @@ -76,7 +76,7 @@ package net.systemeD.potlatch2.controller { /** Creates the WayUI for the parallel way. */ override public function enterState():void { selection=[parallelise.parallelWay]; - editableLayer.createWayUI(firstSelected as Way); + layer.createWayUI(firstSelected as Way); startlon =controller.map.coord2lon(controller.map.mouseX); startlatp=controller.map.coord2latp(controller.map.mouseY); } diff --git a/net/systemeD/potlatch2/controller/SelectedWay.as b/net/systemeD/potlatch2/controller/SelectedWay.as index 1c15243c..fd978beb 100644 --- a/net/systemeD/potlatch2/controller/SelectedWay.as +++ b/net/systemeD/potlatch2/controller/SelectedWay.as @@ -33,8 +33,8 @@ package net.systemeD.potlatch2.controller { /** Tidy up UI as we transition to a new state without the current selection. */ protected function clearSelection(newState:ControllerState):void { if ( selectCount ) { - editableLayer.setHighlight(firstSelected, { selected: false, hover: false }); - editableLayer.setHighlightOnNodes(firstSelected as Way, { selectedway: false }); + layer.setHighlight(firstSelected, { selected: false, hover: false }); + layer.setHighlightOnNodes(firstSelected as Way, { selectedway: false }); selection = []; if (!newState.isSelectionState()) { controller.updateSelectionUI(); } } @@ -85,7 +85,7 @@ package net.systemeD.potlatch2.controller { if (!clicked || (wayList && wayList.length<2)) { return this; } if (!wayList) { - wayList=[initWay].concat(editableLayer.findWaysAtPoint(clicked.x,clicked.y,initWay)); + wayList=[initWay].concat(layer.findWaysAtPoint(clicked.x,clicked.y,initWay)); } wayList=wayList.slice(1).concat(wayList[0]); // Find the new way's index of the currently "selected" node, to facilitate keyboard navigation @@ -95,7 +95,7 @@ package net.systemeD.potlatch2.controller { /** Perform deletion of currently selected way. */ public function deleteWay():ControllerState { - editableLayer.setHighlightOnNodes(firstSelected as Way, {selectedway: false}); + layer.setHighlightOnNodes(firstSelected as Way, {selectedway: false}); selectedWay.remove(MainUndoStack.getGlobalStack().addAction); return new NoSelection(); } @@ -104,13 +104,13 @@ package net.systemeD.potlatch2.controller { override public function enterState():void { if (firstSelected!=initWay) { clearSelection(this); - editableLayer.setHighlight(initWay, { selected: true, hover: false }); - editableLayer.setHighlightOnNodes(initWay, { selectedway: true }); + layer.setHighlight(initWay, { selected: true, hover: false }); + layer.setHighlightOnNodes(initWay, { selectedway: true }); selection = [initWay]; controller.updateSelectionUI(); initWay.addEventListener(Connection.WAY_REORDERED, updateSelectionUI, false, 0, true); } - editableLayer.setPurgable(selection,false); + layer.setPurgable(selection,false); } /** Officially leave the state, remembering the current way's tags for future repeats. */ // TODO: tweak this so that repeat tags aren't remembered if you only select a way in order to branch off it. (a la PL1) @@ -118,7 +118,7 @@ package net.systemeD.potlatch2.controller { if (firstSelected.hasTags()) { controller.clipboards['way']=firstSelected.getTagsCopy(); } - editableLayer.setPurgable(selection,true); + layer.setPurgable(selection,true); firstSelected.removeEventListener(Connection.WAY_REORDERED, updateSelectionUI); clearSelection(newState); } diff --git a/net/systemeD/potlatch2/controller/SelectedWayNode.as b/net/systemeD/potlatch2/controller/SelectedWayNode.as index fbe7cea4..03ba21cb 100644 --- a/net/systemeD/potlatch2/controller/SelectedWayNode.as +++ b/net/systemeD/potlatch2/controller/SelectedWayNode.as @@ -25,9 +25,9 @@ package net.systemeD.potlatch2.controller { return; clearSelection(this); - editableLayer.setHighlight(way, { hover: false }); - editableLayer.setHighlight(node, { selected: true }); - editableLayer.setHighlightOnNodes(way, { selectedway: true }); + layer.setHighlight(way, { hover: false }); + layer.setHighlight(node, { selected: true }); + layer.setHighlightOnNodes(way, { selectedway: true }); selection = [node]; parentWay = way; controller.updateSelectionUI(); selectedIndex = index; initIndex = index; @@ -35,9 +35,9 @@ package net.systemeD.potlatch2.controller { protected function clearSelection(newState:ControllerState):void { if ( selectCount ) { - editableLayer.setHighlight(parentWay, { selected: false }); - editableLayer.setHighlight(firstSelected, { selected: false }); - editableLayer.setHighlightOnNodes(parentWay, { selectedway: false }); + layer.setHighlight(parentWay, { selected: false }); + layer.setHighlight(firstSelected, { selected: false }); + layer.setHighlightOnNodes(parentWay, { selectedway: false }); selection = []; if (!newState.isSelectionState()) { controller.updateSelectionUI(); } } @@ -106,13 +106,13 @@ package net.systemeD.potlatch2.controller { override public function enterState():void { selectNode(parentWay,initIndex); - editableLayer.setPurgable(selection,false); + layer.setPurgable(selection,false); } override public function exitState(newState:ControllerState):void { if (firstSelected.hasTags()) { controller.clipboards['node']=firstSelected.getTagsCopy(); } - editableLayer.setPurgable(selection,true); + layer.setPurgable(selection,true); clearSelection(newState); } @@ -146,8 +146,8 @@ package net.systemeD.potlatch2.controller { if (parentWay.getLastNode() == n) { return this; } } - editableLayer.setHighlightOnNodes(parentWay, { selectedway: false } ); - editableLayer.setPurgable([parentWay],true); + layer.setHighlightOnNodes(parentWay, { selectedway: false } ); + layer.setPurgable([parentWay],true); MainUndoStack.getGlobalStack().addAction(new SplitWayAction(parentWay, ni)); return new SelectedWay(parentWay); @@ -162,7 +162,7 @@ package net.systemeD.potlatch2.controller { } public function deleteNode():ControllerState { - editableLayer.setPurgable(selection,true); + layer.setPurgable(selection,true); firstSelected.remove(MainUndoStack.getGlobalStack().addAction); return new SelectedWay(parentWay); } @@ -182,7 +182,7 @@ package net.systemeD.potlatch2.controller { // First, look for POI nodes in 20x20 pixel box around the current node // FIXME: why aren't we using a hitTest for this? - var hitnodes:Array = editableLayer.connection.getObjectsByBbox( + var hitnodes:Array = layer.connection.getObjectsByBbox( map.coord2lon(p.x-10), map.coord2lon(p.x+10), map.coord2lat(p.y-10), @@ -194,7 +194,7 @@ package net.systemeD.potlatch2.controller { } } - var ways:Array=editableLayer.findWaysAtPoint(q.x, q.y, selectedWay); + var ways:Array=layer.findWaysAtPoint(q.x, q.y, selectedWay); for each (var w:Way in ways) { // hit a way, now let's see if we hit a specific node for (var i:uint = 0; i < w.length; i++) { diff --git a/net/systemeD/potlatch2/utils/ShpImporter.as b/net/systemeD/potlatch2/utils/ShpImporter.as index 45d020c0..dd0cf6ce 100644 --- a/net/systemeD/potlatch2/utils/ShpImporter.as +++ b/net/systemeD/potlatch2/utils/ShpImporter.as @@ -45,6 +45,7 @@ package net.systemeD.potlatch2.utils { for (key in dr.values) { v=dr.values[key]; while (v.substr(v.length-1,1)==" ") v=v.substr(0,v.length-1); + while (v.substr(0,1)==" ") v=v.substr(1); if (v!='') tags[key.toLowerCase()]=v; } diff --git a/resources/stylesheets/core_interactive.css b/resources/stylesheets/core_interactive.css index 6fec5f74..0c02f611 100644 --- a/resources/stylesheets/core_interactive.css +++ b/resources/stylesheets/core_interactive.css @@ -5,7 +5,9 @@ relation[type=restriction] node { z-index:11; icon-image: icons/restriction.png; /* Interactive way behaviour */ way::highlight :hover { z-index: 2; width: eval('_width+10'); color: #ffff99; } +way::highlight :hover :background { color: lightcyan; } way::highlight :selected { z-index: 2; width: eval('_width+10'); color: yellow; opacity: 0.7;} +way::highlight :selected :background { color: cyan; } way::highlight :restrictfrom { z-index: -1; width: eval('_width+10'); color: red; opacity: 0.7;} way::highlight :restrictto { z-index: -1; width: eval('_width+10'); color: blue; opacity: 0.7;} /*way !:drawn !:hasTags{ z-index:10; width: 0.5; color: red; }*/ @@ -21,4 +23,5 @@ node !:drawn :hasTags { z-index: 9; icon-image: circle; icon-width: 4; color: bl node :hasTags :selectedway { z-index: 9; icon-image: square; icon-width: 8; color: black; layer: 5; } node !:drawn :selectedway { z-index: 9; icon-image: square; icon-width: 8; color: red; casing-color: #cc0000; casing-width: 1; layer: 5; } node::selectedNode :selected { z-index: 1; icon-image: square; icon-width: eval('_width+10'); color: yellow; interactive: no; layer: 5; } +node::selectedNode :selected :background { color: cyan; } node::junctionNode :junction :selectedway { z-index: 8; icon-image: square; icon-width: 12; casing-color: black; casing-width: 1; layer: 5; } From 9c420a26968b1671087409d70c722fc7199930e8 Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Wed, 15 Jun 2011 23:28:18 +0100 Subject: [PATCH 83/89] Unify selection ControllerStates so they can work on either background or editable objects --- net/systemeD/halcyon/Map.as | 8 ++ net/systemeD/halcyon/MapPaint.as | 5 ++ .../actions/RemoveNodeByIndexAction.as | 2 +- net/systemeD/potlatch2/EditController.as | 8 +- .../potlatch2/controller/ControllerState.as | 27 +++--- .../potlatch2/controller/SelectArea.as | 13 ++- .../controller/SelectedBackgroundNode.as | 68 --------------- .../controller/SelectedBackgroundWay.as | 86 ------------------- .../potlatch2/controller/SelectedMultiple.as | 8 +- .../potlatch2/controller/SelectedPOINode.as | 16 ++-- .../potlatch2/controller/SelectedWay.as | 35 +++++--- .../potlatch2/controller/SelectedWayNode.as | 2 +- 12 files changed, 85 insertions(+), 193 deletions(-) delete mode 100644 net/systemeD/potlatch2/controller/SelectedBackgroundNode.as delete mode 100644 net/systemeD/potlatch2/controller/SelectedBackgroundWay.as diff --git a/net/systemeD/halcyon/Map.as b/net/systemeD/halcyon/Map.as index 1377d446..8a45b074 100644 --- a/net/systemeD/halcyon/Map.as +++ b/net/systemeD/halcyon/Map.as @@ -291,6 +291,14 @@ package net.systemeD.halcyon { return editableLayer; } + /** Find which paint object an entity will be displayed on. */ + public function getLayerForEntity(entity:Entity):MapPaint { + for (var i:uint=0; i1) { return new SelectedMultiple(sel); } - else if (sel[0] is Way) { return new SelectedWay(sel[0]); } + var layer:MapPaint=_map.getLayerForEntity(sel[0]); + + if (sel.length>1) { return new SelectedMultiple(sel, layer); } + else if (sel[0] is Way) { return new SelectedWay(sel[0], layer); } else if (sel[0] is Node && Node(sel[0]).hasParentWays) { var way:Way=sel[0].parentWays[0] as Way; return new SelectedWayNode(way, way.indexOfNode(sel[0] as Node)); } else { - return new SelectedPOINode(sel[0] as Node); + return new SelectedPOINode(sel[0] as Node, layer); } } diff --git a/net/systemeD/potlatch2/controller/ControllerState.as b/net/systemeD/potlatch2/controller/ControllerState.as index 3c02e1b4..416216d6 100644 --- a/net/systemeD/potlatch2/controller/ControllerState.as +++ b/net/systemeD/potlatch2/controller/ControllerState.as @@ -108,20 +108,23 @@ package net.systemeD.potlatch2.controller { if ( paint && paint.isBackground ) { if (event.type == MouseEvent.MOUSE_DOWN && ((event.shiftKey && event.ctrlKey) || event.altKey) ) { // alt-click to pull data out of vector background layer - paint.setHighlight(entity, { hover:false, selected: false }); - if (entity is Way) paint.setHighlightOnNodes(Way(entity), { selectedway: false }); - var newEntity:Entity=paint.pullThrough(entity,controller.map.editableLayer); - if (entity is Way ) { return new SelectedWay(newEntity as Way); } - else if (entity is Node) { return new SelectedPOINode(newEntity as Node); } + var newSelection:Array=[]; + if (selection.indexOf(entity)==-1) { selection=[entity]; } + for each (var entity:Entity in selection) { + paint.setHighlight(entity, { hover:false, selected: false }); + if (entity is Way) paint.setHighlightOnNodes(Way(entity), { selectedway: false }); + newSelection.push(paint.pullThrough(entity,controller.map.editableLayer)); + } + return controller.findStateForSelection(newSelection); } else if (!paint.interactive) { return null; } else if (event.type == MouseEvent.MOUSE_DOWN && paint.interactive) { - if (entity is Way ) { return new SelectedBackgroundWay(entity as Way, paint); } - else if (entity is Node ) { return new SelectedBackgroundNode(entity as Node, paint); } + if (entity is Way ) { return new SelectedWay(entity as Way, paint); } + else if (entity is Node ) { if (!entity.hasParentWays) return new SelectedPOINode(entity as Node, paint); } else if (entity is Marker) { return new SelectedMarker(entity as Marker, paint); } - } else if ( event.type == MouseEvent.MOUSE_UP) { + } else if ( event.type == MouseEvent.MOUSE_UP && !event.ctrlKey) { return (this is NoSelection) ? null : new NoSelection(); - } else if ( event.type == MouseEvent.CLICK && focus == null && map.dragstate!=map.DRAGGING) { + } else if ( event.type == MouseEvent.CLICK && focus == null && map.dragstate!=map.DRAGGING && !event.ctrlKey) { return (this is NoSelection) ? null : new NoSelection(); } @@ -139,11 +142,11 @@ package net.systemeD.potlatch2.controller { return new DragSelection(selection, event); } else if (entity) { return new DragSelection([entity], event); - } else if (event.ctrlKey) { - return new SelectArea(event.localX,event.localY); + } else if (event.ctrlKey && !layer.isBackground) { + return new SelectArea(event.localX,event.localY,selection); } - } else if ( (event.type==MouseEvent.CLICK || event.type==MouseEvent.MOUSE_UP) && focus == null && map.dragstate!=map.DRAGGING) { + } else if ( (event.type==MouseEvent.CLICK || event.type==MouseEvent.MOUSE_UP) && focus == null && map.dragstate!=map.DRAGGING && !event.ctrlKey) { return (this is NoSelection) ? null : new NoSelection(); } return null; diff --git a/net/systemeD/potlatch2/controller/SelectArea.as b/net/systemeD/potlatch2/controller/SelectArea.as index 1a0ad60b..b00b944b 100644 --- a/net/systemeD/potlatch2/controller/SelectArea.as +++ b/net/systemeD/potlatch2/controller/SelectArea.as @@ -12,8 +12,11 @@ package net.systemeD.potlatch2.controller { private var endY:Number; private var box:Shape; private const TOLERANCE:uint=4; + private var originalSelection:Array; - public function SelectArea(x:Number,y:Number) { + public function SelectArea(x:Number,y:Number,sel:Array) { + selection = sel.concat(); + originalSelection = sel.concat(); startX=endX=x; startY=endY=y; } @@ -29,7 +32,7 @@ package net.systemeD.potlatch2.controller { var a:Number; if (startX>endX) { a=startX; startX=endX; endX=a; } if (startY>endY) { a=startY; startY=endY; endY=a; } - if (endX-startX1) { return this; } return controller.findStateForSelection(selection); + + } else if ( event.type == MouseEvent.MOUSE_UP && selection.indexOf(focus)>-1 ) { + return this; } var cs:ControllerState = sharedMouseEvents(event, entity); return cs ? cs : this; diff --git a/net/systemeD/potlatch2/controller/SelectedPOINode.as b/net/systemeD/potlatch2/controller/SelectedPOINode.as index 2e6af17c..b3279501 100644 --- a/net/systemeD/potlatch2/controller/SelectedPOINode.as +++ b/net/systemeD/potlatch2/controller/SelectedPOINode.as @@ -1,13 +1,16 @@ package net.systemeD.potlatch2.controller { import flash.events.*; + import flash.display.*; import flash.ui.Keyboard; import net.systemeD.potlatch2.EditController; import net.systemeD.halcyon.connection.*; + import net.systemeD.halcyon.MapPaint; public class SelectedPOINode extends ControllerState { protected var initNode:Node; - public function SelectedPOINode(node:Node) { + public function SelectedPOINode(node:Node, layer:MapPaint=null) { + if (layer) this.layer=layer; initNode = node; } @@ -32,11 +35,14 @@ package net.systemeD.potlatch2.controller { override public function processMouseEvent(event:MouseEvent, entity:Entity):ControllerState { if (event.type==MouseEvent.MOUSE_MOVE) { return this; } - if (event.type==MouseEvent.MOUSE_DOWN && event.ctrlKey && entity && entity!=firstSelected) { - return new SelectedMultiple([firstSelected,entity]); - } - if (event.type==MouseEvent.MOUSE_DOWN && event.shiftKey && !entity) { + var paint:MapPaint = getMapPaint(DisplayObject(event.target)); + + if (event.type==MouseEvent.MOUSE_DOWN && event.ctrlKey && entity && entity!=firstSelected && paint==layer) { + return new SelectedMultiple([firstSelected,entity],layer); + } else if (event.type==MouseEvent.MOUSE_DOWN && event.shiftKey && !entity && !layer.isBackground) { return new DrawQuadrilateral(firstSelected as Node); + } else if ( event.type == MouseEvent.MOUSE_UP && entity==firstSelected ) { + return this; } var cs:ControllerState = sharedMouseEvents(event, entity); return cs ? cs : this; diff --git a/net/systemeD/potlatch2/controller/SelectedWay.as b/net/systemeD/potlatch2/controller/SelectedWay.as index fd978beb..192e2417 100644 --- a/net/systemeD/potlatch2/controller/SelectedWay.as +++ b/net/systemeD/potlatch2/controller/SelectedWay.as @@ -1,8 +1,10 @@ package net.systemeD.potlatch2.controller { + import flash.display.*; import flash.events.*; import flash.geom.Point; import flash.ui.Keyboard; + import net.systemeD.halcyon.MapPaint; import net.systemeD.halcyon.connection.*; import net.systemeD.potlatch2.tools.Quadrilateralise; import net.systemeD.potlatch2.tools.Simplify; @@ -19,7 +21,8 @@ package net.systemeD.potlatch2.controller { * @param way The way that is now selected. * @param point The location that was clicked. * @param ways An ordered list of ways sharing a node, to make "way cycling" work. */ - public function SelectedWay(way:Way, point:Point=null, ways:Array=null, index:int=0) { + public function SelectedWay(way:Way, layer:MapPaint=null, point:Point=null, ways:Array=null, index:int=0) { + if (layer) this.layer=layer; initWay = way; clicked = point; wayList = ways; @@ -43,20 +46,23 @@ package net.systemeD.potlatch2.controller { /** Behaviour includes: start drawing a new way, insert a node within this way, select an additional way */ override public function processMouseEvent(event:MouseEvent, entity:Entity):ControllerState { if (event.type==MouseEvent.MOUSE_MOVE || event.type==MouseEvent.ROLL_OVER || event.type==MouseEvent.MOUSE_OUT) { return this; } + var paint:MapPaint = getMapPaint(DisplayObject(event.target)); var focus:Entity = getTopLevelFocusEntity(entity); - if ( event.type == MouseEvent.MOUSE_UP && entity is Node && event.shiftKey ) { + if ( event.type == MouseEvent.MOUSE_UP && entity is Node && event.shiftKey && !layer.isBackground ) { // start new way var way:Way = entity.connection.createWay({}, [entity], MainUndoStack.getGlobalStack().addAction); return new DrawWay(way, true, false); - } else if ( event.type == MouseEvent.MOUSE_DOWN && entity is Way && focus==firstSelected && event.shiftKey) { + } else if ( event.type == MouseEvent.MOUSE_DOWN && entity is Way && focus==firstSelected && event.shiftKey && !layer.isBackground ) { // insert node within way (shift-click) var d:DragWayNode=new DragWayNode(firstSelected as Way, -1, event, true); d.forceDragStart(); return d; - } else if ( event.type == MouseEvent.MOUSE_DOWN && event.ctrlKey && entity && entity!=firstSelected) { + } else if ( event.type == MouseEvent.MOUSE_DOWN && event.ctrlKey && entity && entity!=firstSelected && paint==layer) { // multiple selection - return new SelectedMultiple([firstSelected,entity]); + return new SelectedMultiple([firstSelected,entity],layer); + } else if ( event.type == MouseEvent.MOUSE_UP && focus==firstSelected ) { + return this; } var cs:ControllerState = sharedMouseEvents(event, entity); return cs ? cs : this; @@ -65,17 +71,20 @@ package net.systemeD.potlatch2.controller { /** Behaviour includes: parallel way, repeat tags, reverse direction, simplify, cycle way selection, delete */ override public function processKeyboardEvent(event:KeyboardEvent):ControllerState { switch (event.keyCode) { - case 80: /* P */ return new SelectedParallelWay(firstSelected as Way); - case 81: /* Q */ Quadrilateralise.quadrilateralise(firstSelected as Way, MainUndoStack.getGlobalStack().addAction); return this; case 82: /* R */ repeatTags(firstSelected); return this; - case 86: /* V */ Way(firstSelected).reverseNodes(MainUndoStack.getGlobalStack().addAction); return this; - case 89: /* Y */ Simplify.simplify(firstSelected as Way, controller.map, true); return this; case 191: /* / */ return cycleWays(); case Keyboard.BACKSPACE: case Keyboard.DELETE: if (event.shiftKey) { return deleteWay(); } break; - case 188: /* , */ return new SelectedWayNode(initWay, initIndex); // allows navigating from one way to another by keyboard - case 190: /* . */ return new SelectedWayNode(initWay, initIndex); // using <, > and / - + } + if (!layer.isBackground) { + switch (event.keyCode) { + case 80: /* P */ return new SelectedParallelWay(firstSelected as Way); + case 81: /* Q */ Quadrilateralise.quadrilateralise(firstSelected as Way, MainUndoStack.getGlobalStack().addAction); return this; + case 86: /* V */ Way(firstSelected).reverseNodes(MainUndoStack.getGlobalStack().addAction); return this; + case 89: /* Y */ Simplify.simplify(firstSelected as Way, controller.map, true); return this; + case 188: /* , */ return new SelectedWayNode(initWay, initIndex); // allows navigating from one way to another by keyboard + case 190: /* . */ return new SelectedWayNode(initWay, initIndex); // using <, > and / + } } var cs:ControllerState = sharedKeyboardEvents(event); return cs ? cs : this; @@ -90,7 +99,7 @@ package net.systemeD.potlatch2.controller { wayList=wayList.slice(1).concat(wayList[0]); // Find the new way's index of the currently "selected" node, to facilitate keyboard navigation var newindex:int = Way(wayList[0]).indexOfNode(initWay.getNode(initIndex)); - return new SelectedWay(wayList[0], clicked, wayList, newindex); + return new SelectedWay(wayList[0], layer, clicked, wayList, newindex); } /** Perform deletion of currently selected way. */ diff --git a/net/systemeD/potlatch2/controller/SelectedWayNode.as b/net/systemeD/potlatch2/controller/SelectedWayNode.as index 03ba21cb..86766c2f 100644 --- a/net/systemeD/potlatch2/controller/SelectedWayNode.as +++ b/net/systemeD/potlatch2/controller/SelectedWayNode.as @@ -97,7 +97,7 @@ package net.systemeD.potlatch2.controller { wayList.splice(wayList.indexOf(parentWay),1); // find index of this node in the newly selected way, to maintain state for keyboard navigation var newindex:int = Way(wayList[0]).indexOfNode(parentWay.getNode(initIndex)); - return new SelectedWay(wayList[0], + return new SelectedWay(wayList[0], layer, new Point(controller.map.lon2coord(Node(firstSelected).lon), controller.map.latp2coord(Node(firstSelected).latp)), wayList.concat(parentWay), From 04251dd2da1995cf5cb913e6369d1449f386fedd Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Wed, 15 Jun 2011 23:29:35 +0100 Subject: [PATCH 84/89] Not screwed up any more. At least I think not. --- REFACTOR.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/REFACTOR.txt b/REFACTOR.txt index fd67b902..7ec91735 100644 --- a/REFACTOR.txt +++ b/REFACTOR.txt @@ -19,4 +19,3 @@ There are lots more of these throughout the code, marked with fixmes of the form - remove all back-references to Map except where necessary for lat/long/scale - getParam is messy - stuff sent via flashvars needs somewhere to live: currently in Globals which is ugly -- tileset/setbackground stuff is screwed up again and needs refactoring a little From 547250c98fb4fac4ceaaac526e3b3481487c49d5 Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Thu, 16 Jun 2011 19:55:37 +0100 Subject: [PATCH 85/89] Better handling of conflicting tags when merging and editing ways and nodes --- embedded/warning.png | Bin 0 -> 603 bytes net/systemeD/controls/DataGridWarningField.as | 42 +++++++ .../controls/PromptingTextInputWarning.as | 39 +++++++ net/systemeD/halcyon/connection/Entity.as | 17 +-- .../connection/actions/MergeNodesAction.as | 107 +++++++++--------- .../connection/actions/MergeWaysAction.as | 10 +- net/systemeD/potlatch2/TagGrid.mxml | 2 +- .../potlatch2/controller/SelectedMultiple.as | 28 ++--- .../potlatch2/controller/SelectedWayNode.as | 7 +- .../mapfeatures/editors/FreeTextEditor.mxml | 3 +- 10 files changed, 163 insertions(+), 92 deletions(-) create mode 100644 embedded/warning.png create mode 100644 net/systemeD/controls/DataGridWarningField.as create mode 100644 net/systemeD/controls/PromptingTextInputWarning.as diff --git a/embedded/warning.png b/embedded/warning.png new file mode 100644 index 0000000000000000000000000000000000000000..a9e4ff3991cb0ad2a99cc25e2d13c35e52c680c8 GIT binary patch literal 603 zcmV-h0;K(kP)J2V5SdEtMnl9PhCxc2Fa&}~V}o=Tx)35=bmuS|@d;cT zbY;Loz(q+`1+A}82tI&NTm%Y*7F^UoNilyn))L6H_Q1W1%i%j`bA(=?F!-5EVN!MFB_9*XAp~_l%n771CUH65fQk#;c9J-59jBDOQ<*CorDm33|CLV znm<0~VYP}<3Z)daS`C19yN!q-BK$Z#V4_~XOaDE<2tY)*Zne1F+TuNYlS3Fj19`yz=_l|J pl>P}02k>Sh;xD3f4Z|KZe*u@?eFz-1;S&G=002ovPDHLkV1mMw_G175 literal 0 HcmV?d00001 diff --git a/net/systemeD/controls/DataGridWarningField.as b/net/systemeD/controls/DataGridWarningField.as new file mode 100644 index 00000000..647a614b --- /dev/null +++ b/net/systemeD/controls/DataGridWarningField.as @@ -0,0 +1,42 @@ +package net.systemeD.controls { + import mx.controls.Label; + import mx.controls.listClasses.*; + import flash.display.DisplayObject; + import mx.controls.Image; + + public class DataGridWarningField extends Label { + + private var _image:Image; + [Embed(source="../../../embedded/warning.png")] private var warningIcon:Class; + + function DataGridWarningField():void { + super(); + setStyle('paddingLeft',2); + } + + override protected function createChildren():void { + super.createChildren(); + _image = new Image(); + _image.source = warningIcon; + _image.width = 16; + _image.height = 16; + addChild(DisplayObject(_image)); + } + + override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void { + super.updateDisplayList(unscaledWidth, unscaledHeight); + + if (data.value.indexOf(';')>-1) { + setStyle('color',0xFF0000); + _image.visible=true; + _image.x = width -_image.width -5; + _image.y = height-_image.height-3; + _image.toolTip = "The tag contains more than one value - please check"; + textField.width = width-_image.width-5; + } else { + setStyle('color',0); + _image.visible=false; + } + } + } +} diff --git a/net/systemeD/controls/PromptingTextInputWarning.as b/net/systemeD/controls/PromptingTextInputWarning.as new file mode 100644 index 00000000..36616468 --- /dev/null +++ b/net/systemeD/controls/PromptingTextInputWarning.as @@ -0,0 +1,39 @@ +package net.systemeD.controls { + import flexlib.controls.PromptingTextInput; + import flash.display.DisplayObject; + import mx.controls.Image; + + public class PromptingTextInputWarning extends PromptingTextInput { + + private var _image:Image; + [Embed(source="../../../embedded/warning.png")] private var warningIcon:Class; + + function PromptingTextInputWarning():void { + super(); + } + + override protected function createChildren():void { + super.createChildren(); + _image = new Image(); + _image.source = warningIcon; + _image.width = 16; + _image.height = 16; + addChild(DisplayObject(_image)); + } + + override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void { + super.updateDisplayList(unscaledWidth, unscaledHeight); + if (text && text.indexOf(';')>-1) { + setStyle('color',0xFF0000); + _image.visible=true; + _image.x = width -_image.width -5; + _image.y = height-_image.height-3; + _image.toolTip = "The tag contains more than one value - please check"; + textField.width = width-_image.width-5; + } else { + setStyle('color',0); + _image.visible=false; + } + } + } +} diff --git a/net/systemeD/halcyon/connection/Entity.as b/net/systemeD/halcyon/connection/Entity.as index 2837f398..8b4629bf 100644 --- a/net/systemeD/halcyon/connection/Entity.as +++ b/net/systemeD/halcyon/connection/Entity.as @@ -425,31 +425,22 @@ package net.systemeD.halcyon.connection { /** Copy tags from another entity into this one, creating "key=value1; value2" pairs if necessary. * * @return Array of keys that require manual merging, in order to warn the user. */ - public function mergeTags(source: Entity, performAction:Function):Array { + public function mergeTags(source: Entity, performAction:Function):Boolean { var sourcetags:Object = source.getTagsHash(); - var problem_keys:Array=new Array(); + var conflict:Boolean = false; for (var k:String in sourcetags) { var v1:String = tags[k]; var v2:String = sourcetags[k]; if ( v1 && v1 != v2) { - // This can create broken tags (does anything support "highway=residential; tertiary"?). - // Probably better to do something like: - // highway=residential - // highway:tomerge=tertiary - setTag(k, v1+"; "+v2, performAction); - problem_keys.push(k); + conflict=true; } else { setTag(k, v2, performAction); } } - if (problem_keys.length > 0) - return problem_keys; - else - return null; + return conflict; } - } } diff --git a/net/systemeD/halcyon/connection/actions/MergeNodesAction.as b/net/systemeD/halcyon/connection/actions/MergeNodesAction.as index 60b7d4c1..c037b3b5 100644 --- a/net/systemeD/halcyon/connection/actions/MergeNodesAction.as +++ b/net/systemeD/halcyon/connection/actions/MergeNodesAction.as @@ -1,53 +1,56 @@ -package net.systemeD.halcyon.connection.actions -{ - import net.systemeD.halcyon.connection.*; - - - public class MergeNodesAction extends CompositeUndoableAction { - // Node2's tags are merged into node1, then node2 is deleted. - private var node1:Node; - private var node2:Node; - static public var lastProblemTags:Array; - - public function MergeNodesAction(destnode:Node, sourcenode:Node) { - super("Merge nodes "+destnode.id+" "+sourcenode.id); - this.node1 = destnode; - this.node2 = sourcenode; - lastProblemTags=null; - } - - public override function doAction():uint { - - super.clearActions(); - node1.suspend(); - -// mergeRelations(); TODO - lastProblemTags= node1.mergeTags(node2,push); // TODO use to warn user - node2.replaceWith(node1, push); - node2.remove(push); - - super.doAction(); - node1.resume(); - - return SUCCESS; - } - - public override function undoAction():uint { - node1.suspend(); - super.undoAction(); - node1.resume(); - - return SUCCESS; - } - - public function mergeRelations():void { - for each (var r:Relation in node2.parentRelations) { - // ** needs to copy roles as well - if (r.findEntityMemberIndex(node1)==-1) { - r.appendMember(new RelationMember(node1, ''), push); - } - } - } - } - +package net.systemeD.halcyon.connection.actions +{ + import net.systemeD.halcyon.connection.*; + + + public class MergeNodesAction extends CompositeUndoableAction { + // Node2's tags are merged into node1, then node2 is deleted. + private var node1:Node; + private var node2:Node; + // ** FIXME: not at all elegant having these stuffed in static variables; we should probably use events instead + static public var lastTagsMerged:Boolean; + static public var lastRelationsMerged:Boolean; + + public function MergeNodesAction(destnode:Node, sourcenode:Node) { + super("Merge nodes "+destnode.id+" "+sourcenode.id); + this.node1 = destnode; + this.node2 = sourcenode; + lastTagsMerged=false; + lastRelationsMerged=false; + } + + public override function doAction():uint { + + super.clearActions(); + node1.suspend(); + + lastTagsMerged=node1.mergeTags(node2,push); + node2.replaceWith(node1, push); + node2.remove(push); + + super.doAction(); + node1.resume(); + + return SUCCESS; + } + + public override function undoAction():uint { + node1.suspend(); + super.undoAction(); + node1.resume(); + + return SUCCESS; + } + + public function mergeRelations():void { + for each (var r:Relation in node2.parentRelations) { + // ** needs to copy roles as well + if (r.findEntityMemberIndex(node1)==-1) { + r.appendMember(new RelationMember(node1, ''), push); + lastRelationsMerged=true; + } + } + } + } + } \ No newline at end of file diff --git a/net/systemeD/halcyon/connection/actions/MergeWaysAction.as b/net/systemeD/halcyon/connection/actions/MergeWaysAction.as index 33d5c803..4a5c3b8d 100644 --- a/net/systemeD/halcyon/connection/actions/MergeWaysAction.as +++ b/net/systemeD/halcyon/connection/actions/MergeWaysAction.as @@ -7,7 +7,9 @@ package net.systemeD.halcyon.connection.actions { private var way2:Way; private var toPos:uint; private var fromPos:uint; - static public var lastProblemTags:Array; + // ** FIXME: not at all elegant having these stuffed in static variables; we should probably use events instead + static public var lastTagsMerged:Boolean; + static public var lastRelationsMerged:Boolean; public function MergeWaysAction(way1:Way, way2:Way, toPos:uint, fromPos:uint) { super("Merge ways "+way1.id+" "+way2.id); @@ -15,7 +17,8 @@ package net.systemeD.halcyon.connection.actions { this.way2 = way2; this.toPos = toPos; this.fromPos = fromPos; - lastProblemTags=null; + lastTagsMerged = false; + lastRelationsMerged = false; } public override function doAction():uint { @@ -26,7 +29,7 @@ package net.systemeD.halcyon.connection.actions { way1.suspend(); mergeRelations(); - lastProblemTags = way1.mergeTags(way2,push); + lastTagsMerged = way1.mergeTags(way2,push); mergeNodes(); way2.remove(push); @@ -49,6 +52,7 @@ package net.systemeD.halcyon.connection.actions { // ** needs to copy roles as well if (r.findEntityMemberIndex(way1)==-1) { r.appendMember(new RelationMember(way1, ''), push); + lastRelationsMerged=true; } } } diff --git a/net/systemeD/potlatch2/TagGrid.mxml b/net/systemeD/potlatch2/TagGrid.mxml index 399de61d..17b8615f 100644 --- a/net/systemeD/potlatch2/TagGrid.mxml +++ b/net/systemeD/potlatch2/TagGrid.mxml @@ -29,7 +29,7 @@ - + 0) { - var msg:String = 1 + mergers + " ways merged." - var conflictTags2:Array = new Array(); - // there must be a better way of avoiding duplicates... - for each (var conflict:String in conflictTags) conflictTags2.push(conflict); - if (conflictTags2.length>0) - msg += " *Warning* The following tags conflicted and need attention: " + conflictTags2; + var msg:String = 1 + mergers + " ways merged"; + if (tagConflict && relationConflict) msg+=": check tags and relations"; + else if (tagConflict) msg+=": check conflicting tags"; + else if (relationConflict) msg+=": check relations"; controller.dispatchEvent(new AttentionEvent(AttentionEvent.ALERT, null, msg)); } diff --git a/net/systemeD/potlatch2/controller/SelectedWayNode.as b/net/systemeD/potlatch2/controller/SelectedWayNode.as index 86766c2f..8680e1eb 100644 --- a/net/systemeD/potlatch2/controller/SelectedWayNode.as +++ b/net/systemeD/potlatch2/controller/SelectedWayNode.as @@ -215,11 +215,8 @@ package net.systemeD.potlatch2.controller { private function doMergeNodes(n:Node): ControllerState { n.mergeWith(Node(firstSelected), MainUndoStack.getGlobalStack().addAction); // only merge one node at a time - too confusing otherwise? - var msg:String = "Nodes merged." - if (MergeNodesAction.lastProblemTags) { - // FIXME: ugh, just ugh. - msg += " *Warning* The following tags conflicted and need attention: " + MergeNodesAction.lastProblemTags; - } + var msg:String = "Nodes merged" + if (MergeNodesAction.lastTagsMerged) msg += ": check conflicting tags"; controller.dispatchEvent(new AttentionEvent(AttentionEvent.ALERT, null, msg)); return new SelectedWayNode(n.parentWays[0], Way(n.parentWays[0]).indexOfNode(n)); } diff --git a/net/systemeD/potlatch2/mapfeatures/editors/FreeTextEditor.mxml b/net/systemeD/potlatch2/mapfeatures/editors/FreeTextEditor.mxml index 287fe6bb..a7b142ec 100644 --- a/net/systemeD/potlatch2/mapfeatures/editors/FreeTextEditor.mxml +++ b/net/systemeD/potlatch2/mapfeatures/editors/FreeTextEditor.mxml @@ -3,12 +3,13 @@ xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:edit="net.systemeD.potlatch2.mapfeatures.editors.*" xmlns:flexlib="flexlib.controls.*" + xmlns:controls="net.systemeD.controls.*" width="100%" toolTip="{fieldDescription}" direction="{fieldDirection}" styleName="titledEditor"> - From 8f4239262c5e7ab762c194e4bf34997d9c722543 Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Fri, 17 Jun 2011 09:55:20 +0100 Subject: [PATCH 86/89] Fix tab selection bug --- net/systemeD/potlatch2/TagViewer.mxml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/net/systemeD/potlatch2/TagViewer.mxml b/net/systemeD/potlatch2/TagViewer.mxml index d477a57d..3aa74480 100644 --- a/net/systemeD/potlatch2/TagViewer.mxml +++ b/net/systemeD/potlatch2/TagViewer.mxml @@ -230,6 +230,7 @@ import mx.events.DragEvent; import mx.managers.DragManager; import mx.core.DragSource; + import mx.controls.TabBar; import flexlib.containers.SuperTabNavigator; [Bindable] @@ -379,6 +380,14 @@ private var tabComponents:Object = {}; private function initialiseEditors():void { + // reset tab to 0 to work around TabNavigator bug (#3444) + if (editorStack is TabNavigator) { + try { + var tabBar:TabBar=TabBar(TabNavigator(editorStack).getTabAt(0).parent); + tabBar.selectedIndex=0; + } catch(errObject:Error) {} + } + editorStack.removeAllChildren(); if ( selectedEntity == null || feature == null ) return; From 26b9e06fef2b9f9b06eb45f2468879ae504fb346 Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Fri, 17 Jun 2011 16:48:50 +0100 Subject: [PATCH 87/89] Prevent single-node ways from being created by undo. Could be polished more but the undo system makes it enough of a brainfuck that this'll do for now. --- .../halcyon/connection/MainUndoStack.as | 13 +++++++ net/systemeD/halcyon/connection/Way.as | 4 +- .../connection/actions/AddNodeToWayAction.as | 37 +++++++++++++++++-- .../connection/actions/DeleteWayAction.as | 2 +- .../potlatch2/controller/NoSelection.as | 1 + potlatch2.mxml | 3 +- 6 files changed, 52 insertions(+), 8 deletions(-) diff --git a/net/systemeD/halcyon/connection/MainUndoStack.as b/net/systemeD/halcyon/connection/MainUndoStack.as index be75b6dc..38f87ff0 100644 --- a/net/systemeD/halcyon/connection/MainUndoStack.as +++ b/net/systemeD/halcyon/connection/MainUndoStack.as @@ -103,6 +103,12 @@ package net.systemeD.halcyon.connection { return false; } } + + public function removeLastIfAction(action:Class):void { + if (undoActions.length && undoActions[undoActions.length-1] is action) { + undoActions.pop(); + } + } [Bindable(event="new_undo_item")] public function getUndoDescription():String { @@ -111,6 +117,13 @@ package net.systemeD.halcyon.connection { return null; } + [Bindable(event="new_redo_item")] + public function getRedoDescription():String { + if (redoActions.length==0) return null; + if (redoActions[redoActions.length-1].name) return redoActions[redoActions.length-1].name; + return null; + } + /** * Takes the action most recently undone, does it, and adds it to the undo stack */ diff --git a/net/systemeD/halcyon/connection/Way.as b/net/systemeD/halcyon/connection/Way.as index d5f991cf..0f97958b 100644 --- a/net/systemeD/halcyon/connection/Way.as +++ b/net/systemeD/halcyon/connection/Way.as @@ -94,12 +94,12 @@ package net.systemeD.halcyon.connection { } public function appendNode(node:Node, performAction:Function):uint { - if (node!=getLastNode()) performAction(new AddNodeToWayAction(this, node, nodes, -1)); + insertNode(nodes.length, node, performAction); return nodes.length + 1; } public function prependNode(node:Node, performAction:Function):uint { - if (node!=getFirstNode()) performAction(new AddNodeToWayAction(this, node, nodes, 0)); + insertNode(0, node, performAction); return nodes.length + 1; } diff --git a/net/systemeD/halcyon/connection/actions/AddNodeToWayAction.as b/net/systemeD/halcyon/connection/actions/AddNodeToWayAction.as index 7e291e93..185bf559 100644 --- a/net/systemeD/halcyon/connection/actions/AddNodeToWayAction.as +++ b/net/systemeD/halcyon/connection/actions/AddNodeToWayAction.as @@ -6,6 +6,7 @@ package net.systemeD.halcyon.connection.actions { private var node:Node; private var nodeList:Array; private var index:int; + private var firstNode:Node; public function AddNodeToWayAction(way:Way, node:Node, nodeList:Array, index:int) { super(way, "Add node "+node.id+" to"); @@ -16,8 +17,17 @@ package net.systemeD.halcyon.connection.actions { public override function doAction():uint { var way:Way = entity as Way; - if ( index == -1 ) - index = nodeList.length; + + // undelete way if it was deleted before (only happens on redo) + if (way.deleted) { + way.setDeletedState(false); + if (!firstNode.hasParentWays) firstNode.connection.unregisterPOI(firstNode); + firstNode.addParent(way); + way.connection.dispatchEvent(new EntityEvent(Connection.NEW_WAY, way)); + } + + // add node + if ( index == -1 ) index = nodeList.length; node.addParent(way); nodeList.splice(index, 0, node); markDirty(); @@ -29,13 +39,32 @@ package net.systemeD.halcyon.connection.actions { public override function undoAction():uint { var way:Way = entity as Way; + + // ** FIXME: if the user undoes adding the 2nd node, then we delete the way and create a POI from the + // one remaining node (see below). _However_, when we delete the way, we also need to remove + // it from any relations... and to do that, this needs to be a CompositeUndoableAction. + // Which it isn't (because we want all the markDirty/markClean stuff). So, for now, we'll + // simply refuse to undo adding the 2nd node if the way is in any relations. (This should + // be a vanishingly small case anyway, because usually the AddMemberToRelationAction will + // have been undone already.) + if (way.length==2 && way.parentRelations.length) return FAIL; + + // remove node var removed:Array=nodeList.splice(index, 1); if (nodeList.indexOf(removed[0])==-1) { removed[0].removeParent(way); } markClean(); way.dispatchEvent(new WayNodeEvent(Connection.WAY_NODE_REMOVED, removed[0], way, index)); - return SUCCESS; + // delete way if it's now 1-length, and convert the one remaining node to a POI + if (way.length==1) { + way.setDeletedState(true); + way.dispatchEvent(new EntityEvent(Connection.WAY_DELETED, way)); + firstNode=way.getNode(0); + firstNode.removeParent(way); + if (!firstNode.hasParentWays) firstNode.connection.registerPOI(firstNode); + MainUndoStack.getGlobalStack().removeLastIfAction(BeginWayAction); + } + return SUCCESS; } } } - diff --git a/net/systemeD/halcyon/connection/actions/DeleteWayAction.as b/net/systemeD/halcyon/connection/actions/DeleteWayAction.as index 331826a8..f2fd1bc6 100644 --- a/net/systemeD/halcyon/connection/actions/DeleteWayAction.as +++ b/net/systemeD/halcyon/connection/actions/DeleteWayAction.as @@ -57,7 +57,7 @@ package net.systemeD.halcyon.connection.actions { markClean(); } entity.connection.dispatchEvent(new EntityEvent(Connection.NEW_WAY, way)); - effects.undoAction(); + if (effects) effects.undoAction(); for each(var node:Node in oldNodeList) { nodeList.push(node); node.addParent(way); diff --git a/net/systemeD/potlatch2/controller/NoSelection.as b/net/systemeD/potlatch2/controller/NoSelection.as index 5c5072d2..b780bd25 100644 --- a/net/systemeD/potlatch2/controller/NoSelection.as +++ b/net/systemeD/potlatch2/controller/NoSelection.as @@ -25,6 +25,7 @@ package net.systemeD.potlatch2.controller { if (event.type==MouseEvent.MOUSE_UP && (focus==null || (paint && paint.isBackground)) && map.dragstate!=map.DRAGGING) { map.dragstate=map.NOT_DRAGGING; + // ** FIXME: BeginWayAction ought to be a discrete class var undo:CompositeUndoableAction = new BeginWayAction(); var conn:Connection = layer.connection; var startNode:Node = conn.createNode( diff --git a/potlatch2.mxml b/potlatch2.mxml index 055f0a6f..4754b11b 100644 --- a/potlatch2.mxml +++ b/potlatch2.mxml @@ -51,7 +51,8 @@ enabled="{MainUndoStack.getGlobalStack().canUndo()}" toolTip="{MainUndoStack.getGlobalStack().getUndoDescription() ? 'Undo '+MainUndoStack.getGlobalStack().getUndoDescription() : 'Undo last action'}" /> + enabled="{MainUndoStack.getGlobalStack().canRedo()}" + toolTip="{MainUndoStack.getGlobalStack().getRedoDescription() ? 'Redo '+MainUndoStack.getGlobalStack().getRedoDescription() : 'Redo last action'}" /> From 76ba481b2196e86226e8e9af10377e4fc0772e9d Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Fri, 17 Jun 2011 17:09:05 +0100 Subject: [PATCH 88/89] Make Markers selectable again. --- net/systemeD/halcyon/connection/Connection.as | 1 - net/systemeD/potlatch2/controller/SelectedMarker.as | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/net/systemeD/halcyon/connection/Connection.as b/net/systemeD/halcyon/connection/Connection.as index 4b2dbe41..3e762ff5 100644 --- a/net/systemeD/halcyon/connection/Connection.as +++ b/net/systemeD/halcyon/connection/Connection.as @@ -293,7 +293,6 @@ package net.systemeD.halcyon.connection { } var marker:Marker = markers[id]; if (marker == null) { - trace("new marker"); marker = new Marker(this, id, 0, tags, true, lat, lon); markers[id]=marker; sendEvent(new EntityEvent(NEW_MARKER, marker),false); diff --git a/net/systemeD/potlatch2/controller/SelectedMarker.as b/net/systemeD/potlatch2/controller/SelectedMarker.as index 2af2441f..f1c9129c 100644 --- a/net/systemeD/potlatch2/controller/SelectedMarker.as +++ b/net/systemeD/potlatch2/controller/SelectedMarker.as @@ -34,7 +34,7 @@ package net.systemeD.potlatch2.controller { override public function processMouseEvent(event:MouseEvent, entity:Entity):ControllerState { if (event.type==MouseEvent.MOUSE_MOVE) { return this; } - if (event.type==MouseEvent.MOUSE_UP) { return this; } + if ( (event.type==MouseEvent.MOUSE_UP || event.type==MouseEvent.CLICK) && entity==initMarker ) { return this; } var cs:ControllerState = sharedMouseEvents(event, entity); return cs ? cs : this; } From 5635301a3d180da642a49994b9ebe36524159866 Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Fri, 17 Jun 2011 17:18:37 +0100 Subject: [PATCH 89/89] Don't die if user undoes way creation while in DrawWay. --- net/systemeD/potlatch2/controller/DrawWay.as | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/systemeD/potlatch2/controller/DrawWay.as b/net/systemeD/potlatch2/controller/DrawWay.as index 1984ecef..f8811f9d 100644 --- a/net/systemeD/potlatch2/controller/DrawWay.as +++ b/net/systemeD/potlatch2/controller/DrawWay.as @@ -31,6 +31,8 @@ package net.systemeD.potlatch2.controller { } override public function processMouseEvent(event:MouseEvent, entity:Entity):ControllerState { + if (firstSelected.deleted) return new NoSelection(); // in case user has clicked Undo + var mouse:Point; var node:Node; var paint:MapPaint = getMapPaint(DisplayObject(event.target));