Delaunay triangulation, Delaunay empty circles

28 09 2009

Wiem, że mało ludzi to interesuje lecz chciałbym dzisiaj przedstawić dalszą część moich dygresji na temat triangulacji Delaunay. Po co właściwie zajmować się takim rodzajem triangulacji? Otóż sprawa jest dość prosta – jeżeli zamierzamy napisać własną grę 3D, w której postacie będą poruszały się po scenie, w jakiś sposób musimy wygenerować naszą scenę. Triangulacja Delaunay jest jednym ze sposobów generowania takiej przestrzennej siatki. Jak na razie, zajmijmy się jednak aspektami triangulacji w 2D.

Oczywiście jeżeli zamierzamy pisać grę najlepiej będzie nam zaimplementować ten algorytm w C, C++ lub innym języku obiektowym wysokiego poziomu. By zrozumieć ideę implementacja w C czy C++ nie będzie konieczna, dlatego też wykorzystałem do tego celu Matlaba w wersji 7.3.

Jak pisałem w jednym z poprzednich postów by dokonać triangulacji Delaunay w Matlabie wystarczy skorzystać z jednej z gotowych funkcji oferowanych przez ten program. Przykładowa implementacja mogłaby wyglądać mniej więcej tak:

d=change_kote1;
T=delaunay(d(:,1),d(:,2));
triplot(T,d(:,1),d(:,2),'red');

‘change_kote1′ jest tablicą dwuwymiarową zawierającą współrzędne punktów (x,y).

Co jednak zrobić by sprawdzić czy triangulacja jest prawidłowa? Musimy zbudować okręgi opisane na każdym z trójkątów. Jeżeli w środku każdego z nich nie będzie znajdował się ani jeden wierzchołek triangulacji będzie to oznaczać, że nasza triangulacja działa prawidłowo. Jak się do tego zabrać? Najlepiej do tego celu stworzyć oddzielną funkcję, która dla każdych trzech wierzchołków będzie zwracała promień oraz środek okręgu opisanego na trójkącie utworzonym z tych wierzchołków.

function [kola] = circle(x1,y1,x2,y2,x3,y3)
%obliczenie promienia
a=sqrt((x1-x2)^2+(y1-y2)^2);
b=sqrt((x2-x3)^2+(y2-y3)^2);
c=sqrt((x3-x1)^2+(y3-y1)^2);
promien=a*b*c/sqrt((a+b+c)*(-a+b+c)*(a-b+c)*(a+b-c));
%obliczenie srodka okregu opisanego na trojkacie
A_x=x1;
A_y=y1;
B_x=x2;
B_y=y2;
C_x=x3;
C_y=y3;
D=2*(A_y*C_x+B_y*A_x-B_y*C_x-A_y*B_x-C_y*A_x+C_y*B_x);
sx=(B_y*A_x^2-C_y*A_x^2-B_y^2*A_y+C_y^2*A_y+B_x^2*C_y+A_y^2*B_y+C_x^2*A_y-C_y^2*B_y-C_x^2*B_y-B_x^2*A_y+B_y^2*C_y-A_y^2*C_y)/D;
sy=(A_x^2*C_x+A_y^2*C_x+B_x^2*A_x-B_x^2*C_x+B_y^2*A_x-B_y^2*C_x-A_x^2*B_x-A_y^2*B_x-C_x^2*A_x+C_x^2*B_x-C_y^2*A_x+C_y^2*B_x)/D;
%zwraca promien oraz wspolrzedne x,y srodka okregu opisanego na trojkacie
kola=[promien, sx, sy];

Z ciekawszych rzeczy, na które warto zwrócić uwagę jest wzór na wyrażenie D, sx oraz sy. (sx, sy) – to współrzędne środka okręgu opisanego na trójkącie (w wolnej chwili warto by poszukać lepszego wzoru na ten punkt jeżeli do dyspozycji mamy jedynie wierzchołki trójkąta :P mi lepszego znaleźć się nie udało…).

Ostatnią rzeczą, która została nam do zaimplementowania jest wyświetlanie wszystkich okręgów opisanych:

hold on;
for i=1:1:(max(size(T))-2)
M=circle(d(T(i,1),1),d(T(i,1),2),d(T(i,2),1),d(T(i,2),2),d(T(i,3),1),d(T(i,3),2));
% okrąg o środku (a,b) i promieniu r we wsp. biegunowych
r=M(1); a=M(2); b=M(3); t = linspace(0,2*pi,200); x = a+r*cos(t); y = b+r*sin(t);
plot(x,y,'-','LineWidth',0.1);
axis auto; %axis equal
end

Teraz możemy cieszyć się efektami naszej pracy:

delaunay empty circle

delaunay empty circle

Jeżeli kogoś zainteresował temat triangulacji Delaunay więcej interesujących materiałów można znaleźć na stronach:





rysowanie w niezależnych oknach

26 09 2009

Zmarnowałem dzisiaj sporo czasu by to znaleźć… Aby w Matlabie móc rysować w niezależnych oknach należy skorzystać z funkcji ‘figure’. Nie było dla mnie problemem rysowanie wielu wykresów w jednym oknie lecz właśnie narysowanie wykresów w dwóch niezależnych oknach. Trudno jest znaleźć coś co nie wiadomo właściwie jak się nazywa… Jeżeli ktoś miałby z tym problem to po wpisaniu w pomocy hasła ‘ figure’ znajdzie już wszystkie niezbędne informacje odnośnie szczegółów.





triangulacja Delaunay

25 09 2009

Dla zbioru punktów (x, y) zapisanych w tablicy ‘dane’ przeprowadzenie triangulacji Delaunay odbywa się następująco:

%triangulacja Delaunay
T=delaunayn(dane)
triplot(T,dane(:,1),dane(:,2),'red')

Poniżej zamieszczam efekt triangulacji dla przykładowego zbioru (ponad 1200) punktów:

triangulacja

triangulacja