您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Add place entry point indicators to the map
// ==UserScript== // @name WME Place NavPoints // @namespace WazeDev // @version 2024.09.20.000 // @description Add place entry point indicators to the map // @author MapOMatic // @include /^https:\/\/(www|beta)\.waze\.com\/(?!user\/)(.{2,6}\/)?editor.*$/ // @require https://gf.qytechs.cn/scripts/24851-wazewrap/code/WazeWrap.js // @require https://cdn.jsdelivr.net/npm/@turf/turf@7/turf.min.js // @grant GM_xmlhttpRequest // @connect gf.qytechs.cn // ==/UserScript== /* global W */ /* global OpenLayers */ /* global WazeWrap */ /* global turf */ (function main() { 'use strict'; const SCRIPT_NAME = GM_info.script.name; const SCRIPT_VERSION = GM_info.script.version; const DOWNLOAD_URL = 'https://update.gf.qytechs.cn/scripts/387498/WME%20Place%20NavPoints.user.js'; const _settings = { visible: true, plaVisible: true }; let _layer; // NOTE: There are occasions where the street is not loaded in the model yet, and // the WazeWrap getStreetName function will throw an error. This function will // just return null instead. // function getStreetName(primaryStreetID) { // const street = W.model.streets.getObjectById(primaryStreetID); // if (street) { // return street.name; // } // return null; // } function getOLMapExtent() { let extent = new OpenLayers.Bounds(W.map.getExtent()); extent = extent.transform('EPSG:4326', 'EPSG:3857'); return extent; } function drawLines() { _layer.removeAllFeatures(); if (!_settings.visible) return; const features = []; const bounds = getOLMapExtent().scale(2.0); const zoom = W.map.getZoom(); W.model.venues.getObjectArray() .filter(venue => ( _settings.plaVisible || !venue.isParkingLot()) && bounds.intersectsBounds(venue.getOLGeometry().getBounds()) && (zoom >= 6 || (venue.isResidential() && !venue.attributes.entryExitPoints.length))) .forEach(venue => { const pts = []; let mainColor = venue.isPoint() ? '#0FF' : '#0FF'; let endPoint; // Get the places location. const placePoint = venue.getOLGeometry().getCentroid(); pts.push(placePoint); // Get the main entry/exit point, if it exists. let entryExitPoint; if (venue.attributes.entryExitPoints.length) { entryExitPoint = W.userscripts.toOLGeometry(venue.attributes.entryExitPoints[0].getPoint()); endPoint = entryExitPoint; pts.push(entryExitPoint); } else { endPoint = placePoint; } const geoJsonEndPoint = W.userscripts.toGeoJSONGeometry(endPoint); const closestSegment = findClosestSegment(geoJsonEndPoint, false, false); if (closestSegment) { // Find the closest point on the closest segment (the stop point). const stopPoint = turf.nearestPointOnLine(closestSegment.getGeometry(), geoJsonEndPoint).geometry; pts.push(W.userscripts.toOLGeometry(stopPoint)); const placeStreetID = venue.attributes.streetID; if (placeStreetID) { // The intent here was to highlight places that route to a street with a name // other than the place's street name, but I believe that is too common // of a scenario and distracting. Leaving this code here in case we // can tweak it to be more useful somehow. // const segmentStreetID = closestSegment.attributes.primaryStreetID; // const segmentStreetName = getStreetName(segmentStreetID); // const placeStreetName = getStreetName(placeStreetID); // if (segmentStreetName !== placeStreetName) { // mainColor = '#FFA500'; // } } else { // If the place has no street listed, make the lines red. mainColor = '#F00'; } // Draw the lines. features.push(new OpenLayers.Feature.Vector( new OpenLayers.Geometry.LineString(pts), { isNavLine: true }, { strokeColor: mainColor, strokeWidth: 2, strokeDashstyle: '6 4' } )); // Draw the stop point. features.push( new OpenLayers.Feature.Vector( pts[pts.length - 1], { isNavLine: true }, { pointRadius: 4, strokeWidth: 2, fillColor: '#A00', strokeColor: mainColor, fillOpacity: 1 } ) ); // Draw the entry/exit point, if it exists. if (entryExitPoint) { features.push( new OpenLayers.Feature.Vector( entryExitPoint, { isNavLine: true }, { pointRadius: 4, strokeWidth: 2, strokeColor: mainColor, fillColor: '#FFF', fillOpacity: 1 } ) ); } } }); _layer.addFeatures(features); } function findClosestSegment(mygeometry, ignorePLR, ignoreUnnamedPR) { const segments = W.model.segments.getObjectArray(); let minDistance = Infinity; let closestSegment; segments.forEach(segment => { const { roadType } = segment.attributes; const segmentStreetID = segment.attributes.primaryStreetID; if (!segment.isDeleted() && ![10, 16, 18, 19].includes(roadType) // 10 ped boardwalk, 16 stairway, 18 railroad, 19 runway, 3 freeway && !(ignorePLR && roadType === 20) // PLR && !(ignoreUnnamedPR && roadType === 17 && WazeWrap.Model.getStreetName(segmentStreetID) === null)) { // PR const distanceToSegment = W.userscripts.toOLGeometry(mygeometry).distanceTo(segment.getOLGeometry(), { details: true }); if (distanceToSegment.distance < minDistance) { minDistance = distanceToSegment.distance; closestSegment = segment; } } }); return closestSegment; } function saveSettings() { localStorage.setItem('wme_place_navpoints', JSON.stringify(_settings)); } function errorHandler(callback) { try { callback(); } catch (ex) { console.error(ex); } } function onPlacesLayerCheckedChanged(checked) { _settings.visible = checked; $('#layer-switcher-item_pla_navpoints').attr('disabled', checked ? null : true); saveSettings(); drawLines(); } function onPlaLayerCheckedChanged(checked) { _settings.plaVisible = checked; saveSettings(); drawLines(); } function loadScriptUpdateMonitor() { try { const 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('WME Place NavPoints:', ex); } } function init() { loadScriptUpdateMonitor(); const loadedSettings = JSON.parse(localStorage.getItem('wme_place_navpoints')); $.extend(_settings, loadedSettings); const drawLinesFunc = () => errorHandler(drawLines); W.model.events.register('mergeend', null, drawLinesFunc); W.map.events.register('zoomend', null, drawLinesFunc); W.model.venues.on('objectschanged', drawLinesFunc); W.model.venues.on('objectsadded', drawLinesFunc); W.model.venues.on('objectsremoved', drawLinesFunc); W.model.segments.on('objectschanged', drawLinesFunc); W.model.segments.on('objectsadded', drawLinesFunc); W.model.segments.on('objectsremoved', drawLinesFunc); _layer = new OpenLayers.Layer.Vector('Place NavPoints Layer', { uniqueName: '__PlaceNavPointsLayer', displayInLayerSwitcher: false }); W.map.addLayer(_layer); drawLines(); WazeWrap.Interface.AddLayerCheckbox('Display', 'Place NavPoints', _settings.visible, onPlacesLayerCheckedChanged, null); WazeWrap.Interface.AddLayerCheckbox('Display', 'PLA NavPoints', _settings.visible, onPlaLayerCheckedChanged, null); $('#layer-switcher-item_pla_navpoints').attr('disabled', _settings.visible ? null : true).parent().css({ 'margin-left': '10px' }); } function onWmeReady() { if (WazeWrap && WazeWrap.Ready) { init(); } else { setTimeout(onWmeReady, 100); } } function bootstrap() { if (typeof W === 'object' && W.userscripts?.state.isReady) { onWmeReady(); } else { document.addEventListener('wme-ready', onWmeReady, { once: true }); } } bootstrap(); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址