// ==UserScript==
// @name WME Geometries
// @version 1.1
// @description Import geometry files into Waze Map Editor. Supports GeoJSON, GML, WKT, KML and GPX.
// @include https://*.waze.com/editor/*
// @include https://*.waze.com/*/editor/*
// @exclude https://*.waze.com/user/editor/*
// @exclude https://*.waze.com/*/user/editor/*
// @grant none
// @author Timbones
// @contributor wlodek76
// @namespace https://greasyfork.org/users/3339
// @downloadURL none
// ==/UserScript==
/*
Blah Blah Blah
*/
(function()
{
// maximum number of features that will be shown with labels
var maxlabels = 2500;
// show labels using first attribute that starts or ends with 'name' (case insensitive regexp)
var labelname = /^name|name$/;
// each loaded file will be rendered with one of these colours in ascending order
var colorlist = [ "navy", "purple", "darkgreen", "darkred", "teal", "darkslategray" ];
// -------------------------------------------------------------
var geolist;
var formathelp = 'GeoJSON, WKT';
var formats = { 'GEOJSON':new OpenLayers.Format.GeoJSON(),
'WKT':new OpenLayers.Format.WKT() };
patchOpenLayers(); // patch adds KML, GPX and TXT formats
var EPSG_4326 = new OpenLayers.Projection("EPSG:4326"); // lat,lon
var EPSG_4269 = new OpenLayers.Projection("EPSG:4269"); // NAD 83
var EPSG_3857 = new OpenLayers.Projection("EPSG:3857"); // WGS 84
var layerindex = 0;
// delayed initialisation
setTimeout(init, 654);
Waze.loginManager.events.register("login", null, init);
// add interface to Settings tab
function init()
{
var geobox = document.createElement('div');
geobox.style.paddingTop = '6px';
$("#sidepanel-areas").append(geobox);
var geotitle = document.createElement('h4');
geotitle.innerHTML = 'Import Geometry File';
geobox.appendChild(geotitle);
geolist = document.createElement('ul');
geobox.appendChild(geolist);
var geoform = document.createElement('form');
geobox.appendChild(geoform);
var inputfile = document.createElement('input');
inputfile.type = 'file';
inputfile.id = 'GeometryFile';
inputfile.title = '.geojson, .gml or .wkt';
inputfile.addEventListener('change', addGeometryLayer, false);
geoform.appendChild(inputfile);
var notes = document.createElement('p');
notes.innerHTML = 'Formats: ' + formathelp + '
'
+ 'Coordinates: EPSG:4326, EPSG:3857';
geoform.appendChild(notes);
var inputadd = document.createElement('input');
inputadd.type = 'button';
inputadd.value = 'Clear All';
inputadd.onclick = removeGeometryLayers;
geoform.appendChild(inputadd);
console.log("WME Geometries initialised");
}
// import selected file as a vector layer
function addGeometryLayer() {
// get the selected file from user
var fileList = document.getElementById('GeometryFile');
file = fileList.files[0];
fileList.value = '';
var fileext = file.name.split('.').pop();
var filename = file.name.replace('.' + fileext, '');
fileext = fileext.toUpperCase();
// add list item
color = colorlist[(layerindex++) % colorlist.length];
var fileitem = document.createElement('li');
fileitem.id = file.name;
fileitem.style.color = color;
fileitem.innerHTML = 'Loading...';
geolist.appendChild(fileitem);
// check if format is supported
var parser = formats[fileext];
if (typeof parser == 'undefined') {
fileitem.innerHTML = fileext.toUpperCase() + ' format not supported :(';
fileitem.style.color = 'red';
return;
}
parser.internalProjection = Waze.map.getProjectionObject();
parser.externalProjection = EPSG_4326;
// add a new layer for the geometry
var layerid = 'wme_geometry_'+layerindex;
var WME_Geometry = new OL.Layer.Vector("Geometry: " + filename,
{ rendererOptions: { zIndexing: true },
uniqueName: layerid,
shortcutKey: "S+" + layerindex,
layerGroup: 'wme_geometry'
}
);
var layerStyle = {
strokeColor: color,
strokeOpacity: 0.5,
strokeWidth: 3,
fillColor: color,
fillOpacity: 0.02,
pointRadius: 6,
fontColor: 'white',
labelOutlineColor: color,
labelOutlineWidth: 4,
labelAlign: 'left'
};
WME_Geometry.setZIndex(-9999);
WME_Geometry.displayInLayerSwitcher = true;
// hack in translation:
I18n.translations[I18n.locale].layers.name[layerid] = "WME Geometries: " + filename;
// read the file into the new layer
var reader = new FileReader();
reader.onload = (function(theFile) {
return function(e) {
if (/"EPSG:3857"|:EPSG::3857"/.test(e.target.result)) {
parser.externalProjection = EPSG_3857;
}
else if (/"EPSG:4269"|:EPSG::4269"/.test(e.target.result)) {
parser.externalProjection = EPSG_4269;
}
// load geometry files
var features = parser.read(e.target.result);
// detect bad data
if (features.length === 0) {
fileitem.innerHTML = 'No features loaded :(';
fileitem.style.color = 'red';
WME_Geometry.destroy();
return;
}
// check which attribute can be used for labels
var labelwith = '(no labels)';
if (features.length <= maxlabels) {
for (var attrib in features[0].attributes) {
if (labelname.test(attrib.toLowerCase()) === true) {
if (typeof features[0].attributes[attrib] == 'string') {
labelwith = 'Labels: ' + attrib;
layerStyle.label = '${'+attrib+'}';
break;
}
}
}
}
WME_Geometry.styleMap = new OpenLayers.StyleMap(layerStyle);
// add data to the map
WME_Geometry.addFeatures(features);
Waze.map.addLayer(WME_Geometry);
fileitem.innerHTML = filename;
fileitem.title = fileext.toUpperCase() + " " + parser.externalProjection.projCode
+ ": " + features.length + " features loaded\n" + labelwith;
console.log("WME Geometries: Loaded " + fileitem.title);
};
})(file);
reader.readAsText(file);
}
// clear all
function removeGeometryLayers() {
var layers = Waze.map.getLayersBy("layerGroup","wme_geometry");
for (i = 0; i < layers.length; i++) {
layers[i].destroy();
}
geolist.innerHTML = '';
layerindex = 0;
return false;
}
// ------------------------------------------------------------------------------------
// replace missing functions in OpenLayers 2.12
function patchOpenLayers() {
if (OpenLayers.VERSION_NUMBER != 'Release 2.12') {
console.log("WME Geometries: OpenLayers version mismatch - cannot apply patch");
return;
}
OpenLayers.Format.KML=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{kml:"http://www.opengis.net/kml/2.2",gx:"http://www.google.com/kml/ext/2.2"},kmlns:"http://earth.google.com/kml/2.0",placemarksDesc:"No description available",foldersName:"OpenLayers export",foldersDesc:"Exported on "+new Date,extractAttributes:!0,kvpAttributes:!1,extractStyles:!1,extractTracks:!1,trackAttributes:null,internalns:null,features:null,styles:null,styleBaseUrl:"",fetched:null,maxDepth:0,initialize:function(a){this.regExes=
{trimSpace:/^\s*|\s*$/g,removeSpace:/\s*/g,splitSpace:/\s+/,trimComma:/\s*,\s*/g,kmlColor:/(\w{2})(\w{2})(\w{2})(\w{2})/,kmlIconPalette:/root:\/\/icons\/palette-(\d+)(\.\w+)/,straightBracket:/\$\[(.*?)\]/g};this.externalProjection=new OpenLayers.Projection("EPSG:4326");OpenLayers.Format.XML.prototype.initialize.apply(this,[a])},read:function(a){this.features=[];this.styles={};this.fetched={};return this.parseData(a,{depth:0,styleBaseUrl:this.styleBaseUrl})},parseData:function(a,b){"string"==typeof a&&
(a=OpenLayers.Format.XML.prototype.read.apply(this,[a]));for(var c=["Link","NetworkLink","Style","StyleMap","Placemark"],d=0,e=c.length;d=this.maxDepth)return!1;var c=OpenLayers.Util.extend({},b);c.depth++;for(var d=0,e=a.length;d=e.length)){switch(e.length){case 1:f=e[0];break;case 2:f=e[0];e=e[1];f=3==f.nodeType||4==f.nodeType?f:e;break;default:f=e[1]}if(3==f.nodeType||4==f.nodeType)if(d=d.prefix?d.nodeName.split(":")[1]:d.nodeName,f=OpenLayers.Util.getXmlNodeValue(f))f=f.replace(this.regExes.trimSpace,""),b[d]=f}return b},parseExtendedData:function(a){var b={},c,d,e,f,g=a.getElementsByTagName("Data");c=0;for(d=g.length;c0){parser=this.parseGeometry[type.toLowerCase()];if(parser){geometry=parser.apply(this,[nodeList[0]]);if(this.internalProjection&&this.externalProjection){geometry.transform(this.externalProjection,this.internalProjection)}}else{throw new TypeError("Unsupported geometry type: "+type);}break}}var bounds;var boxNodes=this.getElementsByTagNameNS(node,this.gmlns,"Box");for(i=0;i0){coordString=nodeList[0].firstChild.nodeValue;coordString=coordString.replace(this.regExes.trimSpace,"");
coords=coordString.split(this.regExes.splitSpace)}if(coords.length==0){nodeList=this.getElementsByTagNameNS(node,this.gmlns,"coordinates");if(nodeList.length>0){coordString=nodeList[0].firstChild.nodeValue;coordString=coordString.replace(this.regExes.removeSpace,"");coords=coordString.split(",")}}if(coords.length==0){nodeList=this.getElementsByTagNameNS(node,this.gmlns,"coord");if(nodeList.length>0){var xList=this.getElementsByTagNameNS(nodeList[0],this.gmlns,"X");var yList=this.getElementsByTagNameNS(nodeList[0],this.gmlns,"Y");
if(xList.length>0&&yList.length>0){coords=[xList[0].firstChild.nodeValue,yList[0].firstChild.nodeValue]}}}if(coords.length==2){coords[2]=null}if(this.xy){return new OpenLayers.Geometry.Point(coords[0],coords[1],coords[2])}else{return new OpenLayers.Geometry.Point(coords[1],coords[0],coords[2])}},multipoint:function(node){var nodeList=this.getElementsByTagNameNS(node,this.gmlns,"Point");var components=[];if(nodeList.length>0){var point;for(var i=0;i0){coordString=this.getChildValue(nodeList[0]);coordString=coordString.replace(this.regExes.trimSpace,"");coords=coordString.split(this.regExes.splitSpace);var dim=parseInt(nodeList[0].getAttribute("dimension"));var j,x,y,z;for(var i=0;i0){coordString=this.getChildValue(nodeList[0]);coordString=coordString.replace(this.regExes.trimSpace,"");coordString=coordString.replace(this.regExes.trimComma,",");var pointList=coordString.split(this.regExes.splitSpace);for
(var i=0;i0){var line;for(var i=0;i0){var ring;for(var i=0;i0){var polygon;for(var i=0;i0){var coords=[];if(lpoint.length>0){coordString=lpoint[0].firstChild.nodeValue;coordString=coordString.replace(this.regExes.trimSpace,"");coords=coordString.split(this.regExes.splitSpace)}if(coords.length==2){coords[2]=null}if(this.xy){var lowerPoint=new OpenLayers.Geometry.Point(coords[0],coords[1],coords[2])}else{var lowerPoint=new OpenLayers.Geometry.Point(coords[1],coords[0],coords[2])}}var upoint=this.getElementsByTagNameNS(node,this.gmlns,"upperCorner");if(upoint.length>0){var coords=[];if(upoint.length>0)
{coordString=upoint[0].firstChild.nodeValue;coordString=coordString.replace(this.regExes.trimSpace,"");coords=coordString.split(this.regExes.splitSpace)}if(coords.length==2){coords[2]=null}if(this.xy){var upperPoint=new OpenLayers.Geometry.Point(coords[0],coords[1],coords[2])}else{var upperPoint=new OpenLayers.Geometry.Point(coords[1],coords[0],coords[2])}}if(lowerPoint&&upperPoint){components.push(new OpenLayers.Geometry.Point(lowerPoint.x,lowerPoint.y));components.push(new OpenLayers.Geometry.Point(upperPoint.x,lowerPoint.y));
components.push(new OpenLayers.Geometry.Point(upperPoint.x,upperPoint.y));components.push(new OpenLayers.Geometry.Point(lowerPoint.x,upperPoint.y));components.push(new OpenLayers.Geometry.Point(lowerPoint.x,lowerPoint.y));var ring=new OpenLayers.Geometry.LinearRing(components);envelope=new OpenLayers.Geometry.Polygon([ring])}return envelope},box:function(node){var nodeList=this.getElementsByTagNameNS(node,this.gmlns,"coordinates");var coordString;var coords,beginPoint=null,endPoint=null;if(nodeList.length>0){coordString=
nodeList[0].firstChild.nodeValue;coords=coordString.split(" ");if(coords.length==2){beginPoint=coords[0].split(",");endPoint=coords[1].split(",")}}if(beginPoint!==null&&endPoint!==null){return new OpenLayers.Bounds(parseFloat(beginPoint[0]),parseFloat(beginPoint[1]),parseFloat(endPoint[0]),parseFloat(endPoint[1]))}}},parseAttributes:function(node){var attributes={};var childNode=node.firstChild;var children,i,child,grandchildren,grandchild,name,value;while(childNode){if(childNode.nodeType==1){children=childNode.childNodes;
for(i=0;iTXT';
formats.KML = new OpenLayers.Format.KML();
formats.GPX = new OpenLayers.Format.GPX();
formats.GML = new OpenLayers.Format.GML();
//formats.TXT = new OpenLayers.Format.Text();
}
})();
// ------------------------------------------------------------------------------------