diff options
Diffstat (limited to 'js/dojo/dojox/geo/openlayers')
| -rw-r--r-- | js/dojo/dojox/geo/openlayers/Collection.js | 28 | ||||
| -rw-r--r-- | js/dojo/dojox/geo/openlayers/Feature.js | 79 | ||||
| -rw-r--r-- | js/dojo/dojox/geo/openlayers/Geometry.js | 37 | ||||
| -rw-r--r-- | js/dojo/dojox/geo/openlayers/GeometryFeature.js | 405 | ||||
| -rw-r--r-- | js/dojo/dojox/geo/openlayers/GfxLayer.js | 142 | ||||
| -rw-r--r-- | js/dojo/dojox/geo/openlayers/GreatCircle.js | 122 | ||||
| -rw-r--r-- | js/dojo/dojox/geo/openlayers/JsonImport.js | 151 | ||||
| -rw-r--r-- | js/dojo/dojox/geo/openlayers/Layer.js | 164 | ||||
| -rw-r--r-- | js/dojo/dojox/geo/openlayers/LineString.js | 28 | ||||
| -rw-r--r-- | js/dojo/dojox/geo/openlayers/Map.js | 592 | ||||
| -rw-r--r-- | js/dojo/dojox/geo/openlayers/Patch.js | 67 | ||||
| -rw-r--r-- | js/dojo/dojox/geo/openlayers/Point.js | 27 | ||||
| -rw-r--r-- | js/dojo/dojox/geo/openlayers/TouchInteractionSupport.js | 248 | ||||
| -rw-r--r-- | js/dojo/dojox/geo/openlayers/WidgetFeature.js | 206 | ||||
| -rw-r--r-- | js/dojo/dojox/geo/openlayers/widget/Map.js | 161 |
15 files changed, 2457 insertions, 0 deletions
diff --git a/js/dojo/dojox/geo/openlayers/Collection.js b/js/dojo/dojox/geo/openlayers/Collection.js new file mode 100644 index 0000000..25983b2 --- /dev/null +++ b/js/dojo/dojox/geo/openlayers/Collection.js @@ -0,0 +1,28 @@ +//>>built +define("dojox/geo/openlayers/Collection", [ "dojo/_base/kernel", "dojo/_base/declare", "dojox/geo/openlayers/Geometry" ], + function(dojo, declare, Geometry) { + /*===== + var Geometry = dojox.geo.openlayers.Geometry; + =====*/ + return declare("dojox.geo.openlayers.Collection", Geometry, { + // summary: + // A collection of geometries. _coordinates_ holds an array of + // geometries. + + setGeometries : function(/* Array */g) { + // summary: + // Sets the geometries + // g: Array + // The array of geometries. + this.coordinates = g; + }, + + // summary: + // Retrieves the geometries. + // returns: Array + // The array of geometries defining this collection. + getGeometries : function() { + return this.coordinates; + } + }); + }); diff --git a/js/dojo/dojox/geo/openlayers/Feature.js b/js/dojo/dojox/geo/openlayers/Feature.js new file mode 100644 index 0000000..d6a37ca --- /dev/null +++ b/js/dojo/dojox/geo/openlayers/Feature.js @@ -0,0 +1,79 @@ +//>>built +define("dojox/geo/openlayers/Feature", ["dojo/_base/kernel", "dojo/_base/declare", "dojox/geo/openlayers/Map"], function(dojo, declare, Map){ + + return declare("dojox.geo.openlayers.Feature", null, { + // summary: + // A Feature encapsulates an item so that it can be added to a Layer. + // This class is not attended to be used as it, but serve as a base class + // for specific features such as GeometryFeature which can display georeferenced + // geometries and WidgetFeature which can display georeferenced widgets. + constructor : function(){ + // summary: + // Construct a new Feature + this._layer = null; + this._coordSys = dojox.geo.openlayers.EPSG4326; + }, + + getCoordinateSystem : function(){ + // summary: + // Returns the coordinate system in which coordinates of this feature are expressed. + // returns: OpenLayers.Projection + // The coordinate system in which coordinates of this feature are expressed. + return this._coordSys; + }, + + setCoordinateSystem : function(/* OpenLayers.Projection */cs){ + // summary: + // Set the coordinate system in which coordinates of this feature are expressed. + // cs: OpenLayers.Projection + // The coordinate system in which coordinates of this feature are expressed. + this._coordSys = cs; + }, + + getLayer : function(){ + // summary: + // Returns the Layer to which this feature belongs. + // returns: dojox.geo.openlayers.Layer + // The layer to which this feature belongs. + return this._layer; + }, + + _setLayer : function(/* dojox.geo.openlayers.Layer */l){ + // summary: + // Sets the layer to which this Feature belongs + // description: + // Called when the feature is added to the Layer. + // tags: + // private + this._layer = l; + }, + + render : function(){ + // summary: + // subclasses implements drawing specific behavior. + }, + + remove : function(){ + // summary: + // Subclasses implements specific behavior. + // Called when removed from the layer. + }, + + _getLocalXY : function(p){ + // summary: + // From projected coordinates to screen coordinates + // p: Object + // Object with x and y fields + // tags: + // private + var x = p.x; + var y = p.y; + var layer = this.getLayer(); + var resolution = layer.olLayer.map.getResolution(); + var extent = layer.olLayer.getExtent(); + var rx = (x / resolution + (-extent.left / resolution)); + var ry = ((extent.top / resolution) - y / resolution); + return [rx, ry]; + } + }); +}); diff --git a/js/dojo/dojox/geo/openlayers/Geometry.js b/js/dojo/dojox/geo/openlayers/Geometry.js new file mode 100644 index 0000000..8905dee --- /dev/null +++ b/js/dojo/dojox/geo/openlayers/Geometry.js @@ -0,0 +1,37 @@ +//>>built +define("dojox/geo/openlayers/Geometry", ["dojo/_base/kernel", "dojo/_base/declare"], function(dojo, declare){ + + return declare("dojox.geo.openlayers.Geometry", null, { + // summary: + // A Geometry handles description of shapes to be rendered in a GfxLayer + // using a GeometryFeature feature. + // A Geometry can be + // - A point geometry of type dojox.geo.openlayers.Point. Coordinates are a an + // Object {x, y} + // - A line string geometry of type dojox.geo.openlayers.LineString. Coordinates are + // an array of {x, y} objects + // - A collection geometry of type dojox.geo.openlayers.Collection. Coordinates are an array of geometries. + + // summary: + // The coordinates of the geometry. + // coordinates: {x, y} | Array + coordinates : null, + + // summary: + // The associated shape when rendered + // shape : dojox.gfx.Shape + // The shape + // tags: + // internal + shape : null, + + constructor : function(coords){ + // summary: + // Constructs a new geometry + // coords: {x, y} + // Coordinates of the geometry. {x:<x>, y:<y>} object for a point geometry, array of {x:<x>, y:<y>} + // objects for line string geometry, array of geometries for collection geometry. + this.coordinates = coords; + } + }); +}); diff --git a/js/dojo/dojox/geo/openlayers/GeometryFeature.js b/js/dojo/dojox/geo/openlayers/GeometryFeature.js new file mode 100644 index 0000000..ab75ffe --- /dev/null +++ b/js/dojo/dojox/geo/openlayers/GeometryFeature.js @@ -0,0 +1,405 @@ +//>>built +define("dojox/geo/openlayers/GeometryFeature", ["dojo/_base/kernel", + "dojo/_base/declare", + "dojo/_base/array", + "dojo/_base/lang", + "dojox/gfx/matrix", + "dojox/geo/openlayers/Point", + "dojox/geo/openlayers/LineString", + "dojox/geo/openlayers/Collection", + "dojox/geo/openlayers/Feature"], function(dojo, declare, array, lang, matrix, Point, LineString, + Collection, Feature){ + /*===== + var Feature = dojox.geo.openlayers.Feature; + =====*/ + return declare("dojox.geo.openlayers.GeometryFeature", Feature, { + // summary: + // A Feature encapsulating a geometry. + // description: + // This Feature renders a geometry such as a Point or LineString geometry. This Feature + // is responsible for reprojecting the geometry before creating a gfx shape to display it. + // By default the shape created is a circle for a Point geometry and a polyline for a + // LineString geometry. User can change these behavior by overriding the createShape + // method to create the desired shape. + // example: + // | var geom = new dojox.geo.openlayers.Point({x:0, y:0}); + // | var gf = new dojox.geo.openlayers.GeometryFeature(geom); + + constructor : function(/* dojox.geo.openlayers.Geometry */geometry){ + // summary: + // Constructs a GeometryFeature for the specified geometry. + // geometry: OpenLayer.Geometry + // The geometry to render. + this._geometry = geometry; + this._shapeProperties = {}; + this._fill = null; + this._stroke = null; + }, + + _createCollection : function(/* dojox.geo.openlayers.Geometry */g){ + // summary: + // Create collection shape and add it to the viewport. + // tags: + // private + var layer = this.getLayer(); + var s = layer.getSurface(); + var c = this.createShape(s, g); + var vp = layer.getViewport(); + vp.add(c); + return c; + }, + + _getCollectionShape : function(/* dojox.geo.openlayers.Geometry */g){ + // summary: + // Get the collection shape, create it if necessary + // tags: + // private + var s = g.shape; + if (s == null) { + s = this._createCollection(g); + g.shape = s; + } + return s; + }, + + renderCollection : function(/* undefined | dojox.geo.openlayers.Geometry */g){ + // summary: + // Renders a geometry collection. + // g: undefined | dojox.geo.openlayers.Geometry + // The geometry to render. + if (g == undefined) + g = this._geometry; + + s = this._getCollectionShape(g); + var prop = this.getShapeProperties(); + s.setShape(prop); + + array.forEach(g.coordinates, function(item){ + if (item instanceof Point) + this.renderPoint(item); + else if (item instanceof LineString) + this.renderLineString(item); + else if (item instanceof Collection) + this.renderCollection(item); + else + throw new Error(); + }, this); + this._applyStyle(g); + }, + + render : function(/* undefined || dojox.geo.openlayer.Geometry */g){ + // summary: + // Render a geometry. + // Called by the Layer on which the feature is added. + // g: undefined || dojox.geo.openlayer.Geometry + // The geometry to draw + if (g == undefined) + g = this._geometry; + + if (g instanceof Point) + this.renderPoint(g); + else if (g instanceof LineString) + this.renderLineString(g); + else if (g instanceof Collection) + this.renderCollection(g); + else + throw new Error(); + }, + + getShapeProperties : function(){ + // summary: + // Returns the shape properties. + // returns: Object + // The shape properties. + return this._shapeProperties; + }, + + setShapeProperties : function(/* Object */s){ + // summary: + // Sets the shape properties. + // s: Object + // The shape properties to set. + this._shapeProperties = s; + return this; + }, + + createShape : function(/* Surface */s, /* dojox.geo.openlayers.Geometry */g){ + // summary: + // Called when the shape rendering the geometry has to be created. + // This default implementation creates a circle for a point geometry, a polyline for + // a LineString geometry and is recursively called when creating a collection. + // User may replace this method to produce a custom shape. + // s: dojox.gfx.Surface + // The surface on which the method create the shapes. + // g: dojox.geo.openlayers.Geometry + // The reference geometry + // returns: dojox.gfx.Shape + // The resulting shape. + if (!g) + g = this._geometry; + + var shape = null; + if (g instanceof Point) { + shape = s.createCircle(); + } else if (g instanceof LineString) { + shape = s.createPolyline(); + } else if (g instanceof Collection) { + var grp = s.createGroup(); + array.forEach(g.coordinates, function(item){ + var shp = this.createShape(s, item); + grp.add(shp); + }, this); + shape = grp; + } else + throw new Error(); + return shape; + }, + + getShape : function(){ + // summary: + // Retrieves the shape rendering the geometry + // returns: Shape + // The shape used to render the geometry. + var g = this._geometry; + if (!g) + return null; + if (g.shape) + return g.shape; + this.render(); + return g.shape; + }, + + _createPoint : function(/* dojox.geo.openlayer.Geometry */g){ + // summary: + // Create a point shape + // tags: + // private + var layer = this.getLayer(); + var s = layer.getSurface(); + var c = this.createShape(s, g); + var vp = layer.getViewport(); + vp.add(c); + return c; + }, + + _getPointShape : function(/* dojox.geo.openlayers.Geometry */g){ + // summary: + // get the point geometry shape, create it if necessary + // tags: + // private + var s = g.shape; + if (s == null) { + s = this._createPoint(g); + g.shape = s; + } + return s; + }, + + renderPoint : function(/* undefined | dojox.geo.openlayers.Point */g){ + // summary: + // Renders a point geometry. + // g: undefined | dojox.geo.openlayers.Point + // The geometry to render. + if (g == undefined) + g = this._geometry; + var layer = this.getLayer(); + var map = layer.getDojoMap(); + + s = this._getPointShape(g); + var prop = lang.mixin({}, this._defaults.pointShape); + prop = lang.mixin(prop, this.getShapeProperties()); + s.setShape(prop); + + var from = this.getCoordinateSystem(); + var p = map.transform(g.coordinates, from); + + var a = this._getLocalXY(p); + var cx = a[0]; + var cy = a[1]; + var tr = layer.getViewport().getTransform(); + if (tr) + s.setTransform(matrix.translate(cx - tr.dx, cy - tr.dy)); + + this._applyStyle(g); + }, + + _createLineString : function(/* dojox.geo.openlayers.Geometry */g){ + // summary: + // Create polyline shape and add it to the viewport. + // tags: + // private + var layer = this.getLayer(); + var s = layer._surface; + var shape = this.createShape(s, g); + var vp = layer.getViewport(); + vp.add(shape); + g.shape = shape; + return shape; + }, + + _getLineStringShape : function(/* dojox.geo.openlayers.Geometry */g){ + // summary: + // Get the line string geometry shape, create it if necessary + // tags: + // private + var s = g.shape; + if (s == null) { + s = this._createLineString(g); + g.shape = s; + } + return s; + }, + + renderLineString : function(/* undefined | dojox.geo.openlayers.geometry */g){ + // summary: + // Renders a line string geometry. + // g: undefined | dojox.geo.openlayers.Geometry + // The geometry to render. + if (g == undefined) + g = this._geometry; + var layer = this.getLayer(); + var map = layer.getDojoMap(); + var lss = this._getLineStringShape(g); + var from = this.getCoordinateSystem(); + var points = new Array(g.coordinates.length); // ss.getShape().points; + var tr = layer.getViewport().getTransform(); + array.forEach(g.coordinates, function(c, i, array){ + var p = map.transform(c, from); + var a = this._getLocalXY(p); + if (tr) { + a[0] -= tr.dx; + a[1] -= tr.dy; + } + points[i] = { + x : a[0], + y : a[1] + }; + }, this); + var prop = lang.mixin({}, this._defaults.lineStringShape); + prop = lang.mixin(prop, this.getShapeProperties()); + prop = lang.mixin(prop, { + points : points + }); + lss.setShape(prop); + this._applyStyle(g); + }, + + _applyStyle : function(/* Geometry */g){ + // summary: + // Apply the style on the geometry's shape. + // g: dojox.geo.openlayers.Geometry + // The geometry. + // tags: + // private + if (!g || !g.shape) + return; + + var f = this.getFill(); + + var fill; + if (!f || lang.isString(f) || lang.isArray(f)) + fill = f; + else { + fill = lang.mixin({}, this._defaults.fill); + fill = lang.mixin(fill, f); + } + + var s = this.getStroke(); + var stroke; + if (!s || lang.isString(s) || lang.isArray(s)) + stroke = s; + else { + stroke = lang.mixin({}, this._defaults.stroke); + stroke = lang.mixin(stroke, s); + } + + this._applyRecusiveStyle(g, stroke, fill); + }, + + _applyRecusiveStyle : function(g, stroke, fill){ + // summary: + // Apply the style on the geometry's shape recursively. + // g: dojox.geo.openlayers.Geometry + // The geometry. + // stroke: Object + // The stroke + // fill:Object + // The fill + // tags: + // private + var shp = g.shape; + + if (shp.setFill) + shp.setFill(fill); + + if (shp.setStroke) + shp.setStroke(stroke); + + if (g instanceof Collection) { + array.forEach(g.coordinates, function(i){ + this._applyRecusiveStyle(i, stroke, fill); + }, this); + } + }, + + setStroke : function(/* Object */s){ + // summary: + // Set the stroke style to be applied on the rendered shape. + // s: Object + // The stroke style + this._stroke = s; + return this; + }, + + getStroke : function(){ + // summary: + // Retrieves the stroke style + // returns: Object + // The stroke style + return this._stroke; + }, + + setFill : function(/* Object */f){ + // summary: + // Set the fill style to be applied on the rendered shape. + // f: Object + // The fill style + this._fill = f; + return this; + }, + + getFill : function(){ + // summary: + // Retrieves the fill style + // returns: Object + // The fill style + return this._fill; + }, + + remove : function(){ + // summary: + // Removes the shape from the Surface. + // Called when the feature is removed from the layer. + var g = this._geometry; + var shp = g.shape; + g.shape = null; + if (shp) + shp.removeShape(); + if (g instanceof Collection) { + array.forEach(g.coordinates, function(i){ + this.remove(i); + }, this); + } + }, + + _defaults : { + fill : null, + stroke : null, + pointShape : { + r : 30 + }, + lineStringShape : null + } + + }); +}); diff --git a/js/dojo/dojox/geo/openlayers/GfxLayer.js b/js/dojo/dojox/geo/openlayers/GfxLayer.js new file mode 100644 index 0000000..49faa5e --- /dev/null +++ b/js/dojo/dojox/geo/openlayers/GfxLayer.js @@ -0,0 +1,142 @@ +//>>built +define("dojox/geo/openlayers/GfxLayer", ["dojo/_base/kernel", + "dojo/_base/declare", + "dojo/_base/connect", + "dojo/_base/html", + "dojox/gfx", + "dojox/gfx/_base", + "dojox/gfx/shape", + "dojox/gfx/path", + "dojox/gfx/matrix", + "dojox/geo/openlayers/Feature", + "dojox/geo/openlayers/Layer"], function(dojo, declare, connect, html, gfx, gbase, shape, + path, matrix, Feature, Layer){ + /*===== + var Layer = dojox.geo.openlayers.Layer; + =====*/ + return declare("dojox.geo.openlayers.GfxLayer", Layer, { + // summary: + // A layer dedicated to render dojox.geo.openlayers.GeometryFeature + // description: + // A layer class for rendering geometries as dojox.gfx.Shape objects. + // This layer class accepts Features which encapsulates graphic objects to be added to the map. + // All objects should be added to this group. + // tags: + // private + _viewport : null, + + constructor : function(name, options){ + // summary: + // Constructs a new GFX layer. + var s = dojox.gfx.createSurface(this.olLayer.div, 100, 100); + this._surface = s; + var vp; + if (options && options.viewport) + vp = options.viewport; + else + vp = s.createGroup(); + this.setViewport(vp); + dojo.connect(this.olLayer, "onMapResize", this, "onMapResize"); + this.olLayer.getDataExtent = this.getDataExtent; + }, + + getViewport : function(){ + // summary: + // Gets the viewport + // tags: + // internal + return this._viewport; + }, + + setViewport : function(g){ + // summary: + // Sets the viewport + // g: dojox.gfx.Group + // tags: + // internal + if (this._viewport) + this._viewport.removeShape(); + this._viewport = g; + this._surface.add(g); + }, + + onMapResize : function(){ + // summary: + // Called when map is resized. + // tag: + // protected + this._surfaceSize(); + }, + + setMap : function(map){ + // summary: + // Sets the map for this layer. + // tag: + // protected + this.inherited(arguments); + this._surfaceSize(); + }, + + getDataExtent : function(){ + // summary: + // Get data extent + // tags: + // private + var ret = this._surface.getDimensions(); + return ret; + }, + + getSurface : function(){ + // summary: + // Get the underlying dojox.gfx.Surface + // returns: dojox.gfx.Surface + // The dojox.gfx.Surface this layer uses to draw its GFX rendering. + return this._surface; + }, + + _surfaceSize : function(){ + // summary: + // Recomputes the surface size when being resized. + // tags: + // private + var s = this.olLayer.map.getSize(); + this._surface.setDimensions(s.w, s.h); + }, + + moveTo : function(event){ + // summary: + // Called when this layer is moved or zoommed. + // event: + // The event + var s = dojo.style(this.olLayer.map.layerContainerDiv); + var left = parseInt(s.left); + var top = parseInt(s.top); + + if (event.zoomChanged || left || top) { + var d = this.olLayer.div; + + dojo.style(d, { + left : -left + "px", + top : -top + "px" + }); + + if (this._features == null) + return; + var vp = this.getViewport(); + + vp.setTransform(matrix.translate(left, top)); + + this.inherited(arguments); + + } + }, + + added : function(){ + // summary: + // Called when added to a map. + this.inherited(arguments); + this._surfaceSize(); + } + + }); +}); diff --git a/js/dojo/dojox/geo/openlayers/GreatCircle.js b/js/dojo/dojox/geo/openlayers/GreatCircle.js new file mode 100644 index 0000000..ae0b67d --- /dev/null +++ b/js/dojo/dojox/geo/openlayers/GreatCircle.js @@ -0,0 +1,122 @@ +//>>built +define("dojox/geo/openlayers/GreatCircle", ["dojo/_base/lang", + "dojox/geo/openlayers/GeometryFeature", + "dojox/geo/openlayers/Point", + "dojox/geo/openlayers/LineString"], function(lang, GeometryFeature, Point, lineString){ + + lang.getObject("geo.openlayers", true, dojox); + + dojox.geo.openlayers.GreatCircle = { + + toPointArray : function(p1, p2, increment){ + // summary: + // Create a geodetic line as an array of OpenLayers.Point. + // descritpion: + // Create a geodetic line as an array of OpenLayers.Point between the point p1 + // and the point p2. Result is a polyline approximation for which a new point is + // calculated every <em>increment</em> degrees. + // p1: Point + // The first point of the geodetic line. x and y fields are longitude and + // latitude in decimal degrees. + // p2: Point + // The second point of the geodetic line. x and y fields are longitude and + // latitude in decimal degrees. + // increment: Float + // The value at which a new point is computed. + var startLon = p1.x; + var endLon = p2.x; + var sl = Math.min(startLon, endLon); + var el = Math.max(startLon, endLon); + + var d2r = this.DEG2RAD; + var lat1 = p1.y * d2r; + var lon1 = p1.x * d2r; + var lat2 = p2.y * d2r; + var lon2 = p2.x * d2r; + + if (Math.abs(lon1 - lon2) <= this.TOLERANCE) { + var l = Math.min(lon1, lon2); + lon2 = l + Math.PI; + } + + if (Math.abs(lon2 - lon1) == Math.PI) { + if (lat1 + lat2 == 0.0) { + lat2 += Math.PI / 180000000; + } + } + + var lon = sl * d2r; + var elon = el * d2r; + var incr = increment * d2r; + var wp = []; + var k = 0; + var r2d = this.RAD2DEG; + + while (lon <= elon) { + lat = Math.atan((Math.sin(lat1) * Math.cos(lat2) * Math.sin(lon - lon2) - Math.sin(lat2) * Math.cos(lat1) + * Math.sin(lon - lon1)) + / (Math.cos(lat1) * Math.cos(lat2) * Math.sin(lon1 - lon2))); + var p = { + x : lon * r2d, + y : lat * r2d + }; + wp[k++] = p; + if (lon < elon && (lon + incr) >= elon) + lon = elon; + else + lon = lon + incr; + } + return wp; + }, + + toLineString : function(p1, p2, increment){ + // summary: + // Create a geodetic line as an array of OpenLayers.Geometry.LineString. + // descritpion: + // Create a geodetic line as a OpenLayers.Geometry.LineString between the point p1 + // and the point p2. Result is a polyline approximation for which a new point is + // calculated every <em>increment</em> degrees. + // p1: Point + // The first point of the geodetic line. x and y fields are longitude and + // latitude in decimal degrees. + // p2: Point + // The second point of the geodetic line. x and y fields are longitude and + // latitude in decimal degrees. + // increment: Float + // The value at which a new point is computed. + var wp = this.toPointArray(p1, p2, increment); + var ls = new OpenLayers.Geometry.LineString(wp); + return ls; + }, + + toGeometryFeature : function(p1, p2, increment){ + // summary: + // Create a geodetic line as an array of dojox.geo.openlayers.GeometryFeature. + // description: + // Create a geodetic line as a dojox.geo.openlayers.GeometryFeature between the point p1 + // ant the point p2. Result is a polyline approximation for which a new point is + // calculated every <em>increment</em> degrees. + // p1: Point + // The first point of the geodetic line. x and y fields are longitude and + // latitude in decimal degrees. + // p2: Point + // The second point of the geodetic line. x and y fields are longitude and + // latitude in decimal degrees. + // increment: Float + // The value at which a new point is computed. + // returns: GeometryFeature + // The geodetic line as a GeometryFeature + + var ls = this.toLineString(p1, p2, increment); + return new GeometryFeature(ls); + }, + + DEG2RAD : Math.PI / 180, + + RAD2DEG : 180 / Math.PI, + + TOLERANCE : 0.00001 + }; + + return dojox.geo.openlayers.GreatCircle; +}); diff --git a/js/dojo/dojox/geo/openlayers/JsonImport.js b/js/dojo/dojox/geo/openlayers/JsonImport.js new file mode 100644 index 0000000..ebb9197 --- /dev/null +++ b/js/dojo/dojox/geo/openlayers/JsonImport.js @@ -0,0 +1,151 @@ +//>>built +define("dojox/geo/openlayers/JsonImport", ["dojo/_base/kernel", + "dojo/_base/declare", + "dojo/_base/xhr", + "dojo/_base/lang", + "dojo/_base/array", + "dojox/geo/openlayers/LineString", + "dojox/geo/openlayers/Collection", + "dojo/data/ItemFileReadStore", + "dojox/geo/openlayers/GeometryFeature"], function(dojo, declare, xhr, lang, array, LineString, Collection, + ItemFileReadStore, GeometryFeature){ + + return declare("dojox.geo.openlayers.JsonImport", null, { + // summary: + // Class to load JSON formated ShapeFile as output of the JSon Custom Map Converter. + // description: + // This class loads JSON formated ShapeFile produced by the JSon Custom Map Converter. + // When loading the JSON file, it calls a iterator function each time a feature is read. + // This iterator function is provided as parameter to the constructor. + // + constructor : function(/* Object */params){ + // summary: + // Construct a new JSON importer. + // description: + // Construct a new JSON importer with the specified parameters. These parameters are + // passed through an Object and include: + // <ul> + // <li> url : <em>url</em> </li> The url pointing to the JSON file to load. + // <li> nextFeature : <em>function</em> </li> The function called each time a feature is read. + // The function is called with a GeometryFeature as argument. + // <li> error : <em>function</em> </li> Error function called if something goes wrong. + // </ul> + this._params = params; + }, + + loadData : function(){ + // summary: + // Triggers the loading. + var p = this._params; + xhr.get({ + url : p.url, + handleAs : "json", + sync : true, + load : lang.hitch(this, this._gotData), + error : lang.hitch(this, this._loadError) + }); + }, + + _gotData : function(/* Object */items){ + // summary: + // Called when loading is complete. + // tags: + // private + var nf = this._params.nextFeature; + if (!lang.isFunction(nf)) + return; + + var extent = items.layerExtent; + var ulx = extent[0]; + var uly = extent[1]; + var lrx = ulx + extent[2]; + var lry = uly + extent[3]; + + var extentLL = items.layerExtentLL; + var x1 = extentLL[0]; + var y1 = extentLL[1]; + var x2 = x1 + extentLL[2]; + var y2 = y1 + extentLL[3]; + + var ulxLL = x1; + var ulyLL = y2; + var lrxLL = x2; + var lryLL = y1; + + var features = items.features; + + for ( var f in features) { + var o = features[f]; + var s = o["shape"]; + var gf = null; + if (lang.isArray(s[0])) { + + var a = new Array(); + array.forEach(s, function(item){ + var ls = this._makeGeometry(item, ulx, uly, lrx, lry, ulxLL, ulyLL, lrxLL, lryLL); + a.push(ls); + }, this); + var g = new Collection(a); + gf = new GeometryFeature(g); + nf.call(this, gf); + + } else { + gf = this._makeFeature(s, ulx, uly, lrx, lry, ulxLL, ulyLL, lrxLL, lryLL); + nf.call(this, gf); + } + } + var complete = this._params.complete; + if (lang.isFunction(complete)) + complete.call(this, complete); + }, + + _makeGeometry : function(/* Array */s, /* Float */ulx, /* Float */uly, /* Float */lrx, /* Float */ + lry, /* Float */ulxLL, /* Float */ulyLL, /* Float */lrxLL, /* Float */lryLL){ + // summary: + // Make a geometry with the specified points. + // tags: + // private + var a = []; + var k = 0.0; + for ( var i = 0; i < s.length - 1; i += 2) { + var x = s[i]; + var y = s[i + 1]; + + k = (x - ulx) / (lrx - ulx); + var px = k * (lrxLL - ulxLL) + ulxLL; + + k = (y - uly) / (lry - uly); + var py = k * (lryLL - ulyLL) + ulyLL; + + a.push({ + x : px, + y : py + }); + + } + var ls = new LineString(a); + return ls; + }, + + _makeFeature : function(/* Array */s, /* Float */ulx, /* Float */uly, /* Float */lrx, /* Float */ + lry, /* Float */ulxLL, /* Float */ulyLL, /* Float */lrxLL, /* Float */lryLL){ + // summary: + // Make a GeometryFeature with the specified points. + // tags: + // private + var ls = this._makeGeometry(s, ulx, uly, lrx, lry, ulxLL, ulyLL, lrxLL, lryLL); + var gf = new GeometryFeature(ls); + return gf; + }, + + _loadError : function(){ + // summary: + // Called when an error occurs. Calls the error function is provided in the parameters. + // tags: + // private + var f = this._params.error; + if (lang.isFunction(f)) + f.apply(this, parameters); + } + }); +}); diff --git a/js/dojo/dojox/geo/openlayers/Layer.js b/js/dojo/dojox/geo/openlayers/Layer.js new file mode 100644 index 0000000..c01f79f --- /dev/null +++ b/js/dojo/dojox/geo/openlayers/Layer.js @@ -0,0 +1,164 @@ +//>>built +define("dojox/geo/openlayers/Layer", ["dojo/_base/kernel", "dojo/_base/declare", "dojo/_base/lang", "dojo/_base/array", "dojo/_base/sniff"], + function(dojo, declare, lang, array, sniff){ + + return declare("dojox.geo.openlayers.Layer", null, { + // summary: + // Base layer class for dojox.geo.openlayers.Map specific layers extending OpenLayers.Layer class. + // This layer class accepts Features which encapsulates graphic objects to be added to the map. + // This layer class encapsulates an OpenLayers.Layer. + // This class provides Feature management such as add, remove and feature access. + constructor : function(name, options){ + // summary: + // Constructs a new Layer. + // name: String + // The name of the layer. + // options: Object + // Options passed to the underlying OpenLayers.Layer object. + + var ol = options ? options.olLayer : null; + + if (!ol) + ol = lang.delegate(new OpenLayers.Layer(name, options)); + + this.olLayer = ol; + this._features = null; + this.olLayer.events.register("moveend", this, lang.hitch(this, this.moveTo)); + }, + + renderFeature : function(/* Feature */f){ + // summary: + // Called when rendering a feature is necessary. + // f : Feature + // The feature to draw. + f.render(); + }, + + getDojoMap : function(){ + return this.dojoMap; + }, + + addFeature : function(/* Feature | Array */f){ + // summary: + // Add a feature or an array of features to the layer. + // f : Feature or Array + // The Feature or array of features to add. + if (lang.isArray(f)) { + array.forEach(f, function(item){ + this.addFeature(item); + }, this); + return; + } + if (this._features == null) + this._features = []; + this._features.push(f); + f._setLayer(this); + }, + + removeFeature : function(/* Feature | Array */f){ + // summary : + // Removes a feature or an array of features from the layer. + // f : Feature or Array + // The Feature or array of features to remove. + var ft = this._features; + if (ft == null) + return; + if (f instanceof Array) { + f = f.slice(0); + array.forEach(f, function(item){ + this.removeFeature(item); + }, this); + return; + } + var i = array.indexOf(ft, f); + if (i != -1) + ft.splice(i, 1); + f._setLayer(null); + f.remove(); + }, + + removeFeatureAt : function(index){ + // summary: + // Remove the feature at the specified index. + // description: + // Remove the feature at the specified index. + // index: Number + // The index of the feature to remove. + var ft = this._features; + var f = ft[index]; + if (!f) + return; + ft.splice(index, 1); + f._setLayer(null); + f.remove(); + }, + + getFeatures : function(){ + // summary: + // Retrieves the feature hold by this layer. + // returns: Array + // The untouched array of features hold by this layer. + return this._features; + }, + + getFeatureAt : function(i){ + // summary: + // Returns the i-th feature of this layer. + // i : int + // The index of the feature to return. + // returns : ibm_maps.maps.Layer + // The i-th feature of this layer. + if (this._features == null) + return undefined; + return this._features[i]; + }, + + getFeatureCount : function(){ + // summary: + // Returns the number of the features contained by this layer. + // returns: int + // The number of the features contained by this layer. + if (this._features == null) + return 0; + return this._features.length; + }, + + clear : function(){ + // summary: + // Removes all the features from this layer. + var fa = this.getFeatures(); + this.removeFeature(fa); + }, + + moveTo : function(event){ + // summary: + // Called when the layer is panned or zoomed. + // event: Object + // The event + if (event.zoomChanged) { + if (this._features == null) + return; + array.forEach(this._features, function(f){ + this.renderFeature(f); + }, this); + } + }, + + redraw : function(){ + // summary: + // Redraws this layer + if (sniff.isIE) + setTimeout(lang.hitch(this, function(){ + this.olLayer.redraw(); + }, 0)); + else + this.olLayer.redraw(); + }, + + added : function(){ + // summary: + // Called when the layer is added to the map + } + + }); + }); diff --git a/js/dojo/dojox/geo/openlayers/LineString.js b/js/dojo/dojox/geo/openlayers/LineString.js new file mode 100644 index 0000000..d5d1c0e --- /dev/null +++ b/js/dojo/dojox/geo/openlayers/LineString.js @@ -0,0 +1,28 @@ +//>>built +define("dojox/geo/openlayers/LineString", ["dojo/_base/kernel", "dojo/_base/declare", "dojox/geo/openlayers/Geometry"], function(dojo, declare, + /* ===== + var Geometry = dojox.geo.openlayers.Geometry; + =====*/ Geometry){ + return declare("dojox.geo.openlayers.LineString", Geometry, { + // summary: + // The `dojox.geo.openlayers.LineString` geometry. This geometry holds an array + // of coordinates. + + setPoints : function(p){ + // summary: + // Sets the points for this geometry. + // p : Array + // An array of {x, y} objects + this.coordinates = p; + }, + + getPoints : function(){ + // summary: + // Gets the points of this geometry. + // returns: Array + // The points of this geometry. + return this.coordinates; + } + + }); +}); diff --git a/js/dojo/dojox/geo/openlayers/Map.js b/js/dojo/dojox/geo/openlayers/Map.js new file mode 100644 index 0000000..890f736 --- /dev/null +++ b/js/dojo/dojox/geo/openlayers/Map.js @@ -0,0 +1,592 @@ +//>>built +define("dojox/geo/openlayers/Map", ["dojo/_base/kernel", + "dojo/_base/declare", + "dojo/_base/lang", + "dojo/_base/array", + "dojo/_base/json", + "dojo/_base/html", + "dojox/main", + "dojox/geo/openlayers/TouchInteractionSupport", + "dojox/geo/openlayers/Layer", + "dojox/geo/openlayers/Patch"], function(dojo, declare, lang, array, json, html, dojox, TouchInteractionSupport, + Layer, Patch){ + + dojo.experimental("dojox.geo.openlayers.Map"); + + lang.getObject("geo.openlayers", true, dojox); + + dojox.geo.openlayers.BaseLayerType = { + // summary: + // Defines the base layer types to be used at Map construction time or + // with the setBaseLayerType function. + // description: + // This object defines the base layer types to be used at Map construction + // time or with the setBaseLayerType function. + // OSM: String + // The Open Street Map base layer type selector. + OSM : "OSM", + // WMS: String + // The Web Map Server base layer type selector. + WMS : "WMS", + // GOOGLE: String + // The Google base layer type selector. + GOOGLE : "Google", + // VIRTUAL_EARTH: String + // The Virtual Earth base layer type selector. + VIRTUAL_EARTH : "VirtualEarth", + // BING: String + // Same as Virtual Earth + BING : "VirtualEarth", + // YAHOO: String + // The Yahoo base layer type selector. + YAHOO : "Yahoo", + // ARCGIS: String + // The ESRI ARCGis base layer selector. + ARCGIS : "ArcGIS" + }; + + dojox.geo.openlayers.EPSG4326 = new OpenLayers.Projection("EPSG:4326"); + + var re = /^\s*(\d{1,3})[D°]\s*(\d{1,2})[M']\s*(\d{1,2}\.?\d*)\s*(S|"|'')\s*([NSEWnsew]{0,1})\s*$/i; + dojox.geo.openlayers.parseDMS = function(v, toDecimal){ + // summary: + // Parses the specified string and returns degree minute second or decimal degree. + // description: + // Parses the specified string and returns degree minute second or decimal degree. + // v: String + // The string to parse + // toDecimal: Boolean + // Specifies if the result should be returned in decimal degrees or in an array + // containg the degrees, minutes, seconds values. + // returns: Float | Array + // the parsed value in decimal degrees or an array containing the degrees, minutes, seconds values. + + var res = re.exec(v); + if (res == null || res.length < 5) + return parseFloat(v); + var d = parseFloat(res[1]); + var m = parseFloat(res[2]); + var s = parseFloat(res[3]); + var nsew = res[5]; + if (toDecimal) { + var lc = nsew.toLowerCase(); + var dd = d + (m + s / 60.0) / 60.0; + if (lc == "w" || lc == "s") + dd = -dd; + return dd; + } + return [d, m, s, nsew]; + }; + + Patch.patchGFX(); + + return declare("dojox.geo.openlayers.Map", null, { + // summary: + // A map viewer based on the OpenLayers library. + // + // description: + // The `dojox.geo.openlayers.Map` object allows to view maps from various map providers. + // It encapsulates an `OpenLayers.Map` object on which most operations are delegated. + // GFX layers can be added to display GFX georeferenced shapes as well as Dojo widgets. + // Parameters can be passed as argument at construction time to define the base layer + // type and the base layer parameters such as url or options depending on the type + // specified. These parameters can be any of : + // <br /> + // _baseLayerType_: type of the base layer. Can be any of + // + // * `dojox.geo.openlayers.BaseLayerType.OSM`: Open Street Map base layer + // * `dojox.geo.openlayers.BaseLayerType.WMS`: Web Map Service layer + // * `dojox.geo.openlayers.BaseLayerType.GOOGLE`: Google layer + // * `dojox.geo.openlayers.BaseLayerType.VIRTUAL_EARTH`: Virtual Earth layer + // * `dojox.geo.openlayers.BaseLayerType.BING`: Bing layer + // * `dojox.geo.openlayers.BaseLayerType.YAHOO`: Yahoo layer + // * `dojox.geo.openlayers.BaseLayerType.ARCGIS`: ESRI ArgGIS layer + // + // Note that access to commercial server such as Google, Virtual Earth or Yahoo may need specific licencing. + // + // The parameters value also include : + // + // * `baseLayerName`: The name of the base layer. + // * `baseLayerUrl`: Some layer may need an url such as Web Map Server + // * `baseLayerOptions`: Addtional specific options passed to OpensLayers layer, + // such as The list of layer to display, for Web Map Server layer. + // + // example: + // + // | var map = new dojox.geo.openlayers.widget.Map(div, { + // | baseLayerType : dojox.geo.openlayers.BaseLayerType.OSM, + // | baseLayerName : 'Open Street Map Layer' + // | }); + + // summary: + // The underlying OpenLayers.Map object. + // Should be accessed on read mode only. + olMap : null, + + _tp : null, + + constructor : function(div, options){ + // summary: + // Constructs a new Map object + if (!options) + options = {}; + + div = html.byId(div); + + this._tp = { + x : 0, + y : 0 + }; + + var opts = options.openLayersMapOptions; + + if (!opts) { + opts = { + controls : [new OpenLayers.Control.ScaleLine({ + maxWidth : 200 + }), new OpenLayers.Control.Navigation()] + }; + } + if (options.accessible) { + var kbd = new OpenLayers.Control.KeyboardDefaults(); + if (!opts.controls) + opts.controls = []; + opts.controls.push(kbd); + } + var baseLayerType = options.baseLayerType; + if (!baseLayerType) + baseLayerType = dojox.geo.openlayers.BaseLayerType.OSM; + + html.style(div, { + width : "100%", + height : "100%", + dir : "ltr" + }); + + var map = new OpenLayers.Map(div, opts); + this.olMap = map; + + this._layerDictionary = { + olLayers : [], + layers : [] + }; + + if (options.touchHandler) + this._touchControl = new TouchInteractionSupport(map); + + var base = this._createBaseLayer(options); + this.addLayer(base); + + this.initialFit(options); + }, + + initialFit : function(params){ + var o = params.initialLocation; + if (!o) + o = [-160, 70, 160, -70]; + this.fitTo(o); + }, + + setBaseLayerType : function( + /* dojox.geo.openlayers.Map.BaseLayerType */type){ + // summary: + // Set the base layer type, replacing the existing base layer + // type: dojox.geo.openlayers.BaseLayerType + // base layer type + // returns: OpenLayers.Layer + // The newly created layer. + if (type == this.baseLayerType) + return null; + + var o = null; + if (typeof type == "string") { + o = { + baseLayerName : type, + baseLayerType : type + }; + this.baseLayerType = type; + } else if (typeof type == "object") { + o = type; + this.baseLayerType = o.baseLayerType; + } + var bl = null; + if (o != null) { + bl = this._createBaseLayer(o); + if (bl != null) { + var olm = this.olMap; + var ob = olm.getZoom(); + var oc = olm.getCenter(); + var recenter = !!oc && !!olm.baseLayer && !!olm.baseLayer.map; + + if (recenter) { + var proj = olm.getProjectionObject(); + if (proj != null) + oc = oc.transform(proj, dojox.geo.openlayers.EPSG4326); + } + var old = olm.baseLayer; + if (old != null) { + var l = this._getLayer(old); + this.removeLayer(l); + } + if (bl != null) + this.addLayer(bl); + if (recenter) { + proj = olm.getProjectionObject(); + if (proj != null) + oc = oc.transform(dojox.geo.openlayers.EPSG4326, proj); + olm.setCenter(oc, ob); + } + } + } + return bl; + }, + + getBaseLayerType : function(){ + // summary: + // Retrieves the base layer type. + // returns: dojox.geo.openlayers.BaseLayerType + // The current base layer type. + return this.baseLayerType; + }, + + getScale : function(geodesic){ + // summary: + // Returns the current scale + // geodesic: Boolean + // Tell if geodesic calculation should be performed. If set to + // true, the scale will be calculated based on the horizontal size of the + // pixel in the center of the map viewport. + // returns: Number + // The current scale. + var scale; + var om = this.olMap; + if (geodesic) { + var units = om.getUnits(); + if (!units) { + return null; + } + var inches = OpenLayers.INCHES_PER_UNIT; + scale = (om.getGeodesicPixelSize().w || 0.000001) * inches["km"] * OpenLayers.DOTS_PER_INCH; + } else { + scale = om.getScale(); + } + return scale; + }, + + getOLMap : function(){ + // summary: + // gets the underlying OpenLayers map object. + // returns : OpenLayers.Map + // The underlying OpenLayers map object. + return this.olMap; + }, + + _createBaseLayer : function(params){ + // summary: + // Creates the base layer. + // tags: + // private + var base = null; + var type = params.baseLayerType; + var url = params.baseLayerUrl; + var name = params.baseLayerName; + var options = params.baseLayerOptions; + + if (!name) + name = type; + if (!options) + options = {}; + switch (type) { + case dojox.geo.openlayers.BaseLayerType.OSM: + options.transitionEffect = "resize"; + // base = new OpenLayers.Layer.OSM(name, url, options); + base = new Layer(name, { + olLayer : new OpenLayers.Layer.OSM(name, url, options) + }); + break; + case dojox.geo.openlayers.BaseLayerType.WMS: + if (!url) { + url = "http://labs.metacarta.com/wms/vmap0"; + if (!options.layers) + options.layers = "basic"; + } + base = new Layer(name, { + olLayer : new OpenLayers.Layer.WMS(name, url, options, { + transitionEffect : "resize" + }) + }); + break; + case dojox.geo.openlayers.BaseLayerType.GOOGLE: + base = new Layer(name, { + olLayer : new OpenLayers.Layer.Google(name, options) + }); + break; + case dojox.geo.openlayers.BaseLayerType.VIRTUAL_EARTH: + base = new Layer(name, { + olLayer : new OpenLayers.Layer.VirtualEarth(name, options) + }); + break; + case dojox.geo.openlayers.BaseLayerType.YAHOO: + // base = new OpenLayers.Layer.Yahoo(name); + base = new Layer(name, { + olLayer : new OpenLayers.Layer.Yahoo(name, options) + }); + break; + case dojox.geo.openlayers.BaseLayerType.ARCGIS: + if (!url) + url = "http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer/export"; + base = new Layer(name, { + olLayer : new OpenLayers.Layer.ArcGIS93Rest(name, url, options, {}) + }); + + break; + } + + if (base == null) { + if (type instanceof OpenLayers.Layer) + base = type; + else { + options.transitionEffect = "resize"; + base = new Layer(name, { + olLayer : new OpenLayers.Layer.OSM(name, url, options) + }); + this.baseLayerType = dojox.geo.openlayers.BaseLayerType.OSM; + } + } + + return base; + }, + + removeLayer : function(/* dojox.geo.openlayers.Layer */layer){ + // summary: + // Remove the specified layer from the map. + // layer: dojox.geo.openlayers.Layer + // The layer to remove from the map. + var om = this.olMap; + var i = array.indexOf(this._layerDictionary.layers, layer); + if (i > 0) + this._layerDictionary.layers.splice(i, 1); + var oll = layer.olLayer; + var j = array.indexOf(this._layerDictionary.olLayers, oll); + if (j > 0) + this._layerDictionary.olLayers.splice(i, j); + om.removeLayer(oll, false); + }, + + layerIndex : function(/* dojox.geo.openlayers.Layer */layer, index){ + // summary: + // Set or retrieve the layer index. + // description: + // Set or get the layer index, that is the z-order of the layer. + // if the index parameter is provided, the layer index is set to + // this value. If the index parameter is not provided, the index of + // the layer is returned. + // index: undefined | int + // index of the layer + // returns: int + // the index of the layer. + var olm = this.olMap; + if (!index) + return olm.getLayerIndex(layer.olLayer); + //olm.raiseLayer(layer.olLayer, index); + olm.setLayerIndex(layer.olLayer, index); + + this._layerDictionary.layers.sort(function(l1, l2){ + return olm.getLayerIndex(l1.olLayer) - olm.getLayerIndex(l2.olLayer); + }); + this._layerDictionary.olLayers.sort(function(l1, l2){ + return olm.getLayerIndex(l1) - olm.getLayerIndex(l2); + }); + + return index; + }, + + addLayer : function(/* dojox.geo.openlayers.Layer */layer){ + // summary: + // Add the specified layer to the map. + // layer: dojox.geo.openlayer.Layer + // The layer to add to the map. + layer.dojoMap = this; + var om = this.olMap; + var ol = layer.olLayer; + this._layerDictionary.olLayers.push(ol); + this._layerDictionary.layers.push(layer); + om.addLayer(ol); + layer.added(); + }, + + _getLayer : function(/*OpenLayer.Layer */ol){ + // summary: + // Retrieve the dojox.geo.openlayer.Layer from the OpenLayer.Layer + // tags: + // private + var i = array.indexOf(this._layerDictionary.olLayers, ol); + if (i != -1) + return this._layerDictionary.layers[i]; + return null; + }, + + getLayer : function(property, value){ + // summary: + // Returns the layer whose property matches the value. + // property: String + // The property to check + // value: Object + // The value to match + // returns: dojox.geo.openlayer.Layer | Array + // The layer(s) matching the property's value. Since multiple layers + // match the property's value the return value is an array. + // example: + // var layers = map.getLayer("name", "Layer Name"); + var om = this.olMap; + var ols = om.getBy("layers", property, value); + var ret = new Array(); //[]; + array.forEach(ols, function(ol){ + ret.push(this._getLayer(ol)); + }, this); + return ret; + }, + + getLayerCount : function(){ + // summary: + // Returns the count of layers of this map. + // returns: int + // The number of layers of this map. + var om = this.olMap; + if (om.layers == null) + return 0; + return om.layers.length; + }, + + fitTo : function(o){ + // summary: + // Fits the map on a point,or an area + // description: + // Fits the map on the point or extent specified as parameter. + // o: Object + // Object with key values fit parameters or a JSON string. + // example: + // Examples of arguments passed to the fitTo function : + // | null + // The map is fit on full extent + // + // | { + // | bounds : [ulx, uly, lrx, lry] + // | } + // The map is fit on the specified bounds expressed as decimal degrees latitude and longitude. + // The bounds are defined with their upper left and lower right corners coordinates. + // + // | { + // | position : [longitude, latitude], + // | extent : degrees + // | } + // The map is fit on the specified position showing the extent <extent> around + // the specified center position. + + var map = this.olMap; + var from = dojox.geo.openlayers.EPSG4326; + + if (o == null) { + var c = this.transformXY(0, 0, from); + map.setCenter(new OpenLayers.LonLat(c.x, c.y)); + return; + } + var b = null; + if (typeof o == "string") + var j = json.fromJson(o); + else + j = o; + var ul; + var lr; + if (j.hasOwnProperty("bounds")) { + var a = j.bounds; + b = new OpenLayers.Bounds(); + ul = this.transformXY(a[0], a[1], from); + b.left = ul.x; + b.top = ul.y; + lr = this.transformXY(a[2], a[3], from); + b.right = lr.x; + b.bottom = lr.y; + } + if (b == null) { + if (j.hasOwnProperty("position")) { + var p = j.position; + var e = j.hasOwnProperty("extent") ? j.extent : 1; + if (typeof e == "string") + e = parseFloat(e); + b = new OpenLayers.Bounds(); + ul = this.transformXY(p[0] - e, p[1] + e, from); + b.left = ul.x; + b.top = ul.y; + lr = this.transformXY(p[0] + e, p[1] - e, from); + b.right = lr.x; + b.bottom = lr.y; + } + } + if (b == null) { + if (o.length == 4) { + b = new OpenLayers.Bounds(); + // TODO Choose the correct method + if (false) { + b.left = o[0]; + b.top = o[1]; + + b.right = o[2]; + b.bottom = o[3]; + } else { + ul = this.transformXY(o[0], o[1], from); + b.left = ul.x; + b.top = ul.y; + lr = this.transformXY(o[2], o[3], from); + b.right = lr.x; + b.bottom = lr.y; + } + } + } + if (b != null) { + map.zoomToExtent(b, true); + } + }, + + transform : function(p, from, to){ + // summary: + // Transforms the point passed as argument, expressed in the <em>from</em> + // coordinate system to the map coordinate system. + // description: + // Transforms the point passed as argument without modifying it. The point is supposed to be expressed + // in the <em>from</em> coordinate system and is transformed to the map coordinate system. + // p : Object {x, y} + // The point to transform + // from: OpenLayers.Projection + // The projection in which the point is expressed. + return this.transformXY(p.x, p.y, from, to); + }, + + transformXY : function(x, y, from, to){ + // summary + // Transforms the coordinates passed as argument, expressed in the <em>from</em> + // coordinate system to the map coordinate system. + // description: + // Transforms the coordinates passed as argument. The coordinate are supposed to be expressed + // in the <em>from</em> coordinate system and are transformed to the map coordinate system. + // x : Number + // The longitude coordinate to transform. + // y : Number + // The latitude coordinate to transform. + // from: OpenLayers.Projection + // The projection in which the point is expressed. + + var tp = this._tp; + tp.x = x; + tp.y = y; + if (!from) + from = dojox.geo.openlayers.EPSG4326; + if (!to) + to = this.olMap.getProjectionObject(); + tp = OpenLayers.Projection.transform(tp, from, to); + return tp; + } + + }); + +}); diff --git a/js/dojo/dojox/geo/openlayers/Patch.js b/js/dojo/dojox/geo/openlayers/Patch.js new file mode 100644 index 0000000..93dbe56 --- /dev/null +++ b/js/dojo/dojox/geo/openlayers/Patch.js @@ -0,0 +1,67 @@ +//>>built +define("dojox/geo/openlayers/Patch", [ + "dojo/_base/kernel", + "dojo/_base/lang", // dojo.extend getObject + "dojo/_base/sniff", // dojo.isIE + "dojox/gfx", + "dojox/gfx/shape" +], function(dojo, lang, sniff, gfx, shape){ + + var dgo = lang.getObject("geo.openlayers", true, dojox); + + dgo.Patch = { + + patchMethod : function(/*Object*/type, /*String*/method, /*Function*/execBefore, /*Function*/ + execAfter){ + // summary: + // Patches the specified method of the given type so that the 'execBefore' (resp. 'execAfter') function is + // called before (resp. after) invoking the legacy implementation. + // description: + // The execBefore function is invoked with the following parameter: + // execBefore(method, arguments) where 'method' is the patched method name and 'arguments' the arguments received + // by the legacy implementation. + // The execAfter function is invoked with the following parameter: + // execBefore(method, returnValue, arguments) where 'method' is the patched method name, 'returnValue' the value + // returned by the legacy implementation and 'arguments' the arguments received by the legacy implementation. + // type: Object: the type to patch. + // method: String: the method name. + // execBefore: Function: the function to execute before the legacy implementation. + // execAfter: Function: the function to execute after the legacy implementation. + // tags: + // private + var old = type.prototype[method]; + type.prototype[method] = function(){ + var callee = method; + if (execBefore) + execBefore.call(this, callee, arguments); + var ret = old.apply(this, arguments); + if (execAfter) + ret = execAfter.call(this, callee, ret, arguments) || ret; + return ret; + }; + }, + + patchGFX : function(){ + + var vmlFixRawNodePath = function(){ + if (!this.rawNode.path) + this.rawNode.path = {}; + }; + + var vmlFixFillColors = function() { + if(this.rawNode.fill && !this.rawNode.fill.colors) + this.rawNode.fill.colors = {}; + }; + + if (sniff.isIE <= 8) { + + dojox.geo.openlayers.Patch.patchMethod(gfx.Line, "setShape", vmlFixRawNodePath, null); + dojox.geo.openlayers.Patch.patchMethod(gfx.Polyline, "setShape", vmlFixRawNodePath, null); + dojox.geo.openlayers.Patch.patchMethod(gfx.Path, "setShape", vmlFixRawNodePath, null); + + dojox.geo.openlayers.Patch.patchMethod(shape.Shape, "setFill", vmlFixFillColors, null); + } + } + }; + return dgo.Patch; +}); diff --git a/js/dojo/dojox/geo/openlayers/Point.js b/js/dojo/dojox/geo/openlayers/Point.js new file mode 100644 index 0000000..51db5a1 --- /dev/null +++ b/js/dojo/dojox/geo/openlayers/Point.js @@ -0,0 +1,27 @@ +//>>built +define("dojox/geo/openlayers/Point", ["dojo/_base/kernel", "dojo/_base/declare", "dojox/geo/openlayers/Geometry"], + function(dojo, declare, Geometry){ + /*===== + var Geometry = dojox.geo.openlayers.Geometry; + =====*/ + return declare("dojox.geo.openlayers.Point", Geometry, { + // summary: + // A Point geometry handles description of points to be rendered in a GfxLayer + + setPoint : function(p){ + // summary: + // Sets the point for this geometry. + // p : {x, y} Object + // The point geometry. + this.coordinates = p; + }, + + getPoint : function(){ + // summary: + // Gets the point defining this geometry. + // returns: {x, y} Object + // The point defining this geometry. + return this.coordinates; + } + }); +}); diff --git a/js/dojo/dojox/geo/openlayers/TouchInteractionSupport.js b/js/dojo/dojox/geo/openlayers/TouchInteractionSupport.js new file mode 100644 index 0000000..0ea58f6 --- /dev/null +++ b/js/dojo/dojox/geo/openlayers/TouchInteractionSupport.js @@ -0,0 +1,248 @@ +//>>built +define("dojox/geo/openlayers/TouchInteractionSupport", ["dojo/_base/kernel", + "dojo/_base/declare", + "dojo/_base/connect", + "dojo/_base/html", + "dojo/_base/lang", + "dojo/_base/event", + "dojo/_base/window"], function(dojo, declare, connect, html, lang, event, window){ + + return declare("dojox.geo.openlayers.TouchInteractionSupport", null, { + // summary: + // class to handle touch interactions on a OpenLayers.Map widget + // tags: + // private + + _map : null, + _centerTouchLocation : null, + _touchMoveListener : null, + _touchEndListener : null, + _initialFingerSpacing : null, + _initialScale : null, + _tapCount : null, + _tapThreshold : null, + _lastTap : null, + + constructor : function(/* OpenLayers.Map */map){ + // summary: + // Constructs a new TouchInteractionSupport instance + // map: OpenLayers.Map + // the Map widget this class provides touch navigation for. + this._map = map; + this._centerTouchLocation = new OpenLayers.LonLat(0, 0); + + var div = this._map.div; + + // install touch listeners + connect.connect(div, "touchstart", this, this._touchStartHandler); + connect.connect(div, "touchmove", this, this._touchMoveHandler); + connect.connect(div, "touchend", this, this._touchEndHandler); + + this._tapCount = 0; + this._lastTap = { + x : 0, + y : 0 + }; + this._tapThreshold = 100; // square distance in pixels + + }, + + _getTouchBarycenter : function(touchEvent){ + // summary: + // returns the midpoint of the two first fingers (or the first finger location if only one) + // touchEvent: Event + // a touch event + // returns: dojox.gfx.Point + // the midpoint + // tags: + // private + var touches = touchEvent.touches; + var firstTouch = touches[0]; + var secondTouch = null; + if (touches.length > 1) { + secondTouch = touches[1]; + } else { + secondTouch = touches[0]; + } + + var marginBox = html.marginBox(this._map.div); + + var middleX = (firstTouch.pageX + secondTouch.pageX) / 2.0 - marginBox.l; + var middleY = (firstTouch.pageY + secondTouch.pageY) / 2.0 - marginBox.t; + + return { + x : middleX, + y : middleY + }; + + }, + + _getFingerSpacing : function(touchEvent){ + // summary: + // computes the distance between the first two fingers + // touchEvent: Event + // a touch event + // returns: float + // a distance. -1 if less that 2 fingers + // tags: + // private + var touches = touchEvent.touches; + var spacing = -1; + if (touches.length >= 2) { + var dx = (touches[1].pageX - touches[0].pageX); + var dy = (touches[1].pageY - touches[0].pageY); + spacing = Math.sqrt(dx * dx + dy * dy); + } + return spacing; + }, + + _isDoubleTap : function(touchEvent){ + // summary: + // checks whether the specified touchStart event is a double tap + // (i.e. follows closely a previous touchStart at approximately the same location) + // touchEvent: Event + // a touch event + // returns: boolean + // true if this event is considered a double tap + // tags: + // private + var isDoubleTap = false; + var touches = touchEvent.touches; + if ((this._tapCount > 0) && touches.length == 1) { + // test distance from last tap + var dx = (touches[0].pageX - this._lastTap.x); + var dy = (touches[0].pageY - this._lastTap.y); + var distance = dx * dx + dy * dy; + if (distance < this._tapThreshold) { + isDoubleTap = true; + } else { + this._tapCount = 0; + } + } + this._tapCount++; + this._lastTap.x = touches[0].pageX; + this._lastTap.y = touches[0].pageY; + setTimeout(lang.hitch(this, function(){ + this._tapCount = 0; + }), 300); + + return isDoubleTap; + }, + + _doubleTapHandler : function(touchEvent){ + // summary: + // action performed on the map when a double tap was triggered + // touchEvent: Event + // a touch event + // tags: + // private + // perform a basic 2x zoom on touch + var touches = touchEvent.touches; + var marginBox = html.marginBox(this._map.div); + var offX = touches[0].pageX - marginBox.l; + var offY = touches[0].pageY - marginBox.t; + // clicked map point before zooming + var mapPoint = this._map.getLonLatFromPixel(new OpenLayers.Pixel(offX, offY)); + // zoom increment power + this._map.setCenter(new OpenLayers.LonLat(mapPoint.lon, mapPoint.lat), this._map.getZoom() + 1); + }, + + _touchStartHandler : function(touchEvent){ + // summary: + // action performed on the map when a touch start was triggered + // touchEvent: Event + // a touch event + // tags: + // private + event.stop(touchEvent); + + // test double tap + if (this._isDoubleTap(touchEvent)) { + this._doubleTapHandler(touchEvent); + return; + } + + // compute map midpoint between fingers + var middlePoint = this._getTouchBarycenter(touchEvent); + + this._centerTouchLocation = this._map.getLonLatFromPixel(new OpenLayers.Pixel(middlePoint.x, middlePoint.y)); + + // store initial finger spacing to compute zoom later + this._initialFingerSpacing = this._getFingerSpacing(touchEvent); + + // store initial map scale + this._initialScale = this._map.getScale(); + + // install touch move and up listeners (if not done by other fingers before) + if (!this._touchMoveListener) + this._touchMoveListener = connect.connect(window.global, "touchmove", this, this._touchMoveHandler); + if (!this._touchEndListener) + this._touchEndListener = connect.connect(window.global, "touchend", this, this._touchEndHandler); + + }, + + _touchEndHandler : function(touchEvent){ + // summary: + // action performed on the map when a touch end was triggered + // touchEvent: Event + // a touch event + // tags: + // private + event.stop(touchEvent); + + var touches = touchEvent.touches; + + if (touches.length == 0) { + // disconnect listeners only when all fingers are up + if (this._touchMoveListener) { + connect.disconnect(this._touchMoveListener); + this._touchMoveListener = null; + } + if (this._touchEndListener) { + connect.disconnect(this._touchEndListener); + this._touchEndListener = null; + } + } else { + // recompute touch center + var middlePoint = this._getTouchBarycenter(touchEvent); + + this._centerTouchLocation = this._map.getLonLatFromPixel(new OpenLayers.Pixel(middlePoint.x, middlePoint.y)); + } + }, + + _touchMoveHandler : function(touchEvent){ + // summary: + // action performed on the map when a touch move was triggered + // touchEvent: Event + // a touch event + // tags: + // private + + // prevent browser interaction + event.stop(touchEvent); + + var middlePoint = this._getTouchBarycenter(touchEvent); + + // compute map offset + var mapPoint = this._map.getLonLatFromPixel(new OpenLayers.Pixel(middlePoint.x, middlePoint.y)); + var mapOffsetLon = mapPoint.lon - this._centerTouchLocation.lon; + var mapOffsetLat = mapPoint.lat - this._centerTouchLocation.lat; + + // compute scale factor + var scaleFactor = 1; + var touches = touchEvent.touches; + if (touches.length >= 2) { + var fingerSpacing = this._getFingerSpacing(touchEvent); + scaleFactor = fingerSpacing / this._initialFingerSpacing; + // weird openlayer bug : setting several times the same scale value lead to visual zoom... + this._map.zoomToScale(this._initialScale / scaleFactor); + } + + // adjust map center on barycenter + var currentMapCenter = this._map.getCenter(); + this._map.setCenter(new OpenLayers.LonLat(currentMapCenter.lon - mapOffsetLon, currentMapCenter.lat + - mapOffsetLat)); + + } + }); +}); diff --git a/js/dojo/dojox/geo/openlayers/WidgetFeature.js b/js/dojo/dojox/geo/openlayers/WidgetFeature.js new file mode 100644 index 0000000..530fcd9 --- /dev/null +++ b/js/dojo/dojox/geo/openlayers/WidgetFeature.js @@ -0,0 +1,206 @@ +//>>built +define( + "dojox/geo/openlayers/WidgetFeature", ["dojo/_base/kernel", "dojo/_base/declare", "dojo/_base/html", "dojo/_base/lang", "dojox/geo/openlayers/Feature"], + function(dojo, declare, html, lang, Feature){ + /*===== + var Feature = dojox.geo.openlayers.Feature; + =====*/ + return declare("dojox.geo.openlayers.WidgetFeature", Feature, { + // summary: + // Wraps a Dojo widget, provide geolocalisation of the widget and interface + // to Layer class. + // description: + // This class allows to add a widget in a `dojox.geo.openlayers.Layer`. + // Parameters are passed to the constructor. These parameters describe the widget + // and provide geo-localisation of this widget. + // parameters can be: + // * _createWidget_: Function for widget creation. Must return a `dijit._Widget`. + // * _dojoType_: The class of a widget to create; + // * _dijitId_: The digitId of an existing widget. + // * _widget_: An already created widget. + // * _width_: The width of the widget. + // * _height_: The height of the widget. + // * _longitude_: The longitude, in decimal degrees where to place the widget. + // * _latitude_: The latitude, in decimal degrees where to place the widget. + // You must define a least one widget retrieval parameter and the geo-localization parameters. + _widget : null, + _bbox : null, + + constructor : function(params){ + // summary: + // Constructs a new `dojox.geo.openlayers.WidgetFeature` + // params: Object + // The parameters describing the widget. + this._params = params; + }, + + setParameters : function(params){ + // summary: + // Sets the parameters describing the widget. + // params: Object + // The parameters describing the widget. + this._params = params; + }, + + getParameters : function(){ + // summary: + // Retreives the parameters describing the widget. + // returns: Object + // The parameters describing the widget. + return this._params; + }, + + _getWidget : function(){ + // summary: + // Creates, if necessary the widget and returns it; + // tags: + // private + var params = this._params; + + if ((this._widget == null) && (params != null)) { + var w = null; + + if (typeof (params.createWidget) == "function") { + w = params.createWidget.call(this); + } else if (params.dojoType) { + dojo["require"](params.dojoType); + var c = lang.getObject(params.dojoType); + w = new c(params); + } else if (params.dijitId) { + w = dijit.byId(params.dijitId); + } else if (params.widget) { + w = params.widget; + } + + if (w != null) { + this._widget = w; + if (typeof (w.startup) == "function") + w.startup(); + var n = w.domNode; + if (n != null) + html.style(n, { + position : "absolute" + }); + } + this._widget = w; + } + return this._widget; + }, + + _getWidgetWidth : function(){ + // summary: + // gets the widget width + // tags: + // private + var p = this._params; + if (p.width) + return p.width; + var w = this._getWidget(); + if (w) + return html.style(w.domNode, "width"); + return 10; + }, + + _getWidgetHeight : function(){ + // summary: + // gets the widget height + // tags: + // private + var p = this._params; + if (p.height) + return p.height; + var w = this._getWidget(); + if (w) + return html.style(w.domNode, "height"); + return 10; + }, + + render : function(){ + // summary: + // renders the widget. + // descrption: + // Places the widget accordingly to longitude and latitude defined in parameters. + // This function is called when the center of the maps or zoom factor changes. + var layer = this.getLayer(); + + var widget = this._getWidget(); + if (widget == null) + return; + var params = this._params; + var lon = params.longitude; + var lat = params.latitude; + var from = this.getCoordinateSystem(); + var map = layer.getDojoMap(); + var p = map.transformXY(lon, lat, from); + var a = this._getLocalXY(p); + + var width = this._getWidgetWidth(); + var height = this._getWidgetHeight(); + + var x = a[0] - width / 2; + var y = a[1] - height / 2; + var dom = widget.domNode; + + var pa = layer.olLayer.div; + if (dom.parentNode != pa) { + if (dom.parentNode) + dom.parentNode.removeChild(dom); + pa.appendChild(dom); + } + this._updateWidgetPosition({ + x : x, + y : y, + width : width, + height : height + }); + }, + + _updateWidgetPosition : function(box){ + // summary: + // Places the widget with the computed x and y values + // tags: + // private + // var box = this._params; + + var w = this._widget; + var dom = w.domNode; + + html.style(dom, { + position : "absolute", + left : box.x + "px", + top : box.y + "px", + width : box.width + "px", + height : box.height + "px" + }); + + if (w.srcNodeRef) { + html.style(w.srcNodeRef, { + position : "absolute", + left : box.x + "px", + top : box.y + "px", + width : box.width + "px", + height : box.height + "px" + }); + } + + if (lang.isFunction(w.resize)) + w.resize({ + w : box.width, + h : box.height + }); + }, + + remove : function(){ + // summary: + // removes this feature. + // description: + // Remove this feature by disconnecting the widget from the dom. + var w = this.getWidget(); + if (!w) + return; + var dom = w.domNode; + if (dom.parentNode) + dom.parentNode.removeChild(dom); + } + }); + }); diff --git a/js/dojo/dojox/geo/openlayers/widget/Map.js b/js/dojo/dojox/geo/openlayers/widget/Map.js new file mode 100644 index 0000000..da29758 --- /dev/null +++ b/js/dojo/dojox/geo/openlayers/widget/Map.js @@ -0,0 +1,161 @@ +//>>built +define("dojox/geo/openlayers/widget/Map", ["dojo/_base/kernel", + "dojo/_base/declare", + "dojo/_base/array", + "dojo/_base/html", + "dojo/query", + "dijit/_Widget", + "dojox/geo/openlayers/Map", + "dojox/geo/openlayers/Layer", + "dojox/geo/openlayers/GfxLayer"], function(dojo, declare, array, html, query, Widget, Map, Layer, GfxLayer){ + /*===== + var Widget = dijit.Widget; + =====*/ + return declare("dojox.geo.openlayers.widget.Map", Widget, { + // summary: + // A widget version of the `dojox.geo.openlayers.Map` component. + // description: + // The `dojox.geo.openlayers.widget.Map` widget is the widget + // version of the `dojox.geo.openlayers.Map` component. + // With this widget, user can specify some attributes in the markup suach as + // + // * `baseLayerType`: The type of the base layer. Permitted values are + // * `initialLocation`: The initial location as for the dojox.geo.openlayers.Map.fitTo method + // * `touchHandler`: Tells if we attach touch handler or not. + // + // example: + // + // | <div id="map" dojoType="dojox.geo.openlayers.widget.Map" baseLayerType="Google" initialLocation="{ + // | position : [7.154126, 43.651748], + // | extent : 0.2 }" + // | style="background-color: #b5d0d0; width: 100%; height: 100%;"> + // + + // summay: + // Base layer type as defined in `dojox.geo.openlayer.BaseLayerType + // description: + // baseLayerType can be either + // * `OSM` + // * `WMS` + // * `Google` + // * `VirtualEarth` + // * `Yahoo` + // * `ArcGIS` + // baseLayerType : String + // Base layer type property. + baseLayerType : dojox.geo.openlayers.BaseLayerType.OSM, + + // summary: + // The part of the map shown at startup time. + // description: + // initial location is the string description of the location shown at + // startup time. Format is the same as for the `dojox.geo.openlayers.widget.Map.fitTo` + // method. + // | { + // | bounds : [ulx, uly, lrx, lry] + // | } + // The map is fit on the specified bounds expressed as decimal degrees latitude and longitude. + // The bounds are defined with their upper left and lower right corners coordinates. + // + // | { + // | position : [longitude, latitude], + // | extent : degrees + // | } + // The map is fit on the specified position showing the extent <extent> around + // the specified center position. + initialLocation : null, + + // summary: + // Tells if the touch handler should be attached to the map or not. + // description: + // Tells if the touch handler should be attached to the map or not. + // Touch handler handles touch events so that the widget can be used + // on mobile applications. + touchHandler : false, + + // summary: + // The underlying `dojox.geo.openlayers.Map` object. + // This is s readonly member. + map : null, + + startup : function(){ + // summary: + // Processing after the DOM fragment is added to the document + this.inherited(arguments); + this.map.initialFit({ + initialLocation : this.initialLocation + }); + }, + + buildRendering : function(){ + // summary: + // Construct the UI for this widget, creates the real dojox.geo.openlayers.Map object. + // tags: + // protected + this.inherited(arguments); + var div = this.domNode; + var map = new Map(div, { + baseLayerType : this.baseLayerType, + touchHandler : this.touchHandler + }); + this.map = map; + + this._makeLayers(); + }, + + _makeLayers : function(){ + // summary: + // Creates layers defined as markup. + // tags: + // private + var n = this.domNode; + var layers = /* ?? query. */query("> .layer", n); + array.forEach(layers, function(l){ + var type = l.getAttribute("type"); + var name = l.getAttribute("name"); + var cls = "dojox.geo.openlayers." + type; + var p = dojo.getObject(cls); + if (p) { + var layer = new p(name, {}); + if (layer) + this.map.addLayer(layer); + } + }, this); + }, + + resize : function(b){ + // summary: + // Resize the widget. + // description: + // Resize the domNode and the widget to the dimensions of a box of the following form: + // `{ l: 50, t: 200, w: 300: h: 150 }` + // b: undefined | Box | width, height + // If passed, denotes the new size of the widget. + // Can be either nothing (widget adapts to the div), + // a box, or a width and a height. + + var olm = this.map.getOLMap(); + + var box; + switch (arguments.length) { + case 0: + // case 0, do not resize the div, just the surface + break; + case 1: + // argument, override node box + box = dojo.mixin({}, b); + dojo.marginBox(olm.div, box); + break; + case 2: + // two argument, width, height + box = { + w : arguments[0], + h : arguments[1] + }; + dojo.marginBox(olm.div, box); + break; + } + olm.updateSize(); + } + }); +}); |
