GTAMulti.com - Türkiye'nin Türkçe GTA Sitesi

Ters Trigonometrik Fonksiyonlar

Başlatan squarepants, 14 Eylül 2020, 15:01:13

« önceki - sonraki »

0 Üye ve 2 Ziyaretçi konuyu incelemekte.

squarepants

BAŞLANGIÇ


Herkese iyi forumlar. Trigonometrik fonksiyonlar konusunu ile birlikte ters trigonometrik fonksiyonlara da değinmek istedim. Umarım herkes için faydalı olur.

Ters trigonometrik fonksiyonlar isminden de anlaşılacağı üzere bir trigonometrik fonksiyonun tersinin alınmış halidir. Basit bir örnek ile açıklayacak olursak ;

Sin(30) = 1 / 2 => Arcsin (1 / 2) = 30 derece olacaktır.

Yani kısacası Normalde Sin(x) = y fonksiyonu herhangi bir dik üçgen üzerinde x açısına bağlı olarak bize karşı kenarın uzunluğunu verirken Arcsin(y) = x fonksiyonu ise karşı kenarın uzunluğuna bağlı olarak bize x açısını hesaplar.

Örnek bir birim çember grafiği ;




PAWN UYGULAMASI


Şimdi ise Pawn derleyicisini kullanarak birkaç örnek vermeye çalışalım. Bu arada kullanacağımız ters trigonometrik fonksiyonlar a_samp adlı kütüphane içerisinde tanımlıdır. Öncelikle kafası karışan arkadaşlar için trigonometrik bir cetvel paylaşmak istiyorum :



Şimdi ise 45 derecelik bir açı örneği kullanacağız :

- Arccos Fonksiyonu :
main()
{
    printf("aCos: %f", acos(floatsqroot(2.0) / 2.0)); // Örnek1 Çıktı: 44.999996
    printf("aCos: %d",floatround(acos(floatsqroot(2.0) / 2.0))); // Örnek2 Çıktı: 45
   
}
- Arcsin Fonksiyonu :
main()
{
    printf("aSin: %f", asin(floatsqroot(2.0) / 2.0)); // Örnek1 Çıktı: 44.999996
    printf("aSin: %d",floatround(asin(floatsqroot(2.0) / 2.0))); // Örnek2 Çıktı: 45
   
}
- Arctan Fonksiyonu :
main()
{
    printf("aTan: %f", atan(1.0); // Örnek1 Çıktı: 44.999996
    printf("aTan: %d",floatround(atan(1.0)); // Örnek2 Çıktı: 45
   
}

Örneklerde de görüldüğü gibi fonksiyonların 45 dereceye ait ters trigonometrik fonksiyonlarını aldık , yani örnek bir sin(30) fonksiyonu için 30 derecelik bir açıya göre (karşı / hipotenüs) formülü kullanılır. Yani örneğin Pawn üzerinden gidersek:

floatsin(30.0, degrees) = (karşı / hipotenüs) ise asin((karşı / hipotenüs)) = 30 derece olacaktır. Örnek1'de de görüldüğü gibi ters trigonometrik fonksiyonlar açıya en yakın değeri bizim için hesapladı. Tabii Örnek2'de de gördüğünüz gibi siz bunu floatround() fonksiyonu ile en yakın tam sayıya yuvarlayabilirsiniz. Bu arada floatsqroot() fonksiyonu herhangi bir sayının karekökünü almanızı sağlıyor. Durum incelendiğinde ve Yukarıdaki periyodik cetvel incelendiğinde aCos fonksiyonu için ((Karekök 2) / 2) işlemi tabloda 45 dereceye aittir.


ÖRNEK UYGULAMA


Örneğin Pawn derleyicisini kullanarak örnek bir uygulama daha yapalım. Yapmak istediğimiz şey ise herhangi bir Aktörün spawnlandığı noktada facing angle (yüz açısını) tam da bizim bulunduğumuz noktanın açısına göre ayarlamak istiyoruz. Sanırım bunu bir görsel üzerinde anlatmak daha kolay olacaktır :



Karşı ve Komşu kenarın uzunluklarını hesaplamak için Toplam X ve Y farkını hesaplamamız gerekiyor. Bu durumda elimizde iki kenarın uzunluğu bulunmuş oluyor. Ama facing angle için hala hesaplamamız gereken bir açımız var bu açı ise atan() veya atan2() fonksiyonları ile hesaplanabilir. Neden asin() veya acos() değil diye soracak olursanız bizim bulduğumuz kenarlar karşı ve komşu kenarlarıydı, Elbette pisagor teoremi ile hipotenüsü de hesaplayabiliriz ancak bu durumu bizim için biraz uzatmış olacaktır.

stock Float:Yuz_Acisi(oyID = INVALID_PLAYER_ID, akID = INVALID_ACTOR_ID)
{
    new
Float:ucgen[2],
Float:opos[6],
Float:aci
;

Evet, Float veri tipinde , iki parametreli bir fonksiyon oluşturuyoruz. ucgen adlı 2 elemanlı dizi karşı ve kenar uzunluklarını hesaplayabilmemiz için opos adlı adlı 6 elemanlı dizi ise bizim ve aktörümüzün bulunduğu konumu çekebilmek için aci adlı fonksiyon da ters trigonometrik fonksiyonlar yardımı ile hesaplattığımız sonucu çekmemiz için tanımlandı.
stock Float:Yuz_Acisi(oyID = INVALID_PLAYER_ID, akID = INVALID_ACTOR_ID)
{
    new
Float:ucgen[2],
Float:opos[6],
Float:aci
;
GetPlayerPos(oyID, opos[0], opos[1], opos[2]), GetActorPos(akID, opos[3], opos[4], opos[5]);
ucgen[0] = (opos[3] - opos[0]), ucgen[1] = (opos[4] - opos[1]);

Şimdi ise gördüğünüz gibi kendimiz ve aktörün bulunduğu X ve Y koordinatlarını çektik daa sonra ise karşı ve komşu kenarlarını hesapladık, bu durum bize artık açımızı hesaplayabileceğimiz anlamına geliyor.
stock Float:Yuz_Acisi(oyID = INVALID_PLAYER_ID, akID = INVALID_ACTOR_ID)
{
    new
Float:ucgen[2],
Float:opos[6],
Float:aci
;
GetPlayerPos(oyID, opos[0], opos[1], opos[2]), GetActorPos(akID, opos[3], opos[4], opos[5]);
ucgen[0] = (opos[3] - opos[0]), ucgen[1] = (opos[4] - opos[1]);
        aci = (-atan2(ucgen[0], ucgen[1]));
        if(!(0.0 <= aci <= 90.0)) aci = (-atan2(ucgen[0], ucgen[1]) + 180.0);
        return aci;
}

açımızı atan2 fonksiyonu ile hesaplıyoruz. Tabii dikkat edilmesi gereken bir nokta var. Açı hesaplandığında aktör bize doğru bakmaz sırtını tam bize dönerek açıya uyum gösterir. Bizim istediğimiz ise bize bakmasıydı. Bu durumu -1 ile çarparak tam istediğimiz konuma getiriyoruz. Dikkat edilmesi gereken diğer önemli bir durum ise açı -1 ile çarpıldığında her bölgede aynı durmaz. Yani X ve Y değerleri her zaman pozitif olmayabilir. Bölünebilme kurallarına göre - / + veya + / - herzaman negatif sonuçları döndürür ve negatif bir sayıyı negatif bir sayıyla çarparsanız sonuç pozitif olacaktır bu durumda aktör bize doğru bakmaz. Bu durumu düzeltmek için kodda yaptığımız ufak bir değişiklik var. eğer açı 0 ile 90 derece arasında değil ise açıya bir tam yarım tur attırıyoruz ki açı hesaplanan konumuna dönebilsin. Çünkü birim çemberde X ve Y noktalarının pozitif olduğu tek konum 0 ile 90 derece arasındaki konumdur. Diğer konumlar için bu özellik geçerli değildir.

Örnek Komut :

CMD:aktoraci(playerid, params[])
{
new aktorid;
if(aktorid != INVALID_ACTOR_ID) DestroyActor(aktorid);
new Float:pos[3];
GetPlayerPos(playerid,pos[0], pos[1], pos[2]);
aktorid = CreateActor(0, pos[0]-5, pos[1]-5, pos[2], Yuz_Acisi(playerid, aktorid));
return 1;
}
Umarım açılar konusunda size bilgi verebilmişimdir. İyi forumlar.
Son düzenlenme: 14 Eylül 2020, 16:04:57 ThePosition

Heleina

Konu gerçekten doyurucu. Epey emek harcanmış, teşekkürler.

Tanrı düşmanlarıma acısın ve merhamet göstersin; çünkü ben göstermeyeceğim.

squarepants

Alıntı yapılan: Helen - 15 Eylül 2020, 00:02:55
Konu gerçekten doyurucu. Epey emek harcanmış, teşekkürler.
Yorum için teşekkürler, umarım konu anlamana yardımcı olmuştur.


Oner

Çok detaylı bir konu gibi gözüküyor, matematikten anlamadığımdan kafa basmaz. Yine de isteyenlere yararlı :D

Discord: Ascendency#7970

squarepants

Alıntı yapılan: Oner - 15 Eylül 2020, 14:45:05
Çok detaylı bir konu gibi gözüküyor, matematikten anlamadığımdan kafa basmaz. Yine de isteyenlere yararlı :D
Yorum için teşekkürler. Anlayamamanın temel sebebi konunun üstüne fazla düşmemen, biraz düşersen konu çok daha kolay gelmeye başlar. Bu arada bu konudan da faydalanabilirsin :
https://www.gtamulti.com/forum/anlatimlar/cember-olusumu-trigonometri/