2009-07-29 9 views
40

Potrzebuję znaleźć punkt, który jest wizualnym środkiem wielokąta o nieregularnym kształcie. Przez centrum wizualne rozumiem punkt, który wydaje się być w centrum dużego obszaru wielokąta wizualnie. Aplikacja polega na umieszczeniu etykiety wewnątrz wielokąta.Jaki jest najszybszy sposób na znalezienie "wizualnego" środka wielokąta o nieregularnym kształcie?

Oto rozwiązanie, które wykorzystuje wewnątrz buforowania:

https://web.archive.org/web/20150708063910/http://proceedings.esri.com/library/userconf/proc01/professional/papers/pap388/p388.htm

Jeśli to ma być stosowane, co stanowi skuteczny i szybki sposób znaleźć bufor? Jeśli w jakikolwiek inny sposób należy użyć, to w ten sposób?

Dobrym przykładem naprawdę trudnych wielokątów jest gigantyczne grube U (napisane w Arial Black lub Impact lub jakiejś takiej czcionce).

+0

Co jeśli zbiór zdefiniowany przez wielokąt jest (wysoce) nie wypukły (en.wikipedia.org/wiki/Convex_set); czy może mieć środek poza poligonem? – Reunanen

+0

Tak, ale do celów etykietowania, musielibyśmy znaleźć punkt w środku. –

+0

@Mikhil: aby rozwinąć komentarz @ Pukku, czy mógłbyś napisać "trudny" aspekt tego problemu, tj.kształt, który byłby trudny do oznaczenia z uwagi na "naiwne" odpowiedzi, takie jak środek masy? Jedyne, o czym mogę pomyśleć, to gigantyczny U lub stan Floryda (środek masy tych kształtów znajduje się poza granicami) –

Odpowiedz

7

Jeśli można konwertować wielokąt w obrazie binarnym, wówczas można użyć fundament, który istnieje w dziedzinie przetwarzania obrazu, np .: A Fast Skeleton Algorithm on Block Represented Binary Images.

Jednak w ogólnym przypadku nie jest to uzasadnione z powodu błędów dyskretyzacji i dodatkowej pracy.

Jednakże, może znaleźć te przydatne:

EDIT: Może chcesz szukać punktu, który jest w centrum największego koła zawarte w wielokąt. Niekoniecznie jest to zawsze w obserwowanym ośrodku, ale przez większość czasu zapewne dawałby oczekiwany rezultat, a tylko w nieznacznie patologicznych przypadkach coś, co jest całkowicie wyłączone.

+0

Zobacz także http://stackoverflow.com/questions/1109536/an-algorithm-for-inflating-deflating-offsetting-buffering-polygons –

+2

Myślę, że to twoje najlepsze zakłady jak dotąd . Można dostosować powyższe, pionowo rozciągając wielokąt o współczynnik 2 lub 3, a następnie wyszukując największy okrąg zawarty w rozciągniętym wielokącie. To da ci największą * elipsę * zawartą w wielokącie, która da ci najlepsze miejsce do umieszczenia twojej etykiety. – jprete

+0

Dwa z trzech linków w tej odpowiedzi są martwe. – Nir

-2

Ten problem prawdopodobnie byłby analogiczny do znalezienia "środka masy" przy założeniu jednolitej gęstości.

Edycja: Metoda ta nie będzie działać, gdy wielokąt „dziury”

+0

Nie. Patrz rysunek nr 4 w dokumencie ESRI, do którego jest podłączony OP. –

+0

Wydaje się, że moim założeniem jest to, czego użyli w # 2; jedyny czas, w którym się zepsuje, jest pod tym warunkiem: "Ta metoda daje jednak nieprawidłowy wynik, jeśli wielokąt ma otwory" – Janie

+1

Nie. Wyobraźmy sobie gigantyczną U. Nie ma dziur, a środek masy nie znajduje się wewnątrz granica wielokąta. Myślę, że twoja odpowiedź jest poprawna tylko dla wypukłych wielokątów. –

1

obliczyć położenie punktu (x, y) każdej krawędzi wielokąta. Możesz to zrobić, znajdując różnicę między pozycjami na końcach każdej krawędzi. Weź średnią każdego centrum w każdym wymiarze. To będzie środek wielokąta.

+0

Myślę, że to samo dotyczy mojego rozwiązania, jeśli chodzi o wysoce nie wypukłe kształty ... – Janie

+0

Tak, bez średniej ważonej również nadmiernie podkreśla krótkie krawędzie, nawet jeśli wielokąt jest wypukły. – Reunanen

-1

Myślę, że jeśli zjednoczysz wielokąt z powrotem w jego wierzchołki, a następnie zastosujesz funkcję, by znaleźć największy wypukły kadłub, a następnie znajdziesz środek od tego wypukłego kadłuba, będzie on ściśle pasował do "pozornego" środka.

Znalezienie największej wypukłej daną wierzchołki: Look under the Simple Polygon paragraph.

Średnia wierzchołkami wypukłych kadłuba, aby znaleźć centrum.

+0

Zastanawiam się. Co by się stało, gdyby mój wielokąt był gigantycznym "U"? –

+0

Wybrałaby jedną ze stron. Jakie jest pożądane zachowanie w tej sytuacji? – CookieOfFortune

+0

Dla gigantycznego U dopuszczalne rozwiązanie to środek niższej, grubej sekcji. –

-1

Jeśli rozumiem punkt papieru, z którym się łączyłeś (dość interesujący problem, btw), ta technika "wewnętrznego buforowania" jest nieco analogiczna do modelowania danego kształtu z kawałka cukru, który jest rozpuszczany przez kwas od krawędzi w. (np. gdy odległość bufora wzrasta, pozostaje mniej oryginalnego kształtu) Ostatni pozostały bit jest idealnym miejscem do umieszczenia etykiety.

Jak tego dokonać w algorytmie niestety nie jest dla mnie bardzo jasne ....

+0

Oprogramowanie GIS, takie jak PostGIS, ma takie funkcje, jak ST_Buffer, które to robią. Nie wiem jak, tak szybko. –

-1

można umieścić etykietę w naiwnej centrum (od obwiedni, być może), a następnie przenieść go na podstawie na przecięciach lokalnych krawędzi wielokątów i BB etykiety? Poruszaj się wzdłuż normalnych przecinających się krawędzi, a jeśli wiele krawędzi przecinają się, sumuj ich normalne ruchy?

Po prostu zgaduję; w tego rodzaju problemie prawdopodobnie próbowałbym rozwiązać iteracyjnie, o ile wydajność nie jest zbyt wielkim problemem.

0

Co powiesz na znalezienie "incircle" wielokąta (największego koła, które mieści się w nim), a następnie wyśrodkowanie etykiety w centrum tego? Oto kilka linków, aby zacząć:

http://www.mathopenref.com/polygonincircle.html
https://nrich.maths.org/discus/messages/145082/144373.html?1219439473

To nie będzie działać idealnie na każdym wielokąta, najprawdopodobniej; wielobok, który wyglądałby jak C, miałby etykietę w nieco nieprzewidywalnym miejscu. Ale zaletą byłoby to, że etykieta zawsze nakładałaby się na stałą część wielokąta.

+0

Czy nie będzie to powolne, jeśli wielokąt ma kilka triangulacji? –

+0

Nie wiem; czy to będzie? –

-1

Nie mam zbyt wiele czasu, aby to teraz opracować lub przetestować, ale postaram się zrobić więcej, gdy dostanę szansę.

Użyj centroidów jako podstawowej metody. Sprawdź, czy środek ciężkości znajduje się w wielokącie; jeśli nie, narysuj linię od najbliższego punktu i na drugą stronę wielokąta. W środkowej części sekcji linii znajdującej się w wielokącie umieść etykietę.

Ponieważ punkt znajdujący się najbliżej środka ciężkości prawdopodobnie będzie związany z dość obszernym obszarem, myślę, że może to dać wyniki podobne do incircles Kyralessy. Oczywiście może to zabrzmieć w szał, jeśli masz wielokąt z dziurami. W takim przypadku incircles byłoby prawdopodobnie znacznie lepsze. Z drugiej strony domyślnie stosuje się do (typowej) centroidy dla typowych przypadków.

+0

Patologiczny test 3: symetryczny kształt przypominający sztangę z cienkim prostokątem i dwoma dużymi ośmiokątami na końcach. Centroid znajduje się wewnątrz wielokąta, ale prostokąt jest złym miejscem do oznaczenia, ponieważ może nie pasować. –

1

Nie mówię, że to jest najszybszy, ale da ci punkt wewnątrz wielokąta. Oblicz wartość Straight Skeleton. Punkt, którego szukasz, znajduje się na tym szkielecie. Możesz wybrać na przykład ten z najkrótszą normalną odległością do środka obwiedni.

2

Metoda centroidowa została już zasugerowana wiele razy. Myślę, że jest to doskonały zasób, który opisuje proces (i wiele innych przydatnych sztuczek z wielokątów) bardzo intuicyjnie:

http://paulbourke.net/geometry/polygonmesh/centroid.pdf

Ponadto, za wprowadzanie prostą etykietę UI, może być wystarczające, aby po prostu obliczyć obwiedni pole wielokąta (prostokątny określone przez najniższy i najwyższy współrzędnych x i y w każdym wierzchołku wielokąta) i uzyskanie środek w:

{ 
    x = min_x + (max_x - min_x)/2, 
    y = min_y + (max_y - min_y)/2 
} 

jest nieco szybciej niż obliczanie środka ciężkości, co mogłoby mieć znaczenie dla aplikacji wbudowanej lub osadzonej w czasie rzeczywistym.

Należy również zauważyć, że jeśli wielokąty są statyczne (nie zmieniają formy), można zoptymalizować, zapisując wynik centrowania środka BB/środka masy (względem np. Pierwszego wierzchołka wielokąta), aby struktura danych wieloboku.

+1

Dobre myślenie, ale nie zawsze działa, ponieważ środek obwiedni może znajdować się daleko poza samym polem. ! [Środek obwiedni poza poligonem (img)] (https://www.jonathanschmid.de/ext/stackoverflow-1203135.png) – Jonny

6

Jak o:

Jeśli środek wieloboku znajduje się wewnątrz wielokątu, a następnie użyj go: w innym przypadku:

1) Wydłuż linię od środka ciężkości przez wielokąt dzieląc wielokąt na dwie połówki równego obszaru

2) „Centrum wizualne” to punkt w połowie drogi między najbliższego punktu, gdzie linia dotyka obwodu i następny punkt cięcia obwodu w kierunku odchodzi od ciężkości

Oto kilka zdjęć aby go zilustrować:

enter image description here

enter image description here

+0

Uwielbiam kumpla! Naprawdę sprytnie! Teraz, jeśli chodzi o wdrożenie, ty i ktokolwiek inny rozwiązacie? –

+0

@MaraisRossouw Wysłałem odpowiedź na podobne pytanie do OP, który używa tej metody: http://stackoverflow.com/a/39408054/3628232 –

6

znalazłem bardzo dobre rozwiązanie do tego z MapBox nazywa Polylabel. Pełne źródło jest dostępne również w ich wersji Github.

Zasadniczo próbuje znaleźć wizualne centrum wielokąta, jak powiedział T Austin.

enter image description here

Niektóre dane wskazują, może to być rozwiązanie praktyczne:

Niestety, obliczanie [idealne rozwiązanie] jest bardzo złożony i powolne. Opublikowane rozwiązania tego problemu wymagają albo 01/Ograniczonej triangulacji Delaunay, albo obliczenia prostego szkieletu jako kroków wstępnego przetwarzania - oba są powolne i podatne na błędy.

Dla naszego przypadku użycia nie potrzebujemy dokładnego rozwiązania - chcemy, aby wymieniał pewną precyzję, aby uzyskać większą szybkość. Kiedy umieszczamy etykietę na mapie, ważniejsze jest, aby była obliczona w milisekundach niż , aby była matematycznie doskonała.

Krótka informacja o użyciu. Kod źródłowy działa świetnie dla JavaScript wyjęciu z pudełka jednak jeśli masz zamiar na temat korzystania z tego z „normalnym” wielokąta następnie należy owinąć ją w pustej tablicy jak funkcjonuje tu wziąć GeoJSONPolygons zamiast normalnych wielokątów tj

var myPolygon = [[x1, y1], [x2, y2], [x3, y3]]; 
var center = polylabel([myPolygon]); 
+1

Jak przegapiłem potrzebę dodatkowej tablicy ... ty jesteś ratownik życia! – complistic

+0

@complistic Hah .. szczerze ... Też tęskniłem i zajęło mi to znacznie dłużej niż powinno to znaleźć :) – Chris

Powiązane problemy