User:DressyPear4/Solar

From OpenStreetMap Wiki
Jump to navigation Jump to search

Solar (remove blocos intermediários)

Sempre uso este script em conjunto com o plugin Gridify. A combinação permite remover blocos intermediários com apenas um clique, ideal para fazendas solares ou condomínios onde as construções seguem padrões repetitivos.

Como funciona?

  • Necessário um grupo de polígonos selecionados
  • Para o caso em que os espaços têm a mesma largura dos polígonos, selecione;
    • Remover blocos alternados
  • Para o caso em que os espaços têm o dobro da largura dos polígonos, selecione;
    • Remover dois a cada três blocos

Demonstração

Imagem.gif, clique para visualizar

Código

from org.openstreetmap.josm.gui import MainApplication, Notification
from org.openstreetmap.josm.data.osm import DataSet, Way, Node
from org.openstreetmap.josm.command import DeleteCommand, SequenceCommand
from org.openstreetmap.josm.data.UndoRedoHandler import getInstance
from javax.swing import JOptionPane, JPanel, JLabel, JRadioButton, ButtonGroup, BoxLayout, Box, UIManager

def delete_blocks_and_disconnected_nodes():

    layer = MainApplication.getLayerManager().getActiveLayer()
    if not layer or not hasattr(layer, "data") or not isinstance(layer.data, DataSet):
        Notification("Nenhuma camada de dados ativa encontrada!")\
        .setIcon(UIManager.getIcon("OptionPane.errorIcon"))\
        .show()
        return

    dataset = layer.data
    selected = dataset.getSelectedWays()
    ways = [w for w in selected if w.isClosed() and w.isUsable()]

    if not ways:
        Notification(u"Selecione ao menos um polígono fechado.")\
        .setIcon(UIManager.getIcon("OptionPane.warningIcon"))\
        .show()
        return
    ways.sort(key=lambda way: way.getNodes()[0].getCoor().x if way.getNodes() else float('inf'))

    node_to_blocks = {}

    for way in ways:
        for node in way.getNodes():
            node_to_blocks.setdefault(node, []).append(way)

    processed_blocks = set()
    connected_sequences = []

    for way in ways:
        if way in processed_blocks:
            continue

        sequence = []
        to_process = [way]

        while to_process:
            current = to_process.pop()
            if current in processed_blocks:
                continue

            sequence.append(current)
            processed_blocks.add(current)

            for node in current.getNodes():
                for connected_way in node_to_blocks.get(node, []):
                    if connected_way not in processed_blocks:
                        to_process.append(connected_way)

        if len(sequence) > 2:
            connected_sequences.append(sequence)

    # Criar painel customizado
    panel = JPanel()
    panel.setLayout(BoxLayout(panel, BoxLayout.Y_AXIS))

    info = JLabel(u"<html><b>Escolha o método de remoção:</b><br>"
                  "<span style=\"color:#FF0000\">"
                  u"Bug quando 90°. Girar para resolver.</span></html>")
    info.setAlignmentX(0.0)
    panel.add(info)
    panel.add(Box.createVerticalStrut(12))  # espaço

    rb1 = JRadioButton(u"Remover dois a cada três blocos")
    rb1.setSelected(True)
    rb1.setAlignmentX(0.0)
    rb2 = JRadioButton("Remover blocos alternados")
    rb2.setAlignmentX(0.0)

    group = ButtonGroup()
    group.add(rb1)
    group.add(rb2)

    panel.add(rb1)
    panel.add(rb2)

    result = JOptionPane.showConfirmDialog(None, panel, u"Seleção de método",
                                          JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE)

    if result == JOptionPane.OK_OPTION:
        if rb1.isSelected():
            choice = 0
        else:
            choice = 1
    else:
        return 

    to_delete_blocks = []

    if choice == 0:  # Opcao 1
        for sequence in connected_sequences:
            for i, way in enumerate(sequence):
                if (i % 3) in [1, 2]:
                    to_delete_blocks.append(way)

    elif choice == 1:  # Opcao 2
        for sequence in connected_sequences:
            for i in range(1, len(sequence) - 1, 2):
                to_delete_blocks.append(sequence[i])

    all_commands = []

    for way in to_delete_blocks:
        all_commands.append(DeleteCommand(dataset, way))

    if all_commands:
        sequence_blocks_cmd = SequenceCommand("Remover blocos selecionados", all_commands)
        getInstance().add(sequence_blocks_cmd)
    else:
        sequence_blocks_cmd = None

    to_delete_nodes = [
        node for node in dataset.getNodes()
        if not node.getReferrers() and not node.isDeleted() and node.getId() <= 0
    ]

    node_commands = []
    for node in to_delete_nodes:
        try:
            node_commands.append(DeleteCommand(dataset, node))
        except:
            pass

    if node_commands:
        sequence_nodes_cmd = SequenceCommand(u"Remover nós desconectados", node_commands)
        getInstance().add(sequence_nodes_cmd)

    total_blocks = len(to_delete_blocks)
    total_nodes = len(to_delete_nodes)

    Notification(
          u"Removidos {} blocos e {} nós desconectados.".format(total_blocks, total_nodes))\
    .setIcon(UIManager.getIcon("OptionPane.informationIcon"))\
    .show()

# Executa a funcao
delete_blocks_and_disconnected_nodes()