SafeNet/SDMaps/src/SfmbMapsOL.js

922 lines
22 KiB
JavaScript

function SfmbMapsOL(opts) {
var divObject = opts.divObject,
polyPointCallback = opts.polyPointCallback,
getPolygonCallback = opts.getPolygonCallback,
landmarkCallback = opts.landmarkCallback;
var map;
//never used yet
var datasets = new Object();
// global polygon name used between [get/delete/new]polygon functions
var polygonName;
var selectedMarker;
// transform from WGS 1984 (map's projection)
var fromProjection = new OpenLayers.Projection("EPSG:4326");
// to Spherical Mercator Projection ("normal" projection)
var toProjection = new OpenLayers.Projection("EPSG:900913");
// instantiate the map
this.div = divObject;
var osm = new OpenLayers.Layer.OSM();
map = new OpenLayers.Map({
div: divObject,
// this is if you want to get the tiles from your own server
/*layers: [new OpenLayers.Layer.OSM( "OpenStreetMap",
'http://10.120.1.136/osm_tiles/${z}/${x}/${y}.png')],
*/
layers: [
osm
],
controls: [
new OpenLayers.Control.Navigation({
dragPanOptions: {
enableKinetic: false, // because the effect if not good,
documentDrag: true
}
}),
new OpenLayers.Control.ScaleLine(),
new OpenLayers.Control.PanZoomBar()
],
center:[0, 0],
zoom: 1
});
map.div.oncontextmenu = function noContextMenu(e) {
// use this if you want to handle context menu when is
// triggered by right click
/*
if (OpenLayers.Event.isRightClick(e)){
// do something
}
*/
return false; //cancel the right click of brower
};
map.events.register('click', map, handleMapClick);
function handleMapClick(e)
{
if (geocodePopup != null) {
geocodePopup.destroy();
geocodePopup = null;
}
var lonlat = map.getLonLatFromViewPortPx(e.xy)
.transform(toProjection, fromProjection);
if (landmarkCallback) {
landmarkCallback({latitude:lonlat.lat, longitude:lonlat.lon});
}
// use lonlat
// If you are using OpenStreetMap (etc) tiles and want to convert back
// to gps coords add the following line :-
// lonlat.transform( map.projection,map.displayProjection);
// Longitude = lonlat.lon
// Latitude = lonlat.lat
}
// choose renderers
// and allow testing of specific renderers via "?renderer=Canvas", etc
var renderer = OpenLayers.Util.getParameters(window.location.href).renderer;
renderer = (renderer)
? [renderer]
: OpenLayers.Layer.Vector.prototype.renderers;
// polyline's layer
var polysLayer = new OpenLayers.Layer.Vector("Poly");
// polygon's layer
var polygonsLayer = new OpenLayers.Layer.Vector("Polygon");
// marker's layer
// we can use OpenLayers.Markers but is old and it is still in the lib
// because of backwards compatibility.
var markersLayer = new OpenLayers.Layer.Vector("Markers", {
styleMap: new OpenLayers.StyleMap({'default':{
strokeColor: "#00FF00",
strokeOpacity: 1,
strokeWidth: 3,
fill:true,
fillColor: "yellow",
fillOpacity: 1,
pointRadius: 1,
// label with \n linebreaks
label : "${name}",
labelOutlineColor: "yellow",
BackgroundColor: "yellow",
externalGraphic: "images/${icon}",
graphicWidth:30,
graphicHeight:30,
graphicOpacity:1,
graphicXOffset:-12,
graphicYOffset:-20,
fontColor: "${favColor}",
fontSize: "12px",
fontFamily: "Courier New, monospace",
fontWeight: "bold",
labelAlign: "${align}",
labelXOffset: "0",
labelYOffset: "22",
labelOutlineWidth: 4
}}),
renderers: renderer
});
// add the three layers to the map
map.addLayer(markersLayer);
map.addLayer(polygonsLayer);
map.addLayer(polysLayer);
// control for popup
var selectFeature = new OpenLayers.Control.SelectFeature(
markersLayer,
{ onSelect: createPopup, onUnselect: destroyPopup });
function createPopup(feature) {
selectedMarker = feature.attributes.id;
var FramedCloudCustomized = OpenLayers
.Class(OpenLayers.Popup.FramedCloud, {
displayClass: "olScrollable olPopup",
registerEvents:function() {
this.events = new OpenLayers.Events(this);
}
});
feature.popup = new FramedCloudCustomized("pop",
feature.geometry.getBounds().getCenterLonLat(),
null,
'<div>'+feature.attributes.description+'</div>',
null,
true,
function() { controls['selector'].unselectAll(); }
)
map.addPopup(feature.popup);
}
function destroyPopup(feature) {
selectedMarker = null;
feature.popup.destroy();
feature.popup = null;
}
// new polygon drawing control
var drawFeature = new OpenLayers.Control.DrawFeature(
polygonsLayer,
OpenLayers.Handler.Polygon);
drawFeature.handler.move = emptyMove; // disable animation on drawing
function emptyMove(evt) {
}
drawFeature.handler.dblclick = null; // disable ending with dbl click
// callback after every new point added
drawFeature.handler.callbacks.point = getPolygonToCallback;
function getPolygonToCallback(evt) {
var vertices = drawFeature.handler.getGeometry().getVertices();
return getPointsOfFeatureVertices(vertices);
}
// control for editing polygons
var modifyFeature = new OpenLayers.Control.ModifyFeature(polygonsLayer);
// callback after every polygon point edited
polygonsLayer.events.on({
'featuremodified': function(evt) {
var vertices = evt.feature.geometry.getVertices();
return getPointsOfFeatureVertices(vertices);
}
});
// get the points when add/edit polygon points
function getPointsOfFeatureVertices(vertices) {
var points = [];
for (var i = 0; i < vertices.length; i++) {
var p = new OpenLayers.LonLat(vertices[i].x, vertices[i].y)
.transform(toProjection, fromProjection);
points.push({latitude: p.lat, longitude: p.lon});
}
points = removeDuplicates(points);
points = adjust(points);
if (polyPointCallback) {
polyPointCallback(points);
}
return points; // [{latitude, longitude}...]
}
// group the controls
var controls = {
selector: selectFeature,
polygon: drawFeature,
modify: modifyFeature,
line: new OpenLayers.Control.DrawFeature(polysLayer,
OpenLayers.Handler.Path),
};
// add some atributes: rotation on edit, create new vertices on editing and
// edit only one polygon at a time
controls.modify.mode |= OpenLayers.Control.ModifyFeature.ROTATE;
controls.modify.createVertices = true;
controls.modify.standalone = true;
controls.modify.clickout = false;
// add controls to map
for(var key in controls) {
map.addControl(controls[key]);
}
controls['selector'].activate();
/*
Resize the map to specified position;
*/
SfmbMapsOL.prototype.resize = function(height, width) {
this.div.style.height = height + 'px';
this.div.style.width = width + 'px';
map.updateSize();
}
/*
Put the markers on map
@params
pointsArray: [{id, latitude, longitude, icon, description}...]
setAutozoom: boolean
*/
SfmbMapsOL.prototype.putPoints = function(pointsArray, setAutozoom) {
if (pointsArray.length == 0) {
return;
}
var unselectMarker = undefined;
var bounds = new OpenLayers.Bounds();
for (var i = 0; i < pointsArray.length; i++) {
var oldPoint = markersLayer.getFeaturesByAttribute(
"id",
pointsArray[i].id);
// test if the marker already exists
if (pointsArray[i].id != "" && oldPoint[0] != null
&& oldPoint[0].attributes.lon == pointsArray[i].longitude
&& oldPoint[0].attributes.lat == pointsArray[i].latitude) {
bounds.extend(oldPoint[0].geometry.getBounds());
// leave the point in peace
} else {
// remove the marker
if (oldPoint[0] != null && pointsArray[i].id != "") {
if (pointsArray[i].id == selectedMarker) {
unselectMarker = pointsArray[i].id;
}
this.removePoint(pointsArray[i]); // remove the old point
}
// create marker
var p = pointsArray[i];
var position = new OpenLayers.LonLat(p.longitude, p.latitude)
.transform( fromProjection, toProjection);
var point = new OpenLayers.Geometry.Point(
position.lon,
position.lat);
var pointFeature = new OpenLayers.Feature.Vector(point);
pointFeature.attributes = {
id:p.id ,
name: p.id,
favColor: 'black',
align: "cm",
icon: p.icon ? p.icon : "transparent.png",
description: p.description,
lat:p.latitude,
lon:p.longitude
};
markersLayer.addFeatures([pointFeature]);
bounds.extend(pointFeature.geometry.getBounds());
if (pointsArray[i].id == "") {
markersLayer.destroyFeatures([pointFeature]);
}
}
}
if (unselectMarker) {
this.openInfoBubble(unselectMarker)
unselectMarker = false;
}
if (setAutozoom) {
autozoom(bounds);
}
}
/*
Removes all markers
*/
SfmbMapsOL.prototype.removeAllPoints = function() {
selectFeature.unselectAll();
selectFeature.deactivate();
removeAllItems(markersLayer);
selectFeature.activate();
}
/*
Remove marker
@params
point: {id, latitude, longitude, color, description}
Obs: only the id is needed
*/
SfmbMapsOL.prototype.removePoint = function(point) {
var p = markersLayer.getFeaturesByAttribute("id", point.id);
if (p[0] != null) {
if (p[0].popup != null) {
selectFeature.unselect(p[0]);
}
selectFeature.deactivate();
markersLayer.destroyFeatures([p[0]]);
selectFeature.activate();
}
}
/*
Remove points from map
@params
points: [{id, latitude, longitude, color, description}...]
*/
SfmbMapsOL.prototype.removePoints = function(points) {
if (!points) {
return;
}
for (var i = 0; i < points.length; i++) {
this.removePoint(points[i]);
}
}
//to be used with polygons and polylines and markers
function removeItem(collection, itemId){
var p = collection.getFeaturesByAttribute("name", itemId);
if (p[0] != null) {
collection.destroyFeatures([p[0]]);
}
}
//removes all items from collection safely (calls removeItem on each item)
function removeAllItems(collection){
collection.destroyFeatures();
}
function autozoom(bounds) {
map.zoomToExtent(bounds);
}
SfmbMapsOL.prototype.showLabels = function() {
markersLayer.styleMap.styles.default.defaultStyle.label = "${name}";
markersLayer.redraw();
}
SfmbMapsOL.prototype.hideLabels = function() {
markersLayer.styleMap.styles.default.defaultStyle.label = '';
markersLayer.redraw();
}
/*
@params
points: [{id, latitude, longitude, color, description}...]
*/
SfmbMapsOL.prototype.putLabels = function(points) {
changeLabels(points, "${name}");
}
/*
@params
points: [{id, latitude, longitude, color, description}...]
*/
SfmbMapsOL.prototype.removeLabels = function(points) {
changeLabels(points, "");
}
// Add/remove labels of points markers
function changeLabels(points, add) {
for (var i = 0; i < points.length; i++) {
var p = markersLayer.getFeaturesByAttribute("id", points[i].id);
if (!p[0]) {
continue;
}
p[0].attributes.name = add ? p[0].attributes.id : "";
}
markersLayer.redraw();
}
/*
@params:
lat: latitude - double
lon: longitude - double
zoom: int
*/
SfmbMapsOL.prototype.centerZoom = function(lat, lon, zoom) {
var center = new OpenLayers.LonLat(lon, lat)
.transform( fromProjection, toProjection);
map.panTo(center);
map.zoomTo(zoom);
markersLayer.redraw();
polygonsLayer.redraw();
polysLayer.redraw();
}
/*
@params
mapType: string
*/
SfmbMapsOL.prototype.setMapType = function(mapType) {
// TODO Change layer: maybe Google Maps
}
SfmbMapsOL.prototype.getMapType = function() {
// TODO Change layer: maybe Google Maps
return 'OSM';
}
/*
@params
markerName: string
*/
SfmbMapsOL.prototype.openInfoBubble = function(markerName) {
var p = markersLayer.getFeaturesByAttribute("id", markerName);
//createPopup(p[0]);
selectFeature.unselectAll();
selectFeature.select(p[0]);
}
/*
Add a polygon to map
@params
name: string
color: string
points: [{latitude, longitude}...]
*/
SfmbMapsOL.prototype.setPolygon = function(name, color, points) {
var sitePoints = [];
// create style
var polygonStyle = {
fillColor:color,
fillOpacity:0.4,
strokeColor:color,
strokeOpacity:0.9,
strokeWidth:0.8
};
// group points
for (var i in points) {
var coord = points[i];
var point = new OpenLayers.Geometry.Point(
coord.longitude,
coord.latitude);
// transform from WGS 1984 to Spherical Mercator
point.transform(fromProjection, toProjection);
sitePoints.push(point);
}
sitePoints.push(sitePoints[0]);
var linearRing = new OpenLayers.Geometry.LinearRing(sitePoints);
var geometry = new OpenLayers.Geometry.Polygon([linearRing]);
var polygonFeature = new OpenLayers.Feature.Vector(
geometry,
null,
polygonStyle);
// attributes for keeping name and color in the polygon
polygonFeature.attributes = {
name:name,
color:color
}
polygonsLayer.addFeatures([polygonFeature]);
}
/*
name is optional. If name == null -> remove all
@params
name: string
*/
SfmbMapsOL.prototype.deletePolygon = function(name) {
// if polygon is in newPolygon adding mode
if (controls['polygon'].active
&& (name == polygonName || name == undefined)) {
drawFeature.handler.cancel();
controls['polygon'].deactivate();
return;
}
// maybe the polygon is in editing mode
controls['modify'].deactivate();
if (name) {
removeItem(polygonsLayer, name);
} else {
removeAllItems(polygonsLayer);
}
}
SfmbMapsOL.prototype.deleteAllPolygons = function() {
this.deletePolygon();
}
/*
Add polyline on map
@params
setAutozoom: bool
color: string
thickness: double between 0 and 1
points: [{latitude, longitude}...]
name: poly name
*/
SfmbMapsOL.prototype.setPoly = function(setAutozoom,
color,
thickness,
points, name) {
var nameAttr = "default";
if (name) {
nameAttr = name;
}
var sitePoints = [];
var polyStyle = {
strokeColor:color,
strokeOpacity:thickness,
strokeWidth:5
};
for (var i in points) {
var coord = points[i];
var point = new OpenLayers.Geometry.Point(
coord.longitude,
coord.latitude);
// transform from WGS 1984 to Spherical Mercator
point.transform(fromProjection, toProjection);
sitePoints.push(point);
}
var linearRing = new OpenLayers.Geometry.LineString(sitePoints);
//var geometry = new OpenLayers.Geometry.Polygon([linearRing]);
var polyFeature = new OpenLayers.Feature.Vector(
linearRing,
null,
polyStyle);
polyFeature.attributes = {
name:nameAttr
}
polysLayer.addFeatures([polyFeature]);
}
/*
remove all polys
@params
name: string
*/
SfmbMapsOL.prototype.deletePoly = function(name) {
if (name) {
removeItem(polysLayer, name);
} else {
removeAllItems(polysLayer);
}
}
/*
Begin adding new polygon on the map
Color is optional
@params
name: string
color:string
*/
SfmbMapsOL.prototype.newPolygon = function(name, color) {
if (!color) {
color = blue;
}
polygonName = name;
setStyle(color)
setTempStyle(color);
controls['polygon'].activate();
}
/*
Get the polygon info
name is optional. If name == null -> remove all
@params
name: string
@return:
*/
SfmbMapsOL.prototype.getPolygon = function(name) {
var polygonArray = [];
if (controls['polygon'].active && polygonName == name) {
polygonArray = { name:name,
color: polygonsLayer
.styleMap
.styles
.default
.defaultStyle
.fillColor,
points: getPolygonLatLongFromGeomString(
controls['polygon'].handler.getGeometry())};
} else {
if (name) {
var p = polygonsLayer.getFeaturesByAttribute("name", name);
if (p[0]) {
polygonArray = { name:name,
color: p[0].attributes.color,
points: getPolygonLatLongString(p[0])};
}
} else {
for (i = 0; i < polygonsLayer.features.length; i++) {
f = polygonsLayer.features[i];
polygonArray.push({ name: f.attributes.name,
color:f.attributes.color,
points:getPolygonLatLongString(f)});
}
}
}
console.log(JSON.stringify(polygonArray));
if (getPolygonCallback) {
getPolygonCallback(polygonArray);
}
return polygonArray; //[{name, color, [{latitude, longitude}...]}...]
}
function getPolygonLatLongFromGeomString(geometry) {
var pointsArray = [];
if (!geometry) {
return pointsArray;
}
var points = geometry.components[0].components;
for (var i = 0; i < points.length; i++) {
var p = new OpenLayers.LonLat(points[i].x, points[i].y)
.transform(toProjection, fromProjection);
pointsArray.push({latitude: p.lat, longitude: p.lon});
}
// [{latitude, longitude}...]
return adjust(removeDuplicates(pointsArray));
}
function removeDuplicates(array) {
return array.reduce(function(a,c) {
var dup = _(a).find(function(e){
return e.latitude === c.latitude && e.longitude === c.longitude
});
if (!dup) a.push(c);
return a;
},[]);
}
function adjust(array) {
return array.reduce(function(a, c) {
if (c.longitude < -180 || c.longitude > 180) {
var newLat = 360 - Math.abs(c.longitude);
if (c.longitude >= 0) {
newLat = -newLat;
}
c.longitude = newLat;
}
a.push(c);
return a;
}, []);
}
// get points array
function getPolygonLatLongString(polygon) {
// [{latitude, longitude}...]
return getPolygonLatLongFromGeomString(polygon.geometry);
}
/*
@params:
name: string
*/
SfmbMapsOL.prototype.startEditPolygon = function(name) {
var p = polygonsLayer.getFeaturesByAttribute("name", name);
if (p[0]) {
setTempStyle(p[0].attributes.color);
setStyle(p[0].attributes.color)
controls['modify'].virtualStyle.fillColor = p[0]
.attributes.color;
controls['modify'].virtualStyle.strokeColor = p[0]
.attributes.color;
controls['modify'].activate();
controls['modify'].selectFeature(p[0]);
}
}
function setStyle(color) {
polygonsLayer.styleMap.styles.default.defaultStyle.fillColor=color;
polygonsLayer.styleMap.styles.default.defaultStyle.fillOpacity=0.4;
polygonsLayer.styleMap.styles.default.defaultStyle.strokeColor=color;
polygonsLayer.styleMap.styles.default.defaultStyle.strokeOpacity=0.9;
polygonsLayer.styleMap.styles.default.defaultStyle.strokeWidth=0.8;
}
function setTempStyle(color) {
polygonsLayer.styleMap.styles.temporary.defaultStyle.fillColor=color;
polygonsLayer.styleMap.styles.temporary.defaultStyle.fillOpacity=0.4;
polygonsLayer.styleMap.styles.temporary.defaultStyle.strokeColor=color;
polygonsLayer.styleMap.styles.temporary.defaultStyle.strokeOpacity=0.9;
polygonsLayer.styleMap.styles.temporary.defaultStyle.strokeWidth=0.8;
}
SfmbMapsOL.prototype.endEditPolygon = function() {
// if in add new polygon mode
if (controls['polygon'].active) {
drawFeature.handler.finishGeometry();
//set attributes for keeping the polygon info
polygonsLayer.features[polygonsLayer.features.length - 1]
.attributes.name = polygonName;
polygonsLayer.features[polygonsLayer.features.length - 1]
.attributes.color = polygonsLayer
.styleMap
.styles
.default
.defaultStyle
.fillColor;
controls['polygon'].deactivate();
}
controls['modify'].deactivate();
}
/*
Clear the items from map
@params
markers: [{id, latitude, longitude, color, description}...]
polygons: [[name, color, {latitude, longitude}...]...]
polys: [[{latitude, longitude}...]...]
*/
SfmbMapsOL.prototype.clearFromMap = function(markers, polygons, polys) {
// NOT USED
}
/*
Clear all from map
*/
SfmbMapsOL.prototype.resetAll = function() {
this.removeAllPoints();
this.deletePolygon();
this.deletePoly();
}
/*
@params
name: string
color: string
*/
SfmbMapsOL.prototype.changePolygonColor = function(name, color) {
var p = polygonsLayer.getFeaturesByAttribute("name", name);
if (p[0]) {
p[0].style.fillColor = color;
p[0].style.strokeColor = color;
p[0].attributes.color = color;
setStyle(color)
setTempStyle(color);
controls['modify'].virtualStyle.fillColor = color;
controls['modify'].virtualStyle.strokeColor = color;
controls['modify'].selectFeature(p[0]);
}
}
/*
Geocoding
*/
SfmbMapsOL.prototype.geocode = function(address){
var query =
"http://open.mapquestapi.com/nominatim/v1/search.php?format=json&q="
+ address
+ "&limit=1";
var self = this;
$.post(query,function(data,status){
if (status == "success") {
if (data != "[]") {
self.openSimplePopup(data[0]);
}
}
//alert("Data: " + data + "\nStatus: " + status);
});
}
var geocodePopup;
SfmbMapsOL.prototype.openSimplePopup = function(place){
if (geocodePopup != null) {
geocodePopup.destroy(); geocodePopup = null;
}
var FramedCloudCustomized = OpenLayers
.Class(OpenLayers.Popup.FramedCloud, {
displayClass: "olScrollable olPopup",
registerEvents:function() {
this.events = new OpenLayers.Events(this);
}
});
var position = new OpenLayers.LonLat(place.lon, place.lat)
.transform( fromProjection, toProjection);
geocodePopup = new FramedCloudCustomized("simple_pop",
position,
null,
'<div>'+place.display_name+'</div>',
null,
true,
function() { geocodePopup.destroy(); geocodePopup = null; }
)
map.addPopup(geocodePopup);
map.panTo(position);
//map.zoomTo(13);
}
SfmbMapsOL.prototype.setMapKind = function() {
// TODO
}
SfmbMapsOL.prototype.getMapKind = function() {
return "OSM";
}
}
var SfmbMaps = SfmbMapsOL;