User:DressyPear4/Centroide

From OpenStreetMap Wiki
Jump to navigation Jump to search

Criar centroide

Criar um ponto central em cada geometria pode ser útil quando quiser separar poi ou endereço de edificações

Como funciona?

  • Selecione um ou mais polígonos
  • Será criado um ponto no centro de cada geometria

Demonstração

Imagem.gif, clique para visualizar.

Código

Python

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

from org.openstreetmap.josm.gui import MainApplication, Notification
from org.openstreetmap.josm.data.osm import Node, Way
from org.openstreetmap.josm.data.coor import LatLon, EastNorth
from org.openstreetmap.josm.data.projection import ProjectionRegistry
from org.openstreetmap.josm.command import AddCommand, SequenceCommand
from org.openstreetmap.josm.data.UndoRedoHandler import getInstance
from javax.swing import UIManager

def centroide_area(way, proj):
    coords = [proj.latlon2eastNorth(n.getCoor()) for n in way.getNodes()]
    if coords[0] != coords[-1]:
        coords.append(coords[0])

    sum_east = sum(coord.east() for coord in coords[:-1])
    sum_north = sum(coord.north() for coord in coords[:-1])

    avg_east = sum_east / len(coords[:-1])
    avg_north = sum_north / len(coords[:-1])

    return proj.eastNorth2latlon(EastNorth(avg_east, avg_north))

def main():
    dataset = MainApplication.getLayerManager().getEditDataSet()
    if not dataset:
        Notification(u"Nenhuma camada de edição ativa!")\
            .setIcon(UIManager.getIcon("OptionPane.errorIcon"))\
            .show()
        return

    ways = list(dataset.getSelectedWays())
    if not ways:
        Notification(u"Selecione pelo menos um polígono fechado.")\
            .setIcon(UIManager.getIcon("OptionPane.warningIcon"))\
            .show()
        return

    proj = ProjectionRegistry.getProjection()
    comandos = []

    for way in ways:
        nodes = way.getNodes()
        if len(nodes) < 3 or nodes[0] != nodes[-1]:
            continue 

        centro = centroide_area(way, proj)
        novo_node = Node(centro)

        # Copiar tags do polígono para o ponto
        for key in way.getKeys().keySet():
            novo_node.put(key, way.get(key))

        comandos.append(AddCommand(dataset, novo_node))

    if comandos:
        getInstance().add(SequenceCommand("Criar centroides com tags", comandos))
        Notification("Centroides foram criados com sucesso.")\
            .setIcon(UIManager.getIcon("OptionPane.informationIcon"))\
            .show()
    else:
        Notification(u"Nenhum polígono válido selecionado.")\
            .setIcon(UIManager.getIcon("OptionPane.warningIcon"))\
            .show()

main()

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 Node            = Java.type("org.openstreetmap.josm.data.osm.Node");
const Way             = Java.type("org.openstreetmap.josm.data.osm.Way");
const AddCommand      = Java.type("org.openstreetmap.josm.command.AddCommand");
const SequenceCommand = Java.type("org.openstreetmap.josm.command.SequenceCommand");
const ProjectionRegistry = Java.type("org.openstreetmap.josm.data.projection.ProjectionRegistry");
const EastNorth       = Java.type("org.openstreetmap.josm.data.coor.EastNorth");
const UndoRedoHandler = Java.type("org.openstreetmap.josm.data.UndoRedoHandler");
const UIManager       = Java.type("javax.swing.UIManager");
const ArrayList       = Java.type("java.util.ArrayList");

function calcularCentroide(way, proj) {
    let nodes = way.getNodes();
    let numNodes = nodes.size();
    
    // Ignora o último nó se for igual ao primeiro (fechamento)
    let count = way.isClosed() ? numNodes - 1 : numNodes;
    
    let sumEast = 0;
    let sumNorth = 0;

    for (let i = 0; i < count; i++) {
        let en = proj.latlon2eastNorth(nodes.get(i).getCoor());
        sumEast += en.east();
        sumNorth += en.north();
    }

    let avgEast = sumEast / count;
    let avgNorth = sumNorth / count;

    return proj.eastNorth2latlon(new EastNorth(avgEast, avgNorth));
}

function criarCentroidesComTags() {
    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 dataset = layer.data;
    const selecionados = dataset.getSelectedWays();

    if (selecionados.isEmpty()) {
        new Notification("Selecione pelo menos um polígono fechado.")
            .setIcon(UIManager.getIcon("OptionPane.warningIcon"))
            .show();
        return;
    }

    const proj = ProjectionRegistry.getProjection();
    const comandos = new ArrayList();
    let countCriadors = 0;

    let it = selecionados.iterator();
    while (it.hasNext()) {
        let way = it.next();
        
        // Validação: precisa ter pelo menos 3 nós e ser fechado
        if (way.getNodesCount() < 3 || !way.isClosed()) {
            continue;
        }

        let centroLatLon = calcularCentroide(way, proj);
        let novoNode = new Node(centroLatLon);

        // Copiar tags do polígono para o ponto
        novoNode.setKeys(way.getKeys());

        comandos.add(new AddCommand(dataset, novoNode));
        countCriadors++;
    }

    if (!comandos.isEmpty()) {
        UndoRedoHandler.getInstance().add(new SequenceCommand("Criar centroides com tags", comandos));
        
        new Notification("Centroides foram criados com sucesso.")
            .setIcon(UIManager.getIcon("OptionPane.informationIcon"))
            .show();
    } else {
        new Notification("Nenhum polígono válido selecionado.")
            .setIcon(UIManager.getIcon("OptionPane.warningIcon"))
            .show();
    }
}

criarCentroidesComTags();