// ==UserScript==
// @name WME RA Util
// @namespace https://gf.qytechs.cn/users/30701-justins83-waze
// @version 0.1.2
// @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://gf.qytechs.cn/scripts/23614-wlibext/code/wLibExt.js?version=150020
// @author JustinS83
// @grant none
// ==/UserScript==
(function() {
'use strict';
var RAUtilWindow = null;
var UpdateSegmentGeometry = require('Waze/Action/UpdateSegmentGeometry');
var MoveNode = require("Waze/Action/MoveNode");
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 = 'aliceblue';
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:LightGreen; font-weight: bold;">Roundabout adjustment tools</div>';
alertsHTML += '<div id="content" style="padding: 4px; background-color:White">Shift the roundabout by the configured amount.';//<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;">';
//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 += ' ';
alertsHTML += '<span id="RAShiftLeftBtn" style="cursor:pointer;font-size:14px;border:thin outset black;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 += ' ';
alertsHTML += '<span id="RAShiftRightBtn" style="cursor:pointer;font-size:14px;border:thin outset black;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 += '</br>';
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 += '</div>';
alertsHTML += '</br>';
/*
//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);
//document.getElementById('RAShiftDoubleLeftBtn').addEventListener('click', RAShiftDoubleLeftBtnClick, false);
//document.getElementById('RAShiftDoubleRightBtn').addEventListener('click', RAShiftDoubleRightBtnClick, false);
//document.getElementById('RAShiftDoubleUpBtn').addEventListener('click', RAShiftDoubleUpBtnClick, false);
//document.getElementById('RAShiftDoubleDownBtn').addEventListener('click', RAShiftDoubleDownBtnClick, false);
window.Waze.selectionManager.events.register("selectionchanged", null, checkDisplayTool);
}
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'});
$('#RAUtilWindow' ).draggable();
}
}
else{
$('#RAUtilWindow').css({'visibility': 'hidden'});
$('#RAUtilWindow' ).draggable();
}
}
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));
}
}
function ShiftSegmentsNodesLong(segObj, longOffset)
{
var RASegs = wLib.Model.getAllRoundaboutSegmentsFromObj(segObj);
var gps, newGeometry, originalLength;
//Loop through all RA segments & adjust
console.log(RASegs.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.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));
}
}
//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();
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();
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();
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();
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);
}
})();