OpenStreetMap logo OpenStreetMap



(function() {
    const Node = Java.type("org.openstreetmap.josm.data.osm.Node");
    const Way = Java.type("org.openstreetmap.josm.data.osm.Way");
    const LatLon = Java.type("org.openstreetmap.josm.data.coor.LatLon");
    const EastNorth = Java.type("org.openstreetmap.josm.data.coor.EastNorth");
    const MainApplication = Java.type("org.openstreetmap.josm.gui.MainApplication");
    const ProjectionRegistry = Java.type("org.openstreetmap.josm.data.projection.ProjectionRegistry");
    const Logging = Java.type("org.openstreetmap.josm.tools.Logging");

    function enOf(node) { return ProjectionRegistry.getProjection().latlon2eastNorth(node.getCoor()); }
    function llOf(en) { return ProjectionRegistry.getProjection().eastNorth2latlon(en); }
    function sub(a, b) { return new EastNorth(a.east() - b.east(), a.north() - b.north()); }
    function add(a, b) { return new EastNorth(a.east() + b.east(), a.north() + b.north()); }
    function scale(v, s) { return new EastNorth(v.east() * s, v.north() * s); }
    function length(v) { return Math.hypot(v.east(), v.north()); }
    function normalize(v) { const L = length(v); return scale(v, 1.0 / L); }

    const ds = MainApplication.getLayerManager().getEditDataSet();
    if (ds == null) { Logging.info("No active dataset."); return; }

    ds.getSelectedWays().forEach(function(way) {
        const ccTag = way.get("CC");
        if (ccTag == null) return;
        let nUnits = parseInt(ccTag, 10);
        if (!Number.isFinite(nUnits) || nUnits <= 0) return;
        if (!way.isClosed() || way.getNodes().size() https://wiki.openstreetmap.org/wiki/Tag:!== 5) return;

        const nodes = way.getNodes().toArray();
        const p0 = nodes[0], p1 = nodes[1], p3 = nodes[3];
        const e0 = enOf(p0), e1 = enOf(p1), e3 = enOf(p3);

        const v1 = sub(e1, e0);
        const v2 = sub(e3, e0);
        const L1 = length(v1), L2 = length(v2);
        const longV = (L1 >= L2) ? v1 : v2;
        const shortV = (L1 >= L2) ? v2 : v1;
        const Llong = Math.max(L1, L2), Lshort = Math.min(L1, L2);
        const uLong = normalize(longV), uShort = normalize(shortV);
        const step = Llong / nUnits;

        // Build grid of nodes
        const bottomNodes = [], topNodes = [];
        for (let i = 0; i <= nUnits; i++) {
            const base = add(e0, scale(uLong, i * step));
            const bottomEN = base;
            const topEN = add(base, scale(uShort, Lshort));
            const nBottom = new Node(llOf(bottomEN));
            const nTop = new Node(llOf(topEN));
            ds.addPrimitive(nBottom);
            ds.addPrimitive(nTop);
            bottomNodes.push(nBottom);
            topNodes.push(nTop);
        }

        // Build ways using shared nodes
        for (let i = 0; i < nUnits; i++) {
            const newWay = new Way();
            newWay.addNode(bottomNodes[i]);
            newWay.addNode(bottomNodes[i+1]);
            newWay.addNode(topNodes[i+1]);
            newWay.addNode(topNodes[i]);
            newWay.addNode(bottomNodes[i]); // close
            newWay.put("amenity", "parking_space");
            ds.addPrimitive(newWay);
        }

        Logging.info("Created " + nUnits + " parking_space blocks with shared nodes for way " + way.getId());
    });
})();


Email icon Bluesky Icon Facebook Icon LinkedIn Icon Mastodon Icon Telegram Icon X Icon

Discussion

Log in to leave a comment