User:DressyPear4/Estrela

From OpenStreetMap Wiki
Jump to navigation Jump to search

Criar uma estrela

Não é tão comum mas as vezes encontradas em praças como caminho de pedestres ou espelho de água de um chafariz

Como funciona?

  • Partindo do centro até uma das pontas desenhe uma linha com apenas dois nós
  • Escolha o número de pontas

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, Node
from org.openstreetmap.josm.data.coor import LatLon
from org.openstreetmap.josm.command import AddCommand, DeleteCommand, SequenceCommand
from org.openstreetmap.josm.data.UndoRedoHandler import getInstance
from javax.swing import JOptionPane, JPanel, JLabel, JSpinner, SpinnerNumberModel, UIManager
from java.awt import GridBagLayout, GridBagConstraints, Insets, Dimension
from java.util import LinkedList
import math

def criar_estrela_nodes(cx, cy, raio_externo, num_pontas, angulo_rotacao):
    angulo_base = 2 * math.pi / (num_pontas * 2)
    coords = []

    for i in range(num_pontas * 2):
        angulo = i * angulo_base
        raio = raio_externo if i % 2 == 0 else raio_externo / 2.5
        dx = raio * math.cos(angulo)
        dy = raio * math.sin(angulo)

        # Aplica rotacao
        dx_rot = dx * math.cos(angulo_rotacao) - dy * math.sin(angulo_rotacao)
        dy_rot = dx * math.sin(angulo_rotacao) + dy * math.cos(angulo_rotacao)

        dlat = dy_rot / 111320.0
        dlon = dx_rot / (111320.0 * math.cos(math.radians(cx)))
        lat = cx + dlat
        lon = cy + dlon
        coords.append((lat, lon))

    return coords

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

    dataset = layer.data
    selecionados = dataset.getSelected()

    ways = [x for x in selecionados if isinstance(x, Way)]
    if len(ways) != 1:
        Notification(u"Selecione uma linha com dois nós.")\
        .setIcon(UIManager.getIcon("OptionPane.informationIcon"))\
        .show()
        return

    linha = ways[0]
    if len(linha.getNodes()) != 2:
        Notification(u"A linha deve conter exatamente dois nós.")\
        .setIcon(UIManager.getIcon("OptionPane.informationIcon"))\
        .show()
        return

    centro = linha.getNodes()[0]
    ponta = linha.getNodes()[1]

    cx = centro.getCoor().lat()
    cy = centro.getCoor().lon()
    px = ponta.getCoor().lat()
    py = ponta.getCoor().lon()

    dx = (py - cy) * 111320 * math.cos(math.radians((cx + px) / 2))
    dy = (px - cx) * 111320
    raio = math.hypot(dx, dy)

    # Calcular angulo de orientacao da linha
    delta_x = (py - cy) * math.cos(math.radians((cx + px) / 2))
    delta_y = (px - cx)
    angulo_rot = math.atan2(delta_y, delta_x)

    # Caixa de dialogo
    panel = JPanel()
    panel.setLayout(GridBagLayout())
    c = GridBagConstraints()
    c.insets = Insets(5, 5, 5, 5)

    c.gridx = 0
    c.gridy = 0
    c.anchor = GridBagConstraints.EAST
    panel.add(JLabel(u"Número de pontas:"), c)

    c.gridx = 1
    spinner_model = SpinnerNumberModel(5, 3, 25, 1)
    spinner = JSpinner(spinner_model)
    spinner.setPreferredSize(Dimension(80, 25))
    panel.add(spinner, c)

    resultado = JOptionPane.showConfirmDialog(None, panel, "Criar Estrela", JOptionPane.OK_CANCEL_OPTION)
    if resultado != JOptionPane.OK_OPTION:
        return

    num_pontas = spinner.getValue()
    coords = criar_estrela_nodes(cx, cy, raio, num_pontas, angulo_rot)

    comandos = []
    novos_nos = []

    for lat, lon in coords:
        n = Node(LatLon(lat, lon))
        comandos.append(AddCommand(dataset, n))
        novos_nos.append(n)

    # Fechar a estrela com o primeiro no
    novos_nos.append(novos_nos[0])

    estrela = Way()
    estrela.setNodes(LinkedList(novos_nos))
    comandos.append(AddCommand(dataset, estrela))

    # Remover a linha original e seus dois nos
    comandos.append(DeleteCommand(dataset, linha))
    comandos.append(DeleteCommand(dataset, linha.getNodes()))

    getInstance().add(SequenceCommand("Criar estrela", comandos))
    Notification("Estrela criada com sucesso.")\
    .setIcon(UIManager.getIcon("OptionPane.informationIcon"))\
    .show()

executar()