(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());
});
})();
Discussion