User:DressyPear4/RepeticaoPontosDaLinha
Jump to navigation
Jump to search
Criar cópias de polígonos (Pontos da linha)
Cria cópias de polígonos posicionando nos pontos de uma linha usada como referência
Como funciona?
- Selecione uma linha como referência
- A cópia é sempre feita até o penúltimo ponto, sempre adicione um a mais
- Selecione o polígono a ser copiado
- Selecione um nó do polígono para que as cópias mantenham o ângulo original
- Selecione dois nós do polígono para que as cópias sejam criadas em paralelo com a linha
Demonstração
-
Imagem.gif, clique para visualizar.
-
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.command import AddCommand, SequenceCommand
from org.openstreetmap.josm.data.coor import LatLon
from org.openstreetmap.josm.data.UndoRedoHandler import getInstance
from javax.swing import JOptionPane, UIManager
from java.util import LinkedList
import math
def calcular_angulo(dx, dy):
return math.atan2(dy, dx)
def deslocar_em_metros(lat, lon, dx_m, dy_m):
dlat = dy_m / 111320.0
dlon = dx_m / (111320.0 * math.cos(math.radians(lat)))
return lat + dlat, lon + dlon
def vetor_em_metros(n1, n2):
lat1, lon1 = n1.getCoor().lat(), n1.getCoor().lon()
lat2, lon2 = n2.getCoor().lat(), n2.getCoor().lon()
dx = (lon2 - lon1) * 111320 * math.cos(math.radians((lat1 + lat2) / 2))
dy = (lat2 - lat1) * 111320
return dx, dy
def rotacionar_e_mover_poligono(orig_nodes, n1_base, n2_base, destino1, destino2, rotacionar=True):
if rotacionar:
dx_base, dy_base = vetor_em_metros(n1_base, n2_base)
ang_base = calcular_angulo(dx_base, dy_base)
dx_dest, dy_dest = vetor_em_metros(destino1, destino2)
ang_dest = calcular_angulo(dx_dest, dy_dest)
angulo_rot = ang_dest - ang_base
else:
angulo_rot = 0
base_lat = n1_base.getCoor().lat()
base_lon = n1_base.getCoor().lon()
dest_lat = destino1.getCoor().lat()
dest_lon = destino1.getCoor().lon()
novos_nos = []
for n in orig_nodes:
lat = n.getCoor().lat()
lon = n.getCoor().lon()
dx = (lon - base_lon) * 111320 * math.cos(math.radians((lat + base_lat) / 2))
dy = (lat - base_lat) * 111320
dxr = dx * math.cos(angulo_rot) - dy * math.sin(angulo_rot)
dyr = dx * math.sin(angulo_rot) + dy * math.cos(angulo_rot)
new_lat, new_lon = deslocar_em_metros(dest_lat, dest_lon, dxr, dyr)
novos_nos.append(Node(LatLon(new_lat, new_lon)))
return novos_nos
def executar():
layer = MainApplication.getLayerManager().getEditLayer()
if not layer:
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)]
nodes = [x for x in selecionados if isinstance(x, Node)]
if len(ways) != 2:
Notification(
u"Selecione:\n - Um polígono fechado"
"\n - Uma linha aberta"
u"\n *Um nó, mantem ângulo original"
u"\n *Dois nós, rotaciona em paralelo com a linha  ")\
.setIcon(UIManager.getIcon("OptionPane.informationIcon"))\
.show()
return
way1, way2 = ways
if way1.isClosed():
poligono = way1
linha = way2
else:
poligono = way2
linha = way1
if not poligono.isClosed():
Notification(u"O polígono precisa estar fechado.")\
.setIcon(UIManager.getIcon("OptionPane.warningIcon"))\
.show()
return
if not linha.isClosed() and len(linha.getNodes()) < 2:
Notification(u"A linha deve ter ao menos dois nós.")\
.setIcon(UIManager.getIcon("OptionPane.warningIcon"))\
.show()
return
rotacionar = True
if len(nodes) == 2:
no1, no2 = nodes
if no1 not in poligono.getNodes() or no2 not in poligono.getNodes():
Notification(u"Os dois nós devem pertencer ao polígono.")\
.setIcon(UIManager.getIcon("OptionPane.warningIcon"))\
.show()
return
elif len(nodes) == 1:
no1 = no2 = nodes[0]
rotacionar = False
if no1 not in poligono.getNodes():
Notification(u"O nó selecionado deve pertencer ao polígono.")\
.setIcon(UIManager.getIcon("OptionPane.warningIcon"))\
.show()
return
else:
Notification(
u"<html>Selecione: Dois nós do poligono para definir rotação ou apenas um nó para copiar sem rotacionar.</html>")\
.setIcon(UIManager.getIcon("OptionPane.informationIcon"))\
.show()
return
comandos = []
linha_nos = linha.getNodes()
for i in range(len(linha_nos) - 1):
origem = linha_nos[i]
destino = linha_nos[i + 1]
novos_nos = rotacionar_e_mover_poligono(poligono.getNodes(), no1, no2, origem, destino, rotacionar)
if novos_nos[-1].getCoor().equals(novos_nos[0].getCoor()):
novos_nos.pop()
for n in novos_nos:
comandos.append(AddCommand(dataset, n))
way_novo = Way()
way_nodes = LinkedList(novos_nos)
way_nodes.add(novos_nos[0])
way_novo.setNodes(way_nodes)
way_novo.putAll(poligono.getKeys())
comandos.append(AddCommand(dataset, way_novo))
if comandos:
getInstance().add(SequenceCommand("Copiar poligono orientado", comandos))
Notification(u"Polígonos criados com sucesso.")\
.setIcon(UIManager.getIcon("OptionPane.informationIcon"))\
.show()
executar()