// ==UserScript== // @name WME RA Util // @namespace https://greasyfork.org/users/30701-justins83-waze // @version 2025.02.02.01 // @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/* // @exclude https://www.waze.com/user/editor* // @require https://greasyfork.org/scripts/24851-wazewrap/code/WazeWrap.js // @connect greasyfork.org // @author JustinS83 // @grant GM_xmlhttpRequest // @license GPLv3 // @contributionURL https://github.com/WazeDev/Thank-The-Authors // @downloadURL none // ==/UserScript== /* global W */ /* global WazeWrap */ /* global OpenLayers */ /* global require */ /* global $ */ /* global _ */ /* global I18n */ /* eslint curly: ["warn", "multi-or-nest"] */ /* non-normal RA color:#FF8000 normal RA color:#4cc600 */ (function() { var RAUtilWindow = null; var UpdateSegmentGeometry; var MoveNode, MultiAction; var drc_layer; let wEvents; const SCRIPT_VERSION = GM_info.script.version.toString(); const SCRIPT_NAME = GM_info.script.name; const DOWNLOAD_URL = GM_info.scriptUpdateURL; //var totalActions = 0; var _settings; const updateMessage = "Fixed center calculation - was using custom calculations (for some reason?) in some cases, which also failed because of WME changes - this caused the RA Angle circles to be drawn off center (sometimes incredibly so). Now always using the RA's center position as defined by WME.

Fixed variable scoping in some areas."; function bootstrap(tries = 1) { if (W && W.map && W.model && require && WazeWrap.Ready){ loadScriptUpdateMonitor(); init(); } else if (tries < 1000) setTimeout(function () {bootstrap(++tries);}, 200); } bootstrap(); function loadScriptUpdateMonitor() { let updateMonitor; try { updateMonitor = new WazeWrap.Alerts.ScriptUpdateMonitor(SCRIPT_NAME, SCRIPT_VERSION, DOWNLOAD_URL, GM_xmlhttpRequest); updateMonitor.start(); } catch (ex) { // Report, but don't stop if ScriptUpdateMonitor fails. console.error(`${SCRIPT_NAME}:`, ex); } } function init(){ injectCss(); UpdateSegmentGeometry = require('Waze/Action/UpdateSegmentGeometry'); MoveNode = require("Waze/Action/MoveNode"); MultiAction = require("Waze/Action/MultiAction"); console.log("RA UTIL"); console.log(GM_info.script); if(W.map.events) wEvents = W.map.events; else wEvents = W.map.getMapEventsListener(); RAUtilWindow = document.createElement('div'); RAUtilWindow.id = "RAUtilWindow"; RAUtilWindow.style.position = 'fixed'; RAUtilWindow.style.visibility = 'hidden'; RAUtilWindow.style.top = '15%'; RAUtilWindow.style.left = '25%'; RAUtilWindow.style.width = '510px'; RAUtilWindow.style.zIndex = 100; RAUtilWindow.style.backgroundColor = '#FFFFFE'; RAUtilWindow.style.borderWidth = '0px'; RAUtilWindow.style.borderStyle = 'solid'; RAUtilWindow.style.borderRadius = '10px'; RAUtilWindow.style.boxShadow = '5px 5px 10px Silver'; RAUtilWindow.style.padding = '4px'; var alertsHTML = ''; // start collapse // I put it al the beginning alertsHTML += '
'; //***************** Round About Angles ************************** alertsHTML += '

 Enable Roundabout Angles

'; //***************** Shift Amount ************************** // Define BOX alertsHTML += '
'; alertsHTML += 'Shift amount
Meter(s)'; // Shift amount controls alertsHTML += '
'; //Single Shift Up Button alertsHTML += ''; alertsHTML += ' '; alertsHTML += ''; alertsHTML += '
'; //Single Shift Left Button alertsHTML += ''; alertsHTML += ' '; alertsHTML += ''; alertsHTML += ''; //Single Shift Right Button alertsHTML += ''; alertsHTML += ' '; alertsHTML += ''; alertsHTML += '
'; //Single Shift Down Button alertsHTML += ''; alertsHTML += ' '; alertsHTML += ''; alertsHTML += ''; alertsHTML += '
'; //***************** Rotation ************************** // Define BOX alertsHTML += '
'; alertsHTML += 'Rotation amount
Degree(s)'; // Rotation controls alertsHTML += '
'; // Rotate Button on the Left alertsHTML += ''; alertsHTML += ' '; alertsHTML += ''; alertsHTML += ''; // Rotate button on the Right alertsHTML += ''; alertsHTML += ' '; alertsHTML += ''; alertsHTML += '
'; //********************* Diameter change ****************** // Define BOX alertsHTML += '
'; alertsHTML += 'Change diameter

'; // Diameter Change controls alertsHTML += '
'; // Decrease Button alertsHTML += ''; alertsHTML += ' '; alertsHTML += ''; alertsHTML += ''; // Increase Button alertsHTML += ''; alertsHTML += ' '; alertsHTML += ''; alertsHTML += ''; alertsHTML += '
'; //***************** Bump nodes ********************** // Define BOX alertsHTML += '
'; alertsHTML += 'Move nodes
'; // Move Nodes controls alertsHTML += '
'; // Button A alertsHTML += '
A Node'; // Move node IN alertsHTML += '

in'; // Move node OUT alertsHTML += 'out'; alertsHTML += '

'; // Button B alertsHTML += '
B Node'; // Move node IN alertsHTML += '

in'; // Move node OUT alertsHTML += 'out'; alertsHTML += '

'; alertsHTML += '
'; RAUtilWindow.innerHTML = alertsHTML; document.body.appendChild(RAUtilWindow); $('#RAShiftLeftBtn').click(RAShiftLeftBtnClick); $('#RAShiftRightBtn').click(RAShiftRightBtnClick); $('#RAShiftUpBtn').click(RAShiftUpBtnClick); $('#RAShiftDownBtn').click(RAShiftDownBtnClick); $('#RARotateLeftBtn').click(RARotateLeftBtnClick); $('#RARotateRightBtn').click(RARotateRightBtnClick); $('#diameterChangeDecreaseBtn').click(diameterChangeDecreaseBtnClick); $('#diameterChangeIncreaseBtn').click(diameterChangeIncreaseBtnClick); $('#btnMoveANodeIn').click(function(){moveNodeIn(WazeWrap.getSelectedFeatures()[0].WW.getObjectModel().attributes.id, WazeWrap.getSelectedFeatures()[0].WW.getObjectModel().attributes.fromNodeID);}); $('#btnMoveANodeOut').click(function(){moveNodeOut(WazeWrap.getSelectedFeatures()[0].WW.getObjectModel().attributes.id, WazeWrap.getSelectedFeatures()[0].WW.getObjectModel().attributes.fromNodeID);}); $('#btnMoveBNodeIn').click(function(){moveNodeIn(WazeWrap.getSelectedFeatures()[0].WW.getObjectModel().attributes.id, WazeWrap.getSelectedFeatures()[0].WW.getObjectModel().attributes.toNodeID);}); $('#btnMoveBNodeOut').click(function(){moveNodeOut(WazeWrap.getSelectedFeatures()[0].WW.getObjectModel().attributes.id, WazeWrap.getSelectedFeatures()[0].WW.getObjectModel().attributes.toNodeID);}); $('#shiftAmount').keypress(function(event) { if ((event.which != 46 || $(this).val().indexOf('.') != -1) && (event.which < 48 || event.which > 57)) event.preventDefault(); }); $('#rotationAmount').keypress(function(event) { if ((event.which != 46 || $(this).val().indexOf('.') != -1) && (event.which < 48 || event.which > 57)) event.preventDefault(); }); $('#collapserLink').click(function(){ $("#divWrappers").slideToggle("fast"); if($('#collapser').attr('class') == "fa fa-caret-square-o-down"){ $("#collapser").removeClass("fa-caret-square-o-down"); $("#collapser").addClass("fa-caret-square-o-up"); } else{ $("#collapser").removeClass("fa-caret-square-o-up"); $("#collapser").addClass("fa-caret-square-o-down"); } saveSettingsToStorage(); }); W.selectionManager.events.register("selectionchanged", null, checkDisplayTool); //W.model.actionManager.events.register("afterundoaction",null, undotriggered); //W.model.actionManager.events.register("afterclearactions",null,actionsCleared); var loadedSettings = $.parseJSON(localStorage.getItem("WME_RAUtil")); var defaultSettings = { divTop: "15%", divLeft: "25%", Expanded: true, RoundaboutAngles: true }; _settings = loadedSettings ? loadedSettings : defaultSettings; $('#RAUtilWindow').css('left', _settings.divLeft); $('#RAUtilWindow').css('top', _settings.divTop); $("#chkRARoundaboutAngles").prop('checked', _settings.RoundaboutAngles); $("#chkRARoundaboutAngles").prop('checked', _settings.RoundaboutAngles); if(!_settings.Expanded){ //$("#divWrappers").removeClass("in"); //$("#divWrappers").addClass("collapse"); $("#divWrappers").hide(); $("#collapser").removeClass("fa-caret-square-o-up"); $("#collapser").addClass("fa-caret-square-o-down"); } $("#chkRARoundaboutAngles").click(function(){ saveSettingsToStorage(); if($("#chkRARoundaboutAngles").is(":checked")){ wEvents.register("zoomend", null, DrawRoundaboutAngles); wEvents.register("moveend", null, DrawRoundaboutAngles); DrawRoundaboutAngles(); drc_layer.setVisibility(true); } else{ wEvents.unregister("zoomend", null, DrawRoundaboutAngles); wEvents.unregister("moveend", null, DrawRoundaboutAngles); drc_layer.setVisibility(false); } }); if(_settings.RoundaboutAngles){ wEvents.register("zoomend", null, DrawRoundaboutAngles); wEvents.register("moveend", null, DrawRoundaboutAngles); DrawRoundaboutAngles(); } WazeWrap.Interface.ShowScriptUpdate("WME RA Util", GM_info.script.version, updateMessage, "https://greasyfork.org/en/scripts/23616-wme-ra-util", "https://www.waze.com/forum/viewtopic.php?f=819&t=211079"); } function saveSettingsToStorage() { if (localStorage) { var settings = { divTop: "15%", divLeft: "25%", Expanded: true, RoundaboutAngles: true }; settings.divLeft = $('#RAUtilWindow').css('left'); settings.divTop = $('#RAUtilWindow').css('top'); settings.Expanded = $("#collapser").attr('class').indexOf("fa-caret-square-o-up") > -1; settings.RoundaboutAngles = $("#chkRARoundaboutAngles").is(":checked"); localStorage.setItem("WME_RAUtil", JSON.stringify(settings)); } } function checkDisplayTool(){ if(WazeWrap.hasSelectedFeatures() && WazeWrap.getSelectedFeatures()[0].WW.getType() === 'segment'){ if(!AllSelectedSegmentsRA() || WazeWrap.getSelectedFeatures().length === 0) $('#RAUtilWindow').css({'visibility': 'hidden'}); else{ $('#RAUtilWindow').css({'visibility': 'visible'}); if(typeof jQuery.ui !== 'undefined') $('#RAUtilWindow' ).draggable({ //Gotta nuke the height setting the dragging inserts otherwise the panel cannot collapse stop: function(event, ui) { $('#RAUtilWindow').css("height", ""); saveSettingsToStorage(); } }); //checkSaveChanges(); checkAllEditable(WazeWrap.Model.getAllRoundaboutSegmentsFromObj(WazeWrap.getSelectedFeatures()[0])); } } else{ $('#RAUtilWindow').css({'visibility': 'hidden'}); if(typeof jQuery.ui !== 'undefined') $('#RAUtilWindow' ).draggable({ stop: function(event, ui) { $('#RAUtilWindow').css("height", ""); saveSettingsToStorage(); } }); } } function checkAllEditable(RASegs){ var $RAEditable = $('#RAEditable'); var allEditable = true; var segObj, fromNode, toNode; for(let i=0; i', {id:'RAEditable', style:'color:red'}); $RAEditable.text('One or more segments are locked above your rank or have a closure.'); $('#RAUtilWindow').append($RAEditable); } } return allEditable; } function AllSelectedSegmentsRA(){ for (let i = 0; i < WazeWrap.getSelectedFeatures().length; i++){ if(WazeWrap.getSelectedFeatures()[i].WW.getObjectModel().attributes.id < 0 || !WazeWrap.Model.isRoundaboutSegmentID(WazeWrap.getSelectedFeatures()[i].WW.getObjectModel().attributes.id)) return false; } return true; } function ShiftSegmentNodesLat(segObj, latOffset){ var RASegs = WazeWrap.Model.getAllRoundaboutSegmentsFromObj(segObj); if(checkAllEditable(RASegs)){ var newGeometry, originalLength; var multiaction = new MultiAction(); // multiaction.setModel(W.model); for(let i=0; i 2) { if(nodeID === curSeg.attributes.toNodeID) isANode = false; //Add geo point on the other segment let node = W.model.nodes.getObjectById(nodeID); let currNodePOS = structuredClone(node.attributes.geoJSONGeometry.coordinates); let otherSeg; //other RA segment that we are adding a geo point to let nodeSegs = [...W.model.nodes.getObjectById(nodeID).attributes.segIDs]; nodeSegs = _.without(nodeSegs, sourceSegID); //remove the source segment from the node Segs - we need to find the segment that is a part of the RA that is prior to our source seg for(let i=0; i 2){ let newSegGeo = structuredClone(curSeg.attributes.geoJSONGeometry); newSegGeo.coordinates.splice(isANode ? 1 : newSegGeo.coordinates.length - 1, 0, [currNodePOS[0], currNodePOS[1]]); var multiaction = new MultiAction(); // multiaction.setModel(W.model); multiaction.doSubAction(W.model, new UpdateSegmentGeometry(curSeg, curSeg.attributes.geoJSONGeometry, newSegGeo)); if((otherSeg.attributes.revDirection && !curSeg.attributes.revDirection) || (!otherSeg.attributes.revDirection && curSeg.attributes.revDirection)) isANode = !isANode; //note and remove first geo point, move junction node to this point var newNodeGeometry = { type: 'Point', coordinates: structuredClone(otherSeg.attributes.geoJSONGeometry.coordinates[isANode ? otherSeg.attributes.geoJSONGeometry.coordinates.length - 2 : 1]) }; let newGeo = structuredClone(otherSeg.attributes.geoJSONGeometry); newGeo.coordinates.splice(isANode ? -2 : 1, 1); multiaction.doSubAction(W.model, new UpdateSegmentGeometry(otherSeg, otherSeg.attributes.geoJSONGeometry, newGeo)); //move the node var connectedSegObjs = {}; var emptyObj = {}; for(var j=0; j < node.attributes.segIDs.length;j++){ var segid = node.attributes.segIDs[j]; connectedSegObjs[segid] = structuredClone(W.model.segments.getObjectById(segid).attributes.geoJSONGeometry); } multiaction.doSubAction(W.model, new MoveNode(node, node.attributes.geoJSONGeometry, newNodeGeometry, connectedSegObjs, emptyObj)); W.model.actionManager.add(multiaction); if(_settings.RoundaboutAngles) DrawRoundaboutAngles(); } } //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 = WazeWrap.getSelectedFeatures()[0]; var convertedCoords = WazeWrap.Geometry.ConvertTo4326(segObj.WW.getAttributes().geoJSONGeometry.coordinates[0][0], segObj.WW.getAttributes().geoJSONGeometry.coordinates[0][1]); var gpsOffsetAmount = WazeWrap.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 = WazeWrap.getSelectedFeatures()[0]; var convertedCoords = WazeWrap.Geometry.ConvertTo4326(segObj.WW.getAttributes().geoJSONGeometry.coordinates[0][0], segObj.WW.getAttributes().geoJSONGeometry.coordinates[0][1]); var gpsOffsetAmount = WazeWrap.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 = WazeWrap.getSelectedFeatures()[0]; var gpsOffsetAmount = WazeWrap.Geometry.CalculateLatOffsetGPS($('#shiftAmount').val(), WazeWrap.Geometry.ConvertTo4326(segObj.WW.getAttributes().geoJSONGeometry.coordinates[0][0], segObj.WW.getAttributes().geoJSONGeometry.coordinates[0][1])); 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 = WazeWrap.getSelectedFeatures()[0]; var gpsOffsetAmount = WazeWrap.Geometry.CalculateLatOffsetGPS(-$('#shiftAmount').val(), WazeWrap.Geometry.ConvertTo4326(segObj.WW.getAttributes().geoJSONGeometry.coordinates[0][0], segObj.WW.getAttributes().geoJSONGeometry.coordinates[0][1])); ShiftSegmentNodesLat(segObj, gpsOffsetAmount); //} } //*************** Roundabout Angles ********************** function DrawRoundaboutAngles(){ //---------get or create layer var layers = W.map.getLayersBy("uniqueName","__DrawRoundaboutAngles"); if(layers.length > 0) drc_layer = layers[0]; else { let 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[I18n.currentLocale()].layers.name["__DrawRoundaboutAngles"] = "Roundabout Angles"; W.map.addLayer(drc_layer); drc_layer.setVisibility(true); } localStorage.WMERAEnabled = drc_layer.visibility; if (drc_layer.visibility == false) { drc_layer.removeAllFeatures(); return; } if (W.map.getZoom() < 1) { drc_layer.removeAllFeatures(); return; } //---------collect all roundabouts first var rsegments = {}; for (let iseg in W.model.segments.objects) { let isegment = W.model.segments.getObjectById(iseg); let iattributes = isegment.attributes; let iline = isegment.getOLGeometry().id; let irid = iattributes.junctionID; if (iline !== null && irid != undefined) { let rsegs = rsegments[irid]; if (rsegs == undefined) rsegments[irid] = rsegs = new Array(); rsegs.push(isegment); } } var drc_features = []; //-------for each roundabout do... for (let irid in rsegments) { let rsegs = rsegments[irid]; let isegment = rsegs[0]; let nodes = []; let nodes_x = []; let nodes_y = []; nodes = rsegs.map(seg => seg.attributes.fromNodeID); //get from nodes nodes = [...nodes, ...rsegs.map(seg => seg.attributes.toNodeID)]; //get to nodes add to from nodes nodes = _.uniq(nodes); //remove duplicates let node_objects = W.model.nodes.getByIds(nodes); nodes_x = node_objects.map(n => n.getOLGeometry().x); //get all x locations nodes_y = node_objects.map(n => n.getOLGeometry().y); //get all y locations let sr_x = 0; let sr_y = 0; let radius = 0; let numNodes = nodes_x.length; if (numNodes >= 1) { let ax = nodes_x[0]; let ay = nodes_y[0]; debugger; let junction = W.model.junctions.getObjectById(irid); //var junction_coords = junction && junction.getOLGeometry() && junction.getOLGeometry().coordinates; // if (junction_coords && junction_coords.length == 2) { //---------- get center point from junction model //let lonlat = new OpenLayers.LonLat(junction_coords[0], junction_coords[1]); //lonlat.transform(W.Config.map.projection.remote, W.Config.map.projection.local); //let pt = new OpenLayers.Geometry.Point(lonlat.lon, lonlat.lat); sr_x = junction.getOLGeometry().x; sr_y = junction.getOLGeometry().y; /** } else if (numNodes >= 3) { //-----------simple approximation of centre point calculated from three first points let bx = nodes_x[1]; let by = nodes_y[1]; let cx = nodes_x[2]; let cy = nodes_y[2]; let x1 = (bx + ax) * 0.5; let y11 = (by + ay) * 0.5; let dy1 = bx - ax; let dx1 = -(by - ay); let x2 = (cx + bx) * 0.5; let y2 = (cy + by) * 0.5; let dy2 = cx - bx; let 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.getOLGeometry().bounds); var center = rbounds.getCenterPixel(); sr_x = center.x; sr_y = center.y; }**/ let angles = []; let rr = -1; let r_ix; for(let i=0; i 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; }); let drc_color = (numNodes <= 4) ? "#0040FF" : "#002080"; let drc_point = new OpenLayers.Geometry.Point(sr_x, sr_y ); let drc_circle = new OpenLayers.Geometry.Polygon.createRegularPolygon( drc_point, radius, 10 * W.map.getZoom() ); let drc_feature = new OpenLayers.Feature.Vector(drc_circle, {labelText: "", labelColor: "#000000", strokeColor: drc_color, }); drc_features.push(drc_feature); if (numNodes >= 2 && numNodes <= 4 && W.map.getZoom() >= 5) { for(let i=0; i 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(let i=0; i 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(let i=0; i= 15) kolor = "#FF0000"; else if (angint <= -13 || angint >= 13) kolor = "#FFC000"; let 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(let i=0; i < nodes_x.length; i++) { let ix = nodes_x[i]; let iy = nodes_y[i]; let startPt = new OpenLayers.Geometry.Point( sr_x, sr_y ); let endPt = new OpenLayers.Geometry.Point( ix, iy ); let line = new OpenLayers.Geometry.LineString([startPt, endPt]); let style = {strokeColor:drc_color, strokeWidth:2}; let fea = new OpenLayers.Feature.Vector(line, {}, style); drc_features.push(fea); } } let p1 = new OpenLayers.Geometry.Point( nodes_x[r_ix], nodes_y[r_ix] ); let p2 = new OpenLayers.Geometry.Point( sr_x, sr_y ); let line = new OpenLayers.Geometry.LineString([p1, p2]); let geo_radius = line.getGeodesicLength(W.map.getProjectionObject()); let diam = geo_radius * 2.0; let center_pt = new OpenLayers.Geometry.Point(sr_x, sr_y); drc_features.push(new OpenLayers.Feature.Vector( center_pt, {labelText: (diam.toFixed(0) + "m"), labelColor: "#000000" } )); } } drc_layer.removeAllFeatures(); drc_layer.addFeatures(drc_features); } function injectCss() { var css = [ '.btnMoveNode {width=25px; height=25px; background-color:#92C3D3; cursor:pointer; padding:5px; font-size:14px; border:thin outset black; border-style:solid; border-width: 1px;border-radius:50%; -moz-border-radius:50%; -webkit-border-radius:50%; box-shadow:inset 0px 0px 20px -14px rgba(0,0,0,1); -moz-box-shadow:inset 0px 0px 20px -14px rgba(0,0,0,1); -webkit-box-shadow: inset 0px 0px 20px -14px rgba(0,0,0,1);}', '.btnRotate { width=45px; height=45px; background-color:#92C3D3; cursor:pointer; padding: 5px; font-size:14px; border:thin outset black; border-style:solid; border-width: 1px;border-radius: 50%;-moz-border-radius: 50%;-webkit-border-radius: 50%;box-shadow: inset 0px 0px 20px -14px rgba(0,0,0,1);-moz-box-shadow: inset 0px 0px 20px -14px rgba(0,0,0,1);-webkit-box-shadow: inset 0px 0px 20px -14px rgba(0,0,0,1);}' ].join(' '); $('').appendTo('head'); } })();