User:DressyPear4/DividePoligono2Partes

From OpenStreetMap Wiki
Jump to navigation Jump to search

Divisão de polígono esm duas partes

Pode ser útil para supressão de vegetação onde é cortado por uma estrada, ou um espaço entre placas solares como no segundo exemplo.

Como funciona?

  • Adicione 4 nós em um polígono para determinar o espaço
  • Selecione o polígono ou grupo de polígonos
  • Selecione também os nós centrais que irão se tornar os novos vértices

Demonstração

Código

Python

Última atualização: 2026-03-11

from org.openstreetmap.josm.gui import MainApplication, Notification
from org.openstreetmap.josm.data.osm import Way
from org.openstreetmap.josm.command import AddCommand, ChangeCommand, DeleteCommand, SequenceCommand
from org.openstreetmap.josm.data import UndoRedoHandler
from javax.swing import UIManager
from java.util import ArrayList

def dividir_poligonos_preservando_um_id():
    layer = MainApplication.getLayerManager().getEditLayer()
    if layer is None:
        Notification(u"Nenhuma camada de edição ativa.")\
        .setIcon(UIManager.getIcon("OptionPane.errorIcon"))\
        .show()
        return

    ds = layer.getDataSet()
    selected_nodes = list(ds.getSelectedNodes())
    selected_ways = list(ds.getSelectedWays())

    if not selected_nodes or not selected_ways:
        Notification(u"Necessário 4 nós selecionados em cada polígono.")\
        .setIcon(UIManager.getIcon("OptionPane.informationIcon"))\
        .show()
        return

    cmds = ArrayList()
    count = 0

    for way in selected_ways:
        if not way.isClosed():
            continue

        nodes = list(way.getNodes())
        if nodes[-1] == nodes[0]:
            nodes = nodes[:-1]

        selecionados = [n for n in nodes if n in selected_nodes]
        if len(selecionados) < 4:
            continue

        split_indices = [i for i, n in enumerate(nodes) if n in selected_nodes]
        split_indices = sorted(set(split_indices))
        segmentos = []

        for i in range(len(split_indices)):
            idx_inicio = split_indices[i]
            idx_fim = split_indices[(i + 1) % len(split_indices)]
            if idx_fim <= idx_inicio:
                segmento = nodes[idx_inicio:] + nodes[:idx_fim + 1]
            else:
                segmento = nodes[idx_inicio:idx_fim + 1]

            # só segmentos com pelo menos 3 nós fechados
            if len(segmento) >= 3:
                if segmento[0] != segmento[-1]:
                    segmento.append(segmento[0])
                segmentos.append(segmento)

        if not segmentos:
            continue

        # O primeiro segmento substitui a way original (preservando o ID)
        principal_seg = segmentos[0]
        nova_way = Way(way)  # preserva ID
        nova_way.setNodes(principal_seg)
        nova_way.setKeys(dict(way.getKeys()))
        cmds.add(ChangeCommand(way, nova_way))

        # Os demais segmentos viram novas ways (IDs novos)
        for seg in segmentos[1:]:
            nova_way2 = Way()
            for n in seg:
                nova_way2.addNode(n)
            nova_way2.setKeys(dict(way.getKeys()))
            cmds.add(AddCommand(ds, nova_way2))

        count += 1

    if not cmds.isEmpty():
        seq = SequenceCommand(u"Dividir polígonos (ID original em segmento principal)", cmds)
        UndoRedoHandler.getInstance().add(seq)
        Notification(u"Divididos %d polígono(s)." % count)\
        .setIcon(UIManager.getIcon("OptionPane.informationIcon"))\
        .show()
    else:
        Notification(u"O polígono deve ter 2 nós intermediários selecionados.")\
        .setIcon(UIManager.getIcon("OptionPane.warningIcon"))\
        .show()

dividir_poligonos_preservando_um_id()

JavaScript

Última atualização: 2026-03-11

"use strict";

const MainApplication = Java.type("org.openstreetmap.josm.gui.MainApplication");
const Notification    = Java.type("org.openstreetmap.josm.gui.Notification");
const Way             = Java.type("org.openstreetmap.josm.data.osm.Way");
const AddCommand      = Java.type("org.openstreetmap.josm.command.AddCommand");
const ChangeCommand   = Java.type("org.openstreetmap.josm.command.ChangeCommand");
const SequenceCommand = Java.type("org.openstreetmap.josm.command.SequenceCommand");
const UndoRedoHandler = Java.type("org.openstreetmap.josm.data.UndoRedoHandler");
const UIManager       = Java.type("javax.swing.UIManager");
const ArrayList       = Java.type("java.util.ArrayList");

function dividirPoligonosPreservandoUmId() {
    const layer = MainApplication.getLayerManager().getEditLayer();
    if (!layer || !layer.data) {
        new Notification("Nenhuma camada de edição ativa.")
            .setIcon(UIManager.getIcon("OptionPane.errorIcon")).show();
        return;
    }

    const ds = layer.data;
    const selectedNodes = ds.getSelectedNodes();
    const selectedWays = ds.getSelectedWays();

    if (selectedNodes.isEmpty() || selectedWays.isEmpty()) {
        new Notification("Necessário 4 nós selecionados em cada polígono.")
            .setIcon(UIManager.getIcon("OptionPane.informationIcon")).show();
        return;
    }

    const cmds = new ArrayList();
    let count = 0;

    let itWays = selectedWays.iterator();
    while (itWays.hasNext()) {
        let way = itWays.next();
        if (!way.isClosed()) continue;

        let nodes = way.getNodes();
        let nodesList = [];
        for (let i = 0; i < nodes.size() - 1; i++) {
            nodesList.push(nodes.get(i));
        }

        let splitIndices = [];
        for (let i = 0; i < nodesList.length; i++) {
            if (selectedNodes.contains(nodesList[i])) {
                splitIndices.push(i);
            }
        }

        // Permite apenas 2 ou 4 nós selecionados
        if (splitIndices.length !== 2 && splitIndices.length !== 4) {
            continue; 
        }

        let segmentos = [];
        for (let i = 0; i < splitIndices.length; i++) {
            let idxInicio = splitIndices[i];
            let idxFim = splitIndices[(i + 1) % splitIndices.length];
            
            let segmento = [];
            if (idxFim <= idxInicio) {
                segmento = nodesList.slice(idxInicio).concat(nodesList.slice(0, idxFim + 1));
            } else {
                segmento = nodesList.slice(idxInicio, idxFim + 1);
            }

            if (segmento.length >= 3) {
                segmento.push(segmento[0]);
                segmentos.push(segmento);
            }
        }

        if (segmentos.length < 2) continue;

        // Primeiro segmento herda o ID
        let wayPrincipal = new Way(way);
        let listPrincipal = new ArrayList();
        segmentos[0].forEach(n => listPrincipal.add(n));
        wayPrincipal.setNodes(listPrincipal);
        cmds.add(new ChangeCommand(way, wayPrincipal));

        // Demais segmentos viram novas ways
        for (let i = 1; i < segmentos.length; i++) {
            let wayNova2 = new Way();
            let listNova = new ArrayList();
            segmentos[i].forEach(n => listNova.add(n));
            wayNova2.setNodes(listNova);
            wayNova2.setKeys(way.getKeys());
            cmds.add(new AddCommand(ds, wayNova2));
        }
        count++;
    }

    if (!cmds.isEmpty()) {
        UndoRedoHandler.getInstance().add(new SequenceCommand("Dividir polígonos (ID original em segmento principal)", cmds));
        new Notification("Divididos " + count + " polígono(s).")
            .setIcon(UIManager.getIcon("OptionPane.informationIcon")).show();
    } else {
        new Notification("O polígono deve ter 2 nós intermediários selecionados.")
            .setIcon(UIManager.getIcon("OptionPane.warningIcon")).show();
    }
}

dividirPoligonosPreservandoUmId();