WAZEPT Segments

Facilitates the standardization of segments

目前為 2020-10-14 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         WAZEPT Segments
// @version      2020.10.15
// @description  Facilitates the standardization of segments
// @author       J0N4S13 ([email protected])
// @include 	   /^https:\/\/(www|beta)\.waze\.com\/(?!user\/)(.{2,6}\/)?editor.*$/
// @exclude        https://www.waze.com/user/*editor/*
// @exclude        https://www.waze.com/*/user/*editor/*
// @grant        none
// @namespace https://greasyfork.org/users/218406
// ==/UserScript==

(function() {
    var version = GM_info.script.version;
    setTimeout(function() {
        var myVar = setInterval(myTimer, 500);
        if(W.loginManager.getUserRank()>2)
            var split = setInterval(insertButtons, 500);
    }, 2000);
    var indexselected = "";
    var valueselected = "";
    var array_data = {};
    var array_roads = {};

    function receivedata() {
        return new Promise(resolve => {
            var url_data = "https://spreadsheets.google.com/feeds/list/1s_vcC-ENS7JdkVmVH2QceGMA058tan2UUPlQGd6AhwU/1/public/values?alt=json";

            $.getJSON(url_data, function(data) {

                var entry = data.feed.entry;

                $(entry).each(function(){
                    var elem = [this.gsx$emoji.$t, this.gsx$descricao.$t, this.gsx$bloqueio.$t];
                    array_data[ this.gsx$funcionalidade.$t ] = elem;
                    array_roads[this.gsx$funcionalidade.$t] = [this.gsx$emoji.$t, this.gsx$descricao.$t];
                });
            });
            var timer = setInterval(check_data, 100);

            function check_data() {
                if(eval("array_data['SEG_ESTACIONAMENTO'] !== undefined"))
                {
                    clearInterval(timer);
                    resolve('true');
                }
            }

        });
    }

    function optionsUser() {

        var $auto_link;
        var $settings = $('<li><a href="#sidepanel-LAND" data-toggle="tab" aria-expanded="true">LAND</a></li>');
        $("#user-tabs ul").append($settings);

        var $home = $('<div id="sidepanel-LAND" class="tab-pane"><b>WME Landmark</b><br><br><b><i>Definições</i></b><br><br>');
        var div_sidepnale = document.createElement("div");
        div_sidepnale.id = "sidepanel-LAND";
        div_sidepnale.className = "tab-pane";

        var label_home = document.createElement("label");
        label_home.innerHTML = 'WAZEPT Landmark (Version: ' + version + ")";
        label_home.style.cssText = 'font-size: 15px;color:blue;';
        div_sidepnale.appendChild(label_home);

        $("div.tab-content")[0].prepend(div_sidepnale);
    }

    async function dataCall() {
        var result = await receivedata();
        //optionsUser();
    }

    setTimeout(() => {
        dataCall();
    }, 500);

    function myTimer() {
        var n_bloqueio;
        var nivel;
        var lvl_atual;
        var lvl_max;

        var typeData = null;
        if(eval("W.selectionManager.getSelectedFeatures()[0] !== undefined"))
            typeData = W.selectionManager.getSelectedFeatures()[0].model.type;

        if(typeData == "segment")
        {

            if (!$("#signsroad").length) {
                var signsroad = document.createElement("div");
                signsroad.id = 'signsroad';

                $.each(array_roads, function(func , emoji) {

                    // The sign background
                    var addsign = document.createElement("div");
                    addsign.id = 'sign_' + func;

                    // Get width/height of sign background img
                    addsign.style.cssText = 'cursor:pointer;float:left;width:34px;height:34px;';
                    // Credits for some of these parts go to t0cableguy & Rickzabel
                    addsign.onclick = function() {

                        indexselected = func;

                        if(indexselected == 'SEG_ESTACIONAMENTO')
                        {
                            defineRoadType(20);
                            defineSpeed("30");
                            defineLockRankRoad(array_data['SEG_ESTACIONAMENTO'][2]);
                            defineStreetRoad("");
                        }

                        if(indexselected == 'SEG_SECUNDARIA')
                        {
                            defineRoadType(1);
                            defineSpeed("50");
                            defineLockRankRoad(array_data['SEG_SECUNDARIA'][2]);
                        }

                        if(indexselected == 'SEG_PRINCIPAL')
                        {
                            defineRoadType(2);
                            defineSpeed("50");
                            defineLockRankRoad(array_data['SEG_PRINCIPAL'][2]);
                        }

                        if(indexselected == 'SEG_MUNICIPAL')
                        {
                            defineRoadType(7);
                            defineSpeed("90");
                            defineLockRankRoad(array_data['SEG_MUNICIPAL'][2]);
                        }

                        if(indexselected == 'SEG_NACIONAL')
                        {
                            defineRoadType(6);
                            defineSpeed("90");
                            defineLockRankRoad(array_data['SEG_NACIONAL'][2]);
                        }

                        if(indexselected == 'SEG_RESERVADA')
                        {
                            defineRoadType(3);
                            defineSpeed("100");
                            defineLockRankRoad(array_data['SEG_RESERVADA'][2]);
                        }

                        if(indexselected == 'SEG_AUTOESTRADA')
                        {
                            defineRoadType(3);
                            defineSpeed("120");
                            defineLockRankRoad(array_data['SEG_AUTOESTRADA'][2]);
                        }

                        if(indexselected == 'LD_ROTUNDA')
                        {
                            let coords = [];
                            let segsfeitos = [];
                            let segmentos = W.selectionManager.getSelectedFeatures()[0].model.getRoundabout().attributes.segIDs;
                            let primeiro = W.selectionManager.getSelectedFeatures()[0].model.attributes.id;
                            let segmento = primeiro;
                            let feitos = 0;

                            do{
                                let seg = W.selectionManager.model.segments.getObjectById(segmento);
                                let geo = seg.geometry.components
                                for (let i=0; i<geo.length - 1; i++) {
                                    let linha = [geo[i].x, geo[i].y];
                                    coords.push(linha);
                                }

                                W.selectionManager.model.nodes.getObjectById(seg.attributes.toNodeID).attributes.segIDs.forEach(function(aux){
                                    if(aux != segmento && segmentos.includes(aux) && !segsfeitos.includes(aux))
                                    {
                                        segsfeitos.push(segmento);
                                        segmento = aux;
                                    }
                                });
                                feitos++;
                            } while (feitos < segmentos.length)

                                let AddLandmark= require("Waze/Action/AddLandmark");
                            var wazefeatureVectorLandmark = require("Waze/Feature/Vector/Landmark");

                            var poi = new wazefeatureVectorLandmark();
                            var geometry = new OpenLayers.Geometry.Polygon();

                            var TabLine2 = [];

                            for (var n=0; n < coords.length; n++)
                            {
                                var point = new OpenLayers.Geometry.Point(coords[n][0] ,coords[n][1]);
                                TabLine2.push(point);
                            }


                            var LineString2 = new OpenLayers.Geometry.LinearRing(TabLine2);
                            poi.geometry = new OpenLayers.Geometry.Polygon(LineString2);
                            poi.attributes.categories = new Array("FARM","JUNCTION_INTERCHANGE");

                            let rank = array_data['LD_ROTUNDA'][2];
                            rank--;
                            let bloquear;
                            if(W.loginManager.user.rank >= rank)
                                bloquear = rank;
                            else
                                bloquear = W.loginManager.user.rank;
                            poi.attributes.lockRank = bloquear;

                            W.model.actionManager.add(new AddLandmark(poi));

                        }

                        if(indexselected == 'DATA_PORTAGENS')
                        {

                            let myRoad = W.selectionManager.getSelectedFeatures()[0].model.attributes;

                            var from = "";
                            var to = "";
                            var sentido = "";

                            if(myRoad.fwdDirection == true && myRoad.revDirection == true)
                            {
                                $( "#divSentidos" ).show();
                            }
                            else
                            {
                                if(myRoad.fwdDirection == true) //A to B
                                {
                                    from = myRoad.fromNodeID;
                                    to = myRoad.toNodeID;
                                    sentido = "TRUE";
                                }

                                else if(myRoad.revDirection == true)//B to A
                                {
                                    from = myRoad.toNodeID;
                                    to = myRoad.fromNodeID;
                                    sentido = "FALSE";
                                }
                                var $temp = $("<input>");
                                $("body").append($temp);
                                $temp.val(sentido + "|" + $('a[class=permalink]').attr('href') + "|" + from + "|" + to).select();
                                document.execCommand("copy");
                                $temp.remove();
                            }

                        }

                    }
                    if($('span[class=full-address]').text().indexOf('Portugal') != -1 || func == "DATA_PORTAGENS")
                    {
                        var emojivalue = document.createElement("div");
                        emojivalue.id = 'emoji_' + func;
                        emojivalue.style.cssText = 'text-align:center;font-size:14px;visibility:visible;';
                        emojivalue.innerHTML = emoji[0];
                        emojivalue.title = emoji[1];
                        addsign.appendChild(emojivalue);
                        signsroad.appendChild(addsign);
                    }
                });

                var btnAB = document.createElement("button");
                btnAB.innerHTML = 'A->B';
                btnAB.id = 'btnAB';
                btnAB.style.cssText = 'height: 20px;font-size:11px';

                btnAB.onclick = function() {
                    let myRoad = W.selectionManager.getSelectedFeatures()[0].model.attributes;
                    if(myRoad.fwdDirection == true) //A to B
                    {
                        var $temp = $("<input>");
                        $("body").append($temp);
                        $temp.val("TRUE" + "|" + $('a[class=permalink]').attr('href') + "|" + myRoad.fromNodeID + "|" + myRoad.toNodeID).select();
                        document.execCommand("copy");
                        $temp.remove();
                    }
                }

                var btnBA = document.createElement("button");
                btnBA.innerHTML = 'B->A';
                btnBA.id = 'btnBA';
                btnBA.style.cssText = 'height: 20px;font-size:11px';

                btnBA.onclick =  function() {
                    let myRoad = W.selectionManager.getSelectedFeatures()[0].model.attributes;
                    if(myRoad.revDirection == true) //B to A
                    {
                        var $temp = $("<input>");
                        $("body").append($temp);
                        $temp.val("FALSE" + "|" + $('a[class=permalink]').attr('href') + "|" + myRoad.toNodeID + "|" + myRoad.fromNodeID).select();
                        document.execCommand("copy");
                        $temp.remove();
                    }
                }

                var divSentidos = document.createElement("div");
                divSentidos.id = 'divSentidos';
                divSentidos.appendChild(btnAB);
                divSentidos.appendChild(btnBA);

                var divLandmarkScript = document.createElement("div");
                divLandmarkScript.id = 'divLandmarkScript';
                divLandmarkScript.style.cssText = 'float:left;';
                divLandmarkScript.appendChild(signsroad);
                divLandmarkScript.appendChild(divSentidos);

                $("div #segment-edit-general").prepend(divLandmarkScript);
                $( "#divSentidos" ).hide();
            }
        }
    }

    function getSelectedVenue() {
        const features = WazeWrap.getSelectedFeatures();
        // Be sure to check for features.length === 1, in case multiple venues are currently selected.
        return features.length === 1 && features[0].model.type === 'venue'
            ? features[0].model : undefined;
    }

    function defineSpeed (speed) {
        let UpdateObject= require("Waze/Action/UpdateObject");
        $.each(W.selectionManager.getSelectedFeatures(), function(i, segment) {
            var seg_id = segment.model.getID();
            var seg = W.model.segments.getObjectById(seg_id);
            if(segment.model.attributes.fwdMaxSpeed == null && segment.model.attributes.fwdMaxSpeed == null)
                W.model.actionManager.add(new UpdateObject(seg, {'fwdMaxSpeed': speed, 'revMaxSpeed': speed}));
            else if(segment.model.attributes.fwdMaxSpeed == null)
                W.model.actionManager.add(new UpdateObject(seg, {'fwdMaxSpeed': speed}));
            else if(segment.model.attributes.fwdMaxSpeed == null)
                W.model.actionManager.add(new UpdateObject(seg, {'revMaxSpeed': speed}));
        });
    }

    function defineRoadType (type) {
        let UpdateObject= require("Waze/Action/UpdateObject");
        $.each(W.selectionManager.getSelectedFeatures(), function(i, segment) {
            var seg_id = segment.model.getID();
            var seg = W.model.segments.getObjectById(seg_id);
            W.model.actionManager.add(new UpdateObject(seg, {'roadType': type}));
        });
    }

    function defineLockRankRoad (rank) {
        let UpdateObject= require("Waze/Action/UpdateObject");
        rank--;
        var bloquear;
        if(W.loginManager.user.rank >= rank)
            bloquear = rank;
        else
            bloquear = W.loginManager.user.rank;
        $.each(W.selectionManager.getSelectedFeatures(), function(i, segment) {
            let lock = segment.model.attributes.lockRank;
            var seg_id = segment.model.getID();
            var seg = W.model.segments.getObjectById(seg_id);
            if(lock < bloquear)
                W.model.actionManager.add(new UpdateObject(seg, {'lockRank': bloquear}));
        });
    }

    function defineStreetRoad(street) {
        let UpdateFeatureAddress = require("Waze/Action/UpdateFeatureAddress");
        $.each(W.selectionManager.getSelectedFeatures(), function(i, segment) {
            var seg_id = segment.model.getID();
            if(seg_id == "-100")
            {
                $("input[id=empty-street]").prop('checked', true).change().focusout();
                $("input[id=empty-city]").prop('checked', true).change().focusout();
                $(".save-button.waze-btn.waze-btn-blue.waze-btn-smaller").trigger('click');
            }
            else
            {
                var seg = W.model.segments.getObjectById(seg_id);
                var address = segment.model.getAddress().attributes;
                var newAddressAtts = {
                    streetName: street,
                    emptyStreet: street==""?true:false,
                    cityName: "",
                    emptyCity: true,
                    countryID: address.country.id
                };
                W.model.actionManager.add(new UpdateFeatureAddress(seg, newAddressAtts,{streetIDField:"primaryStreetID"}));
            }
        });
    }

    // Split Segments

    function insertButtons() {

        if (W.selectionManager.getSelectedFeatures().length !== 1)
            return;

        try {
            if (document.getElementById('split-segment') !== null)
                return;
        } catch (e) {}

        var btn1 = $('<button class="action-button waze-btn waze-btn-white" title="Criar dois novos segmentos">Dividir em 2 segmentos paralelos</button>');
        btn1.click(createSegments);

        var strMeters = "metros";

        // 2014-01-09: Add River Width Combobox
        var selSegmentsDistance = $('<select id="segmentsDistance" data-type="numeric" class="form-control" />');
        selSegmentsDistance.append($('<option value="5">5 ' + strMeters + '</option>'));
        selSegmentsDistance.append($('<option value="7">7 ' + strMeters + '</option>'));
        selSegmentsDistance.append($('<option value="9">9 ' + strMeters + '</option>'));
        selSegmentsDistance.append($('<option value="11">11 ' + strMeters + '</option>'));
        selSegmentsDistance.append($('<option value="13">13 ' + strMeters + '</option>'));
        selSegmentsDistance.append($('<option value="15">15 ' + strMeters + '</option>'));
        selSegmentsDistance.append($('<option value="17">17 ' + strMeters + '</option>'));
        selSegmentsDistance.append($('<option value="19">19 ' + strMeters + '</option>'));
        selSegmentsDistance.append($('<option value="21">21 ' + strMeters + '</option>'));
        selSegmentsDistance.append($('<option value="23">23 ' + strMeters + '</option>'));
        selSegmentsDistance.append($('<option value="25">25 ' + strMeters + '</option>'));

        var cnt = $('<div id="split-segment" />');

        var divGroup1 = $('<div class="form-group" />');
        divGroup1.append($('<label class="control-label">Distância entre os dois segmentos paralelos:</label>'));
        divGroup1.append(selSegmentsDistance);
        var divControls1 = $('<div class="controls-container" />');
        divGroup1.append(divControls1);
        cnt.append(divGroup1);

        var divGroup2 = $('<div class="form-group"/>');
        var divControls2 = $('<div class="btn-toolbar" />');
        divControls2.append(btn1);
        divGroup2.append(divControls2);
        cnt.append(divGroup2);

        $(cnt).insertAfter("#segment-edit-general .more-actions");

        selSegmentsDistance = document.getElementById('segmentsDistance');
        if (selSegmentsDistance !== null) {
            for (var i = 0; i < selSegmentsDistance.options.length; i++) {
                if (selSegmentsDistance.options[i].value == localStorage.getItem("metersSplitSegment")) {
                    selSegmentsDistance.selectedIndex = i;
                    break;
                }
            }
        }
        $('#segmentsDistance').change(function(){
            localStorage.setItem("metersSplitSegment", $("#segmentsDistance").val());
        });
    }

    localStorage.setItem("metersSplitSemgment", JSON.stringify(_settings));

    function createSegments() {
        var wazefeatureVectorSegment = require("Waze/Feature/Vector/Segment");
        var UpdateSegmentGeometry= require("Waze/Action/UpdateSegmentGeometry");
        var UpdateObject= require("Waze/Action/UpdateObject");

        var sel = W.selectionManager.getSelectedFeatures()[0].model;
        var streetVertices = sel.geometry.getVertices();
        var esquerdaPoints = null;
        var direitaPoints = null;

        var i;
        var leftPa,
            rightPa,
            leftPb,
            rightPb;
        var prevLeftEq,
            prevRightEq;

        var displacement = $( "#segmentsDistance" ).val();

        var first = 0;

        for (i = first; i < streetVertices.length - 1; i++) {
            var pa = streetVertices[i];
            var pb = streetVertices[i + 1];

            var points = [pa, pb];
            var ls = new OpenLayers.Geometry.LineString(points);
            var len = ls.getGeodesicLength(W.map.getProjectionObject());
            var scale = (len + displacement / 2) / len;

            leftPa = pa.clone();
            leftPa.resize(scale, pb, 1);
            rightPa = leftPa.clone();
            leftPa.rotate(90, pa);
            rightPa.rotate(-90, pa);

            leftPb = pb.clone();
            leftPb.resize(scale, pa, 1);
            rightPb = leftPb.clone();
            leftPb.rotate(-90, pb);
            rightPb.rotate(90, pb);

            var leftEq = getEquation({
                'x1': leftPa.x,
                'y1': leftPa.y,
                'x2': leftPb.x,
                'y2': leftPb.y
            });
            var rightEq = getEquation({
                'x1': rightPa.x,
                'y1': rightPa.y,
                'x2': rightPb.x,
                'y2': rightPb.y
            });
            if (esquerdaPoints === null && direitaPoints === null) {
                esquerdaPoints = [leftPa];
                direitaPoints = [rightPa];
            } else {
                var li = intersectX(leftEq, prevLeftEq);
                var ri = intersectX(rightEq, prevRightEq);
                if (li && ri) {
                    if (i >= 0) {
                        esquerdaPoints.unshift(li);
                        direitaPoints.push(ri);

                        if (i == 0) {
                            esquerdaPoints = [li];
                            direitaPoints = [ri];
                        }
                    }
                } else {
                    if (i >= 0) {
                        esquerdaPoints.unshift(leftPb.clone());
                        direitaPoints.push(rightPb.clone());

                        if (i == 0) {
                            esquerdaPoints = [leftPb];
                            direitaPoints = [rightPb];
                        }
                    }
                }
            }

            prevLeftEq = leftEq;
            prevRightEq = rightEq;

        }
        esquerdaPoints.push(leftPb);
        direitaPoints.push(rightPb);

        esquerdaPoints.unshift(esquerdaPoints[esquerdaPoints.length-1]);
        esquerdaPoints.pop();

        var newSegEsq = sel.attributes.geometry.clone();
        var newSegDir = sel.attributes.geometry.clone();

        var segmentos = SplitSegment(sel);

        newSegEsq.components = esquerdaPoints.reverse();
        newSegDir.components = direitaPoints;

        var segmentoEsquerdo = W.model.segments.getObjectById(segmentos[0]);
        var segmentoDireito = W.model.segments.getObjectById(segmentos[1]);

        W.model.actionManager.add(new UpdateSegmentGeometry(segmentoEsquerdo,segmentoEsquerdo.geometry,newSegEsq));
        W.model.actionManager.add(new UpdateSegmentGeometry(segmentoDireito,segmentoDireito.geometry,newSegDir));

        W.model.actionManager.add(new UpdateObject(segmentoEsquerdo, {'revDirection': false}));
        W.model.actionManager.add(new UpdateObject(segmentoDireito, {'fwdDirection': false}));

    }

    function getEquation(segment) {
        if (segment.x2 == segment.x1)
            return {
                'x': segment.x1
            };

        var slope = (segment.y2 - segment.y1) / (segment.x2 - segment.x1);
        var offset = segment.y1 - (slope * segment.x1);
        return {
            'slope': slope,
            'offset': offset
        };
    }


    function intersectX(eqa, eqb, defaultPoint) {
        if ("number" == typeof eqa.slope && "number" == typeof eqb.slope) {
            if (eqa.slope == eqb.slope)
                return null;

            var ix = (eqb.offset - eqa.offset) / (eqa.slope - eqb.slope);
            var iy = eqa.slope * ix + eqa.offset;
            return new OpenLayers.Geometry.Point(ix, iy);
        } else if ("number" == typeof eqa.x) {
            return new OpenLayers.Geometry.Point(eqa.x, eqb.slope * eqa.x + eqb.offset);
        } else if ("number" == typeof eqb.y) {
            return new OpenLayers.Geometry.Point(eqb.x, eqa.slope * eqb.x + eqa.offset);
        }
        return null;
    }


    function SplitSegment(road)
    {
        let SplitSegments= require("Waze/Action/SplitSegments");
        let UpdateSegmentGeometry= require("Waze/Action/UpdateSegmentGeometry");

        if(road.arePropertiesEditable())
        {
            var geo=road.geometry.clone();
            var action=null;
            if(geo.components.length<2)
            {
                return undefined;
            }
            if(geo.components.length==2)
            {
                geo.components.splice(1,0,new OpenLayers.Geometry.Point(((geo.components[1].x+geo.components[0].x)/2),((geo.components[1].y+geo.components[0].y)/2)));
                W.model.actionManager.add(new UpdateSegmentGeometry(road,road.geometry,geo));
            }
            action=new SplitSegments(road,{splitAtPoint:road.geometry.components[Math.ceil(road.geometry.components.length/2-1)]});
            W.model.actionManager.add(action);
            var RoadIds=new Array();
            if(action.splits!==null)
            {
                for(var i=0;i<action.splits.length;i++)
                {
                    RoadIds.push(action.splits[i].attributes.id);
                }
            }
            return RoadIds;
        }
    }
})();