Algorytm sprawdzający, czy dwa woksele są ze sobą połączone

11

Szukam dobrych algorytmów dla następującego problemu: Biorąc pod uwagę siatkę 3D wokseli (które mogą być puste lub wypełnione), jeśli wybiorę dwa niesąsiadujące woksele, chcę wiedzieć, czy są one połączone ze sobą przez inne woksele.

Na przykład (aby zilustrować sytuację w 2D), gdzie # to wypełniony kwadrat:

  1 2 3
a # # #
b # #
c # # #

Jeśli wybiorę a3 i c3, chcę jak najszybciej ustalić, czy są one połączone; jeśli istnieje ścieżka między a3 i c3 przez wypełnione piksele. (Rzeczywista sytuacja jest oczywiście w siatce wokseli 3D).

Patrzyłem na algorytmy wypełniania zalewów i algorytmy wyszukiwania ścieżek, ale nie jestem pewien, który wybrać. Oba wykonują niepotrzebną pracę: funkcja Flood próbuje wypełnić wszystkie woksele, ale nie jest to konieczne. Algorytmy ustalania ścieżki zwykle dotyczą znalezienia najkrótszej ścieżki, co również nie jest konieczne. Muszę tylko wiedzieć, czy tam jest ścieżka.

Jakiego algorytmu powinienem używać?

Edycja: na podstawie komentarzy, myślę, że powinienem dodać: zawartość wokseli nie jest z góry znana, a także algorytm jest potrzebny do wykrycia, czy usunięcie (opróżnienie) woksela spowodowałoby pęknięcie grupy wokseli na dwie lub więcej mniejszych grup.

Bram Vaessen
źródło
W przykładzie będzie prawidłowa ścieżka od A3 do c3 być następujące: c3->c2->b2->a2->a3?
to prawda
Bram Vaessen

Odpowiedzi:

12

* Działałoby dobrze. Szukanie ścieżki jest tym, czego chcesz, znalezienie najkrótszej ścieżki jest równie szybkie (lub szybsze) niż znalezienie jakiejkolwiek ścieżki. W tej sytuacji A * jest najbardziej odpowiedni, biorąc pod uwagę punkt początkowy i końcowy. oznacza to, że masz dodatkową heurystykę, aby przyspieszyć wyszukiwanie.

W przypadku A * zazwyczaj pierwsza znaleziona ścieżka jest najkrótsza, więc nie wykonuje dodatkowej pracy po znalezieniu ścieżki.

wprowadź opis zdjęcia tutaj

Dla niektórych optymalizacji sprawdź moją odpowiedź tutaj .

MichaelHouse
źródło
wygląda jakby naprawdę strzela do przodu, dopóki nie natrafi ten mur wtedy to rodzaj skrada
GameDev-ER
1
@ GameDev-er Tak, to z powodu heurystyki. Gdyby nie było przeszkody, byłoby to bardzo szybkie wyszukiwanie, prawie prosta linia.
MichaelHouse
Przy lepszym sortowaniu węzłów najpierw rozszerzy to ścieżkę najbliższą końcowemu węzłowi. Jeśli masz szybką strukturę danych do porządkowania węzłów, posortuj je według odległości do celu, aby uzyskać najbardziej bezpośrednią ścieżkę.
MichaelHouse
9

Jeśli jesteś przygotowany na wstępne przetwarzanie i zjedzenie kosztów przechowywania, wówczas dzielenie wokseli na połączone grupy w czasie kompilacji daje oczywistą odpowiedź na pytanie „czy w ogóle istnieje ścieżka”. Istnieje ścieżka między dwoma wokselami, jeśli należą do tej samej grupy. Problem polega na tym, że musisz gdzieś przechowywać informacje o grupie, a to zależy od układu danych. Jeśli przechowujesz prostą listę, możesz po prostu podzielić ją na wiele list, po jednej dla każdej grupy powiązanej przestrzennie. Jeśli organizujesz się w jakimś BVH, prawdopodobnie możesz uzyskać dość dobrą wydajność, jeśli możesz powiedzieć, że „wszystkie woksele w tym węźle i poniżej należą do grupy X”.

Alternatywnie, możesz zrobić przestrzenne wstępne partycjonowanie i przechowywać mniejszy zestaw wokseli „hub” dla każdej połączonej grupy. Następnie możesz znaleźć ścieżkę ze źródła i wokseli docelowych do najbliższego woksela piasty, który powinien być znacznie krótszy / tańszy w obliczeniu ścieżki. Jeśli możesz znaleźć ścieżkę od woksela do woksela hub, wtedy woksel jest częścią grupy wokseli hub. Dzięki inteligentnemu wyborowi tych wokseli piasty możesz zminimalizować liczbę przejść ścieżek. Np. Kula może mieć w środku tylko jeden woksel piasty, ale długa cienka grupa może mieć woksel piasty co X wokseli na swojej długości. Jeśli woksele źródłowe i docelowe znajdują się na dowolnym końcu długości, muszą znaleźć się w najwyżej X wokselach, aby znaleźć piastę, i chociaż może istnieć ogromna liczba wokseli między początkiem a końcem długości,

Wszystko zależy od tego, jak patologiczne są twoje grupy wokselowe: jeśli spodziewasz się dużej liczby małych, niepowiązanych grup, wzrost kosztów przechowywania będzie znacznie przewyższał wydajność samego wyszukiwania ścieżek. Jeśli oczekujesz stosunkowo niewielu połączonych grup, ale o dziwnych topologiach, wówczas naiwne wyszukiwanie ścieżek może być niezwykle kosztowne, a koszt przechowywania i minimalne wyszukiwanie ścieżek jest znacznie tańszą opcją.

MrCranky
źródło
1
To właściwa odpowiedź, ale aby ją skutecznie wdrożyć, nie powinna być przechowywana jako lista. Dodaj wskaźnik do każdego woksela, który wskazuje na „reprezentatywny woksel”, który ustawiasz za pomocą algorytmu znajdowania związku. Jest to stały koszt magazynowania na woksel i zasadniczo liniowy w liczbie krawędzi dla kosztu obliczeniowego.
Neil G
Ciekawe pomysły, ale są dwie rzeczy, które mogą skomplikować sytuację. Po pierwsze, zawartość siatki wokseli nie jest z góry znana, więc aby tworzyć woksele hubów, potrzebowałbym również algorytmu, który mógłby określić, które woksele powinny być hubami.
Bram Vaessen
1
Drugi problem polega na tym, że algorytm jest potrzebny zaraz po usunięciu jednego woksela, aby ustalić, czy grupa, której był częścią, jest podzielona na mniejsze grupy z powodu usunięcia tego woksela.
Bram Vaessen
@BramVaessen Jeśli szukasz wszystkich relacji między parami - a w szczególności tego, czy grupy się „rozpadają”, to jest to nieco inna sprawa niż po prostu osiągalność (chociaż osiągalność jest najłatwiejszym sposobem na poradzenie sobie z tym); Zachęcam do dodania szczegółowych informacji na temat tego, czego szukasz w pierwotnym pytaniu, ponieważ może to pozwolić na lepsze odpowiedzi na „problem związany z pytaniem”.
Steven Stadnicki
Aby zachować czystość, zadałem swój początkowy problem w innym pytaniu tutaj gamedev.stackexchange.com/questions/50953/…
Bram Vaessen
4

Nie znam się dobrze na wokselach, ale wyobrażam sobie, że można uzyskać całkiem niezłą wydajność dzięki zastosowaniu algorytmu najlepszego wyszukiwania, takiego jak A *. Problem z użyciem A * w tym przypadku polega na tym, że heurystyczny, którego normalnie by się użył, ma na celu ustalenie priorytetu znalezienia najkrótszej ścieżki, a nie tylko „dowolnej ścieżki” tak szybko, jak to możliwe.

Możesz mieć trochę szczęścia, używając alternatywnej heurystyki, która rozszerza mniej węzłów, takich jak

f (p) = g (p) + w (p) * h (p)

gdzie w> = 1. zmniejszasz wartość „w” im bardziej zbliżasz się do celu, tym samym nadając wyższy priorytet kosztowi ścieżki „g”, im bardziej zbliżasz się do woksela, którego szukasz.

Mam nadzieję, że to pomoże!

Matthew R.
źródło