// ==UserScript==
// @name WME Bad Junction Angle Info
// @description Shows "Bad Angle Infos" of all Junctions in the editing area
// @include /^https:\/\/(www|beta)\.waze\.com\/(?!user\/)(.{2,6}\/)?editor.*$
// @require https://gf.qytechs.cn/scripts/24851-wazewrap/code/WazeWrap.js
// @version 1.9.0
// @grant none
// @namespace https://wms.kbox.at/
// @copyright 2021 Gerhard; 2018 seb-d59, 2016 Michael Wikberg <[email protected]>
// @license CC-BY-NC-SA
// @icon data:image/png;base64,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
// ==/UserScript==
/**
* This script is based on the code from "WME Junction angle Info".
* Thanks for the great work to the authors of the original script:
*/
/**
* Copyright 2016 Michael Wikberg <[email protected]>
* WME Junction Angle Info extension is licensed under a Creative Commons
* Attribution-NonCommercial-ShareAlike 3.0 Unported License.
*
* Contributions by:
* 2014 Paweł Pyrczak "tkr85" <[email protected]>
* 2014 "AlanOfTheBerg" <[email protected]>
* 2014 "berestovskyy" <?>
* 2015 "FZ69617" <?>
* 2015 "wlodek76" <?>
* 2016 Sergey Kuznetsov "WazeRus" <[email protected]> (Russian translation)
* 2016 "MajkiiTelini" <?> Czech translation
* 2016 "witoco" <?> (Latin-American Spanish translation)
* 2017 "seb-d59" (Check override instruction and French translation) <https://www.waze.com/forum/memberlist.php?mode=viewprofile&u=16863068>
* 2019 thank to Sapozhnik for the Ukrainian (український) translation
*/
/*jshint eqnull:true, nonew:true, nomen:true, curly:true, latedef:true, unused:strict, noarg:true, loopfunc:true */
/*jshint trailing:true, forin:true, noempty:true, maxparams:7, maxerr:100, eqeqeq:true, strict:true, undef:true */
/*jshint bitwise:true, newcap:true, immed:true, onevar:true, browser:true, nonbsp:true, freeze:true */
/*global I18n, $*/
/* global _ */
/* global W */
/* global WazeWrap */
function run_aja() {
"use strict";
// var TURN_ANGLE = 45.50; //Turn vs. keep angle - based on map experiments (45.04 specified in Wiki).
// var GRAY_ZONE = 1.5; //Gray zone angle intended to prevent from irregularities observed on map.
/*
* First some variable and enumeration definitions
*/
var junctionangle_version = "1.2.5";
var name = "Bad Junction Angle Info";
var junctionangle_debug = 0; //0: no output, 1: basic info, 2: debug 3: verbose debug, 4: insane debug
var aja_last_restart = 0;
var aja_roundabout_points = [];
var aja_options = {};
var aja_mapLayer;
var scriptenabled = true;
var pointSize = 12;
var decimals = 2;
/*
* Main logic functions
*/
function junctionangle_init() {
// Register event listeners
WazeWrap.Events.register('selectionchanged', null, aja_calculate);
WazeWrap.Events.register('moveend', null, aja_calculate);
WazeWrap.Events.register('afteraction', null, aja_calculate);
WazeWrap.Events.register('moveend', null, aja_calculate);
window.W.model.segments.on({
"objectschanged": aja_calculate,
"objectsremoved": aja_calculate
});
window.W.model.nodes.on({
"objectschanged": aja_calculate,
"objectsremoved": aja_calculate
});
window.W.map.getOLMap().events.register("zoomend", null, aja_calculate);
window.W.map.getOLMap().events.register("move", null, aja_calculate);
//Add support for translations. Default (and fallback) is "en".
//Note, don't make typos in "acceleratorName", as it has to match the layer name (with whitespace removed)
// to actually work. Took me a while to figure that out...
I18n.translations[window.I18n.locale].layers.name.alljunction_angles = name;
/**
* Initialize BJAI OpenLayers vector layer
*/
if (window.W.map.getLayersBy("uniqueName","alljunction_angles").length === 0) {
// Create a vector layer and give it your style map.
aja_mapLayer = new window.OpenLayers.Layer.Vector(name, {
displayInLayerSwitcher: true,
uniqueName: "alljunction_angles",
shortcutKey: "S+j",
accelerator: "toggle" + name.replace(/\s+/g,''),
className: "alljunction-angles",
styleMap: new window.OpenLayers.StyleMap(aja_style())
});
window.W.map.addLayer(aja_mapLayer);
aja_log("version " + junctionangle_version + " loaded.", 0);
aja_log(window.W.map, 3);
aja_log(window.W.model, 3);
aja_log(window.W.loginManager, 3);
aja_log(window.W.selectionManager, 3);
aja_log(aja_mapLayer, 3);
aja_log(window.OpenLayers, 3);
} else {
aja_log("Oh, nice.. We already had a layer?", 3);
}
WazeWrap.Interface.AddLayerCheckbox("display", "Bad Junction Angle Info", true, LayerToggled);
aja_apply();
// MTE mode event
// reload after changing WME units
W.prefs.on('change:isImperial', function(){
aja_apply();
});
aja_calculate();
}
function LayerToggled(checked){
aja_mapLayer.setVisibility(checked);
scriptenabled = checked;
}
function findLayer(partOf_id){
var layer;
for (var i=0; i < window.W.map.layers.length; i++){
if (window.W.map.layers[i].id.search(partOf_id) != -1){
layer={id: window.W.map.layers[i].id, name: window.W.map.layers[i].name, number : i};
aja_log("Number: " + i + "; id : " + layer.id + "; name :" + layer.name ,3);
return layer;
}
}
}
function testLayerZIndex(){
// seb-d59:
// Here i search the selection layer and i read the z-index
// and put BJAI's layer under this one.
var zIndex = 0;
aja_mapLayer.setZIndex(500);
// now selection layer has no name ...
var layer = {}
layer = findLayer("OpenLayers_Layer_Vector_RootContainer");
var layerOBJ = window.W.map.layers[layer.number];
//aja_log("id : " + layerOBJ.id + "; name :" + layerOBJ.name + " zIndex: " + layerOBJ.getZIndex() ,3);
zIndex = parseInt(layerOBJ.getZIndex()) - 1 ;
aja_mapLayer.setZIndex(zIndex);
aja_log("aja_mapLayer new zIndex: " + aja_mapLayer.getZIndex() ,3);
}
function aja_calculate_real() {
var aja_start_time = Date.now();
var aja_nodes = [];
var restart = false;
aja_log("Actually calculating now", 2);
aja_roundabout_points = [];
aja_log(window.W.map, 3);
if (typeof aja_mapLayer === 'undefined') {
return;
}
//clear old info
aja_mapLayer.destroyFeatures();
testLayerZIndex();
if (!scriptenabled) return;
_.each(W.model.segments.getObjectArray(), s => {
if(![5, 10, 16, 18, 19].includes(s.attributes.roadType)){
let segmentsAtt = s.attributes;
if (segmentsAtt.fromNodeID != null &&
aja_nodes.indexOf(segmentsAtt.fromNodeID) === -1) {
aja_nodes.push(segmentsAtt.fromNodeID);
}
if (segmentsAtt.toNodeID != null &&
aja_nodes.indexOf(segmentsAtt.toNodeID) === -1) {
aja_nodes.push(segmentsAtt.toNodeID);
}
}
});
aja_log(aja_nodes, 3);
var aja_label_distance;
/*
* Define a base distance to markers, depending on the zoom level
*/
switch (window.W.map.getOLMap().zoom) {
case 22: //10:
aja_label_distance = 2.8;
break;
case 21: //9:
aja_label_distance = 4;
break;
case 20: //8:
aja_label_distance = 8;
break;
case 19: //7:
aja_label_distance = 15;
break;
case 18: //6:
aja_label_distance = 25;
break;
case 17: //5:
aja_label_distance = 40;
break;
case 16: //4:
aja_label_distance = 80;
break;
case 15: //3:
aja_label_distance = 150;
break;
case 14: //2:
aja_label_distance = 300;
break;
case 13: //1:
aja_label_distance = 400;
break;
default:
aja_log("Unsupported zoom level: " + window.W.map.getOLMap().zoom + "!", 2);
}
aja_label_distance *= (1 + (0.2 * parseInt(decimals)));
aja_log("zoom: " + window.W.map.getOLMap().zoom + " -> distance: " + aja_label_distance, 2);
//Start looping through selected nodes
for (var i = 0; i < aja_nodes.length; i++) {
var node = getByID(window.W.model.nodes,aja_nodes[i]);
var angles = [];
var aja_selected_segments_count = 0;
var aja_selected_angles = [];
var a;
if (node == null || !node.hasOwnProperty('attributes')) {
//Oh oh.. should not happen? We want to use a node that does not exist
aja_log("Oh oh.. should not happen?",2);
aja_log(node, 2);
aja_log(aja_nodes[i], 2);
aja_log(window.W.model, 3);
aja_log(window.W.model.nodes, 3);
continue;
}
//check connected segments
var aja_current_node_segments = node.attributes.segIDs;
aja_log("Alle aja_current_node_segments",2);
aja_log(aja_current_node_segments.length,2);
aja_log(node, 2);
// Remove non driveable Segments
for( var ii = 0; ii < aja_current_node_segments.length; ii++){
if([5, 10, 16, 18, 19].includes(window.W.model.segments.objects[aja_current_node_segments[ii]].attributes.roadType)){
aja_current_node_segments.splice(ii, 1);
ii--;
}
}
aja_log(aja_current_node_segments.length,2);
//ignore of we have less than 2 segments
if (aja_current_node_segments.length <= 2) {
aja_log("Found only " + aja_current_node_segments.length + " connected segments at " + aja_nodes[i] +
", not calculating anything...", 2);
continue;
}
aja_log("Mehr als 2 aja_current_node_segments",2);
aja_log(aja_current_node_segments.length,2);
aja_log("Calculating angles for " + aja_current_node_segments.length + " segments", 2);
aja_log(aja_current_node_segments, 3);
aja_current_node_segments.forEach(function (nodeSegment, j) {
var s = window.W.model.segments.objects[nodeSegment];
if(typeof s === 'undefined') {
//Meh. Something went wrong, and we lost track of the segment. This needs a proper fix, but for now
// it should be sufficient to just restart the calculation
aja_log("Failed to read segment data from model. Restarting calculations.", 1);
if(aja_last_restart === 0) {
aja_last_restart = new Date().getTime();
setTimeout(function(){aja_calculate();}, 500);
}
restart = true;
}
a = aja_getAngle(aja_nodes[i], s);
aja_log("Segment " + nodeSegment + " angle is " + a, 2);
angles[j] = [a, nodeSegment, s == null ? false : true];
if (s == null ? false : true) {
aja_selected_segments_count++;
}
});
if(restart) { return; }
aja_log(angles, 2);
var ha, point;
//sort angle data (ascending)
angles.sort(function (a, b) {
return a[0] - b[0];
});
aja_log(angles, 3);
aja_log(aja_selected_segments_count, 3);
//get all segment angles
for (var iii = 0; iii < angles.length - 1; iii++) {
for (var jjj = iii + 1; jjj < angles.length; jjj++) {
a = (360 + (angles[(jjj) % angles.length][0] - angles[iii][0])) % 360;
if (a > 180) {
a = 360 - a;
ha = (360 + ((a / 2) + angles[jjj][0])) % 360;
} else {
ha = (360 + ((a / 2) + angles[iii][0])) % 360;
}
aja_log(a,3);
aja_log("Angle between " + angles[iii][1] + " and " + angles[(jjj) % angles.length][1] + " is " +
a + " and position for label should be at " + ha, 1);
// if (a < 10.26 || (a > 133 && a < 136 )) {
if ((a > 133 && a < 136 )) {
point = new window.OpenLayers.Geometry.Point(
node.geometry.x + (aja_label_distance * 1.25 * Math.cos((ha * Math.PI) / 180)),
node.geometry.y + (aja_label_distance * 1.25 * Math.sin((ha * Math.PI) / 180))
);
aja_draw_marker(point, node, aja_label_distance, a, ha);
}
}
}
}
aja_last_restart = 0;
var aja_end_time = Date.now();
aja_log("Calculation took " + String(aja_end_time - aja_start_time) + " ms", 2);
}
/*
* Drawing functions
*/
/**
*
* @param point Estimated point for marker
* @param node Node the marker is for
* @param aja_label_distance Arbitrary distance to be used in moving markers further away etc
* @param a Angle to display
* @param ha Angle to marker from node (FIXME: either point or ha is probably unnecessary)
* @param withRouting true: show routing guessing markers, false: show "normal" angle markers
* @param aja_junction_type If using routing, this needs to be set to the desired type
*/
function aja_draw_marker(point, node, aja_label_distance, a, ha, withRouting, aja_junction_type) {
//Try to estimate of the point is "too close" to another point
//(or maybe something else in the future; like turn restriction arrows or something)
//FZ69617: Exctract initial label distance from point
var aja_tmp_distance = Math.abs(ha) % 180 < 45 || Math.abs(ha) % 180 > 135 ?
(point.x - node.geometry.x) / (Math.cos((ha * Math.PI) / 180)) :
(point.y - node.geometry.y) / (Math.sin((ha * Math.PI) / 180));
aja_log("Starting distance estimation", 3);
while(aja_mapLayer.features.some(function(feature){
if(typeof feature.attributes.aja_type !== 'undefined' && feature.attributes.aja_type !== 'roundaboutOverlay') {
//Arbitrarily chosen minimum distance.. Should actually use the real bounds of the markers,
//but that didn't work out.. Bounds are always 0..
if(aja_label_distance / 1.4 > feature.geometry.distanceTo(point)) {
aja_log(aja_label_distance / 1.5 > feature.geometry.distanceTo(point) + " is kinda close..", 3);
return true;
}
}
return false;
})) {
//add 1/4 of the original distance and hope for the best =)
aja_tmp_distance += aja_label_distance / 4;
aja_log("setting distance to " + aja_tmp_distance, 2);
point = new window.OpenLayers.Geometry.Point(
node.geometry.x + (aja_tmp_distance * Math.cos((ha * Math.PI) / 180)),
node.geometry.y + (aja_tmp_distance * Math.sin((ha * Math.PI) / 180))
);
}
aja_log("Distance estimation done", 3);
var anglePoint = new window.OpenLayers.Feature.Vector(
point,
{ angle: aja_round(180 - a) + "°", aja_type: "generic" }
);
aja_log(anglePoint, 3);
//Draw a line to the point
aja_mapLayer.addFeatures([
new window.OpenLayers.Feature.Vector(
new window.OpenLayers.Geometry.LineString([node.geometry, point]),
{},
{strokeOpacity: 0.9, strokeWidth: 2.2, strokeDashstyle: "solid", strokeColor: "#ff9966"}
)
]
);
//push the angle point
aja_mapLayer.addFeatures([anglePoint]);
}
function aja_get_first_point(segment) {
return segment.geometry.components[0];
}
function aja_get_last_point(segment) {
return segment.geometry.components[segment.geometry.components.length - 1];
}
function aja_get_second_point(segment) {
return segment.geometry.components[1];
}
function aja_get_next_to_last_point(segment) {
return segment.geometry.components[segment.geometry.components.length - 2];
}
//get the absolute angle for a segment end point
function aja_getAngle(aja_node, aja_segment) {
aja_log("node: " + aja_node, 2);
aja_log("segment: " + aja_segment, 2);
if (aja_node == null || aja_segment == null) { return null; }
var aja_dx, aja_dy;
if (aja_segment.attributes.fromNodeID === aja_node) {
aja_dx = aja_get_second_point(aja_segment).x - aja_get_first_point(aja_segment).x;
aja_dy = aja_get_second_point(aja_segment).y - aja_get_first_point(aja_segment).y;
} else {
aja_dx = aja_get_next_to_last_point(aja_segment).x - aja_get_last_point(aja_segment).x;
aja_dy = aja_get_next_to_last_point(aja_segment).y - aja_get_last_point(aja_segment).y;
}
aja_log(aja_node + " / " + aja_segment + ": dx:" + aja_dx + ", dy:" + aja_dy, 2);
var aja_angle = Math.atan2(aja_dy, aja_dx);
return ((aja_angle * 180 / Math.PI)) % 360;
}
/**
* Decimal adjustment of a number. Borrowed (with some modifications) from
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
* aja_round(55.55); with 1 decimal // 55.6
* aja_round(55.549); with 1 decimal // 55.5
* aja_round(55); with -1 decimals // 60
* aja_round(54.9); with -1 decimals // 50
*
* @param {Number} value The number.
* @returns {Number} The adjusted value.
*/
function aja_round(value) {
var aja_rounding = -parseInt(decimals);
var valueArray;
if (typeof aja_rounding === 'undefined' || +aja_rounding === 0) {
return Math.round(value);
}
value = +value;
// If the value is not a number or the exp is not an integer...
if (isNaN(value) || !(typeof aja_rounding === 'number' && aja_rounding % 1 === 0)) {
return NaN;
}
// Shift
valueArray = value.toString().split('e');
value = Math.round(+(valueArray[0] + 'e' + (valueArray[1] ? (+valueArray[1] - aja_rounding) : -aja_rounding)));
// Shift back
valueArray = value.toString().split('e');
return +(valueArray[0] + 'e' + (valueArray[1] ? (+valueArray[1] + aja_rounding) : aja_rounding));
}
/*
* WME interface helper functions
*/
var aja_apply = function applyAJAOptions() {
aja_log("Applying stored (or default) settings", 2);
if(typeof window.W.map.getLayersBy("uniqueName","alljunction_angles")[0] === 'undefined') {
aja_log("WME not ready yet, trying again in 400 ms", 2);
setTimeout(function(){aja_apply();}, 400);
return;
}
window.W.map.getLayersBy("uniqueName","alljunction_angles")[0].styleMap = aja_style();
aja_calculate_real();
aja_log(aja_options, 2);
};
var aja_reset = function resetAJAOptions() {
aja_log("Resetting settings", 2);
if(localStorage != null) {
localStorage.removeItem("wme_bja_options");
}
aja_options = {};
aja_apply();
return false;
};
var aja_calculation_timer = {
start: function() {
aja_log("Starting timer", 2);
this.cancel();
var aja_calculation_timer_self = this;
this.timeoutID = window.setTimeout(function(){aja_calculation_timer_self.calculate();}, 200);
},
calculate: function() {
aja_calculate_real();
delete this.timeoutID;
},
cancel: function() {
if(typeof this.timeoutID === "number") {
window.clearTimeout(this.timeoutID);
aja_log("Cleared timeout ID : " + this.timeoutID, 2);
delete this.timeoutID;
}
}
};
function aja_calculate() {
aja_calculation_timer.start();
}
function aja_style() {
aja_log("Point radius will be: " + (parseInt(pointSize, 10)) +
(parseInt(decimals > 0 ? (4 * parseInt(decimals)).toString() : "0")), 2);
return new window.OpenLayers.Style({
fillColor: "#ffff00",
strokeColor: "#ff9966",
strokeWidth: 2,
label: "${angle}",
fontWeight: "bold",
pointRadius: parseInt(pointSize, 10) +
(parseInt(decimals) > 0 ? 4 * parseInt(decimals) : 0),
fontSize: "10px"
});
}
/*
* Bootstrapping and logging
*/
function aja_bootstrap(retries) {
retries = retries || 0;
//If Waze has not been defined in ~15 seconds, it probably won't work anyway. Might need tuning
//for really slow devices?
if (retries >= 30) {
aja_log("Failed to bootstrap 30 times. Giving up.", 0);
return;
}
try {
//User logged in and WME ready
if (
!(document.querySelector('.list-unstyled.togglers .group') === null) &&
aja_is_model_ready() &&
aja_is_dom_ready() &&
window.W.loginManager.isLoggedIn()) {
setTimeout(function () {
junctionangle_init();
}, 500);
}
//Some part of the WME was not yet fully loaded. Retry.
else {
setTimeout(function () {
aja_bootstrap(++retries);
}, 500);
}
} catch (err) {
aja_log(err, 1);
setTimeout(function () {
aja_bootstrap(++retries);
}, 500);
}
}
function aja_is_model_ready() {
if(typeof window.W === 'undefined' || typeof window.W.map === 'undefined') {
return false;
} else {
//return 'undefined' !== typeof window.W.map.events.register &&
return 'undefined' !== typeof window.W.map.getOLMap().events.register &&
'undefined' !== typeof window.W.selectionManager.events.register &&
'undefined' !== typeof window.W.loginManager.events.register;
}
}
function aja_is_dom_ready() {
if(null === document.getElementById('user-info')) {
return false;
} else {
return document.getElementById('user-info').getElementsByClassName('nav-tabs').length > 0 &&
document.getElementById('user-info').getElementsByClassName('tab-content').length > 0;
}
}
/**
* Debug logging.
* @param aja_log_msg
* @param aja_log_level
*/
function aja_log(aja_log_msg, aja_log_level) {
if(typeof aja_log_level === 'undefined') { aja_log_level = 1; }
if (aja_log_level <= junctionangle_debug) {
if (typeof aja_log_msg === "object") {
console.log(aja_log_msg);
}
else {
console.log("WME Bad JAI: " + aja_log_msg);
}
}
}
function getByID(obj, id){
if (typeof(obj.getObjectById) == "function"){
return obj.getObjectById(id);
}else if (typeof(obj.getObjectById) == "undefined"){
return obj.get(id);
}
}
aja_bootstrap();
}
//Dynamically create, add and run the script in the real page context. We really do need access to many of the objects...
var DLScript = document.createElement("script");
DLScript.textContent = '' +
run_aja.toString() + ' \n' +
'run_aja();';
DLScript.setAttribute("type", "application/javascript");
document.body.appendChild(DLScript);