Feature Your Map

get poi data from osm

目前为 2024-04-04 提交的版本。查看 最新版本

// ==UserScript==
// @name         Feature Your Map
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  get poi data from osm
// @author       KaKa
// @match        https://map-making.app/maps/*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_setClipboard
// @license      MIT
// @icon         https://www.google.com/s2/favicons?domain=geoguessr.com
// @require      https://cdn.jsdelivr.net/npm/sweetalert2@11
// ==/UserScript==

(function() {
    'use strict';


    const API_URL = "https://overpass-api.de/api/interpreter";

    async function fetchData(query, mode,feature) {
        const requestBody = !mode?
              `[out:json][timeout:180];area[name="${query}"]; (nwr(area)[${feature}]; );out geom;` :
        `[out:json][timeout:180];nwr[${feature}](poly:"${query}");out geom;`;
        const response = await fetch(API_URL, {
            method: "POST",
            body: "data=" + encodeURIComponent(requestBody),
        });

        if (!response.ok) {
            throw new Error("Network response was not ok");
        }

        return response.json();
    }

    async function getData(query, mode,features) {
        try {
            const js = {
                "name": "",
                "customCoordinates": [],
                "extra": {
                    "tags": {},
                    "infoCoordinates": []
                }
            };
            let elements = [];
            for (let feature of features) {
                let requests = [];
                if ( mode === 'polygon') {
                    requests.push(fetchData(query, true, feature[1]));
                } else {
                    requests.push(fetchData(query, false, feature[1]));
                }

                const responses = await Promise.all(requests);

                responses.forEach(response => {
                    if (response.elements && response.elements.length > 0) {
                        elements.push(...response.elements);
                    }
                });
                writeData(elements, feature[0], js);


            }
            if (js.customCoordinates.length === 0) {
                if (mode === 'area') {
                    alert("Cannot find this place, the place name you entered may be incorrect.");
                } else if (mode === 'polygon') {
                    alert("Please check if your geojson file format is correct.");
                }
            }
            if (js.customCoordinates.length > 0) {
                GM_setClipboard(JSON.stringify(js));
                alert("JSON data has been copied to your clipboard!");
            }
        } catch (error) {
            console.error("Error fetching data:", error);
        }
    }

    function writeData(coordinates, feature, js) {
        for (let i = 0; i < coordinates.length; i++) {
            if (coordinates[i].geometry) {
                let nodes = coordinates[i].geometry;
                let randomIndex = Math.floor(Math.random() * nodes.length);
                let randomCoordinate = nodes[randomIndex];
                let tag;
                if (coordinates[i].tags && coordinates[i].tags.highway) {
                    tag = [coordinates[i].tags.highway, feature];
                } else {
                    tag = [feature];
                }
                if (randomCoordinate.lat && randomCoordinate.lon) {
                    js.customCoordinates.push({
                        "lat": randomCoordinate.lat,
                        "lng": randomCoordinate.lon,
                        "extra": {
                            "tags": tag
                        }
                    });
                }
            } else if (coordinates[i].lat && coordinates[i].lon && !isCoordinateExists(js.customCoordinates, coordinates[i].lat, coordinates[i].lon)) {
                js.customCoordinates.push({
                    "lat": coordinates[i].lat,
                    "lng": coordinates[i].lon,
                    "extra": {
                        "tags": [feature]
                    }
                });
            }
        }
    }

    function isCoordinateExists(coordinates, lat, lon) {
        for (let i = 0; i < coordinates.length; i++) {
            if (coordinates[i].lat === lat && coordinates[i].lng === lon) {
                return true;
            }
        }

        return false;
    }

    function getInput(features) {
    const option = confirm('Do you want to upload a Geojson file? If you click "Cancel",you will need to enter a location name');

        if (option) {
            const input = document.createElement('input');
            input.type = 'file';
            input.style.position = 'absolute';
            input.style.right = '120px';
            input.style.top = '15px';
            input.addEventListener('change', async event => {
                const file = event.target.files[0];
                if (file) {
                    try {
                        var query = await readFile(file);
                        getData(query,'polygon',features)
                        document.body.removeChild(input);
                    } catch (error) {
                        console.error('Error reading file:', error);
                        document.body.removeChild(input);
                    }
                }
            });

            document.body.appendChild(input);

    } else {
        let query = prompt('Please enter a location name(eg:Paris)');
        if (query === null) {
            alert('You cancelled the input!');
        } else {
            query = query.trim();
            while (query.length === 0) {
                alert('You must enter a valid location name!');
                query = prompt('Please enter a location name(eg:Paris)');
                if (query === null) {
                    alert('You cancelled the input!');
                    break;
                }
                query = query.trim();
            }
            if (query) {
                getData(query,'area',features);
            }
        }
    }
}

    function extractCoordinates(p) {
        let results = [];
        let polygons=p.features
        polygons.forEach(data => {
            let coordinates = [];
            data.geometry.coordinates.forEach(polygon => {
                polygon[0].forEach(coordinatePair => {
                    let coordinate = [coordinatePair[1], coordinatePair[0]].join(' ');
                    coordinates.push(coordinate);
                });
            });
            let result = coordinates.join(' ');
            result = result.replace(/,/g, ' ');
            results.push(result);
        });
        return results;

    }

    function readFile(file) {
        return new Promise((resolve, reject) => {
            const reader = new FileReader();

            reader.onload = function(event) {
                const jsonContent = event.target.result;

                try {
                    const data = JSON.parse(jsonContent);

                    if (data.features && data.features.length > 0) {
                        const coordinates = extractCoordinates(data);
                        resolve(coordinates);
                    }
                    else {
                        console.error('Invalid Geojson format.');
                        alert('Invalid Geojson format!');
                        resolve('error')
                    }
                } catch (error) {
                    console.error('Error parsing Geojson:', error);
                    alert('Error parsing Geojson!');
                    resolve('error')
                }
            };

            reader.readAsText(file);
        });
    }
    function runScript(features){
        if (features&&features.length>0){
        getInput(features)}
        else{
        alert('Please select a feature at least!')}
    }


    async function getFeatures() {
        const { value: formValues } = await Swal.fire({
            title: 'Feature Your Map',
            html:
    '<div style="display: flex; justify-content: space-between;"><div style="display: flex; align-items: center;"><input id="swal-input1" class="swal2-input" type="checkbox" value="bridge"><span style="margin-left: 1px;">bridge</span></div><div style="display: flex; align-items: center;"><input id="swal-input2" class="swal2-input" type="checkbox" value="bus stop"><span style="margin-right: 95px;">bus stop</span></div></div>' +
    '<div style="display: flex; justify-content: space-between;"><div style="display: flex; align-items: center;"><input id="swal-input3" class="swal2-input" type="checkbox" value="utility pole"><span style="margin-left: 1px;">utility pole</span></div><div style="display: flex; align-items: center;"><input id="swal-input4" class="swal2-input" type="checkbox" value="traffic light"><span style="margin-right:78px;">traffic light</span></div></div>' +
    '<div style="display: flex; justify-content: space-between;"><div style="display: flex; align-items: center;"><input id="swal-input5" class="swal2-input" type="checkbox" value="lamppost"><span style="margin-left: 1px;">lamppost</span></div><div style="display: flex; align-items: center;"><input id="swal-input6" class="swal2-input" type="checkbox" value="crosswalk"><span style="margin-right: 85px;">crosswalk</span></div></div>' +
    '<div style="display: flex; justify-content: space-between;"><div style="display: flex; align-items: center;"><input id="swal-input7" class="swal2-input" type="checkbox" value="level crossing"><span style="margin-left: 0.5px;">level crossing</span></div><div style="display: flex; align-items: center;"><input id="swal-input8" class="swal2-input" type="checkbox" value="postbox"><span style="margin-right: 85px;">postbox</span></div></div>' +
    '<div style="display: flex; justify-content: space-between;"><div style="display: flex; align-items: center;"><input id="swal-input9" class="swal2-input" type="checkbox" value="hydrant"><span style="margin-left: 1px;">hydrant</span></div><div style="display: flex; align-items: center;"><input id="swal-input10" class="swal2-input" type="checkbox" value="milestone"><span style="margin-right: 82px;">milestone</span></div></div>',
            focusConfirm: false,
            preConfirm: () => {
                return [
                    document.getElementById('swal-input1').checked,
                    document.getElementById('swal-input2').checked,
                    document.getElementById('swal-input3').checked,
                    document.getElementById('swal-input4').checked,
                    document.getElementById('swal-input5').checked,
                    document.getElementById('swal-input6').checked,
                    document.getElementById('swal-input7').checked,
                    document.getElementById('swal-input8').checked,
                    document.getElementById('swal-input9').checked,
                    document.getElementById('swal-input10').checked
                ]
            }
        })

        if (formValues) {
            var features = []
            var tags = [['bridge', '"bridge"="yes"'],
                        ['bus stop', '"highway"="bus_stop"'] ,
                        ['utility pole', '"power"="pole"'],
                        ['traffic light', '"highway"="traffic_signals"'],
                        ['lamppost', '"highway"="street_lamp"'],
                        ['crosswalk', '"highway"="crossing"'],
                        ['level crossing', '"railway"="level_crossing"'],
                        ['postbox', '"amenity"="post_box"'],
                        ['hydrant', '"emergency"="fire_hydrant"'],
                        ['milestone', '"highway"="milestone"']]
            for (var i = 0; i < formValues.length; i++) {
                if (formValues[i]) {
                    features.push(tags[i])
                }
            }
            runScript(features)
        }
    }

    var triggerButton = document.createElement("BUTTON");
    triggerButton.innerHTML = "Feature Your Map";
    triggerButton.style.position = 'fixed';
    triggerButton.style.right = '20px';
    triggerButton.style.top = '12px';
    triggerButton.style.borderRadius = "12px";
    triggerButton.style.padding = "10px 20px";
    triggerButton.style.border = "none";
    triggerButton.style.backgroundColor = "#4CAF50";
    triggerButton.style.color = "white";
    triggerButton.style.cursor = "pointer";
    document.body.appendChild(triggerButton);

    triggerButton.addEventListener("click", getFeatures);


})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址