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 radians
função, pois ST_Rotate
espera 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_rotate
com que ele seja girado no sentido horário.radians(<angle> * -1)