Como criar cadeias de linhas com um ângulo e comprimento definidos, fixados em um ponto

8

Eu quero criar cadeias de linhas com um ângulo definido (por exemplo, 160 °) e comprimento (por exemplo, 2m) que são fixados a vários pontos de outra cadeia de linhas. Então, eu quero usar a função ST_DumpPoints para encontrar os pontos e vincular as cadeias de linhas criadas a eles. Existe uma maneira de declarar um ângulo (α) durante a criação da cadeia de linhas? Aqui está um exemplo de imagem:

insira a descrição da imagem aqui

Eu quero criar as cadeias de linhas azuis.

EDITAR

O ângulo (α2) na imagem não é realmente exemplar. Mas sim um azimute de 160 ° (como α1).

ATUALIZAR

A resposta do Evil Genius me ajudou a calcular a largura máxima de um polígono com um determinado aspecto.

Stefan
fonte

Respostas:

11

Você pode fazer isso de maneiras diferentes, dependendo do tipo de saída que deseja, mas o conceito é o mesmo. Geralmente é mais fácil fazer uma rotação simples seguida por uma tradução, em vez de tentar calcular as coordenadas em uma única etapa.

Nesse caso, as etapas básicas são:

  • Crie uma linha do comprimento desejado na origem (0,0). Essa linha deve percorrer o eixo a partir do qual você deseja medir o ângulo e ter o centro na origem.
  • Gire a linha ao redor da origem.
  • Traduza a linha pelas coordenadas do ponto em que você deseja que ela seja centralizada.

A seguinte visualização PostGIS cria as linhas do seu cenário de exemplo. Algumas coisas são assumidas:

  • A coluna de geometria é chamada shape
  • O ângulo é medido a partir do eixo x. Seu desenho de exemplo foi um pouco confuso desde que você mencionou 40 graus pela primeira vez, desenhou uma linha vertical pontilhada, mas disse que deveria estar em torno de 160 graus. Eu interpretei que isso significa que você realmente deseja medir a partir do eixo x.
  • Os dados são projetados nas mesmas unidades com as quais você deseja medir (ou seja, metros).

    CREATE OR REPLACE VIEW <viewname> AS
    WITH vertices AS
    (SELECT 
          objectid, 
          (ST_DumpPoints(shape)).path[1] AS v_id, 
          (ST_DumpPoints(shape)).geom AS vertex
    FROM <source_data>
    )
    SELECT
        objectid,
        v_id,
        ST_SetSRID(ST_Translate(ST_Rotate(ST_MakeLine(ST_MakePoint( 1.0,0.0), 
                                                      ST_MakePoint(-1.0,0.0)),
                                          radians(40)), ST_X(vertex), ST_Y(Vertex)),
                                          ST_SRID(vertex)) AS newline
    FROM vertices

Para detalhar o que realmente está acontecendo com essa última linha, começando pelo mais interno: ST_SetSRID(ST_Translate(ST_Rotate(ST_MakeLine(ST_MakePoint( 0,1.0), ST_MakePoint(0,-1.0)), radians(40)), ST_X(vertex), ST_Y(Vertex)), ST_SRID(vertex)) AS newline

  • ST_MakePoint(1.0,0.0)e ST_MakePoint(-1.0,0.0): Crie os pontos finais para uma linha horizontal com o comprimento desejado e centralizada na origem.
  • ST_MakeLine(...): Use nossos pontos finais criados recentemente para criar uma linha.
  • ST_Rotate(..., radians(40)): Gire essa nova linha ao redor da origem.
  • ST_Translate(..., ST_X(vertex), ST_Y(vertex)): Centralize a linha girada no nosso ponto de referência (entrada).
  • ST_SetSRID(..., ST_SRID(vertex)): Dê à nova linha o mesmo SRID da geometria de entrada.

Se você estiver usando o PostGIS 2.0, poderá simplificar isso, pois poderá especificar uma origem diferente ST_Rotate. Se você quiser girar para um ângulo com base na inclinação da linha, terá que calcular isso primeiro e adicioná-lo ao ângulo de rotação.

Se os dados não forem projetados nas mesmas unidades que você deseja medir, você ainda poderá fazer algo semelhante, mas precisará de uma etapa extra:

  • Crie uma linha (projetada em algo que use o que você deseja medir)
  • Rodar
  • Reprojetar para sua projeção alvo
  • Traduzir para o ponto de destino

Editar

Agora eu entendo o que você quer dizer com ângulo. Essencialmente, você deseja uma rotação no sentido horário a partir do eixo Y (0 está acima, 90 está certo, 180 está desativado etc.).

Você ainda precisa usar a radiansfunção, pois ST_Rotateespera o ângulo em radianos. Você deve conseguir o ângulo correto com duas pequenas alterações:

  • Comece com uma linha vertical (use ST_MakePoint(0.0,1.0)e ST_MakePoint(0.0,-1.0))
  • Multiplique seu ângulo por -1. Isso o tornará negativo, fazendo ST_rotatecom que ele seja girado no sentido horário.radians(<angle> * -1)
Gênio do mal
fonte
Você é um gênio do mal! Obrigado. Funciona perfeitamente, mas configurando o ângulo certo. Trabalho com ângulos (armazenados em uma coluna), que são como uma exposição ou aspecto (0 a 360 graus). Um aspecto de 200 °, por exemplo (como a direção geográfica SSW): quando planto as cadeias de linhas, elas não têm o ângulo reto. Usando graus (), a direção geográfica é como SSE e usando radianos () como SW.
27613 Stefan #
@StefanB. Estou feliz que tenha sido útil! Eu editei minha resposta (muito abaixo) para mostrar como você deve conseguir o ângulo que deseja.
Mal Genius
Funciona. Ideia brilhante!
27613 Stefan