/* =========================================== generic tool for polygon drawing over google maps map =========================================== */ if (typeof(google) !== 'undefined') { function MarkerGMaps() { var opts = arguments[0] if(opts.position) { opts.position = new google.maps.LatLng(opts.position[0], opts.position[1]); } google.maps.Marker.apply(this, arguments); } _.extend(MarkerGMaps.prototype, google.maps.Marker.prototype, { bind: function(ev, callback) { google.maps.event.addListener(this, ev, function(e) { e._latlng = [e.latLng.lat(), e.latLng.lng()]; callback(e) }); }, geojson: function() { return cdb.geo.gmaps.PathView.getGeoJSON(this, 'Point'); } } ); function PolygonGMaps() { google.maps.Polygon.apply(this, arguments); } var gmapsPolyPrototype = { bind: function(ev, callback) { google.maps.event.addListener(this, ev, function(e) { e._latlng = [e.latlng.lat, e.latlng.lng]; callback(e) }); }, setPath: function(points) { google.maps.Polygon.prototype.setPath.call(this, _(points).map(function(p) { return new google.maps.LatLng(p[0], p[1]); }) ); }, setVertex: function(index, latlng) { this.getPath().setAt(index, new google.maps.LatLng(latlng[0], latlng[1])); } } _.extend(PolygonGMaps.prototype, google.maps.Polygon.prototype, gmapsPolyPrototype, { geojson: function() { return cdb.geo.gmaps.PathView.getGeoJSON(this, 'MultiPolygon'); } } ); function PolylineGMaps() { google.maps.Polyline.apply(this, arguments); } _.extend(PolylineGMaps.prototype, google.maps.Polyline.prototype, gmapsPolyPrototype, { geojson: function() { return cdb.geo.gmaps.PathView.getGeoJSON(this, 'MultiLineString'); } } ); } var MarkerLeaflet = L.Marker.extend({ initialize: function(opts) { if(opts.icon) { opts.icon = L.icon({ iconUrl: opts.icon.url, iconAnchor: [opts.icon.anchor.x, opts.icon.anchor.y] }) } if(opts.position) { opts.position = new L.LatLng(opts.position[0], opts.position[1]); } var args = [opts.position].concat(Array.prototype.slice.call(arguments)); L.Marker.prototype.initialize.apply(this, args); var opts = arguments[0] || {} if(opts.map) { this.map = opts.map; this.addTo(opts.map); } }, bind: function(ev, callback) { var self = this; this.on(ev, function(e) { e._latlng = [self.getLatLng().lat, self.getLatLng().lng]; callback(e); }); }, setMap: function(map) { if(map) { this.addTo(map); } else { this.map.removeLayer(this); } }, geojson: function() { return this.toGeoJSON().geometry; } }); /** polygon and polyline shares prototype */ var PathPrototype = { initialize: function() { this._parent.prototype.initialize.apply(this, arguments); var opts = arguments[0] || {} if(opts.map) { this.map = opts.map; this.addTo(opts.map); } opts.stroke = opts.strokeOpacity > 0; opts.color = opts.strokeColor; opts.fill = opts.fillOpacity > 0; opts.weight = opts.strokeWeight; opts.opacity = opts.strokeOpacity; this.setStyle(opts); }, bind: function(ev, callback) { this.on(ev, function(e) { e.latLng = e.latlng; callback(e); }); }, setVertex: function(index, latlng) { var ll = this.getLatLngs(); ll[index] = new L.LatLng(latlng[0], latlng[1]); this.setLatLngs(ll); }, setPath: function(points) { var ll = _(points).map(function(p) { return new L.LatLng(p[0], p[1]); }); this.setLatLngs(ll); }, setMap: function(map) { if(map) { this.addTo(map); } else { this.map.removeLayer(this); } } }; var PolygonLeaflet = L.Polygon.extend(PathPrototype).extend({ _parent: L.Polygon, geojson: function() { // transform to multipolygon var geo = this.toGeoJSON().geometry; return { type: 'MultiPolygon', coordinates: [geo.coordinates] }; } }); var PolylineLeaflet = L.Polyline.extend(PathPrototype).extend({ _parent: L.Polyline, geojson: function() { // transform to multipolygon var geo = this.toGeoJSON().geometry; return { type: 'MultiLineString', coordinates: [geo.coordinates] }; } }); var BaseDrawTool = cdb.core.View.extend({ image: { url: cdb.config.get('assets_url') + '/images/layout/edit_marker_icon.png', anchor: {x: 5, y: 5} }, _setObjects: function() { if(this.mapview.map.get('provider') == 'googlemaps') { this.Marker = MarkerGMaps; this.Polygon = PolygonGMaps; this.Polyline = PolylineGMaps; } else { this.Marker = MarkerLeaflet; this.Polygon = PolygonLeaflet; this.Polyline = PolylineLeaflet; } } }); var PointDrawTool = BaseDrawTool.extend({ image: { url: cdb.config.get('assets_url') + '/images/layout/default_marker.png', anchor: {x: 11, y: 11} }, initialize: function() { this.mapview = this.options.mapview; this.map = this.mapview.getNativeMap(); this.marker = null; this._setObjects(); }, canFinish: function() { return this.marker != null; }, start: function() { this.mapview.bind('click', function(e, latlng) { this.marker = new this.Marker({ position: latlng, map: this.map, icon: this.image, draggable: true, flat : true, raiseOnDrag: false }); this.mapview.unbind('click', null, this); }, this); }, clean: function() { this.marker && this.marker.setMap(null); this.mapview.unbind('click', null, this); }, getGeoJSON: function() { return this.marker.geojson(); } }); var PolygonDrawTool = BaseDrawTool.extend({ initialize: function() { _.bindAll(this, 'add_vertex', '_add_vertex'); this.mapview = this.options.mapview; this.map = this.mapview.getNativeMap(); this._setObjects(); this.reset(); }, canFinish: function() { return this.vertex.length >= 3; }, start: function() { this.mapview.unbind('click', this.add_vertex); this.mapview.bind('click', this.add_vertex); this.reset(); }, reset: function() { var self = this; if(this.feature !== undefined) { this.feature.setMap(null); delete this.feature; } if(this.markers !== undefined) { _.each(this.markers, function(m) { m.setMap(null); }); } this.markers = []; this.vertex = []; this.createOverlays(); }, createOverlays: function() { this.feature = new this.Polygon({ path:[], fillColor: "white", fillOpacity: 0.4, strokeOpacity: 1.0, strokeColor: '#397DBA', strokeWeight: 4, clickable: false, map: this.map }); }, clean: function() { this.reset(); this.mapview.unbind('click', this.add_vertex); this.feature.setMap(null); delete this.feature; }, _add_vertex: function(latLng) { var marker = new this.Marker({ position: latLng, map: this.map, icon: this.image, draggable: true, flat : true, raiseOnDrag: false }); marker.index = this.vertex.length; this.markers.push(marker); this.vertex.push(latLng); this.feature.setPath(this.vertex); return marker; }, add_vertex: function(e, latLng) { var marker = this._add_vertex(latLng); marker.bind("drag", function(e) { self.mapview.unbind('click', self.add_vertex); self.vertex[marker.index] = e._latlng; self.feature.setVertex(marker.index, e._latlng); }); marker.bind("dragend", function(e) { self.feature.setVertex(marker.index, e._latlng); self.vertex[marker.index] = e._latlng; _.defer(function() { self.mapview.bind('click', self.add_vertex); }); }); var self = this; }, getGeoJSON: function() { return this.feature.geojson(); } }); var PolylineDrawTool = PolygonDrawTool.extend({ createOverlays: function() { // not shown this.feature = new this.Polyline({ path:[], strokeOpacity: 1.0, strokeColor: '#397DBA', strokeWeight: 4, fillOpacity: 0.0, clickable: false, map: this.map }); }, canFinish: function() { return this.vertex.length >= 2; }, });