define("dojox/geo/openlayers/GeometryFeature", [ "dojo/_base/declare", "dojo/_base/array", "dojo/_base/lang", "dojox/gfx/matrix", "./Point", "./LineString", "./Collection", "./Feature" ], function(declare, array, lang, matrix, Point, LineString, Collection, 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(geometry){ // summary: // Constructs a GeometryFeature for the specified geometry. // geometry: dojox/geo/openlayers/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(g){ // summary: // Renders a geometry collection. // g: 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(g){ // summary: // Render a geometry. // Called by the Layer on which the feature is added. // g: 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(s){ // summary: // Sets the shape properties. // s: Object // The shape properties to set. this._shapeProperties = s; return this; }, createShape: function(s, 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: // 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: // Returns the shape rendering the geometry // returns: // 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; // dojox.gfx.shape.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(g){ // summary: // Renders a point geometry. // g: dojox/geo/openlayers/Point? // The geometry to render, or the current instance geometry if not specified. 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(g){ // summary: // Renders a line string geometry. // g: 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(g){ // summary: // Apply the style on the geometry's shape. // g: 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(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: // Returns the stroke style // returns: // The stroke style return this._stroke; }, setFill: function(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: // Returns the fill style // returns: // 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 } }); });