Rysowanie polilinii w kształcie okręgu
Google Maps API pozwala na rysowanie polilinii - z łamanych można stworzyć proste figury takie jak kwadrat czy trójkąt. W tym tutorialu napiszemy funkcję, która będzie rysować okrąg / koło.
Rysowanie okręgu o środku w zadanym punkcie i o zadanym promieniu
Nie istnieje prosta metoda rysowania okręgów w Google Maps API. Obejściem problemu jest narysowanie foremnego wieloboku o takiej liczbie boków, by sprawiał wrażenie bycia kołem.
Z obserwacji wynika, że wielokąty foremne o liczbie boków >20 są już wystarczająco podobne do okręgu. Wykonamy więc n-iteracji (n>20) pętli, w każdej z iteracji wyznaczając n-ty wierzchołek takiego wielokąta. Połączone wierzchołki dadzą okrąg. Zasadnicza pętla wygląda następująco:
var punkty=[];
for(i=0;i<dokladnosc;i++)
{
var kat=360*i/dokladnosc;
kat = Math.PI*kat/180;
var srodekXY = mapa.fromLatLngToDivPixel(srodek);
var nowyPunktXY = new GPoint(srodekXY.x+parseFloat(promien)*Math.cos(kat),srodekXY.y+parseFloat(promien)*Math.sin(kat));
punkty.push(mapa.fromDivPixelToLatLng(nowyPunktXY));
}
gdzie dokladnosc określa liczbę boków wielokąta, srodek to geograficzne koordynaty środka okręgu, promien to promień koła w pixelach.
Aby wyznaczyć współrzędne wierzchołka, posługujemy się następującą metodą:
Z tego schematu jasno wynika, jak wyznaczyć wartości b i a:
- a = c*cosβ
- b = c*sinβ
Można więc łatwo wyznaczyć współrzędne punktu, znając kąt β. Kąt ten stanowi i/dokladnosc*360 stopni, gdzie i to numer iteracji, a dokladnosc to ilość iteracji. Taki kąt należy wyrazić w radianach, mnożąc go razy PI i dzieląc przez 180 stopni. Ostatecznie:
var kat=360*i/dokladnosc; kat = Math.PI*kat/180;
Po wykonaniu całej pętli należy jeszcze dodać ponownie pierwszy element tablicy punkty po to, by okrąg był zamknięty. Otrzymamy tablicę punktów, którą wystarczy przekazać jako pierwszy argument przy tworzeniu polilinii / polilinii z wypełnieniem.
W przykładzie 10.1 stworzyłem funkcję okrag(), która wykorzystując opisaną tu metodą tworzy okrąg, o zadanych parametrach. Jeśli podano kolor wypełnienia, to narysowane zostanie również wypełnienie (GPolygon). przykład 1pokaż kod przykładu
Rysowanie okręgu opisanego na trzech punktach
Sprawa komplikuje się, jeśli chcesz rysować okręgi opisane na trzech zadanych punktach. Krótkie matematyczne wyjaśnienie problemu:
- łączymy punkty odcinkami, wybieramy dowolne dwa odcinki
- dla każdego odcinka wyznaczamy równanie prostej prostopadłej to tej, w której zawiera się odcinek, przechodzącej przez środek odcinka (symetralna odcinka)
- wyznaczamy punkt przecięcia się dwóch symetralnych
- tak wyznaczony punkt będzie środkiem koła
Pomocna w wyznaczeniu symetralnej jest wiedza, że współczynniki kierunkowe dwóch prostych prostopadłych pomnożone przez siebie dają -1. Nie będę tu pokazywał krok po kroku jak wyznaczyć potrzebne wartości, odpowiednie parametry wstawione są już w przykładzie 10.2, wygląda to następująco:
a = mapa.fromLatLngToDivPixel(a); b = mapa.fromLatLngToDivPixel(b); c = mapa.fromLatLngToDivPixel(c); var ax = a.x; var ay = a.y; var bx = b.x; var by = b.y; var cx = c.x; var cy = c.y; var p1 = (bx-ax)/(ay-by); var p2 = (cx-ax)/(ay-cy); var nx = (p1*(ax+bx)/2 - p2*(ax+cx)/2 - (ay+by)/2 + (ay+cy)/2)/(p1-p2); var ny = p2 * (nx - (ax+cx)/2)+(ay+cy)/2; var dl = Math.pow(Math.pow((nx-cx),2) + Math.pow((ny-cy),2),0.5);
Po wyznaczeniu środka (współrzędne nx i ny) wyznaczam jeszcze długość promienia, licząc zwyczajną odległość od środka do wybranego punktu. Mając środek i promień robimy dokładnie to samo, co w poprzednim przykładzie. Pełny kod, służący do rysowania okręgu, opisanego na trzech punktach dostępny jest w przykładzie 2 przykład 2pokaż kod przykładu
Rysowanie łuku
Równie proste jest rysowanie łuku - przykład pierwszy można stosunkowo prosto przerobić tak, by wyświetlał fragment okręgu (łuk) lub fragment koła (wycinek). Figura ta będzie charakteryzowana czterema parametrami - punktem środkowym, promieniem, rozwartością łuku (w stopniach) oraz obrotem (w stopniach).
W przykładzie 1 do obliczania kąta kolejnego rysowanego punktu korzystaliśmy z formuły:
var kat=360*i/dokladnosc;
Teraz należy wprowadzić drobne poprawki. Przede wszystkim, obrót liczymy od pozycji wskazówek zegara na godzinie 12.00, podczas gdy funkcje sinus i cosinus jako początek układu przyjmują "godzinę 3.00". Odejmujemy więc od wartości kąta 90 stopni. Zamiast 360 stopniowego zakresu interesuje nad jedynie ten, jaki faktycznie posiada rysowany łuk. Niech zmienna luk_kat odpowiada za rozwartość łuku, wówczas:
var kat=-90+luk_kat*i/dokladnosc;
Oczywiście, nie można zapomnieć o pozycji początkowej. Uwzględniając ją mamy:
var kat = -90+start+luk_kat*i/dokladnosc;
Używając takiej formuły i dokonując lekkiej modyfikacji przekazywanych argumentów do funkcji rysującej, otrzymujemy przykład numer 3 (sprawdź jego źródło, by zobaczyć, jakie zmiany zaszły w funkcji, przemianowanej na luk(). przykład 3pokaż kod przykładu






