您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
WME UrSuS Tools: LV Kadastrs
// ==UserScript== // @name WME UT Kadastrs // @namespace http://ursus.id.lv // @version 1.0.1 // @description WME UrSuS Tools: LV Kadastrs // @author UrSuS // @match https://*.waze.com/*editor* // @license MIT/BSD/X11 // @icon data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgoKPHN2ZwogICB3aWR0aD0iNjMuOTk5OTk2bW0iCiAgIGhlaWdodD0iNjQuMDAwMDE1bW0iCiAgIHZpZXdCb3g9IjAgMCA2My45OTk5OTYgNjQuMDAwMDE1IgogICB2ZXJzaW9uPSIxLjEiCiAgIGlkPSJzdmc1IgogICBpbmtzY2FwZTp2ZXJzaW9uPSIxLjIgKGRjMmFlZGFmMDMsIDIwMjItMDUtMTUpIgogICBzb2RpcG9kaTpkb2NuYW1lPSJ3bWUga2FkYXN0cnMuc3ZnIgogICB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNwYWNlcy9pbmtzY2FwZSIKICAgeG1sbnM6c29kaXBvZGk9Imh0dHA6Ly9zb2RpcG9kaS5zb3VyY2Vmb3JnZS5uZXQvRFREL3NvZGlwb2RpLTAuZHRkIgogICB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogIDxzb2RpcG9kaTpuYW1lZHZpZXcKICAgICBpZD0ibmFtZWR2aWV3NyIKICAgICBwYWdlY29sb3I9IiNmZmZmZmYiCiAgICAgYm9yZGVyY29sb3I9IiM2NjY2NjYiCiAgICAgYm9yZGVyb3BhY2l0eT0iMS4wIgogICAgIGlua3NjYXBlOnNob3dwYWdlc2hhZG93PSIyIgogICAgIGlua3NjYXBlOnBhZ2VvcGFjaXR5PSIwLjAiCiAgICAgaW5rc2NhcGU6cGFnZWNoZWNrZXJib2FyZD0iMCIKICAgICBpbmtzY2FwZTpkZXNrY29sb3I9IiNkMWQxZDEiCiAgICAgaW5rc2NhcGU6ZG9jdW1lbnQtdW5pdHM9Im1tIgogICAgIHNob3dncmlkPSJmYWxzZSIKICAgICBpbmtzY2FwZTp6b29tPSIxLjAzMzA4MjIiCiAgICAgaW5rc2NhcGU6Y3g9IjY3Ljc1ODQwMSIKICAgICBpbmtzY2FwZTpjeT0iNzU3LjQ0MjEzIgogICAgIGlua3NjYXBlOndpbmRvdy13aWR0aD0iMTkyMCIKICAgICBpbmtzY2FwZTp3aW5kb3ctaGVpZ2h0PSIxMDA1IgogICAgIGlua3NjYXBlOndpbmRvdy14PSItOSIKICAgICBpbmtzY2FwZTp3aW5kb3cteT0iLTkiCiAgICAgaW5rc2NhcGU6d2luZG93LW1heGltaXplZD0iMSIKICAgICBpbmtzY2FwZTpjdXJyZW50LWxheWVyPSJsYXllcjEiCiAgICAgc2hvd2d1aWRlcz0idHJ1ZSI+CiAgICA8c29kaXBvZGk6Z3VpZGUKICAgICAgIHBvc2l0aW9uPSIzMi4wMDAwMDMsMzIuMDAwMDA3IgogICAgICAgb3JpZW50YXRpb249IjEsMCIKICAgICAgIGlkPSJndWlkZTgzMCIKICAgICAgIGlua3NjYXBlOmxvY2tlZD0iZmFsc2UiIC8+CiAgICA8c29kaXBvZGk6Z3VpZGUKICAgICAgIHBvc2l0aW9uPSIzMi4wMDAwMDEsMzIuMDAwMDA5IgogICAgICAgb3JpZW50YXRpb249IjAsLTEiCiAgICAgICBpZD0iZ3VpZGU4MzIiCiAgICAgICBpbmtzY2FwZTpsb2NrZWQ9ImZhbHNlIiAvPgogIDwvc29kaXBvZGk6bmFtZWR2aWV3PgogIDxkZWZzCiAgICAgaWQ9ImRlZnMyIiAvPgogIDxnCiAgICAgaW5rc2NhcGU6bGFiZWw9IkxheWVyIDEiCiAgICAgaW5rc2NhcGU6Z3JvdXBtb2RlPSJsYXllciIKICAgICBpZD0ibGF5ZXIxIgogICAgIHRyYW5zZm9ybT0idHJhbnNsYXRlKC01NC40MzczMywtMTczLjI3MjY1KSI+CiAgICA8cmVjdAogICAgICAgc3R5bGU9ImZpbGw6I2EwMmMyYztzdHJva2Utd2lkdGg6MjYuNDU4MyIKICAgICAgIGlkPSJyZWN0ODE4IgogICAgICAgd2lkdGg9IjY0IgogICAgICAgaGVpZ2h0PSI2NCIKICAgICAgIHg9IjU0LjQzNzMzMiIKICAgICAgIHk9IjE3My4yNzI2NiIgLz4KICAgIDxnCiAgICAgICB0cmFuc2Zvcm09Im1hdHJpeCgxLjE5MzY3MDgsMCwwLDEuMTkzNjcwOCw1Ni42Mzc5MTgsMTc1LjM4OTExKSIKICAgICAgIGlkPSJnODI0Ij4KICAgICAgPHBhdGgKICAgICAgICAgZD0ibSAyNy41LDIuNjc0IGMgLTYuMTgxLDAgLTExLjk0NCwyLjc3NyAtMTUuODMzLDcuNzA4IEMgOC45NTgsMTMuODU0IDcuNSwxOC4xNiA3LjUsMjIuNTM1IHYgMy42OCBDIDcuNSwyNy44MTIgNi44NzUsMjkuMzQgNS44MzMsMzAuNDUxIDUsMzEuMjg1IDMuOTU4LDMxLjkxIDIuODQ3LDMyLjE4OCBjIDAuNDE3LDEuMDQxIDEuMzg5LDIuNjM4IDMuMTI1LDQuMzc1IDEuNDU5LDEuNTI3IDMuMTk1LDIuNzc3IDUuMDcsMy42OCB2IC0wLjA2OSBjIDEuMTgsLTEuODA2IDMuMTI1LC0yLjg0OCA1LjI3NywtMi44NDggMC40MTcsMCAwLjc2NCwwLjA3IDEuMTgxLDAuMTM5IDIuNSwwLjQ4NiA0LjQ0NCwyLjQzMSA0LjkzMSw0Ljg2MSBoIDUuMTM4IGMgNS4zNDgsMCAxMC40MTcsLTIuMjIyIDE0LjA5OCwtNS44MzMgNS42OTQsLTUuNjk0IDcuNDMsLTE0LjIzNiA0LjMwNSwtMjEuNTk3IEMgNDIuODQ3LDcuNDY1IDM1LjYyNSwyLjY3NCAyNy41LDIuNjc0IFoiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNhMDJjMmMiCiAgICAgICAgIGlkPSJwYXRoODIwIiAvPgogICAgICA8cGF0aAogICAgICAgICBkPSJNIDI3LjUsMC4xNzQgQyAyMC42MjUsMC4xNzQgMTQuMTY3LDMuMjI5IDkuNzkyLDguNzE1IDYuNjY3LDEyLjY3NCA1LDE3LjUzNSA1LDIyLjYwNCB2IDMuNjExIGMgMCwxLjg3NSAtMS4zMTksMy42MTEgLTMuODg5LDMuNzUgLTAuNjI1LDAgLTEuMTExLDAuNDg2IC0xLjE4LDEuMTExIC0wLjA3LDEuNjY3IDEuNzM2LDQuNzkyIDQuMjM2LDcuMjkyIDEuNzM2LDEuNzM2IDMuNzUsMy4xMjUgNS45MDIsNC4yMzYgLTAuNjk0LDMuODIgMi4yOTIsNy4yOTIgNi4xODEsNy4yOTIgaCAwLjA2OSBjIDIuOTg3LDAgNS40ODcsLTIuMDgzIDYuMTEyLC00LjkzMSBoIDUuMjA4IGMgMC41NTUsMi44NDggMy4wNTUsNC45MzEgNi4xMTEsNC45MzEgMC42OTQsMCAxLjQ1OCwtMC4xMzkgMi4xNTMsLTAuMzQ3IDEuNzM2LC0wLjU1NiAzLjA1NSwtMS44NzUgMy42OCwtMy42MTIgMC41NTYsLTEuNTk3IDAuNDg2LC0zLjE5NCAwLC00LjUxMyAxLjM4OSwtMC45MDMgMi42MzksLTEuODc1IDMuODIsLTMuMDU2IEMgNDcuNjM5LDM0LjIwMSA1MCwyOC41MDcgNTAsMjIuNjA0IDUwLDE2LjYzMiA0Ny42MzksMTEuMDc2IDQzLjQwMyw2Ljg0IDM5LjE2NywyLjQ2NSAzMy40NzIsMC4xNzQgMjcuNSwwLjE3NCBaIG0gMCwyLjUgYyA4LjA1NiwwIDE1LjM0Nyw0Ljg2MSAxOC40NzIsMTIuMjkxIDMuMTI1LDcuNDMxIDEuMzg5LDE1Ljk3MiAtNC4zMDUsMjEuNTk4IC0zLjY4MSwzLjY4IC04Ljc1LDUuODMzIC0xNC4wOTgsNS44MzMgSCAyMi40MzEgQyAyMS45NDQsMzkuODk2IDIwLDM4LjAyMSAxNy41LDM3LjUzNSBjIC0wLjQxNywtMC4wNyAtMC43NjQsLTAuMTM5IC0xLjE4MSwtMC4xMzkgLTIuMDgzLDAgLTQuMDk3LDEuMDQyIC01LjI3NywyLjg0NyB2IDAuMDcgQyA5LjE2NywzOS4zNCA3LjUsMzguMDkgNS45NzIsMzYuNjMyIDQuMjM2LDM0Ljg5NiAzLjI2NCwzMy4yMjkgMi44NDcsMzIuMjU3IDQuMDI4LDMxLjk3OSA1LDMxLjM1NCA1LjgzMywzMC41MjEgNi44NzUsMjkuMzQgNy41LDI3Ljg4MiA3LjUsMjYuMjg1IHYgLTMuNjgxIGMgMCwtNC4zNzUgMS40NTgsLTguNjggNC4xNjcsLTEyLjE1MyBDIDE1LjU1Niw1LjM4MiAyMS4zMTksMi42NzQgMjcuNSwyLjY3NCBaIgogICAgICAgICBpZD0icGF0aDgyMiIKICAgICAgICAgc3R5bGU9ImZpbGw6I2ZmZmZmZiIgLz4KICAgIDwvZz4KICAgIDxnCiAgICAgICBhcmlhLWxhYmVsPSJVVCIKICAgICAgIGlkPSJ0ZXh0ODI4IgogICAgICAgc3R5bGU9ImZvbnQtc2l6ZTozMC42NzMycHg7bGluZS1oZWlnaHQ6MS4yNTtmb250LWZhbWlseTpXYXplOy1pbmtzY2FwZS1mb250LXNwZWNpZmljYXRpb246V2F6ZTtsZXR0ZXItc3BhY2luZzowcHg7d29yZC1zcGFjaW5nOjBweDtmaWxsOiNmZmZmZmY7c3Ryb2tlLXdpZHRoOjAuMTE1MDI0Ij4KICAgICAgPHBhdGgKICAgICAgICAgZD0ibSA4OC4zMTk3NzQsMjA4LjEyNTI2IHEgMCwyLjc5MTI2IC0xLjI1NzYwMiw0LjYwMDk4IC0xLjI1NzYwMSwxLjc3OTA1IC0zLjI4MjAzMiwyLjYzNzkgLTIuMDI0NDMxLDAuODU4ODUgLTQuMzU1NTk1LDAuODU4ODUgLTIuMzAwNDksMCAtNC4zMjQ5MjEsLTAuODU4ODUgLTIuMDI0NDMxLC0wLjg1ODg1IC0zLjI4MjAzMiwtMi42Mzc5IC0xLjI1NzYwMiwtMS43NzkwNCAtMS4yNTc2MDIsLTQuNTcwMyB2IC0xMy4xODk0OCBxIDAsLTAuMjQ1MzggMC4xODQwNCwtMC40Mjk0MiAwLjE4NDAzOSwtMC4yMTQ3MiAwLjQ2MDA5OCwtMC4yMTQ3MiBoIDIuNzkxMjYxIHEgMC4yNzYwNTksMCAwLjQ2MDA5OCwwLjIxNDcyIDAuMjE0NzEyLDAuMTg0MDQgMC4yMTQ3MTIsMC40Mjk0MiB2IDEyLjkxMzQyIHEgMCwyLjE0NzEyIDEuMjU3NjAyLDMuMzc0MDUgMS4yNTc2MDEsMS4yMjY5MyAzLjQ5Njc0NCwxLjIyNjkzIDIuMjY5ODE3LDAgMy41Mjc0MTksLTEuMjI2OTMgMS4yNTc2MDEsLTEuMjI2OTMgMS4yNTc2MDEsLTMuMzc0MDUgdiAtMTIuOTEzNDIgcSAwLC0wLjI0NTM4IDAuMTg0MDM5LC0wLjQyOTQyIDAuMjE0NzEyLC0wLjIxNDcyIDAuNDkwNzcxLC0wLjIxNDcyIGggMi43OTEyNjEgcSAwLjI0NTM4NiwwIDAuNDI5NDI1LDAuMjE0NzIgMC4yMTQ3MTMsMC4xODQwNCAwLjIxNDcxMywwLjQyOTQyIHoiCiAgICAgICAgIGlkPSJwYXRoODc4IiAvPgogICAgICA8cGF0aAogICAgICAgICBkPSJtIDkwLjQzNjIxNSwxOTcuNDUwOTkgdiAtMi40NTM4NiBxIDAsLTAuMjc2MDUgMC4xODQwNCwtMC40NjAwOSAwLjE4NDAzOSwtMC4yMTQ3MiAwLjQ2MDA5OCwtMC4yMTQ3MiBoIDE2Ljk5Mjk1NyBxIDAuMjc2MDUsMCAwLjQ2MDA5LDAuMjE0NzIgMC4xODQwNCwwLjE4NDA0IDAuMTg0MDQsMC40NjAwOSB2IDIuNDUzODYgcSAwLDAuMjc2MDYgLTAuMTg0MDQsMC40NjAxIC0wLjE4NDA0LDAuMTg0MDQgLTAuNDYwMDksMC4xODQwNCBoIC02LjM4MDAzIHYgMTcuMDIzNjIgcSAwLDAuMjc2MDYgLTAuMjE0NzEsMC40OTA3NyAtMC4xODQwNCwwLjE4NDA0IC0wLjQ2MDEsMC4xODQwNCBoIC0yLjkxMzk1NCBxIC0wLjI3NjA1OSwwIC0wLjQ2MDA5OCwtMC4xODQwNCAtMC4xODQwNCwtMC4yMTQ3MSAtMC4xODQwNCwtMC40OTA3NyB2IC0xNy4wMjM2MiBoIC02LjM4MDAyNSBxIC0wLjI3NjA1OSwwIC0wLjQ2MDA5OCwtMC4xODQwNCAtMC4xODQwNCwtMC4xODQwNCAtMC4xODQwNCwtMC40NjAxIHoiCiAgICAgICAgIGlkPSJwYXRoODgwIiAvPgogICAgPC9nPgogIDwvZz4KPC9zdmc+Cg== // @exclude https://www.waze.com/user/editor* // @require https://greasyfork.org/scripts/24851-wazewrap/code/WazeWrap.js // @require https://greasyfork.org/scripts/383120-proj4-wazedev/code/proj4-Wazedev.js // @connect lvmgeoserver.lvm.lv // @connect docs.google.com // @grant GM_info // @grant GM_xmlhttpRequest // ==/UserScript== /* globals proj4 */ (function (proj4) { 'use strict'; const sScriptName = GM_info.script.name; GM_info.script.version; let wmeSDK; let aGlobalFetchedAddresses = []; let aWMEValidAddressVenues = []; let aWMEPolygonHighlightFeatures = []; let aAddressConnectionLinesFeatures = []; let aWMEPolygonHighlightBlueFeatures = []; let aMissingFetchedAddresses = []; let aHoverFeatures = []; let iPopupTimeout; let $KadastrsMenuPopupDiv; let oAddHouseNumber; let aVasarnicas = []; function fetchSheetData() { const SHEET_ID = "1W230EX3e0ECeF44Ls0GtvI_Iwn9tceidJYT7T4vjJJw"; const SHEET_NAME = "Sheet1"; const url = `https://docs.google.com/spreadsheets/d/${SHEET_ID}/gviz/tq?tqx=out:csv&sheet=${SHEET_NAME}`; GM_xmlhttpRequest({ method: "GET", url: url, onload: response => { if (response.status === 200) { const csvData = response.responseText; const aRows = csvData.trim().split("\n"); const aParsedResult = aRows.slice(1).map(row => { const aCols = row.split(","); return { name: aCols[0].trim().replace(/^"(.*)"$/, "$1"), parent: aCols[1].trim().replace(/^"(.*)"$/, "$1") }; }); aVasarnicas = aParsedResult; } else { console.error("Failed to fetch data:", response); } } }); } function createElem(type, attrs = {}, eventListener = {}) { const oElement = document.createElement(type); for (const [sKey, vValue] of Object.entries(attrs)) { if (sKey in oElement) { oElement[sKey] = vValue; } else if (sKey === "classList" && Array.isArray(vValue)) { oElement.classList.add(...vValue); } else { oElement.setAttribute(sKey, vValue); } } for (const [sEventType, fnHandler] of Object.entries(eventListener)) { if (fnHandler) { oElement.addEventListener(sEventType, fnHandler); } } return oElement; } function getOLMapExtent() { let extent = W.map.getExtent(); if (Array.isArray(extent)) { extent = new OpenLayers.Bounds(extent); extent.transform("EPSG:4326", "EPSG:3857"); } return extent; } function addKFetchButton() { const divOverlayMain = document.getElementById("overlay-buttons-region"); if (!divOverlayMain) { return; } const mStyle = { position: "absolute", top: "0px", right: "60px", width: "44px", zIndex: "1" }; const mainDiv = createElem("div"); Object.assign(mainDiv.style, mStyle); const btnDiv = createElem("div", { classList: ["overlay-buttons-container top"] }); const owz = createElem("wz-button", { color: "clear-icon", classList: ["overlay-button"], disabled: "false" }, { click: fetchKadastrsData }); const h6 = createElem("h6", { classList: ["w-icon"], textContent: "K" }); h6.style["font-family"] = "Waze Boing Medium"; h6.style["line-height"] = "24px"; owz.appendChild(h6); btnDiv.appendChild(owz); mainDiv.appendChild(btnDiv); divOverlayMain.appendChild(mainDiv); } function initScript() { if (!unsafeWindow.getWmeSdk) { throw new Error("SDK not available"); } wmeSDK = unsafeWindow.getWmeSdk({ scriptId: "wmeUTKadastrs", scriptName: "UrSuS Tools: Kadastrs" }); if (typeof proj4 === "undefined") { const oScript = document.createElement("script"); oScript.type = "text/javascript"; oScript.src = "https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.4.4/proj4.js"; document.getElementsByTagName("head")[0].appendChild(oScript); } oAddHouseNumber = require("Waze/Actions/AddHouseNumber"); addKFetchButton(); fetchSheetData(); } void unsafeWindow.SDK_INITIALIZED.then(initScript); async function fetchKadastrsData() { wazedevtoastr.options = { closeButton: false, debug: false, newestOnTop: false, progressBar: false, rtl: false, positionClass: "toast-bottom-center", preventDuplicates: false, onclick: null, showDuration: 300, hideDuration: 1000, timeOut: 5000, extendedTimeOut: 1000, showEasing: "swing", hideEasing: "linear", showMethod: "fadeIn", hideMethod: "fadeOut" }; if (wmeSDK.Map.getZoomLevel() < 17) { WazeWrap.Alerts.warning(sScriptName, `You are on ${wmeSDK.Map.getZoomLevel()} Zoom Level, HouseNumbers won't be fetched!`); } WazeWrap.Alerts.info(sScriptName, "KadastrsAddress Fetching started"); let sURL = "https://lvmgeoserver.lvm.lv/geoserver/publicwfs/wfs?layer=publicwfs&SERVICE=WFS&REQUEST=GetFeature"; sURL += "&VERSION=2.0.0&TYPENAMES=publicwfs:arisbuilding&STARTINDEX=0&COUNT=500&SRSNAME=urn:ogc:def:crs:EPSG::3059&BBOX="; sURL += getBBox3059(); sURL += ",urn:ogc:def:crs:EPSG::3059&outputFormat=application/json"; const sVenueResponseJSON = await makeGetRequest(sURL); processFetchedDataNewMode(sVenueResponseJSON); } async function processFetchedDataNewMode(responseText) { const oParser = new OpenLayers.Format.GeoJSON(); aGlobalFetchedAddresses = oParser.read(responseText); WazeWrap.Alerts.info(sScriptName, `${aGlobalFetchedAddresses.length} Kadastrs Address Fetched`); let sWazeVenueURL = `https://${window.location.hostname}/row-Descartes/app/Features?bbox=${getBBoxv2()}`; sWazeVenueURL += "&language=en-GB&v=2&venueLevel=4&venueFilter=1%2C1%2C0%2C0"; const sVenueResponseJSON = await makeGetRequest(sWazeVenueURL); const oParsedObject = JSON.parse(sVenueResponseJSON); let aWazeVenues = oParsedObject.venues.objects; aWMEValidAddressVenues = []; WazeWrap.Alerts.info(sScriptName, `${aWazeVenues.length} WME Address Fetched`); let aWazeHouseNumbers = []; if (wmeSDK.Map.getZoomLevel() >= 17) { const aSegments = W.model.segments .getObjectArray() .filter((oObject) => oObject.getAttribute("hasHNs")); const oMapExtGeometry = getOLMapExtent().toGeometry(); const aSegmentsOnScreen = aSegments .map((oSegment) => { if (oMapExtGeometry.intersects(oSegment.getAttribute("geometry"))) { return oSegment.getID(); } }) .filter((oItem) => !!oItem); const oResults = await W.controller.descartesClient.getHouseNumbers(aSegmentsOnScreen); aWazeHouseNumbers = oResults.segmentHouseNumbers.objects; } aMissingFetchedAddresses = [...aGlobalFetchedAddresses]; aWazeVenues.map((oVenue) => { let { name: sStreetName, city: sCity } = findStreetName(oVenue.streetID); let oAddressRegex; if (!oVenue.houseNumber && sStreetName === "") { if (oVenue.name) { const sConverted = `"${oVenue.name.replace(", ", '", ')}${sCity !== "" ? '"' : ""}`; oAddressRegex = getRegex([sConverted, sCity]); } } else if (!oVenue.houseNumber) { if (sStreetName.slice(-4) === "pag.") { const aAddress = sStreetName.split(", "); sStreetName = `"${aAddress[0]}", ${aAddress[1]}`; } else { sStreetName = `"${sStreetName}"`; } oAddressRegex = getRegex([sStreetName, sCity]); } else { const sHouseNumber = oVenue.houseNumber.toUpperCase().replace("-", " k-"); const bIsVasarnica = aVasarnicas.some(mRecord => mRecord.name === sStreetName && mRecord.parent === sCity); if (bIsVasarnica) { oAddressRegex = getRegex([`"${sStreetName} ${sHouseNumber}"`, sCity]); } else { oAddressRegex = getRegex([`${sStreetName} ${sHouseNumber}`, sCity]); } } if (oAddressRegex) { excludeKadastrsAddressConsistentWithWME(oAddressRegex, oVenue); } }); WazeWrap.Alerts.info(sScriptName, `${aMissingFetchedAddresses.length} Kadastrs Addresses Not Present`); const aConvertedAddresses = aGlobalFetchedAddresses .map(mRowKadastrsAddress => { const mKadastrsAddress = convertKadastrsAddressStringToParts(mRowKadastrsAddress.attributes.std, ""); if (!mKadastrsAddress) { return undefined; } return { cityName: mKadastrsAddress.cityName, streetName: mKadastrsAddress.streetName, houseNumber: mKadastrsAddress.houseNumber, name: mKadastrsAddress.name, cityId: "", streetID: "" }; }) .filter(oItem => !!oItem); const iFailedAddressIndex = populateIds(aConvertedAddresses); if (iFailedAddressIndex) { const mMissingAddress = aGlobalFetchedAddresses[iFailedAddressIndex]; const aLonLat = proj4("EPSG:3059", "EPSG:4326", [mMissingAddress.geometry.x, mMissingAddress.geometry.y]); wmeSDK.Map.setMapCenter({ lonLat: { lon: aLonLat[0], lat: aLonLat[1] }, zoomLevel: 19 }); } aConvertedAddresses.forEach(mConvertedAddress => { const sHN = mConvertedAddress.houseNumber.includes(" k-") ? mConvertedAddress.houseNumber.replace(" k-", "-") : mConvertedAddress.houseNumber; aWazeVenues = aWazeVenues.filter(mVenue => mVenue.streetID !== mConvertedAddress.streetID || mVenue.houseNumber?.toUpperCase() !== sHN); }); WazeWrap.Alerts.info(sScriptName, `${aWazeVenues.length} WME Venues with incorrect or missing Addresses`); aWazeHouseNumbers.map(oWazeHouseNumber => { const mSegStreet = W.model.segments.getObjectById(oWazeHouseNumber.attributes.segID).getAddress().attributes ?.street?.attributes; const { name: sStreetName, city: sCity } = findStreetName(mSegStreet.id); const oAddressRegex = getRegex([sStreetName + " " + oWazeHouseNumber.attributes.number.toUpperCase(), sCity]); excludeKadastrsAddressConsistentWithWME(oAddressRegex, oWazeHouseNumber); }); addKadastrsLayerWithFeatures(aGlobalFetchedAddresses); clearHighlightedAdressFeatures(); let bIsVenueLayerHidden = false; aWazeVenues.forEach(oVenue => { const OLVenue = W.map.venueLayer.getOlFeatureByFeatureId(oVenue.id); if (!OLVenue) { bIsVenueLayerHidden = true; return; } highlightVenue2(OLVenue); }); aWMEValidAddressVenues.forEach(oVenue => { const OLVenue = W.map.venueLayer.getOlFeatureByFeatureId(oVenue.id); if (!OLVenue) { bIsVenueLayerHidden = true; return; } highlightVenue2(OLVenue, true); }); if (bIsVenueLayerHidden) { WazeWrap.Alerts.warning(sScriptName, "Please activate Venues or Residential Layer"); } setTimeout(() => W.map.getLayerByUniqueName("venues").redraw(), 0); } function addKadastrsLayerWithFeatures(aKadastrsFeatures) { const aFeaturesForLayer = []; const pointLayer = new OpenLayers.Layer.Vector("LVWMEKadastrsPointLayer", { rendererOptions: { zIndexing: true } }); const oExistingLayer = W.map.getLayersByName("LVWMEKadastrsPointLayer")[0]; const layerContainer = W.selectionManager.getWebMapSelectionMediator().getRootContainerLayer(); if (oExistingLayer) { oExistingLayer.destroyFeatures(); W.map.removeLayer(oExistingLayer); const indexToRemove = W.map.layers.indexOf(oExistingLayer); if (indexToRemove !== -1) { layerContainer.layers.splice(indexToRemove, 1); } } aKadastrsFeatures.forEach(mFeature => { const aCoords = proj4("EPSG:3059", "EPSG:900913", [mFeature.geometry.x, mFeature.geometry.y]); mFeature.geometry.x = aCoords[0]; mFeature.geometry.y = aCoords[1]; const point = new OpenLayers.Geometry.Point(aCoords[0], aCoords[1]); const featureStyle = { label: "K", pointRadius: 15, fillColor: "#00695C", fillOpacity: 0.8, strokeColor: "#cc6633", strokeWidth: 2, strokeOpacity: 0.8, fontColor: "black", labelOutlineColor: "white", labelOutlineWidth: 3, repositoryObject: { isDeleted: () => false, isNew: () => false, getType: () => null, getID: () => -1 } }; const feature = new OpenLayers.Feature.Vector(point, null, featureStyle); feature.data = mFeature; aFeaturesForLayer.push(feature); }); pointLayer.addFeatures(aFeaturesForLayer); const selectControl = new OpenLayers.Control.SelectFeature(pointLayer, { hover: true, onSelect: onFeatureHoverEvent, onUnselect: onFeatureUnHoverEvent }); W.map.addControl(selectControl); selectControl.activate(); W.map.addLayer(pointLayer); layerContainer.layers.push(pointLayer); layerContainer.collectRoots(); } function checkTooltip() { window.clearTimeout(iPopupTimeout); } function onFeatureHoverEvent(e) { window.clearTimeout(iPopupTimeout); const mKadastrsAddress = convertKadastrsAddressStringToParts(e.data.attributes.std, "waze"); if (!mKadastrsAddress) { return; } const placeGeom = e.geometry.getCentroid(); const placePt = new OpenLayers.Geometry.Point(placeGeom.x, placeGeom.y); if (!$KadastrsMenuPopupDiv) { $KadastrsMenuPopupDiv = createElem("div", { id: "kadastrsMenuDiv", style: "z-index:9998; visibility:visible; position:absolute; margin: 0px; top: 0px; left: 0px;", "data-tippy-root": false }, { mouseenter: checkTooltip, mouseleave: hideTooltipAfterDelay }); Object.assign($KadastrsMenuPopupDiv.style, { zIndex: 9998, visibility: "visible", position: "absolute", margin: "0px", top: "0px", left: "0px" }); W.map.getEl()[0].appendChild($KadastrsMenuPopupDiv); } const divElemRoot = createElem("div", { id: "kadastrsMenuDiv-tooltip", classList: ["tippy-box"], "data-state": "hidden", tabindex: "-1", "data-theme": "light-border", "data-animation": "fade", role: "tooltip", "data-placement": "top", style: "max-width: 350px; transition-duration:300ms;" }); const divTippyContent = createElem("div", { id: "kadastrsMenuDiv-content", classList: ["tippy-content"], "data-state": "hidden", style: "transition-duration: 300ms;" }); const oAddressTextDiv = createElem("div", { classList: ["coordinates-wrapper"] }); const oVenuesTextDiv = createElem("div", { classList: ["coordinates-wrapper"], style: "white-space: pre-wrap;" }); let sVenues = "❌"; if (e.data.data.Venues) { sVenues = e.data.data.Venues.map((oVenue) => oVenue.name).join("\r\n•"); if (e.data.data.Venues.length > 1) { sVenues = "\r\n•" + sVenues + "\r\n"; } } oVenuesTextDiv.innerHTML = `Venues: ${sVenues} \n Residential: ${(e.data.data.Residential ?? []).length === 1 ? "✅" : e.data.data.Residential ?? "❌"} HN: ${(e.data.data.HN ?? []).length === 1 ? "✅" : e.data.data.HN ?? "❌"}`; divTippyContent.appendChild(oVenuesTextDiv); const oInputForm = createElem("div", { classList: ["wz-text-input-inner-container"] }); const oInputInput = createElem("wz-text-input", { value: e.data.attributes.std }); oInputInput.appendChild(oInputForm); oAddressTextDiv.appendChild(oInputInput); divTippyContent.appendChild(oAddressTextDiv); const mSDKSelection = wmeSDK.Editing.getSelection(); if (mSDKSelection?.ids.length === 1) { const oApplyAddressForm = createElem("div", { classList: ["external-providers-control", "form-group"] }); divTippyContent.appendChild(oApplyAddressForm); const oApplyAddressFormLabel = createElem("wz-label", { "html-for": "" }); oApplyAddressFormLabel.innerText = "Apply Address to selected Venue:"; oApplyAddressForm.appendChild(oApplyAddressFormLabel); const fnFullyApplyToSelectedClick = () => applyAddress(e, "full"); const oWZButtonFullyApplyToSelectedPlace = createElem("wz-button", { color: "secondary", size: "sm", classList: ["overlay-button"], disabled: "false", textContent: "Full" }, { click: fnFullyApplyToSelectedClick }); const oWZIconFullyApplyToSelectedPlace = createElem("i", { classList: ["w-icon w-icon-location-check-fill"], style: "font-size:18px;" }); oWZButtonFullyApplyToSelectedPlace.prepend(oWZIconFullyApplyToSelectedPlace); oApplyAddressForm.appendChild(oWZButtonFullyApplyToSelectedPlace); const fnApplyKeepingNameToSelectedClick = () => applyAddress(e, ""); const oWZButtonApplyKeepingNameToSelectedPlace = createElem("wz-button", { color: "secondary", size: "sm", classList: ["overlay-button"], disabled: "false", textContent: "Keep Name" }, { click: fnApplyKeepingNameToSelectedClick }); const oWZIconApplyKeepingNameToSelectedPlace = createElem("i", { classList: ["w-icon w-icon-location-fill"], style: "font-size: 18px;" }); oWZButtonApplyKeepingNameToSelectedPlace.prepend(oWZIconApplyKeepingNameToSelectedPlace); oApplyAddressForm.appendChild(oWZButtonApplyKeepingNameToSelectedPlace); const fnPasteViensetaAddressClick = () => applyAddress(e, "vienseta"); const oWZButtonApplyAsViensetaToSelectedPlace = createElem("wz-button", { color: "secondary", size: "sm", classList: ["overlay-button"], disabled: "false", textContent: "Keep Name adding Vienseta" }, { click: fnPasteViensetaAddressClick }); const oWZIconApplyAsViensetaToSelectedPlace = createElem("i", { classList: ["w-icon w-icon-home"], style: "font-size: 18px;" }); oWZButtonApplyAsViensetaToSelectedPlace.prepend(oWZIconApplyAsViensetaToSelectedPlace); oApplyAddressForm.appendChild(oWZButtonApplyAsViensetaToSelectedPlace); } const oCreateVenueForm = createElem("div", { classList: ["external-providers-control", "form-group"] }); divTippyContent.appendChild(oCreateVenueForm); const oCreateVenueFormLabel = createElem("wz-label", { "html-for": "" }); oCreateVenueFormLabel.innerText = "Create Venue:"; oCreateVenueForm.appendChild(oCreateVenueFormLabel); if (!e.data.data.Residential) { const fnCreateResidentialClick = () => createResidential(e); const oWZIconCreateResidential = createElem("i", { classList: ["w-icon w-icon-navigation-now-fill"], style: "font-size:18px;" }); const oWZButtonCreateResidential = createElem("wz-button", { color: "secondary", size: "sm", classList: ["overlay-button"], disabled: "false", textContent: "Residential" }, { click: fnCreateResidentialClick }); oWZButtonCreateResidential.prepend(oWZIconCreateResidential); oCreateVenueForm.appendChild(oWZButtonCreateResidential); } if (!e.data.data.HN) { const fnCreateHNClick = () => createHN(e); const oWZButtonCreateHN = createElem("wz-button", { color: "secondary", size: "sm", classList: ["overlay-button"], disabled: "false", textContent: "HN" }, { click: fnCreateHNClick }); const oWZIconCreateHN = createElem("i", { classList: ["w-icon w-icon-home"], style: "font-size:18px;" }); oWZButtonCreateHN.prepend(oWZIconCreateHN); oCreateVenueForm.appendChild(oWZButtonCreateHN); } const fnForceCreateClick = () => createVenue(e); const oWZButtonCreatePlace = createElem("wz-button", { color: "secondary", size: "sm", classList: ["overlay-button"], disabled: "false", textContent: `${e.data.data.Venues ? "Force Create Place" : "Place"}` }, { click: fnForceCreateClick }); const oWZIconCreatePlace = createElem("i", { classList: ["w-icon w-icon-polygon"], style: "font-size:18px;" }); oWZButtonCreatePlace.prepend(oWZIconCreatePlace); oCreateVenueForm.appendChild(oWZButtonCreatePlace); divElemRoot.appendChild(divTippyContent); $KadastrsMenuPopupDiv.replaceChildren(divElemRoot); const aLonLat = proj4("EPSG:900913", "EPSG:4326", [placeGeom.x, placeGeom.y]); const mPopupPixelPosition = W.map.getPixelFromLonLat({ lon: aLonLat[0], lat: aLonLat[1] }); mPopupPixelPosition.origX = mPopupPixelPosition.x; $KadastrsMenuPopupDiv.clientWidth / 2; const dataPlacement = "right"; $KadastrsMenuPopupDiv.style.transform = `translate(${Math.round(mPopupPixelPosition.x + 24)}px, ${Math.round(mPopupPixelPosition.y - 24)}px)`; $KadastrsMenuPopupDiv.querySelector("#kadastrsMenuDiv-tooltip")?.setAttribute("data-placement", dataPlacement); $KadastrsMenuPopupDiv.querySelector("#kadastrsMenuDiv-tooltip")?.setAttribute("data-state", "visible"); $KadastrsMenuPopupDiv.querySelector("#kadastrsMenuDiv-content")?.setAttribute("data-state", "visible"); let aFoundVenues = []; if (e.data.data.Venues) { aFoundVenues = [...aFoundVenues, ...e.data.data.Venues]; } if (e.data.data.Residential) { aFoundVenues = [...aFoundVenues, ...e.data.data.Residential]; } if (e.data.data.HN) { aFoundVenues = [...aFoundVenues, ...e.data.data.HN]; } aHoverFeatures = []; aFoundVenues.forEach(sFoundVenueKey => { highlightVenue(sFoundVenueKey); }); aFoundVenues.forEach(sFoundVenueKey => { drawConnectionLines(sFoundVenueKey, placePt); }); aHoverFeatures = [...aAddressConnectionLinesFeatures]; W.map.getLayerByUniqueName("venues").addFeatures(aHoverFeatures); setTimeout(() => W.map.getLayerByUniqueName("venues").redraw(), 0); } function createGeometry(e) { const vertex = 29.4; const poly = new OpenLayers.Geometry.LinearRing([ new OpenLayers.Geometry.Point(e.data.geometry.x - vertex, e.data.geometry.y - vertex / 2), new OpenLayers.Geometry.Point(e.data.geometry.x - vertex, e.data.geometry.y + vertex / 2), new OpenLayers.Geometry.Point(e.data.geometry.x + vertex, e.data.geometry.y + vertex / 2), new OpenLayers.Geometry.Point(e.data.geometry.x + vertex, e.data.geometry.y - vertex / 2), new OpenLayers.Geometry.Point(e.data.geometry.x - vertex, e.data.geometry.y - vertex / 2) ]); poly.rotate(10, poly.getCentroid()); return new OpenLayers.Geometry.Polygon([poly]); } function applyAddress(e, sMode) { const mAddressBuffer = convertKadastrsAddressStringToParts(e.data.attributes.std, "waze"); if (!mAddressBuffer) { return; } const selection = wmeSDK.Editing.getSelection(); if (!selection || selection.objectType !== "venue") { return; } if (selection.ids.length > 0) { if (sMode === "vienseta") { let oStreet = findStreetId(mAddressBuffer.cityName, mAddressBuffer.name); if (!oStreet) { oStreet = findStreetId(`${mAddressBuffer.cityName}, ${mAddressBuffer.pagastsName}`, mAddressBuffer.name); } if (!oStreet) { const oNewStreet = wmeSDK.DataModel.Streets.addStreet({ cityId: mAddressBuffer.cityID, streetName: mAddressBuffer.name }); updateVenue(selection.ids[0].toString(), { streetID: oNewStreet.id }); } else { updateVenue(selection.ids[0].toString(), { streetID: oStreet.attributes.id }); } } else { updateVenue(selection.ids[0].toString(), { houseNumber: mAddressBuffer.houseNumber, streetID: mAddressBuffer.streetID, name: sMode === "full" ? mAddressBuffer.name : undefined }); } } } function updateVenue(sVenueId, mAddressData) { if (mAddressData.houseNumber?.includes(" k-")) { mAddressData.houseNumber = mAddressData.houseNumber.replace(" k-", "-"); } if (mAddressData.streetID) { wmeSDK.DataModel.Venues.updateAddress({ venueId: sVenueId, houseNumber: mAddressData.houseNumber, streetId: mAddressData.streetID }); } if (mAddressData.name) { try { wmeSDK.DataModel.Venues.updateVenue({ venueId: sVenueId, name: mAddressData.name, lockRank: 2 }); } catch (oError) { } } } function createResidential(e) { const WMEAddressParams = convertKadastrsAddressStringToParts(e.data.attributes.std, "waze"); if (!WMEAddressParams) { return; } const oGeometry = createGeometry(e); const movedPoi = oGeometry.getCentroid(); movedPoi.x += 7; movedPoi.y -= 7; const sVenueId = wmeSDK.DataModel.Venues.addVenue({ category: "RESIDENTIAL", geometry: W.userscripts.toGeoJSONGeometry(movedPoi) }).toString(); updateVenue(sVenueId, WMEAddressParams); wmeSDK.Editing.setSelection({ selection: { ids: [sVenueId], objectType: "venue" } }); } function createHN(e) { const WMEAddressParams = convertKadastrsAddressStringToParts(e.data.attributes.std, "waze"); if (!WMEAddressParams) { return; } const oGeometry = createGeometry(e); const aStreetSegments = W.model.segments.getByAttributes({ primaryStreetID: WMEAddressParams.streetID }); if (aStreetSegments.length > 0) { const closestSegment = aStreetSegments.reduce((min, segment) => oGeometry.distanceTo(segment.getOLGeometry(), { details: true }).distance < oGeometry.distanceTo(min.getOLGeometry(), { details: true }).distance ? segment : min); const oHNPoint = oGeometry.getCentroid(); oHNPoint.x += 7; oHNPoint.y += 7; const fractionPoint = findClosestPoint(oHNPoint, closestSegment.getOLGeometry()); if (!fractionPoint) { return; } const oFractionPoint = new OpenLayers.Geometry.Point(fractionPoint.x, fractionPoint.y); const epsg900913 = new OpenLayers.Projection("EPSG:900913"); const epsg4326 = new OpenLayers.Projection("EPSG:4326"); oHNPoint.transform(epsg900913, epsg4326); oFractionPoint.transform(epsg900913, epsg4326); const oHouseNumber = new Vs({ forced: false, fractionPoint: { coordinates: [oFractionPoint.x, oFractionPoint.y], type: "Point" }, geoJSONGeometry: { coordinates: [oHNPoint.x, oHNPoint.y], type: "Point" }, number: WMEAddressParams.houseNumber, segID: closestSegment.getID(), id: W.model.segmentHouseNumbers.generateUniqueID() }); W.model.actionManager.add(new oAddHouseNumber(oHouseNumber)); } } function createVenue(e) { const WMEAddressParams = convertKadastrsAddressStringToParts(e.data.attributes.std, "waze"); if (!WMEAddressParams) { alert(`Street not found on map. Please check if it actually exist ${e.data.attributes.std}`); return; } const oGeometry = createGeometry(e); const sVenueId = wmeSDK.DataModel.Venues.addVenue({ category: "OTHER", geometry: W.userscripts.toGeoJSONGeometry(oGeometry) }).toString(); updateVenue(sVenueId, WMEAddressParams); wmeSDK.Editing.setSelection({ selection: { ids: [sVenueId], objectType: "venue" } }); } function drawConnectionLines(foundVenueKey, placePt) { const label = ""; let placeGeomTarget; if (foundVenueKey.type === "houseNumber") { placeGeomTarget = foundVenueKey.getOLGeometry().getCentroid(); } else { placeGeomTarget = W.model.venues.objects[foundVenueKey.id].getOLGeometry().getCentroid(); } const poiPt = new OpenLayers.Geometry.Point(placeGeomTarget.x, placeGeomTarget.y); const lsLine = new OpenLayers.Geometry.LineString([placePt, poiPt]); const addressConnectionLineFeature = new OpenLayers.Feature.Vector(lsLine, {}, { strokeWidth: 3, strokeDashstyle: "12 8", strokeColor: "#FF0", label, labelYOffset: 45, fontColor: "#FF0", fontWeight: "bold", labelOutlineColor: "#000", labelOutlineWidth: 4, fontSize: "18" }); aAddressConnectionLinesFeatures.push(addressConnectionLineFeature); } function highlightVenue(foundVenue, placePt) { if (foundVenue.type === "houseNumber") ; else { const placeGeomTarget = W.model.venues.objects[foundVenue.id].getOLGeometry().getCentroid(); new OpenLayers.Geometry.Point(placeGeomTarget.x, placeGeomTarget.y); const OLVenue = W.map.venueLayer.getOlFeatureByFeatureId(foundVenue.id); if (OLVenue.geometry.getArea() !== 0) { OLVenue.geometry.getGeodesicArea(W.map.getProjectionObject()); } if (OLVenue.geometry.getArea() !== 0) { const mStyle = { fillColor: "#00695C", fillOpacity: 0.5, strokeWidth: 3, strokeDashstyle: "12 8", strokeColor: "blue", label: "", labelYOffset: 45, fontColor: "#FF0", fontWeight: "bold", labelOutlineColor: "#000", labelOutlineWidth: 4, fontSize: "18" }; OLVenue.style = mStyle; aWMEPolygonHighlightBlueFeatures.push(OLVenue); } } } function hideTooltipAfterDelay() { iPopupTimeout = window.setTimeout(hideCustomPopup, 300); } function onFeatureUnHoverEvent(e) { hideTooltipAfterDelay(); aAddressConnectionLinesFeatures.forEach(feature => { feature.destroy(); feature = null; }); aAddressConnectionLinesFeatures = []; aWMEPolygonHighlightBlueFeatures.forEach(feature => { feature.style = null; }); aWMEPolygonHighlightBlueFeatures = []; setTimeout(() => W.map.getLayerByUniqueName("venues").redraw(), 0); } function highlightVenue2(OLVenue, bIsValid) { if (OLVenue.geometry.getArea() !== 0) { OLVenue.geometry.getGeodesicArea(W.map.getProjectionObject()); } if (OLVenue.geometry.getArea() !== 0) { const mStyle = { fillColor: "#00695C", fillOpacity: 0.5, strokeWidth: 3, strokeDashstyle: "12 8", strokeColor: `${bIsValid ? "green" : "red"}`, label: "", labelYOffset: 45, fontColor: "#FF0", fontWeight: "bold", labelOutlineColor: "#000", labelOutlineWidth: 4, fontSize: "18" }; OLVenue.style = mStyle; aWMEPolygonHighlightFeatures.push(OLVenue); } } function clearHighlightedAdressFeatures() { if (aWMEPolygonHighlightFeatures.length > 0) { let layer = aWMEPolygonHighlightFeatures[0].layer; aWMEPolygonHighlightFeatures.forEach(feature => { feature.style = null; layer = feature.layer; }); layer?.redraw(); aWMEPolygonHighlightFeatures = []; } } function hideCustomPopup() { if ($KadastrsMenuPopupDiv) { $KadastrsMenuPopupDiv.querySelector("#kadastrsMenuDiv-content")?.setAttribute("data-state", "hidden"); $KadastrsMenuPopupDiv.querySelector("#kadastrsMenuDiv-tooltip")?.setAttribute("data-state", "hidden"); $KadastrsMenuPopupDiv.replaceChildren(); } } function findStreetId(sCityName, sStreetName, bVienseta) { return Object.values(W.model.streets.objects).find((street) => { if (!W.model.cities.objects[street.attributes.cityID]) { console.log("Error: no City"); } if (street.attributes.name === sStreetName && W.model.cities.objects[street.attributes.cityID].attributes.name.includes(sCityName)) { return true; } }); } function populateIds(addresses) { const streetCache = {}; for (const [index, address] of addresses.entries()) { if (!streetCache[address.streetName]) { const oStreet = findStreetId(address.cityName, address.streetName); if (!oStreet && address.streetName !== "") { const sErrorMsg = "Error: Can't find street: " + address.streetName + " in City: " + address.cityName; console.log(sErrorMsg); alert(sErrorMsg); return index; } if (oStreet) { streetCache[address.streetName] = oStreet.attributes.id; } } address.streetID = streetCache[address.streetName]; } return undefined; } function convertKadastrsAddressStringToParts(sAddress, sMode) { const aAddress = sAddress.split(", "); const bNoCity = aAddress[1].slice(-4) === "pag."; const sCityName = bNoCity ? "" : aAddress[1]; const sPagastsName = bNoCity ? aAddress[1] : aAddress[2]; bNoCity ? aAddress[2] : aAddress[3]; bNoCity ? aAddress[3] : aAddress[4]; const sStreetNameOrHN = aAddress[0]; let sName = ""; let sHN = ""; let bVienseta = false; let bVasarnica = false; if (bNoCity) { sName = `${sStreetNameOrHN.slice(1, -1)}, ${sPagastsName}`; const sStreetName = ""; return { cityName: sCityName, streetName: sStreetName, houseNumber: sHN, name: sName }; } else { if (sStreetNameOrHN.startsWith('"') && sStreetNameOrHN.endsWith('"')) { sName = sStreetNameOrHN.slice(1, -1); const aVasarnica = sName.split(" "); const sLast = aVasarnica.pop(); const sVasarnicaName = aVasarnica.join(" "); const bIsVasarnica = aVasarnicas.some(mRecord => mRecord.name === sVasarnicaName && mRecord.parent === aAddress[1]); if (bIsVasarnica) { bVasarnica = true; sHN = aVasarnica.length > 0 ? sLast ?? "" : ""; sName = sHN; } else { bVienseta = true; } } else { const aStreetNameAndHN = sStreetNameOrHN.split(" "); sName = ""; sHN = aStreetNameAndHN.pop() ?? ""; if (sHN.includes("k-")) { sHN = `${aStreetNameAndHN.pop()} ${sHN}`; sName = sHN.replace(" k", ""); } else { sName = sHN; } } const iLastIndex = sStreetNameOrHN.lastIndexOf(" " + sHN); const sStreetName = sHN === "" ? "" : iLastIndex === -1 ? sStreetNameOrHN : bVasarnica ? sStreetNameOrHN.substring(1, iLastIndex) : sStreetNameOrHN.substring(0, iLastIndex); if (sMode !== "waze") { return { cityName: sCityName, streetName: bVienseta ? "" : sStreetName, houseNumber: sHN, name: sName }; } else { const oStreet = Object.values(W.model.streets.objects).find((street) => { if (street.attributes.name === sStreetName && W.model.cities.objects[street.attributes.cityID].attributes.name.includes(sCityName)) { return true; } }); let oCity; if (!oStreet) { oCity = Object.values(W.model.cities.objects).find((oCity) => { return oCity.attributes.name === sCityName; }); } return { cityID: oStreet ? oStreet.attributes.cityID : oCity ? oCity.attributes.id : undefined, streetID: oStreet ? oStreet.attributes.id : undefined, houseNumber: sHN, name: sName, cityName: sCityName, pagastsName: sPagastsName }; } } } function makeGetRequest(sURL) { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "GET", url: sURL, onload: response => resolve(response.responseText), onerror: error => reject(error) }); }); } function excludeKadastrsAddressConsistentWithWME(oAddressRegex, oVenueOrHouseNumber) { const indexToRemove = aMissingFetchedAddresses.findIndex(mFetchedAddresses => oAddressRegex.test(mFetchedAddresses.attributes.std)); if (indexToRemove > -1) { aMissingFetchedAddresses.splice(indexToRemove, 1); } const indexToUpdate = aGlobalFetchedAddresses.findIndex(mFetchedAddresses => oAddressRegex.test(mFetchedAddresses.attributes.std)); if (indexToUpdate > -1) { if (oVenueOrHouseNumber.type === "houseNumber") { if (!aGlobalFetchedAddresses[indexToUpdate].data.HN) { aGlobalFetchedAddresses[indexToUpdate].data.HN = []; } aGlobalFetchedAddresses[indexToUpdate].data.HN.push(oVenueOrHouseNumber); } else { aWMEValidAddressVenues.push(oVenueOrHouseNumber); if (oVenueOrHouseNumber.categories[0] === "RESIDENCE_HOME") { if (!aGlobalFetchedAddresses[indexToUpdate].data.Residential) { aGlobalFetchedAddresses[indexToUpdate].data.Residential = []; } aGlobalFetchedAddresses[indexToUpdate].data.Residential.push(oVenueOrHouseNumber); } else { if (!aGlobalFetchedAddresses[indexToUpdate].data.Venues) { aGlobalFetchedAddresses[indexToUpdate].data.Venues = []; } aGlobalFetchedAddresses[indexToUpdate].data.Venues.push(oVenueOrHouseNumber); } } } } function getRegex(aStrings) { const regexPattern = aStrings.map(v => v).join("\\s*,\\s*"); return new RegExp(regexPattern); } function findStreetName(iStreetId) { if (!W.model.streets.objects[iStreetId]) { return { name: "", city: "" }; } const sName = W.model.streets.objects[iStreetId].attributes.name; const iCity = W.model.streets.objects[iStreetId].attributes.cityID; const sCity = W.model.cities.objects[iCity].attributes.countryID === 123 ? W.model.cities.objects[iCity].attributes.name : ""; return { name: sName, city: sCity }; } function getBBoxv2() { const mapExtent = W.map.getExtent(); return mapExtent.toString(); } function getBBox3059() { const extent = W.map.getExtent(); if (Array.isArray(extent)) { proj4.defs("EPSG:3059", "+proj=tmerc +lat_0=0 +lon_0=24 +k=0.9996 +x_0=500000 +y_0=-6000000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs +type=crs"); const aConvertedPoints = [ ...proj4("EPSG:4326", "EPSG:3059", extent.slice(0, 2)).reverse(), ...proj4("EPSG:4326", "EPSG:3059", extent.slice(2, 4)).reverse() ]; const string = aConvertedPoints.join(); return string; } } class Vs { type = "houseNumber"; attributes; _prevID; version; state; constructor(e) { this.attributes = e; } static defaults() { return { forced: false, fractionPoint: null, id: "", side: null, valid: false }; } changeID(e) { (this._prevID = this.getID()), this.setID(e); } merge(e) { Object.assign(this.attributes, e); } setID(e) { this.attributes.id = e; } setVersion(e) { this.version = e; } setState(e) { this.state = e; } getAttributes() { return this.attributes; } getAttribute(e) { return this.attributes[e]; } getGeometry() { return this.getAttribute("geoJSONGeometry"); } getID() { return this.attributes.id; } getUniqueIdentifier() { return { objectId: this.getID(), objectType: this.getType() }; } getUniqueID() { return `${this.getType()}: ${this.getID()}`; } getType() { return this.type; } getSide() { return this.attributes.side; } getSegmentId() { return this.attributes.segID; } setSegmentId(e) { this.attributes.segID = e; } getNumber() { return this.attributes.number; } setNumber(e) { this.attributes.number = e; } isForced() { return this.attributes.forced; } isValid() { return this.attributes.valid; } getFractionPoint() { return this.attributes.fractionPoint; } setFractionPoint(e) { this.attributes.fractionPoint = e; } isDeleted() { return Boolean(this.state && this.state === "DELETE"); } } function findClosestPoint(point, lineString) { let closestPoint = null; let closestDistance = Infinity; for (let i = 0; i < lineString.components.length - 1; i++) { const segmentStart = lineString.components[i]; const segmentEnd = lineString.components[i + 1]; const segmentVector = { x: segmentEnd.x - segmentStart.x, y: segmentEnd.y - segmentStart.y }; const pointVector = { x: point.x - segmentStart.x, y: point.y - segmentStart.y }; const dotProduct = pointVector.x * segmentVector.x + pointVector.y * segmentVector.y; const t = dotProduct / (segmentVector.x * segmentVector.x + segmentVector.y * segmentVector.y); const closestPointOnSegment = {}; if (t < 0) { closestPointOnSegment.x = segmentStart.x; closestPointOnSegment.y = segmentStart.y; } else if (t > 1) { closestPointOnSegment.x = segmentEnd.x; closestPointOnSegment.y = segmentEnd.y; } else { closestPointOnSegment.x = segmentStart.x + t * segmentVector.x; closestPointOnSegment.y = segmentStart.y + t * segmentVector.y; } const distance = calculateDistance(closestPointOnSegment, point); if (distance < closestDistance) { closestDistance = distance; closestPoint = closestPointOnSegment; } } return closestPoint; } function calculateDistance(point1, point2) { const dx = point1.x - point2.x; const dy = point1.y - point2.y; return Math.sqrt(dx * dx + dy * dy); } })(proj4);