Comment créer des chaînes de lignes avec un angle et une longueur définis, qui sont fixées à un point

8

Je veux créer des lignes de ligne avec un angle défini (par exemple 160 °) et une longueur (par exemple 2m) qui sont fixées à un certain nombre de points d'une autre ligne. Donc, je veux utiliser la fonction ST_DumpPoints pour trouver les points et leur lier les chaînes de lignes créées. Existe-t-il un moyen de déclarer un angle (α) lors de la création de la chaîne de lignes? Voici un exemple d'image:

entrez la description de l'image ici

Je veux créer les linestrings bleus.

ÉDITER

L'angle (α2) dans l'image n'est pas vraiment exemplaire. Mais plutôt un azimut de 160 ° (comme α1).

MISE À JOUR

La réponse d'Evil Genius m'a aidé à calculer la largeur maximale d'un polygone avec un aspect donné.

Stefan
la source

Réponses:

11

Vous pouvez accomplir cela de différentes manières selon le type de sortie que vous recherchez, mais le concept est le même. Il est généralement plus facile de faire une simple rotation suivie d'une translation plutôt que d'essayer de calculer les coordonnées en une seule étape.

Dans ce cas, les étapes de base sont les suivantes:

  • Créez une ligne de la longueur souhaitée à l'origine (0,0). Cette ligne doit courir le long de l'axe à partir duquel vous souhaitez mesurer votre angle et avoir son centre à l'origine.
  • Faites pivoter la ligne autour de l'origine.
  • Traduisez la ligne par les coordonnées du point sur lequel vous souhaitez qu'elle soit centrée.

La vue PostGIS suivante crée les lignes à partir de votre exemple de scénario. Quelques hypothèses sont supposées:

  • La colonne de géométrie est appelée shape
  • L'angle est mesuré à partir de l'axe x. Votre exemple de dessin était un peu déroutant puisque vous avez mentionné pour la première fois 40 degrés, dessiné une ligne verticale en pointillés, mais que vous aviez ensuite dit qu'il devrait être d'environ 160 degrés. J'ai interprété cela comme signifiant que vous voulez réellement mesurer à partir de l'axe des x.
  • Les données sont projetées dans les mêmes unités avec lesquelles vous souhaitez mesurer (c.-à-d. Des mètres).

    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
    

Pour décomposer ce qui se passe réellement avec cette dernière ligne, en commençant par le plus intérieur: 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)et ST_MakePoint(-1.0,0.0): Créez les points d'extrémité pour une ligne horizontale qui est notre longueur souhaitée et centrée sur l'origine.
  • ST_MakeLine(...): Utilisez nos points de terminaison nouvellement créés pour créer une ligne.
  • ST_Rotate(..., radians(40)): Faites pivoter cette nouvelle ligne autour de l'origine.
  • ST_Translate(..., ST_X(vertex), ST_Y(vertex)): Centrez la ligne pivotée sur notre point de référence (entrée).
  • ST_SetSRID(..., ST_SRID(vertex)): Donnez à la nouvelle ligne le même SRID que la géométrie en entrée.

Si vous utilisez PostGIS 2.0, vous pouvez simplifier cela car vous pouvez spécifier une origine différente pour ST_Rotate. Si vous souhaitez faire pivoter selon un angle basé sur la pente de la ligne, vous devrez d'abord le calculer et l'ajouter à l'angle de rotation.

Si les données ne sont pas projetées dans les mêmes unités que celles que vous souhaitez mesurer, vous pouvez toujours faire quelque chose de similaire, mais vous aurez besoin d'une étape supplémentaire:

  • Créez une ligne (projetée dans quelque chose qui utilise ce que vous voulez mesurer)
  • Tourner
  • Reprojetez à votre projection cible
  • Traduire au point cible

Éditer

Je comprends maintenant ce que vous entendez par l'angle. Essentiellement, vous voulez une rotation dans le sens horaire à partir de l'axe Y (0 est haut, 90 est droit, 180 est bas, etc.).

Vous devez toujours utiliser la radiansfonction, car ST_Rotateattendez l'angle en radians. Vous devriez pouvoir obtenir l'angle correct avec deux petits changements:

  • Commencez par une ligne verticale (utilisez ST_MakePoint(0.0,1.0)et ST_MakePoint(0.0,-1.0))
  • Multipliez votre angle par -1. Cela le rendra négatif, provoquant ST_rotatesa rotation dans le sens horaire.radians(<angle> * -1)
Génie du mal
la source
Tu es un mauvais génie! Merci. Cela fonctionne parfaitement, mais en configurant le bon angle. Je travaille avec des angles (stockés dans une colonne), qui sont comme une exposition ou un aspect (0 à 360 degrés). Un aspect de 200 ° par exemple (comme la géo direction SSW): quand je trace les linestrings ils n'ont pas le bon angle. En utilisant les degrés (), la direction géographique est comme SSE et en utilisant les radians () comme SW.
Stefan
@StefanB. Je suis content que ce soit utile! J'ai édité ma réponse (tout en bas) pour montrer comment vous devriez pouvoir atteindre l'angle que vous voulez.
Evil Genius
Ça marche. Idée brillante!
Stefan