您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Draws angles for typical roundabout and overlays helper line to adjust geometry of roundabout.
- // ==UserScript==
- // @name WME Roundabout Angles
- // @namespace http://userscripts.org/scripts/show/440831
- // @description Draws angles for typical roundabout and overlays helper line to adjust geometry of roundabout.
- // @include https://www.waze.com/editor/*
- // @include https://www.waze.com/*/editor/*
- // @include https://editor-beta.waze.com/*
- // @version 1.06
- // @grant none
- // @copyright 2014 wlodek76
- // @copyright 2014,2016 FZ69617
- // ==/UserScript==
- /*
- * Version history:
- *
- * 1.06 (20160405)
- * - New: Roundabount Angles layer enablement persisted in local storege.
- * - New: Added yellow color marker for uncertain angles.
- * - Change: Roundabount center taken from junction model geomentry if available.
- * - Change: Logic slightly modified in order to better support various roundabount types.
- * - Other: Minor code refactoring and cleanup.
- *
- * 1.05 (20141002)
- * - New: Added support for roundabouts with 1 or 2 nodes.
- * - Improvement: Simplified roundabout markers starts displaying at zoom level 1.
- * - Improvement: Minimal required zoom level to compute roundabout angles changed to 5 (was 6).
- * - Improvement: Light blue marker circle is now displayed only with roundabouts for which the script
- * can measure angles. The other roundabouts (with more than 4 nodes) are displayed a bit darker.
- * - Optimization: Significantly improved script execution performance.
- *
- * 1.04.1 (20141001)
- * - Fix: Adapted to WME v1.6-297 by FZ69617.
- */
- var wmech_version = "1.06"
- //---------------------------------------------------------------------------------------
- function bootstrapRoundaboutAngles()
- {
- var bGreasemonkeyServiceDefined = false;
- try {
- bGreasemonkeyServiceDefined = (typeof Components.interfaces.gmIGreasemonkeyService === "object");
- }
- catch (err) { /* Ignore */ }
- if (typeof unsafeWindow === "undefined" || ! bGreasemonkeyServiceDefined) {
- unsafeWindow = ( function () {
- var dummyElem = document.createElement('p');
- dummyElem.setAttribute('onclick', 'return window;');
- return dummyElem.onclick();
- }) ();
- }
- /* begin running the code! */
- setInterval(DrawRoundaboutAngles, 500);
- // setInterval( function() {
- // console.time('DrawRoundaboutAngles');
- // DrawRoundaboutAngles();
- // console.timeEnd('DrawRoundaboutAngles');
- // }, 500 );
- console.log("WME Roundabout Angles " + wmech_version + " started.");
- }
- //---------------------------------------------------------------------------------------
- function DrawRoundaboutAngles()
- {
- if (Waze == null || Waze.map == null || Waze.model == null || OpenLayers == null) return;
- //---------get or create layer
- var layers = Waze.map.getLayersBy("uniqueName","__DrawRoundaboutAngles");
- var drc_layer;
- if(layers.length > 0) {
- drc_layer = layers[0];
- } else {
- var drc_style = new OpenLayers.Style({
- fillOpacity: 0.0,
- strokeOpacity: 1.0,
- fillColor: "#FF40C0",
- strokeColor: "${strokeColor}",
- strokeWidth: 10,
- fontWeight: "bold",
- pointRadius: 0,
- label : "${labelText}",
- fontFamily: "Tahoma, Courier New",
- labelOutlineColor: "#FFFFFF",
- labelOutlineWidth: 3,
- fontColor: "${labelColor}",
- fontSize: "10px"
- });
- drc_layer = new OpenLayers.Layer.Vector("Roundabout Angles", {
- displayInLayerSwitcher: true,
- uniqueName: "__DrawRoundaboutAngles",
- styleMap: new OpenLayers.StyleMap(drc_style)
- });
- I18n.translations.en.layers.name["__DrawRoundaboutAngles"] = "Roundabout Angles";
- Waze.map.addLayer(drc_layer);
- drc_layer.setVisibility(localStorage.WMERAEnabled == "true");
- }
- localStorage.WMERAEnabled = drc_layer.visibility;
- if (drc_layer.visibility == false) {
- drc_layer.removeAllFeatures();
- return;
- }
- if (Waze.map.zoom < 1) {
- drc_layer.removeAllFeatures();
- return;
- }
- //---------collect all roundabouts first
- var rsegments = {};
- for (var iseg in Waze.model.segments.objects) {
- var isegment = Waze.model.segments.get(iseg);
- var iattributes = isegment.attributes;
- var iline = isegment.geometry.id;
- var irid = iattributes.junctionID;
- if (iline !== null && irid != undefined) {
- var rsegs = rsegments[irid];
- if (rsegs == undefined) {
- rsegments[irid] = rsegs = new Array();
- }
- rsegs.push(isegment);
- }
- }
- // var rcount = 0, scount = 0;
- // for (var irid in rsegments) {
- // var rsegs = rsegments[irid];
- // scount += rsegs.length;
- // ++rcount;
- // }
- // console.log("Roundabouts found: " + rcount + ", segments: " + scount);
- var drc_features = [];
- //-------for each roundabout do...
- for (var irid in rsegments) {
- var rsegs = rsegments[irid];
- var isegment = rsegs[0];
- var jsegment;
- var nodes = new Array();
- var nodes_x = new Array();
- var nodes_y = new Array();
- for (var j = 0; j < rsegs.length; ++j) {
- jsegment = rsegs[j];
- var jattributes = jsegment.attributes;
- if (nodes.indexOf(jattributes.fromNodeID) == -1) {
- nodes.push(jattributes.fromNodeID);
- }
- if (nodes.indexOf(jattributes.toNodeID) == -1) {
- nodes.push(jattributes.toNodeID);
- }
- }
- var node_objects = Waze.model.nodes.getByIds(nodes);
- for (var i=0; i < node_objects.length; ++i) {
- var node = node_objects[i];
- nodes_x.push(node.geometry.x);
- nodes_y.push(node.geometry.y);
- }
- var sr_x = 0;
- var sr_y = 0;
- var radius = 0;
- var numNodes = nodes_x.length;
- if (numNodes >= 1) {
- //-----------throw short segments
- /* while (nodes_x.length > 4) {
- var id = 0;
- var dmin = 99999999;
- for(var i=0; i<nodes_x.length; i++) {
- for(var j=0; j<nodes_x.length; j++) {
- if (i == j) continue;
- var x1 = nodes_x[i];
- var y1 = nodes_y[i];
- var x2 = nodes_x[j];
- var y2 = nodes_y[j];
- var dx = x1 - x2;
- var dy = y1 - y2;
- var d = dx*dx + dy*dy;
- if (d < dmin) { dmin = d; id = i; }
- }
- }
- nodes_x.splice(id, 1);
- nodes_y.splice(id, 1);
- } */
- var ax = nodes_x[0];
- var ay = nodes_y[0];
- var junction = Waze.model.junctions.get(irid);
- var junction_coords = junction && junction.geometry && junction.geometry.coordinates;
- if (junction_coords && junction_coords.length == 2) {
- //---------- get center point from junction model
- var lonlat = new OpenLayers.LonLat(junction_coords[0], junction_coords[1]);
- lonlat.transform(Waze.map.displayProjection, Waze.map.projection);
- var pt = lonlat.toPoint();
- sr_x = pt.x;
- sr_y = pt.y;
- }
- else if (numNodes >= 3) {
- //-----------simple approximation of centre point calculated from three first points
- var bx = nodes_x[1];
- var by = nodes_y[1];
- var cx = nodes_x[2];
- var cy = nodes_y[2];
- var x1 = (bx + ax) * 0.5;
- var y11 = (by + ay) * 0.5;
- var dy1 = bx - ax;
- var dx1 = -(by - ay);
- var x2 = (cx + bx) * 0.5;
- var y2 = (cy + by) * 0.5;
- var dy2 = cx - bx;
- var dx2 = -(cy - by);
- sr_x = (y11 * dx1 * dx2 + x2 * dx1 * dy2 - x1 * dy1 * dx2 - y2 * dx1 * dx2)/ (dx1 * dy2 - dy1 * dx2);
- sr_y = (sr_x - x1) * dy1 / dx1 + y11;
- }
- else {
- //---------- simple bounds-based calculation of center point
- var rbounds = new OpenLayers.Bounds();
- rbounds.extend(isegment.geometry.bounds);
- rbounds.extend(jsegment.geometry.bounds);
- var center = rbounds.getCenterPixel();
- sr_x = center.x;
- sr_y = center.y;
- }
- var angles = [];
- var rr = -1;
- var r_ix;
- for(var i=0; i<nodes_x.length; i++) {
- var dx = nodes_x[i] - sr_x;
- var dy = nodes_y[i] - sr_y;
- var rr2 = dx*dx + dy*dy;
- if (rr < rr2) {
- rr = rr2;
- r_ix = i;
- }
- var angle = Math.atan2(dy, dx);
- angle = (360.0 + (angle * 180.0 / Math.PI));
- if (angle < 0.0) angle += 360.0;
- if (angle > 360.0) angle -= 360.0;
- angles.push(angle);
- }
- radius = Math.sqrt(rr);
- //---------sorting angles for calulating angle difference between two segments
- angles = angles.sort(function(a,b) { return a - b; });
- angles.push( angles[0] + 360.0);
- angles = angles.sort(function(a,b) { return a - b; });
- //console.log(angles);
- var drc_color = (numNodes <= 4) ? "#0040FF" : "#002080";
- var drc_point = new OpenLayers.Geometry.Point(sr_x, sr_y );
- var drc_circle = new OpenLayers.Geometry.Polygon.createRegularPolygon( drc_point, radius, 10 * Waze.map.zoom );
- var drc_feature = new OpenLayers.Feature.Vector(drc_circle, {labelText: "", labelColor: "#000000", strokeColor: drc_color, } );
- drc_features.push(drc_feature);
- if (numNodes >= 2 && numNodes <= 4 && Waze.map.zoom >= 5) {
- for(var i=0; i<nodes_x.length; i++) {
- var ix = nodes_x[i];
- var iy = nodes_y[i];
- var startPt = new OpenLayers.Geometry.Point( sr_x, sr_y );
- var endPt = new OpenLayers.Geometry.Point( ix, iy );
- var line = new OpenLayers.Geometry.LineString([startPt, endPt]);
- var style = {strokeColor:drc_color, strokeWidth:2};
- var fea = new OpenLayers.Feature.Vector(line, {}, style);
- drc_features.push(fea);
- }
- var angles_int = [];
- var angles_float = [];
- var angles_sum = 0;
- for(var i=0; i<angles.length - 1; i++) {
- var ang = angles[i+1] - angles[i+0];
- if (ang < 0) ang += 360.0;
- if (ang < 0) ang += 360.0;
- if (ang < 135.0) {
- ang = ang - 90.0;
- }
- else {
- ang = ang - 180.0;
- }
- angles_sum += parseInt(ang);
- angles_float.push( ang );
- angles_int.push( parseInt(ang) );
- }
- if (angles_sum > 45) angles_sum -= 90;
- if (angles_sum > 45) angles_sum -= 90;
- if (angles_sum > 45) angles_sum -= 90;
- if (angles_sum > 45) angles_sum -= 90;
- if (angles_sum < -45) angles_sum += 90;
- if (angles_sum < -45) angles_sum += 90;
- if (angles_sum < -45) angles_sum += 90;
- if (angles_sum < -45) angles_sum += 90;
- if (angles_sum != 0) {
- for(var i=0; i<angles_int.length; i++) {
- var a = angles_int[i];
- var af = angles_float[i] - angles_int[i];
- if ( (a < 10 || a > 20) && (af < -0.5 || af > 0.5) ) {
- angles_int[i] += -angles_sum;
- break;
- }
- }
- }
- if (numNodes == 2) {
- angles_int[1] = -angles_int[0];
- angles_float[1] = -angles_float[0];
- }
- for(var i=0; i<angles.length - 1; i++) {
- var arad = (angles[i+0] + angles[i+1]) * 0.5 * Math.PI / 180.0;
- var ex = sr_x + Math.cos (arad) * radius * 0.5;
- var ey = sr_y + Math.sin (arad) * radius * 0.5;
- var angint = angles_int[i];
- var kolor = "#004000";
- if (angint <= -15 || angint >= 15) kolor = "#FF0000";
- else if (angint <= -13 || angint >= 13) kolor = "#FFC000";
- var pt = new OpenLayers.Geometry.Point(ex, ey);
- drc_features.push(new OpenLayers.Feature.Vector( pt, {labelText: (angint + "°"), labelColor: kolor } ));
- //drc_features.push(new OpenLayers.Feature.Vector( pt, {labelText: (+angles_float[i].toFixed(2) + "°"), labelColor: kolor } ));
- }
- }
- else {
- for(var i=0; i < nodes_x.length; i++) {
- var ix = nodes_x[i];
- var iy = nodes_y[i];
- var startPt = new OpenLayers.Geometry.Point( sr_x, sr_y );
- var endPt = new OpenLayers.Geometry.Point( ix, iy );
- var line = new OpenLayers.Geometry.LineString([startPt, endPt]);
- var style = {strokeColor:drc_color, strokeWidth:2};
- var fea = new OpenLayers.Feature.Vector(line, {}, style);
- drc_features.push(fea);
- }
- }
- var p1 = new OpenLayers.Geometry.Point( nodes_x[r_ix], nodes_y[r_ix] );
- var p2 = new OpenLayers.Geometry.Point( sr_x, sr_y );
- var line = new OpenLayers.Geometry.LineString([p1, p2]);
- var geo_radius = line.getGeodesicLength(Waze.map.projection);
- var diam = geo_radius * 2.0;
- var pt = new OpenLayers.Geometry.Point(sr_x, sr_y);
- drc_features.push(new OpenLayers.Feature.Vector( pt, {labelText: (diam.toFixed(0) + "m"), labelColor: "#000000" } ));
- }
- }
- drc_layer.removeAllFeatures();
- drc_layer.addFeatures(drc_features);
- }
- //---------------------------------------------------------------------------------------
- bootstrapRoundaboutAngles();