WME Circles

Kreise im WME erstellen

// ==UserScript==
// @name         WME Circles
// @namespace    http://tampermonkey.net/
// @version      2023.07.29
// @description  Kreise im WME erstellen
// @namespace    https://greasyfork.org/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();
})();