Çok fazla tartışma yaratan ve “başka işin gücün yok mu!” gibi söylemlere maruz kalmama neden olan yazı serisi ile yeniden karşınızdayım. Bugün incelediğimiz önermeyi olabildiğince detaylandırarak ne kadar işsiz olduğum bilgisini daha fazla kişiye ulaştırmayı hedefliyorum. Önceki yazıda belirttiğim gibi bu yazıda yağmurun yağacağı uzayda bir nesne oluşturarak bu nesnenin farklı hızlarda hareket etmesini sağlayacağız. Daha sonra ise bu nesnenin farklı senaryolarda ne kadar ıslandığını inceleyerek herkesin uykularını kaçıran sorulara cevap arayacağız…
Yazının asıl konusuna geçmeden önce önceki yazıdaki kodlarda yaptığım ufak bir değişikliğe değinmek istiyorum. Önceki yazıda birim zamanda üretilen yağmur damlası sayısını hesapladıktan sonra tam sayıya yuvarlama işlemi yapıyordum. Ancak bu durum yağmur şiddetinin olması gerekenden bir miktar yüksek vaya düşük olmasına neden olabilir. Bu nedenle yağmuru oluşturan fonksiyonu aşağıdaki gibi düzenledim.
% Üretilecek damla sayısının belirlenmesi
ngen = Drop.ngen + Drop.dp;
genDrop = floor(ngen);
Drop.dp = ngen - genDrop;
% Damlaların üretimi
Drop.positions = [Drop.positions;
Space.size(1)*rand(genDrop, 1), ...
Space.size(2)*rand(genDrop, 1), ...
Space.size(3)*ones(genDrop, 1)];
Burada ngen üretilecek damla sayısını, Drop.dp önceki damla üretiminden arta kalan kısmı ifade etmektedir. Yani t anında 4.5 adet damla üretilmesi gerektiği hesaplandığında, t anında 4 damla üretiliyor ve 0.5 damla bir sonraki zaman dilimine aktarılıyor. Böylelikle ortalamada ulaşılması gereken yağmur şiddetine tam olarak erişiliyor. Kodların düzenlenmiş halini github reposunda paylaştım. Dilerseniz oradan tam halini inceleyebilirsiniz.
Bu yazıda ise daha önce belirttiğim gibi yağmurun yağacağı uzay içerisinde insanı temsil eden bir nesne tanımlayacağız. Bu nesnenin boyutlarını ve hızını kontrol edebilmemiz gerekmektedir. Buna göre nesnenin bilgilerini aşağıdaki gibi tanımlayabiliriz.
% Nesnenin bilgileri
Object.size = [0.28, 1.75]; % Nesnenin boyutları [m]
Object.velocity = 5; % Nesnenin hareket hızı [m/sn]
Object.movement = Object.velocity*Time.dt; % Nesnenin hareket vektörü [m]
Object.position = [1, Object.size(2)/2]; % Nesnenin başlangıç konumu [m]
% Nesnenin sınırları
Object.edges = [Object.position(1)-Object.size(1)/2,...
Object.position(1)+Object.size(1)/2;
Object.position(2)-Object.size(2)/2,...
Object.position(2)+Object.size(2)/2];
Burada görüldüğü gibi nesnenin boyutlarını, hızını ve uzay içerisindeki başlangıç konumunu istediğimiz gibi belirleyebiliyoruz. Nesnenin sınırlarını belirten Object.edges değişkeni ise hem görselleştirme, hem de yağmur damlalarının nesneye çarpıp çarpmadığının kontrolü için kullanacağız. Tabii ki değişkenlerin boyutlarından bu kodların iki boyutlu uzay için oluşturulduğunu görebilirsiniz. Neden doğrudan üç boyutta yazmıyorsun diye soracak olursanız. Aslında yazabilirim ancak simülasyon çalışmalarında önce sistemi en basit haliyle oluşturup daha sonra detayları eklemenin hata olasılığını azaltan bir strateji olduğunu düşünüyorum. Şimdi nesneyi hareket ettirecek fonksiyonu yazarak devam edebiliriz.
function [Object] = f_Movement2D(Object, Space, plottingFlag)
% Bu fonksiyon girdi olarak verilen nesnenin konumunu değiştiri ve
% görselleştirir.
% Girdiler -------
% Object : Nesnenin bilgilerini içeren structure
% Object.movement : Nesnenin x eksenindeki hareket vektörü
% Object.position : Nesnenin konumu
% Object.edges : Nesnenin sınırları
% Space : Nesnenin hareket ettiği uzayın bilgileri
% Space.size : Uzayın boyutları
% prottingFlag : Görselleştirme bayrağı
% Çıktılar -------
% Object : Nesnenin güncellenmiş bilgileri
% Object.position : Nesnenin güncellenmiş konumu
% Object.edges : Nesnenin güncellenmiş sınırları
% ----------------
% Nesnenin hareketi
Object.position(1) = Object.position(1) + Object.movement;
% Nesnenin sınırları
Object.edges = [Object.position(1)-Object.size(1)/2,...
Object.position(1)+Object.size(1)/2;
Object.position(2)-Object.size(2)/2,...
Object.position(2)+Object.size(2)/2];
% Görselleştirme için oluşturulan değişkenler
Draw.x = [Object.edges(1,1), Object.edges(1,2), Object.edges(1,2), ...
Object.edges(1,1), Object.edges(1,1)];
Draw.y = [Object.edges(2,1), Object.edges(2,1), Object.edges(2,2), ...
Object.edges(2,2), Object.edges(2,1)];
% Nesnenin görselleştirilmesi
if plottingFlag == true
plot(Draw.x, Draw.y, 'Black', "LineWidth", 1);
xlim([0, Space.size(1)]); ylim([0, Space.size(2)]);
xlabel("X [m]"); ylabel("Y [m]");
end
end
Burada görüldüğü gibi oluşturduğumuz nesneyi sadece x ekseni doğrultusunda hareket ettiriyoruz. Önceki bölümde yağmurun yağış açısını değiştirebilecek şekilde bir program oluşturduğumuz için nesneyi tek bir doğrultuda hareket ettirmek bizim için yeterli olacaktır. Şimdi zaman döngüsünü yazarak program çıktısını inceleyebiliriz.
% Zaman döngüsü
for i = 1:length(Time.axis)
% Nesnenin hareketi
Object = f_Movement2D(Object, Space, plottingFlag);
% Görselleştirme
if plottingFlag
exportgraphics(f1, gifFile, Append=true);
drawnow;
pause(Time.dt);
end
end
Görüldüğü gibi zaman döngüsünde sadece nesnenin hareketini sağlayan fonksiyon çağırılıyor. Kodların tamamını yine github reposundaki “mainObjectMove2D.m” dosyasında bulabilirsiniz. Buna göre programın çıktısı Şekil 1’de verildiği gibi oluşmaktadır.

Evet nesnenin şekli her ne kadar insana benzemese de bu küçük detaylara takılmamıza gerek yok bence. 🙂 Diğer yandan yazdığımız kodların nesneyi istediğimiz şekilde hareket ettirdiğini görüyoruz. Şimdi üç boyuta geçerek nesnemizin Şekil 2’de görüldüğü gibi hareket etmesini sağlayabiliriz.

Harika! Artık üç boyutlu uzayda yağmur yağmasını sağlayan ve bir nesneyi hareket ettiren programlara sahibiz. Bu aşamadan sonra tek yapmamız gereken bu iki kodu uygun bir şekilde birleştirmek. İki programı da birbirine benzer şekilde yazdığımızdan dolayı zaman döngüsünü aşağıdaki gibi düzenleyerek bu işlemi kolaylıkla gerçekleştirebiliriz.
% Zaman döngüsü
for i = 1:length(Time.axis)
% Yağmur damlalarının üretimi ve hareketi
Drop = f_Rainfall3D(Drop, Space, plottingFlag); hold on;
% Nesnenin hareketi
Object = f_Movement3D(Object, Space, plottingFlag); hold off;
% Cisme temas eden damlaların sayılması
[Drop, Counter] = f_DropCounter3D(Drop, Object);
DropCounter = DropCounter + Counter;
% Görselleştirme
if plottingFlag
exportgraphics(f1, gifFile, Append=true);
drawnow;
pause(Time.dt);
end
end
Burada görüldüğü gibi zaman döngüsünde öncelikle yağmur damlaları güncelleniyor, daha sonra ise oluşturduğumuz nesne hareket ettiriliyor. Devamında ise nesneye temas eden yağmur damlalarının sayılması ve bu damlaların yok edilmesi için aşağıda verilen f_DropCounter3D fonksiyonu kullanılmaktadır.
function [Drop, Counter] = f_DropCounter3D(Drop, Object)
% Bu fonksiyon cisme temas eden damlaları sayar ve bu damlaları siler
% Girdiler ------
% Drop : Damlaların bilgilerini içeren structure
% Drop.positions : Damlaların konumları
% Object : Nesnenin bilgilerini içeren structure
% Object.edges : Nesnenin sınırları
% Çıktılar ------
% Drop : Damlaların güncellenmiş bilgileri
% Drop.positions : Güncellenmiş damla konumları
% Counter : Nesneye temas eden damla sayısı
% ---------------
% Nesneye temas eden damlaların indislerinin belirlenmesi
Indexes = Drop.positions(:,1)>=Object.edges(1,1) & ...
Drop.positions(:,1)<Object.edges(1,2) & ...
Drop.positions(:,2)>=Object.edges(2,1) & ...
Drop.positions(:,2)<Object.edges(2,2) & ...
Drop.positions(:,3)>=Object.edges(3,1) & ...
Drop.positions(:,3)<Object.edges(3,2);
% Temas eden damlaların sayısı
Counter = sum(Indexes);
% Temas eden damlaların silinmesi
Drop.positions(Indexes, :) = [];
end
Sonuç olarak bu programın çıktısında Şekil 2’de oluşturduğumuz nesnenin önceki yazıda oluşturduğumuz yağmurun altında hareket ettiğini görmeyi bekliyoruz. Şekil 3’teki program çıktısının bu beklentilerimize cevap verdiğini görebilirsiniz.

Şekile dikkatli bakacak olursanı bazı damlaların nesneye temas ettikten sonra kaybolduğunu görebilirsiniz. Mükemmel! Sizi bilmem ama benim açımdan en fazla keyif aldığım yazı serisinin bu olduğunu söyleyebilirim. 🙂 Ancak bu yazı yeterince uzun olduğu için nesnenin farklı senaryolarda ne kadar ıslandığını test ettiğimiz bölümleri sonraki yazıya bırakıyorum. O zaman sonraki yazıda görüşene kadar kendinize iyi bakın efendim…