您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Providing basic utility for RA adjustment without the need to delete & recreate
当前为
// ==UserScript== // @name WME RA Util // @namespace https://greasyfork.org/users/30701-justins83-waze // @version 0.1.8 // @description Providing basic utility for RA adjustment without the need to delete & recreate // @include https://www.waze.com/editor/* // @include https://www.waze.com/*/editor/* // @include https://beta.waze.com/* // @require https://greasyfork.org/scripts/9794-wlib/code/wLib.js?version=106259 // @require https://greasyfork.org/scripts/23614-wlibext/code/wLibExt.js?version=150020 // @author JustinS83 // @grant none // @license // ==/UserScript== /* global W */ /* global wLib */ /* Todo: -diameter change -Determine if it is a circle -If a circle, determine center of circle -shift diagonal? -stretch diagonal? non-normal RA color:#FF8000 normal RA color:#4cc600 */ (function() { 'use strict'; var RAUtilWindow = null; var UpdateSegmentGeometry = require('Waze/Action/UpdateSegmentGeometry'); var MoveNode = require("Waze/Action/MoveNode"); var totalActions = 0; function bootstrap(tries) { tries = tries || 1; if (window.W && window.W.map && window.W.model) { init(); } else if (tries < 1000) { setTimeout(function () {bootstrap(tries++);}, 200); } } bootstrap(); function init(){ RAUtilWindow = document.createElement('div'); RAUtilWindow.id = "RAUtilWindow"; RAUtilWindow.style.position = 'fixed'; RAUtilWindow.style.visibility = 'hidden'; RAUtilWindow.style.top = '25%'; RAUtilWindow.style.left = '25%'; RAUtilWindow.style.zIndex = 100; RAUtilWindow.style.backgroundColor = '#BEDCE5'; RAUtilWindow.style.borderWidth = '3px'; RAUtilWindow.style.borderStyle = 'solid'; RAUtilWindow.style.borderRadius = '10px'; RAUtilWindow.style.boxShadow = '5px 5px 10px Silver'; RAUtilWindow.style.padding = '4px'; var alertsHTML = '<div id="header" style="padding: 4px; background-color:#4cc600; font-weight: bold;">Roundabout Utility</div>'; alertsHTML += '<div id="content" style="padding: 4px; background-color:White">';//A set of utilities for modifying roundabouts allowing preservation of segment data.';//<br>Double arrows shift by 2x configured value.'; alertsHTML += '</br>'; alertsHTML += 'Shift amount: <input type="text" name="shiftAmount" id="shiftAmount" size="1" style="border: 1px solid #000000" value="1"/> meter(s) </div>'; alertsHTML += '<div id="controls" style="padding: 4px;">'; alertsHTML += '<div id="singleShift">';// style="float:left;">';// padding-bottom:45px;">'; alertsHTML += '<table style="table-layout:fixed;width:60px;height:84px;">'; alertsHTML += '<tr style="width:20px;height:28px;">'; alertsHTML += '<td align="center"></td>'; alertsHTML += '<td align="center">'; //Single Shift Buttons alertsHTML += '<span id="RAShiftUpBtn" style="cursor:pointer;font-size:14px;border:thin outset black;padding:2px;">';//margin-left:23px;">'; alertsHTML += '<i class="fa fa-angle-up"> </i>'; alertsHTML += '<span id="UpBtnCaption" style="font-weight: bold;"></span>'; alertsHTML += '</span>'; //alertsHTML += '</br>'; alertsHTML += '</td>'; alertsHTML += '<td align="center"></td>'; alertsHTML += '</tr>'; alertsHTML += '<tr style="width:20px;height:28px;">'; alertsHTML += '<td align="center">'; //alertsHTML += ' '; alertsHTML += '<span id="RAShiftLeftBtn" style="cursor:pointer;font-size:14px;border:thin outset black;padding:2px;padding-right:4px;">';//position:relative;padding:2px;padding-left:3px;padding-right:3px;margin-left:0px;top:10px;">'; alertsHTML += '<i class="fa fa-angle-left"> </i>'; alertsHTML += '<span id="LeftBtnCaption" style="font-weight: bold;"></span>'; alertsHTML += '</span>'; alertsHTML += '</td>'; alertsHTML += '<td align="center"></td>'; alertsHTML += '<td align="center">'; //alertsHTML += ' '; alertsHTML += '<span id="RAShiftRightBtn" style="cursor:pointer;font-size:14px;border:thin outset black;padding:2px;padding-left:4px;">';//position:relative;padding:2px;padding-left:3px;padding-right:3px;top:10px;margin-left:15px;">'; alertsHTML += '<i class="fa fa-angle-right"> </i>'; alertsHTML += '<span id="RightBtnCaption" style="font-weight: bold;"></span>'; alertsHTML += '</span>'; alertsHTML += '</td>'; alertsHTML += '</tr>'; //alertsHTML += '</br>'; alertsHTML += '<tr style="width:20px;height:28px;">'; alertsHTML += '<td align="center"></td>'; alertsHTML += '<td align="center">'; //alertsHTML += ' '; alertsHTML += '<span id="RAShiftDownBtn" style="cursor:pointer;font-size:14px;border:thin outset black;padding:2px;">';//;position:relative;top:20px;margin-left:17px;">'; alertsHTML += '<i class="fa fa-angle-down"> </i>'; alertsHTML += '<span id="DownBtnCaption" style="font-weight: bold;"></span>'; alertsHTML += '</span>'; alertsHTML += '</td>'; alertsHTML += '<td align="center"></td>'; alertsHTML += '</tr>'; //alertsHTML += '</br>'; alertsHTML += '</table>'; alertsHTML += '</div>'; alertsHTML += '</div>'; /* //Double Shift Buttons alertsHTML += '<div id="doubleShift" style="position:relative;top:-18px;">'; alertsHTML += '<span id="RAShiftDoubleUpBtn" style="cursor:pointer;font-size:14px;border:thin outset black;padding:2px;margin-left:30px;">'; alertsHTML += '<i class="fa fa-angle-double-up"> </i>'; alertsHTML += '<span id="DoubleUpBtnCaption" style="font-weight: bold;"></span>'; alertsHTML += '</span>'; alertsHTML += '</br>'; alertsHTML += ' '; alertsHTML += '<span id="RAShiftDoubleLeftBtn" style="cursor:pointer;font-size:14px;border:thin outset black;padding:2px;margin-left:23px;">'; alertsHTML += '<i class="fa fa-angle-double-left"> </i>'; alertsHTML += '<span id="DoubleLeftBtnCaption" style="font-weight: bold;"></span>'; alertsHTML += '</span>'; alertsHTML += ' '; alertsHTML += '<span id="RAShiftDoubleRightBtn" style="cursor:pointer;font-size:14px;border:thin outset black;padding:2px;">'; alertsHTML += '<i class="fa fa-angle-double-right"> </i>'; alertsHTML += '<span id="DoubleRightBtnCaption" style="font-weight: bold;"></span>'; alertsHTML += '</span>'; alertsHTML += '</br>'; alertsHTML += ' '; alertsHTML += '<span id="RAShiftDoubleDownBtn" style="cursor:pointer;font-size:14px;border:thin outset black;padding:2px;">'; alertsHTML += '<i class="fa fa-angle-double-down"> </i>'; alertsHTML += '<span id="DoubleDownBtnCaption" style="font-weight: bold;"></span>'; alertsHTML += '</span>'; alertsHTML += '</div>'; alertsHTML += '</div>'; */ RAUtilWindow.innerHTML = alertsHTML; document.body.appendChild(RAUtilWindow); document.getElementById('RAShiftLeftBtn').addEventListener('click', RAShiftLeftBtnClick, false); document.getElementById('RAShiftRightBtn').addEventListener('click', RAShiftRightBtnClick, false); document.getElementById('RAShiftUpBtn').addEventListener('click', RAShiftUpBtnClick, false); document.getElementById('RAShiftDownBtn').addEventListener('click', RAShiftDownBtnClick, false); $('#shiftAmount').keypress(function(event) { if ((event.which != 46 || $(this).val().indexOf('.') != -1) && (event.which < 48 || event.which > 57)) { event.preventDefault(); } }); window.Waze.selectionManager.events.register("selectionchanged", null, checkDisplayTool); W.model.actionManager.events.register("afterundoaction",null, undotriggered); W.model.actionManager.events.register("afterclearactions",null,actionsCleared); } function undotriggered(){ checkSaveChanges(); } function actionsCleared(){ checkSaveChanges(); totalActions = 0; } function checkDisplayTool(){ if(W.selectionManager.hasSelectedItems() && Waze.selectionManager.selectedItems[0].model.type === 'segment'){ if(!AllSelectedSegmentsRA() || W.selectionManager.selectedItems.length === 0) $('#RAUtilWindow').css({'visibility': 'hidden'}); else{ $('#RAUtilWindow').css({'visibility': 'visible'}); if(typeof jQuery.ui !== 'undefined') $('#RAUtilWindow' ).draggable(); } } else{ $('#RAUtilWindow').css({'visibility': 'hidden'}); if(typeof jQuery.ui !== 'undefined') $('#RAUtilWindow' ).draggable(); } checkSaveChanges(); } var pendingChanges = false; /** Returns false if there are pending changes, true if no changes need saved. */ function checkSaveChanges(){ var $RASaveChanges = $('#RAUtilSaveChanges'); if(W.model.actionManager.index >= 0 && (totalActions === 0 && (W.model.actionManager.actions.length > 0))){ if($RASaveChanges.length === 0){ $RASaveChanges = $('<div>', {id:'RAUtilSaveChanges', style:'color:red'}); $RASaveChanges.text('You must save your changes before using this utility.'); $('#RAUtilWindow').append($RASaveChanges); pendingChanges = true; } } else { $RASaveChanges.remove(); pendingChanges = false; } } function AllSelectedSegmentsRA() { for (i = 0; i < W.selectionManager.selectedItems.length; i++){ if(W.selectionManager.selectedItems[i].model.attributes.id < 0 || !wLib.Model.isRoundaboutSegmentID(W.selectionManager.selectedItems[i].model.attributes.id)) return false; } return true; } function ShiftSegmentNodesLat(segObj, latOffset) { var RASegs = wLib.Model.getAllRoundaboutSegmentsFromObj(segObj); var gps; var newGeometry = segObj.geometry.clone(); var originalLength = segObj.geometry.components.length; for(i=0; i<RASegs.length; i++){ segObj = W.model.segments.get(RASegs[i]); newGeometry = segObj.geometry.clone(); originalLength = segObj.geometry.components.length; for(j=1; j < originalLength-1; j++){ gps = wLib.Geometry.ConvertTo4326(segObj.geometry.components[j].x, segObj.geometry.components[j].y); gps.lat += latOffset; newGeometry.components.splice(j,0, new OL.Geometry.Point(segObj.geometry.components[j].x, wLib.Geometry.ConvertTo900913(segObj.geometry.components[j].x,gps.lat).lat)); newGeometry.components.splice(j+1,1); } newGeometry.components[0].calculateBounds(); newGeometry.components[originalLength-1].calculateBounds(); W.model.actionManager.add(new UpdateSegmentGeometry(segObj, segObj.geometry, newGeometry)); var node = W.model.nodes.objects[segObj.attributes.toNodeID]; var newNodeGeometry = node.geometry.clone(); gps = wLib.Geometry.ConvertTo4326(node.attributes.geometry.x, node.attributes.geometry.y); gps.lat += latOffset; newNodeGeometry.y = wLib.Geometry.ConvertTo900913(node.geometry.x, gps.lat).lat; newNodeGeometry.calculateBounds(); W.model.actionManager.add(new MoveNode(node, node.geometry, newNodeGeometry)); totalActions +=2; } } function ShiftSegmentsNodesLong(segObj, longOffset) { var RASegs = wLib.Model.getAllRoundaboutSegmentsFromObj(segObj); var gps, newGeometry, originalLength; //Loop through all RA segments & adjust for(i=0; i<RASegs.length; i++){ segObj = W.model.segments.get(RASegs[i]); newGeometry = segObj.geometry.clone(); originalLength = segObj.geometry.components.length; for(j=1; j < originalLength-1; j++){ gps = wLib.Geometry.ConvertTo4326(segObj.geometry.components[j].x, segObj.geometry.components[j].y); gps.lon += longOffset; newGeometry.components.splice(j,0, new OL.Geometry.Point(wLib.Geometry.ConvertTo900913(gps.lon, segObj.geometry.components[j].y).lon, segObj.geometry.components[j].y)); newGeometry.components.splice(j+1,1); } newGeometry.components[0].calculateBounds(); newGeometry.components[originalLength-1].calculateBounds(); W.model.actionManager.add(new UpdateSegmentGeometry(segObj, segObj.geometry, newGeometry)); var node = W.model.nodes.objects[segObj.attributes.toNodeID]; var newNodeGeometry = node.geometry.clone(); gps = wLib.Geometry.ConvertTo4326(node.attributes.geometry.x, node.attributes.geometry.y); gps.lon += longOffset; newNodeGeometry.x = wLib.Geometry.ConvertTo900913(gps.lon, node.geometry.y).lon; newNodeGeometry.calculateBounds(); W.model.actionManager.add(new MoveNode(node, node.geometry, newNodeGeometry)); totalActions +=2; } } //Left function RAShiftLeftBtnClick(e) { // this traps the click to prevent it falling through to the underlying area name element and potentially causing the map view to be relocated to that area... e.stopPropagation(); if(!pendingChanges){ var segObj = W.selectionManager.selectedItems[0]; var convertedCoords = wLib.Geometry.ConvertTo4326(segObj.geometry.components[0].x, segObj.geometry.components[0].y); var gpsOffsetAmount = wLib.Geometry.CalculateLongOffsetGPS(-$('#shiftAmount').val(), convertedCoords.lon, convertedCoords.lat); ShiftSegmentsNodesLong(segObj, gpsOffsetAmount); } } //Right function RAShiftRightBtnClick(e) { // this traps the click to prevent it falling through to the underlying area name element and potentially causing the map view to be relocated to that area... e.stopPropagation(); if(!pendingChanges){ var segObj = W.selectionManager.selectedItems[0]; var convertedCoords = wLib.Geometry.ConvertTo4326(segObj.model.geometry.components[0].x, segObj.model.geometry.components[0].y); var gpsOffsetAmount = wLib.Geometry.CalculateLongOffsetGPS($('#shiftAmount').val(), convertedCoords.lon, convertedCoords.lat); ShiftSegmentsNodesLong(segObj, gpsOffsetAmount); } } //Up function RAShiftUpBtnClick(e) { // this traps the click to prevent it falling through to the underlying area name element and potentially causing the map view to be relocated to that area... e.stopPropagation(); if(!pendingChanges){ var segObj = W.selectionManager.selectedItems[0]; var gpsOffsetAmount = wLib.Geometry.CalculateLatOffsetGPS($('#shiftAmount').val(), wLib.Geometry.ConvertTo4326(segObj.geometry.components[0].x, segObj.geometry.components[0].y)); ShiftSegmentNodesLat(segObj, gpsOffsetAmount); } } //Down function RAShiftDownBtnClick(e) { // this traps the click to prevent it falling through to the underlying area name element and potentially causing the map view to be relocated to that area... e.stopPropagation(); if(!pendingChanges){ var segObj = W.selectionManager.selectedItems[0]; var gpsOffsetAmount = wLib.Geometry.CalculateLatOffsetGPS(-$('#shiftAmount').val(), wLib.Geometry.ConvertTo4326(segObj.geometry.components[0].x, segObj.geometry.components[0].y)); ShiftSegmentNodesLat(segObj, gpsOffsetAmount); } } })();