Cara membuat linestrings dengan sudut dan panjang yang pasti, yang ditetapkan ke suatu titik

8

Saya ingin membuat linestring dengan sudut tertentu (mis. 160 °) dan panjang (misalnya 2m) yang ditetapkan ke sejumlah titik linestring lain. Jadi, saya ingin menggunakan fungsi ST_DumpPoints untuk menemukan poin dan mengikat linestrings yang dibuat padanya. Apakah ada cara untuk menyatakan sudut (α) selama pembuatan linestring? Berikut ini contoh gambarnya:

masukkan deskripsi gambar di sini

Saya ingin membuat linestrings biru.

EDIT

Sudut (α2) dalam gambar tidak benar-benar teladan. Melainkan azimuth 160 ° (seperti α1).

MEMPERBARUI

Jawaban dari Genius Jahat membantu saya menghitung lebar maksimum poligon dengan aspek tertentu.

Stefan
sumber

Jawaban:

11

Anda dapat melakukan ini dengan beberapa cara berbeda tergantung pada jenis output yang Anda inginkan, tetapi konsepnya sama. Umumnya lebih mudah untuk melakukan rotasi sederhana diikuti oleh terjemahan daripada mencoba menghitung koordinat dalam satu langkah.

Dalam hal ini, langkah-langkah dasarnya adalah:

  • Buat garis dengan panjang yang diinginkan di titik asal (0,0). Baris ini harus dijalankan di sepanjang sumbu yang Anda inginkan untuk mengukur sudut dan dari pusatnya pada titik asal.
  • Putar garis di sekitar titik asal.
  • Terjemahkan garis dengan koordinat titik yang Anda inginkan untuk dipusatkan.

Tampilan PostGIS berikut membuat garis-garis dari skenario contoh Anda. Beberapa hal diasumsikan:

  • Kolom geometri disebut shape
  • Sudut diukur dari sumbu x. Contoh gambar Anda agak membingungkan karena Anda pertama kali menyebutkan 40 derajat, menggambar garis vertikal bertitik, tetapi kemudian mengatakan itu harus sekitar 160 derajat. Saya telah menafsirkan bahwa itu berarti Anda benar-benar ingin mengukur dari sumbu x.
  • Data diproyeksikan dalam unit yang sama yang ingin Anda ukur (mis. Meter).

    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

Untuk memecah apa yang sebenarnya terjadi dengan baris terakhir itu, mulai dari yang paling dalam: 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)dan ST_MakePoint(-1.0,0.0): Buat titik akhir untuk garis horizontal yang panjangnya diinginkan dan berpusat pada titik asal.
  • ST_MakeLine(...): Gunakan titik akhir kami yang baru dibuat untuk membuat garis.
  • ST_Rotate(..., radians(40)): Putar baris baru di sekitar titik asal.
  • ST_Translate(..., ST_X(vertex), ST_Y(vertex)): Tengahkan garis yang diputar ke titik referensi (input) kami.
  • ST_SetSRID(..., ST_SRID(vertex)): Berikan baris baru SRID yang sama dengan geometri input.

Jika Anda menggunakan PostGIS 2.0, Anda dapat menyederhanakan ini karena Anda dapat menentukan asal yang berbeda ST_Rotate. Jika Anda ingin memutar sudut berdasarkan kemiringan garis, Anda harus menghitungnya terlebih dahulu dan menambahkannya ke sudut rotasi.

Jika data tidak diproyeksikan dalam unit yang sama yang ingin Anda ukur, Anda masih bisa melakukan hal serupa, tetapi Anda akan memerlukan langkah ekstra:

  • Buat garis (diproyeksikan pada sesuatu yang menggunakan apa yang ingin Anda ukur)
  • Memutar
  • Proyeksi ulang proyeksi target Anda
  • Menerjemahkan ke titik target

Edit

Saya sekarang mengerti apa yang Anda maksud dengan sudut. Pada dasarnya, Anda menginginkan rotasi searah jarum jam dari sumbu Y (0 naik, 90 benar, 180 turun, dll.).

Anda masih perlu menggunakan radiansfungsi itu karena ST_Rotatemengharapkan sudut dalam radian. Anda harus bisa mendapatkan sudut yang benar dengan dua perubahan kecil:

  • Mulai dengan garis vertikal (gunakan ST_MakePoint(0.0,1.0)dan ST_MakePoint(0.0,-1.0))
  • Lipat gandakan sudut Anda dengan -1. Ini akan membuatnya negatif, menyebabkan ST_rotateuntuk memutarnya searah jarum jam.radians(<angle> * -1)
Genius Jahat
sumber
Anda seorang jenius jahat! Terima kasih. Ini berfungsi sempurna, tetapi mengatur sudut kanan. Saya bekerja dengan sudut (disimpan dalam kolom), yang seperti eksposisi atau aspek (0 hingga 360 derajat). Aspek 200 ° misalnya (seperti geo direction SSW): ketika saya memplot linestrings, mereka tidak memiliki sudut kanan. Menggunakan derajat () arah geonya seperti SSE dan menggunakan radian () seperti SW.
Stefan
@StanB. Saya senang itu membantu! Saya telah mengedit jawaban saya (paling bawah) untuk menunjukkan bagaimana Anda harus dapat mencapai sudut yang Anda inginkan.
Evil Genius
Berhasil. Ide brilian!
Stefan