// ==UserScript==
// @name WME Circles
// @namespace http://tampermonkey.net/
// @version 2023.07.29
// @description Kreise im WME erstellen
// @namespace https://gf.qytechs.cn/de/users/863740-horst-wittlich
// @author vertexcode
// @match https://*.waze.com/editor*
// @match https://*.waze.com/*/editor*
// @match https://beta.waze.com/editor*
// @match https://beta.waze.com/*/editor*
// @icon https://www.google.com/s2/favicons?sz=64&domain=waze.com
// @grant none
// @license MIT
// ==/UserScript==
// Versions Format
// yyyy.mm.dd
(function() {
'use strict';
let uOpenLayers;
let uWaze;
let radiusLayer, infoLayer;
let polygonControl;
function addSidePanel() {
// create the content of the side-panel tab
let addon = document.createElement('section');
addon.id = "wme-circle-addon";
addon.innerHTML = '<h3>WME Circles v1</h3><p id="circles-current-radius"></p>';
let userTabs = document.getElementById('user-info');
let navTabs = document.getElementsByClassName('nav-tabs', userTabs)[0];
let tabContent = document.getElementsByClassName('tab-content', userTabs)[0];
let tab = document.createElement('li');
tab.innerHTML = '<a href="#sidepanel-wme-circles" data-toggle="tab">Circles</a>';
navTabs.appendChild(tab);
addon.id = "sidepanel-wme-circles";
addon.className = "tab-pane";
tabContent.appendChild(addon);
let toggleEntry = document.createElement('div');
let checkbox = document.createElement("wz-checkbox");
checkbox.id = 'wme-circles-edit-mode';
checkbox.className = "hydrated";
checkbox.appendChild(document.createTextNode('Enable Edit Mode'));
toggleEntry.appendChild(checkbox);
addon.appendChild(toggleEntry);
checkbox.addEventListener('click', (e) => {
if (e.target.checked) {
polygonControl.activate();
} else {
polygonControl.deactivate();
}
});
let clearCircles = document.createElement('div');
clearCircles.style.display = 'flex';
clearCircles.style.flexDirection = 'column';
clearCircles.style.gap = '5px';
clearCircles.style.marginTop = '15px';
let clearButton = document.createElement('wz-button');
clearButton.id = 'wme-circles-clear';
clearButton.className = 'hydrated';
clearButton.appendChild(document.createTextNode('Clear Circles'));
clearButton.addEventListener('click', (e) => {
infoLayer.destroyFeatures();
radiusLayer.destroyFeatures();
checkbox.checked = false;
polygonControl.deactivate();
});
let selectButton = document.createElement('wz-button');
selectButton.id = 'wme-circles-select';
selectButton.className = 'hydrated';
selectButton.appendChild(document.createTextNode('Select Streets within'));
selectButton.addEventListener('click', (e) => {
let toSelect = [];
for (let s of uWaze.map.segmentLayer.features) {
for (let r of radiusLayer.features) {
if (r.geometry.intersects(s.geometry)) {
toSelect.push(s);
}
}
}
uWaze.selectionManager.selectFeatures(toSelect);
checkbox.checked = false;
polygonControl.deactivate();
});
clearCircles.appendChild(clearButton);
clearCircles.appendChild(selectButton);
addon.appendChild(clearCircles);
}
function radiusInit() {
radiusLayer = new uOpenLayers.Layer.Vector("WME Circle Control Layer", {
displayInLayerSwitcher: true,
uniqueName: "__CircleControlLayer",
visibility: true,
style: {
"fillColor": "#c40606",
"fillOpacity": 0.2,
"strokeColor": "#c40606",
"strokeOpacity": 1,
"strokeWidth": 1,
"strokeLinecap": "round",
"strokeDashstyle": "solid",
"pointRadius": 6,
"pointerEvents": "visiblePainted",
"labelAlign": "cm",
"labelOutlineColor": "white",
"labelOutlineWidth": 3
}
});
infoLayer = new uOpenLayers.Layer.Vector("WME Circle Visual Layer", {
displayInLayerSwitcher: true,
uniqueName: "__DrawCircleDisplayLayer",
visibility: true
});
let polygonHandler = uOpenLayers.Handler.RegularPolygon;
polygonControl = new uOpenLayers.Control.DrawFeature(radiusLayer, polygonHandler, {
handlerOptions: {
sides: 100
}
});
uWaze.map.addLayer(radiusLayer);
uWaze.map.addLayer(infoLayer);
uWaze.map.addControl(polygonControl);
addSidePanel();
polygonControl.handler.callbacks.move = function (e) {
let linearRing = new uOpenLayers.Geometry.LinearRing(e.components[0].components);
let geometry = new uOpenLayers.Geometry.Polygon([linearRing]);
let polygonFeature = new uOpenLayers.Feature.Vector(geometry, null);
let polybounds = polygonFeature.geometry.getBounds();
let minX = polybounds.left;
let minY = polybounds.bottom;
let maxX = polybounds.right;
let maxY = polybounds.top;
let startX = (minX + maxX) / 2;
let startY = (minY + maxY) / 2;
let startPoint = new uOpenLayers.Geometry.Point(startX, startY);
let endPoint = new uOpenLayers.Geometry.Point(maxX, startY);
let radius = new uOpenLayers.Geometry.LineString([startPoint, endPoint]);
let len = radius.getGeodesicLength(new uOpenLayers.Projection("EPSG:900913"));
let unit = 'm';
if (len > 1000) {
len = Math.round((len / 1000) * 100) / 100;
unit = "km";
}
let rad = document.getElementById('circles-current-radius');
rad.innerHTML = 'Current Radius: ' + len + ' ' + unit;
}
polygonControl.events.on({
'click': function(e) {
console.log('foo');
},
'featureadded': function (e) {
let rad = document.getElementById('circles-current-radius');
rad.innerHTML = '';
let f = e.feature;
let minX = f.geometry.bounds.left;
let minY = f.geometry.bounds.bottom;
let maxX = f.geometry.bounds.right;
let maxY = f.geometry.bounds.top;
let startX = (minX + maxX) / 2;
let startY = (minY + maxY) / 2;
let startPoint = new uOpenLayers.Geometry.Point(startX, startY);
let endPoint = new uOpenLayers.Geometry.Point(maxX, startY);
let radius = new uOpenLayers.Geometry.LineString([startPoint, endPoint]);
let len = radius.getGeodesicLength(new uOpenLayers.Projection("EPSG:900913"));
let centerStyle = {
strokeColor: "#c40606",
strokeWidth: 2,
pointRadius: 5,
fillOpacity: 0.2
};
let unit = 'm';
if (len > 1000) {
len = Math.round((len / 1000) * 100) / 100;
unit = "km";
}
let lineStyle = {
strokeColor: "#c40606",
strokeWidth: 3,
label: len + ' ' + unit,
labelAlign: "left",
labelXOffset: "20",
labelYOffset: "10",
labelOutlineColor: "white",
labelOutlineWidth: 3
};
let center = new uOpenLayers.Feature.Vector(startPoint, {}, centerStyle);
let radiusLine = new uOpenLayers.Feature.Vector(radius, { 'length': len }, lineStyle);
infoLayer.addFeatures([center, radiusLine]);
}
});
}
function radiusBootstrap() {
uWaze = window.W || unsafeWindow.W;
uOpenLayers = window.OpenLayers || unsafeWindow.OpenLayers;
if (typeof (uOpenLayers) === 'undefined' || typeof (uWaze) === 'undefined' || typeof (uWaze.map) === 'undefined' || document.querySelector('.list-unstyled.togglers .group') === null) {
setTimeout(radiusBootstrap, 500);
} else {
radiusInit();
}
}
radiusBootstrap();
})();