Wątek przeniesiony 2022-12-30 10:43 z Bazy danych przez Riddle.

Losowe punkty w obszarze terytorium Polski

0

mam za zadanie połączyć się z bazą danych postgresql przez c++ zrobiłem to za pomocą biblioteki pqxx i napisać funkcję która wygeneruje losowe punkty w obszarze granic Polski i zapisze je w tabeli punkty(x,y,z), (min 1000 punktów, dla wartości Z czyli wysokości proszę przyjąć zakres od 0 do 300 metrów). Przyznam się szczerze, że nawet nie wiem do końca czy mam to zrobić w sql jako funkcję czy w c++.

Treść całego zadania

  • zainstalowanie bazy danych PostgreSQL z rozszerzeniem przestrzennym (POST GIS)

  • w bazie danych należy stworzyć tabelę punkty (X,Y,Z) - w języku C# lub C++ napisać program który połączy się z bazą danych - proszę napisać funkcję która wygeneruje losowe punkty w obszarze granic Polski i zapisze je w tabeli punkty (min 1000 punktów, dla wartości Z czyli wysokości proszę przyjąć zakres od 0 do 300 metrów)

  • proszę napisać test który będzie sprawdzał czy generowane punkty są w odległości min 3 km od siebie

  • proszę stworzyć tabelę województwa i zaimportować tam granice województw

  • proszę napisać funkcję która dla każdego województwa wypisze wszystkie wygenerowane punkty które zawierają się w jego obrysie.

  • Granica polski i województw jest zaimportowana do postgresql i wiem, że mogę wygenerować losowe punkty z QDIS, ale w treści jest napisane, żeby taką funkcję napisać i tak jak zaznaczam nie wiem czy chodzi o namisanie jej w programie czy w sql i w sumie to pytanie odnośi się też do napisania testu.

3

Pokaż co już zrobiłeś.

1

Z tego co rozumiem to musisz użyć jednego z typów geometrycnych w PostgreSQL. Dokumentacja jest tutaj//www.postgresql.org/docs/current/datatype-geometric.html

Tutaj jest artykuł z którego ja kiedyś korzystałem przy podobnym zadaniu w pracy: https://engineering.zalando.com/posts/2021/12/maps-with-postgresql-and-postgis.html

Kod musisz napisać w C# albo w C++, który . Ja radziłbym Ci iść w C# zamiast C++, ale jeśli znasz C++ dobrze to też może być. Ale jesli nie znasz go dobrze to łatwiej Ci będzie ogarnąc podstawy C# niż borykać się z ewentualnymi problemami w C++.

Wygenerowanie punktów w granicach polski jest bardzo proste, po prostu bierzesz 2 losowe punkty na granicy, na przeciwległych krancach i generujesz losowy punkt, z tym, że trzeba sprawdzić czy wygenerował się w granicach bo istenieje ryzyko, że akurat wziąłeś punkty, które łączą się linią(chociaż częściowo) narysowaną poza granicami :)

2
daniel1302 napisał(a):

Wygenerowanie punktów w granicach polski jest bardzo proste, po prostu bierzesz 2 losowe punkty na granicy, na przeciwległych krancach i generujesz losowy punkt, z tym, że trzeba sprawdzić czy wygenerował się w granicach bo istenieje ryzyko, że akurat wziąłeś punkty, które łączą się linią(chociaż częściowo) narysowaną poza granicami :)

To rozwiązanie daje nierównomierny rozkład, co może być problemem (a może i nie być). Ja bym sugerował sprawdzić, czy Polska lepiej wypełnia koło, czy prostokąt (intuicyjnie wydaje się, że prostokąt, ale nie jestem pewien), a potem losować punkt w tym kole/prostokącie, i jeśli wypada wewnątrz granic, to go zostawić, a jak nie, to ponowić losowanie.

Większe ryzyko ponawiania losowania, za to równomierny rozkład punktów.

1
Althorion napisał(a):
daniel1302 napisał(a):

Wygenerowanie punktów w granicach polski jest bardzo proste, po prostu bierzesz 2 losowe punkty na granicy, na przeciwległych krancach i generujesz losowy punkt, z tym, że trzeba sprawdzić czy wygenerował się w granicach bo istenieje ryzyko, że akurat wziąłeś punkty, które łączą się linią(chociaż częściowo) narysowaną poza granicami :)

To rozwiązanie daje nierównomierny rozkład, co może być problemem (a może i nie być). Ja bym sugerował sprawdzić, czy Polska lepiej wypełnia koło, czy prostokąt (intuicyjnie wydaje się, że prostokąt, ale nie jestem pewien), a potem losować punkt w tym kole/prostokącie, i jeśli wypada wewnątrz granic, to go zostawić, a jak nie, to ponowić losowanie.

Większe ryzyko ponawiania losowania, za to równomierny rozkład punktów.

Po wylosowaniu 2ch punktów na granice, wyliczamy odległość, losujemy jako pow(rand(sqrt(len)),2) tym samym eliminujemy nierównomierność rozkładu oraz eliminujemy powtarzanie losowania.

0
Riddle napisał(a):

Pokaż co już zrobiłeś.

1.Połączenie c++ postgresql
2.wczytanie plików shh do bazy https://gis-support.pl/baza-wiedzy-2/dane-do-pobrania/granice-administracyjne/ polska i województwa
3.stworzenie tabeli x,y,z typu geometrycznego

#include <string>
#include <iostream>
#include <pqxx/pqxx>
#include <random>
#include <pqxx/stream_to.hxx>    
#include <pqxx/transaction_base.hxx>
#include <pqxx/stream_from.hxx>

int main()
{

    std::string connectionString = "host=localhost port=5432 dbname=test user=postgres password = XXX";

    try
    {
        pqxx::connection connectionObject(connectionString.c_str());
        pqxx::work worker(connectionObject);

        pqxx::result response = worker.exec("SELECT * FROM punkt");

        for (size_t i = 0; i < response.size(); i++)
        {
            std::cout << "Id: " << response[i][0] << " X: " << response[i][1] << " Y: " << response[i][2] << " Z: " << response[i][3] << std::endl;
        }
    }
    catch (const std::exception& e)
    {
        std::cerr << e.what() << std::endl;
    }
    system("pause");
}
0

Czy tę funkcję mam napisać w jakimś frameworku? np Qt. Bo rozumiem, że muszę pobrać zaimplementowane dane obszaru Polski z postgresql, stworzyć jakiegoś fora, lub jakąś inną pętle iterować minimum 10000 razy i generować losowe punkty, po czym je zapisać w tabeli x,y,z. Czy mam to zrobić w SQL?

1

Nie ma co kombinować, szczególnie, że Polska jest dość prostokątna.

  1. Wczytujesz polygon granic polski.
  2. Liczysz minimalny prostokąt zawierający całość Polski
  3. Losujesz punkt w prostokącie (co jest łatwe, bo masz do wylosowania po prostu współrzędne X i Y w konkretnych zakresach).
  4. Następnie testujesz czy wylosowany punkt leży wewnątrz granic Polski.
  5. Jeśli nie to ponownie losujesz punkt w prostokącie (skaczesz do 3).

Jako że mówimy o współrzędnych geograficznych, to pojawia efekt, że północ będzie bardziej preferowana od południa.
Jeśli to problem, to łatwo wprowadzić poprawkę w punkcie 3 by wsiąść to pod uwagę (inny rozkład losowania szerokości geograficznej).

W Qt wszystkie kroki są proste do zrealizowania, bo dużo jest już gotowe. Np bool QPainterPath::contains(const QPointF &point) const.

Nie wiem, jakby to miało wyglądać po stronie PostgreSQL.

1 użytkowników online, w tym zalogowanych: 0, gości: 1