User:DressyPear4/DivideLinhaXNos

From OpenStreetMap Wiki
Jump to navigation Jump to search

Dividir linha/polígono a cada X nós

Ideal para arquivos pegos de outras fontes usados para importação, o JOSM não permite que sejam enviadas geometrias com mais de 2000 nós. O script permite saber a quantidade de nós de cada linha e fazer uma divisão central ou em várias partes.

Como funciona?

  • Selecionar uma linha ou polígono
  • Escolher a quantidade de nós resultante em cada seguimento
    • A quantidade de nós não deve ser maior ou igual à quantidade da linha original

Demonstração

Imagem.gif, clique para visualizar.

Código

from org.openstreetmap.josm.gui import MainApplication, Notification
from org.openstreetmap.josm.data.osm import Way, Relation, RelationMember
from org.openstreetmap.josm.data import UndoRedoHandler
from org.openstreetmap.josm.command import SequenceCommand, ChangeCommand, AddCommand, DeleteCommand
from javax.swing import JOptionPane, JPanel, JLabel, JSpinner, SpinnerNumberModel
from javax.swing import UIManager
from java.awt import GridLayout
from java.util import ArrayList

ds = MainApplication.getLayerManager().getEditDataSet()

if ds is None:
    Notification(u"Nenhuma camada de edição ativa.")\
   .setIcon(UIManager.getIcon("OptionPane.errorIcon"))\
   .show()
   
else:
    selected = list(ds.getSelected())
    if len(selected) != 1 or not isinstance(selected[0], Way):
        Notification(u"Selecione uma linha ou polígono para dividir!")\
        .setIcon(UIManager.getIcon("OptionPane.informationIcon"))\
        .show()
        
    else:
        way = selected[0]
        total_nodes = len(way.getNodes())

        panel = JPanel(GridLayout(3, 1))
        panel.add(JLabel(u"A linha selecionada contém {} nós.".format(total_nodes)))
        spinner = JSpinner(SpinnerNumberModel(100, 2, 1900, 100))
        panel.add(spinner)
        info_msg = u"<html><i><span style='color:red;'>ATENÇÃO! Se a linha é membro de uma relação,<br>os novos membros devem ser adicionados manualmente.</span></i></html>"
        panel.add(JLabel(info_msg))

        result = JOptionPane.showConfirmDialog(None, panel, u"Dividir linha a cada X nós",
                                               JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE)

        if result == JOptionPane.OK_OPTION:
            step = spinner.getValue()

            if step >= total_nodes:
                Notification(u"O valor escolhido é maior ou igual ao número de nós. Nada será dividido.")\
               .setIcon(UIManager.getIcon("OptionPane.warningIcon"))\
               .show()
            else:
                nodes = list(way.getNodes())
                new_ways = []

                for i in range(0, total_nodes - 1, step):
                    part_nodes_py = nodes[i:i + step + 1]
                    if len(part_nodes_py) < 2:
                        continue

                    part_nodes_java = ArrayList()
                    for node in part_nodes_py:
                        part_nodes_java.add(node)

                    new_way = Way()
                    new_way.setNodes(part_nodes_java)
                    new_way.setKeys(way.getKeys())
                    new_ways.append(new_way)

                if len(new_ways) == 0:
                    Notification("Nenhum segmento foi criado.")\
                   .setIcon(UIManager.getIcon("OptionPane.warningIcon"))\
                   .show()
                else:
                    cmds = []

                    # Atualiza a way original com os primeiros nos
                    way_mod = Way(way)
                    way_mod.setNodes(new_ways[0].getNodes())
                    cmds.append(ChangeCommand(ds, way, way_mod))

                    for w in new_ways[1:]:
                        cmds.append(AddCommand(ds, w))

                    UndoRedoHandler.getInstance().add(SequenceCommand("Dividir linha em segmentos", cmds))

                    Notification("Linha dividida em {} segmentos.".format(len(new_ways)))\
                   .setIcon(UIManager.getIcon("OptionPane.informationIcon"))\
                   .show()