Niedawno natknąłem się na problem, w którym miałem cztery okręgi (punkty środkowe i promień) i musiałem obliczyć powierzchnię sumy tych okręgów.
Przykładowe zdjęcie:
Dla dwóch kręgów to całkiem proste,
Mogę po prostu obliczyć ułamek powierzchni każdego koła, który nie znajduje się wewnątrz trójkątów, a następnie obliczyć pole powierzchni trójkątów.
Ale czy istnieje sprytny algorytm, którego mogę użyć, gdy jest więcej niż dwa okręgi?
Odpowiedzi:
Znajdź wszystkie przecięcia okręgów na zewnętrznym obwodzie (np. B, D, F, H na poniższym diagramie). Połącz je ze środkami odpowiednich okręgów, aby utworzyć wielokąt. Obszar sumy okręgów to obszar wielokąta + obszar wycinków koła określony przez kolejne punkty przecięcia i środek okręgu pomiędzy nimi. Musisz również uwzględnić wszelkie dziury.
źródło
Jestem pewien, że istnieje sprytny algorytm, ale tutaj jest głupi, aby oszczędzić konieczności szukania go;
Jasne, że to głupie, ale:
źródło
Odpowiedź Antsa Aasmy dała podstawową ideę, ale chciałem uczynić ją trochę bardziej konkretną. Spójrz na pięć kręgów poniżej i sposób, w jaki zostały rozłożone.
Rozpoznanie tych 3 rodzajów kropek jest łatwe. Teraz skonstruuj graficzną strukturę danych, w której węzły to niebieskie kropki i czerwone kropki z białym wnętrzem. Dla każdego okręgu umieść krawędź między środkiem koła (niebieska kropka) a każdym z jego przecięć (czerwone kropki z białym wnętrzem) na jego granicy.
To rozkłada sumę koła na zestaw wielokątów (zacieniowane na niebiesko) i okrągłe fragmenty koła (zacieniowane na zielono), które są rozłączne parami i zakrywają oryginalną sumę (czyli partycję). Ponieważ każdy element tutaj jest czymś, co jest łatwe do obliczenia pola powierzchni, możesz obliczyć pole sumy powierzchni elementów.
źródło
W przypadku innego rozwiązania niż poprzednie można oszacować oszacowanie z dowolną dokładnością przy użyciu drzewa czwórkowego.
Działa to również w przypadku dowolnej unii kształtu, jeśli możesz stwierdzić, czy kwadrat znajduje się wewnątrz, czy na zewnątrz, czy też przecina kształt.
Każda komórka ma jeden ze stanów: pusta, pełna, częściowa
Algorytm polega na „rysowaniu” okręgów w drzewie czwórnym zaczynając od małej rozdzielczości (np. 4 komórki oznaczone jako puste). Każda komórka to:
Kiedy skończysz, możesz obliczyć oszacowanie powierzchni: pełne komórki dają dolną granicę, puste komórki dają wyższą granicę, częściowe komórki dają maksymalny błąd powierzchni.
Jeśli błąd jest dla Ciebie zbyt duży, udoskonalaj częściowe komórki, aż uzyskasz odpowiednią precyzję.
Myślę, że będzie to łatwiejsze do wdrożenia niż metoda geometryczna, która może wymagać obsługi wielu specjalnych przypadków.
źródło
Uwielbiam podejście do przypadku 2 przecinających się okręgów - oto jak użyłbym niewielkiej odmiany tego samego podejścia dla bardziej złożonego przykładu.
Może to dać lepszy wgląd w uogólnianie algorytmu dla większej liczby częściowo nakładających się okręgów.
Różnica polega na tym, że zaczynam od połączenia centrów (więc między środkami okręgów jest wierzchołek, a nie między miejscami, w których przecinają się okręgi). Myślę, że to pozwala lepiej uogólnić.
(w praktyce może metoda Monte-Carlo się opłaca)
(źródło: secretGeek.net )
źródło
Jeśli chcesz uzyskać dyskretną (a nie ciągłą) odpowiedź, możesz zrobić coś podobnego do algorytmu malowania pikseli.
Narysuj okręgi na siatce, a następnie pokoloruj każdą komórkę siatki, jeśli jest w większości zawarta w okręgu (tj. Co najmniej 50% jej powierzchni znajduje się wewnątrz jednego z okręgów). Zrób to dla całej siatki (gdzie siatka obejmuje cały obszar pokryty okręgami), a następnie policz liczbę kolorowych komórek w siatce.
źródło
Hmm, bardzo ciekawy problem. Moje podejście byłoby prawdopodobnie podobne do następujących:
(dotyczy to dowolnego kształtu, czy to koła, czy innego)
Gdzie
A ∪ B
oznacza A związek B iA ∩ B
oznacza A przecina B (możesz to rozwiązać od pierwszego kroku.(To jest to samo, co powyżej, gdzie
A
zostało zastąpioneA∪B
)Gdzie
area(A∪B)
właśnie wypracowaliśmy iarea((A∪B)∩C)
można znaleźć:Gdzie znowu można znaleźć obszar (A∩B∩C) z góry.
Najtrudniejszy jest ostatni krok - im więcej okręgów zostanie dodanych, tym bardziej się to skomplikuje. Uważam, że istnieje rozszerzenie umożliwiające obliczenie obszaru przecięcia ze skończoną sumą lub alternatywnie można to rozwiązać rekursywnie.
Również w odniesieniu do użycia metody Monte-Carlo do przybliżenia obszaru itersekcji, uważam, że możliwe jest zredukowanie przecięcia dowolnej liczby okręgów do przecięcia 4 z tych okręgów, które można dokładnie obliczyć (nie mam pojęcia, jak to zrobić jednak).
Przy okazji prawdopodobnie istnieje lepszy sposób na zrobienie tego - złożoność znacznie wzrasta (prawdopodobnie wykładniczo, ale nie jestem pewien) dla każdego dodanego dodatkowego koła.
źródło
Pracowałem nad problemem symulacji zachodzących na siebie pól gwiazd, próbując oszacować rzeczywistą liczbę gwiazd na podstawie rzeczywistych obszarów dysku w gęstych polach, gdzie większe jasne gwiazdy mogą maskować słabsze. Ja również miałem nadzieję, że uda mi się to zrobić poprzez rygorystyczną analizę formalną, ale nie mogłem znaleźć algorytmu do tego zadania. Rozwiązałem to, generując pola gwiazdowe na niebieskim tle w postaci zielonych dysków, których średnica została określona przez algorytm prawdopodobieństwa. Prosta procedura może sparować je, aby sprawdzić, czy zachodzą na siebie (zmiana koloru pary gwiazd na żółty); następnie liczba pikseli kolorów generuje obserwowany obszar w celu porównania z obszarem teoretycznym. To następnie generuje krzywą prawdopodobieństwa dla prawdziwych zliczeń. Może brutalna siła, ale wydaje się, że działa OK. (źródło: 2from.com )
źródło
Oto algorytm, który powinien być łatwy do wdrożenia w praktyce i można go dostosować tak, aby powodował dowolnie mały błąd:
Kroki 2 i 3 można przeprowadzić za pomocą standardowych, łatwych do znalezienia algorytmów z geometrii obliczeniowej.
Oczywiście im więcej stron użyjesz dla każdego przybliżającego się wielokąta, tym bliższa byłaby dokładna odpowiedź. Możesz przybliżyć użycie wpisanych i opisanych wielokątów, aby uzyskać granice dokładnej odpowiedzi.
źródło
Istnieją skuteczne rozwiązania tego problemu przy użyciu tak zwanych schematów mocy. To jest jednak naprawdę ciężka matematyka i nie jest to coś, czym chciałbym się zająć od ręki. Aby uzyskać „łatwe” rozwiązanie, wyszukaj algorytmy przeglądania linii. Podstawową zasadą jest tutaj podzielenie figury na paski, gdzie obliczenie powierzchni w każdym pasku jest stosunkowo łatwe.
Tak więc na rysunku zawierającym wszystkie okręgi, na których nic nie zostało wytarte, narysuj poziomą linię w każdej pozycji, która jest albo górą, albo dolną częścią okręgu, albo przecięciem 2 okręgów. Zauważ, że wewnątrz tych pasków wszystkie obszary, które musisz obliczyć, wyglądają tak samo: „trapez” z dwoma bokami zastąpionymi okrągłymi segmentami. Jeśli więc potrafisz obliczyć taki kształt, po prostu zrób to dla wszystkich indywidualnych kształtów i zsumuj je. Złożoność tego naiwnego podejścia to O (N ^ 3), gdzie N to liczba okręgów na rysunku. Mając sprytne wykorzystanie struktury danych, możesz ulepszyć tę metodę zamiatania linii do O (N ^ 2 * log (N)), ale jeśli naprawdę nie musisz, prawdopodobnie nie jest to warte zachodu.
źródło
Znalazłem ten link, który może być przydatny. Wydaje się jednak, że nie ma ostatecznej odpowiedzi. Odpowiedzi Google . Innym odniesieniem dla trzech okręgów jest twierdzenie Harukiego . Tam też jest gazeta.
źródło
W zależności od problemu, który próbujesz rozwiązać, może wystarczyć określenie górnej i dolnej granicy. Górna granica jest łatwa, po prostu suma wszystkich okręgów. W przypadku dolnej granicy możesz wybrać pojedynczy promień, tak aby żadne z okręgów się nie nakładały. Aby lepiej to znaleźć, znajdź największy promień (aż do rzeczywistego promienia) dla każdego okręgu, aby się nie nakładał. Powinno być również dość trywialne usunięcie wszelkich całkowicie nakładających się okręgów (wszystkie takie okręgi spełniają | P_a - P_b | <= r_a), gdzie P_a jest środkiem okręgu A, P_b jest środkiem okręgu B, a r_a jest promieniem A ), co poprawia zarówno górną, jak i dolną granicę. Możesz również uzyskać lepszą Górną granicę, jeśli użyjesz wzoru na pary na dowolnych parach, a nie tylko na sumie wszystkich okręgów. Może istnieć dobry sposób na wybranie „najlepszych”
Biorąc pod uwagę górną i dolną granicę, możesz być w stanie lepiej dostroić podejście Monte-Carlo, ale nic konkretnego nie przychodzi na myśl. Inną opcją (ponownie w zależności od aplikacji) jest rasteryzacja okręgów i zliczanie pikseli. Jest to w zasadzie metoda Monte-Carlo ze stałym rozkładem.
źródło
Można to rozwiązać za pomocą twierdzenia Greena ze złożonością n ^ 2log (n). Jeśli nie znasz Twierdzenia Greena i chcesz dowiedzieć się więcej, oto film i notatki z Khan Academy. Ale ze względu na nasz problem myślę, że mój opis wystarczy.
Ogólne równanie twierdzenia Greena
Jeśli wstawię L i M takie, że
Stan: schorzenie
wtedy RHS jest po prostu obszarem Regionu R i można go uzyskać rozwiązując całkę zamkniętą lub LHS i to jest dokładnie to, co zamierzamy zrobić.
Wszystkie związki można rozbić na takie rozłączne zbiory okręgów, które się przecinają
Tak więc całkowanie wzdłuż ścieżki w kierunku przeciwnym do ruchu wskazówek zegara daje nam Obszar regionu, a całkowanie zgodnie z ruchem wskazówek zegara daje nam ujemny obszar . Więc
AreaOfUnion = (Integracja wzdłuż czerwonych łuków w kierunku przeciwnym do ruchu wskazówek zegara + Integracja wzdłuż niebieskich łuków w kierunku zgodnym z ruchem wskazówek zegara)
Ale fajna sztuczka polega na tym, że dla każdego okręgu, jeśli scałkujemy łuki, które nie znajdują się wewnątrz żadnego innego okręgu, otrzymamy wymagany obszar, tj. Uzyskamy całkowanie w kierunku przeciwnym do ruchu wskazówek zegara wzdłuż wszystkich czerwonych łuków i całkowanie wzdłuż wszystkich niebieskich łuków wzdłuż kierunku zgodnego z ruchem wskazówek zegara. ZADANIE WYKONANE!!!
Oto łącze GitHub do mojego kodu C ++
źródło
Podejście do malowania pikseli (zgodnie z sugestią @Loadmaster) przewyższa rozwiązanie matematyczne na wiele sposobów:
Jedyną wadą malowania pikseli jest ograniczona dokładność rozwiązania. Ale można to dostroić, po prostu renderując na większe lub mniejsze płótna, w zależności od sytuacji. Zwróć też uwagę, że wygładzanie krawędzi w kodzie renderowania 2D (często domyślnie włączone) zapewni dokładność lepszą niż na poziomie piksela. Na przykład renderowanie figury 100x100 na płótnie o tych samych wymiarach powinno, moim zdaniem, dać dokładność rzędu 1 / (100 x 100 x 255) = 0,000039% ... co jest prawdopodobnie „wystarczająco dobre” do wszystkich problemów oprócz najbardziej wymagających.
źródło