December 14, 2021

Tekrar Merhaba,

Alt/üst sınıflar arası iletişimde küçük bir sorun vardı. Bunu Ali hocanın önerisiyle abstract keyword'ü ile çözdük. Şimdi aşağıdaki gibi bir çalışır kodumuz var. Lütfen, istediğiniz kadar enter tuşlayın veya boşluk+enter ile farkı görün:

import std.math, std.random, std.stdio;

enum açı = 6;
enum Boyut { X, Y, Z }

struct Point { int x, y; }  // Geçici...
struct Nokta { double x, y, z; }

struct Çizgi {
  Point a;
  Point b;

  this(Nokta a, Nokta b) {
    this.a.x = cast(int)a.x;
    this.a.y = cast(int)a.y;
    this.b.x = cast(int)b.x;
    this.b.y = cast(int)b.y;
  }
}

class Çizici {
  Şekil[] şekiller;

  this() { // 1200x640px bir ekran için farklı boyda 9 şekil dizer:
    for(double x = -500, b = 25; x <= 500; x += 125, b += 5)
    {
      şekiller ~= new Dörtyüzlü(Nokta(x, -200, -100), b);
    }

    foreach(şekil; şekiller) {  // Her eksende, ön tanımlı döndürür
      şekil.döndür(açı, Boyut.X);
      şekil.döndür(açı, Boyut.Y);
      şekil.döndür(açı, Boyut.Z);
    }
  }

  void çiz() { // Her bir şekli sadece Y-ekseninde döndür
    foreach(n, şekil; şekiller) {
      şekil.döndür(açı, Boyut.Y);
      şekil.dönüştür();
      foreach(i, nokta; şekil.kenar) {
        writef("(%d, %d):", n, i);
        writef("[%d, %d - ", nokta.a.x, nokta.a.y);
        writef("%d, %d]\n ", nokta.b.x, nokta.b.y);
      }
    }
  }
}

abstract class Şekil {
  Çizgi[] kenar();
  void dönüştür();

  Nokta[9] noktalar;

  this(Nokta p, double b) {
    auto boyut = Nokta(b, b, b);
    noktalar[0] = Nokta(p.x - boyut.x, p.y - boyut.y, p.z - boyut.z); // A1 Köşesi (-)(-)(-)
    noktalar[3] = Nokta(p.x - boyut.x, p.y + boyut.y, p.z + boyut.z); // B0 Köşesi (-)(+)(+)
    noktalar[5] = Nokta(p.x + boyut.x, p.y - boyut.y, p.z + boyut.z); // C1 Köşesi (+)(-)(+)
    noktalar[6] = Nokta(p.x + boyut.x, p.y + boyut.y, p.z - boyut.z); // D0 Köşesi (+)(+)(-)
    noktalar[8] = Nokta(p.x, p.y, p.z); // Şeklin Merkezi
  }

  void ekseniDöndürüpUyarla(Boyut eksen) {
    döndür(açı, eksen);
    dönüştür();
  }

  void döndür(int açısı, Boyut boyutu) {
    auto angleTheta = cast(double)açısı;
    Nokta cosTheta, sinTheta;

    foreach(ref nokta; noktalar) {
      if(boyutu == Boyut.X || boyutu == Boyut.Z) {
        cosTheta.x = nokta.x * cos(angleTheta);
        sinTheta.x = nokta.x * sin(angleTheta);
      }
      if(boyutu == Boyut.Y || boyutu == Boyut.Z) {
        cosTheta.y = nokta.y * cos(angleTheta);
        sinTheta.y = nokta.y * sin(angleTheta);
      }
      if(boyutu == Boyut.X || boyutu == Boyut.Y) {
        cosTheta.z = nokta.z * cos(angleTheta);
        sinTheta.z = nokta.z * sin(angleTheta);
      }
      if(boyutu == Boyut.X) {
          nokta.x = cosTheta.x + sinTheta.z;
          nokta.z = cosTheta.z - sinTheta.x;
      }
      if(boyutu == Boyut.Y) {
          nokta.y = cosTheta.y - sinTheta.z;
          nokta.z = cosTheta.z + sinTheta.y;
      }
      if(boyutu == Boyut.Z) {
          nokta.x = cosTheta.x - sinTheta.y;
          nokta.y = cosTheta.y + sinTheta.x;
      }
    }
  }
}

class Dörtyüzlü : Şekil {
  Çizgi[6] kenarlar;

  this(Nokta konum, double boyut) {
    super(konum, boyut);
  }

  override void dönüştür() {
    // Nokta, Çizgi() nesnesi üzerinden Dörtyüzlü olur.
    kenarlar[0] = Çizgi(noktalar[5], noktalar[6]);
    kenarlar[1] = Çizgi(noktalar[5], noktalar[0]);
    kenarlar[2] = Çizgi(noktalar[5], noktalar[3]);
    kenarlar[3] = Çizgi(noktalar[3], noktalar[6]);
    kenarlar[4] = Çizgi(noktalar[6], noktalar[0]);
    kenarlar[5] = Çizgi(noktalar[0], noktalar[3]);
  }
  override Çizgi[] kenar() {
    return kenarlar;
  }
}

class Piramit : Şekil {
  Çizgi[8] kenarlar;

  this(Nokta konum, double boyut) {
    super(konum, boyut);
  }

  override void dönüştür() {
    // Nokta, Çizgi() nesnesi üzerinden Piramit olur.
  }

  override Çizgi[] kenar() {
    return kenarlar;
  }
}

class Küp : Şekil {
  Çizgi[12] kenarlar;

  this(Nokta konum, double boyut) {
    super(konum, boyut);
  }

  override void dönüştür() {
    // Nokta, Çizgi() nesnesi üzerinden Küp olur.
  }

  override Çizgi[] kenar() {
    return kenarlar;
  }
}

void main() {
  auto ekran = new Çizici();
  string klavye;
  while ((klavye = readln()) !is null) {
    ekran.çiz();
    if(klavye == " \n") { // boşluk tuşuna da basıldıysa
      auto rasgele = uniform(0, ekran.şekiller.length);     // birini seç
      ekran.şekiller[rasgele].ekseniDöndürüpUyarla(Boyut.X);// X-eksenini
      writefln("%d, X ekseninde döndü...", rasgele);        // döndür...
    }
  }
}

Eğer hesaplanan noktaları ekrana yansıtabilseydiniz, karşınıza 4 yüzü bulunan ve eşkenar üçgenlerden oluşan bir şekil çıkacaktı. Bir sonraki sefer bunu grafiğe dökerek kapsamlı bir şekilde uygulayacağız. Bu sırada, kod içinde konulan Point() sınıfı kaybolacak çünkü kullanılaran grafik kütüphanesinde bulunmakta.

Başarılar...

December 16, 2021

On Tuesday, 14 December 2021 at 20:50:11 UTC, Salih Dincer wrote:

>
void main() {
  auto ekran = new Çizici();
  string klavye;
  while ((klavye = readln()) !is null) {
    ekran.çiz();
    if(klavye == " \n") { // boşluk tuşuna da basıldıysa
      auto rasgele = uniform(0, ekran.şekiller.length);     // birini seç
      ekran.şekiller[rasgele].ekseniDöndürüpUyarla(Boyut.X);// X-eksenini
      writefln("%d, X ekseninde döndü...", rasgele);        // döndür...
    }
  }
}

Ulaşmaya çalıştığımız kodun bütününe, şöyle uzaktan geniş açıyla bakmadan evvel her şeyin tetiklendiği main() ile bir geçiş yapalım mı?

Yukardaki kod: "Text-version" ve yaptığı klavyenin space + enter ve enter tuşlarına göre ayrı bir hesap yapmak. Burada da sonsuz bir döngü var; çok belli olmasa da aşağıda da:

import arsd.simpledisplay, std.random;

  enum windowWidth  = 1200;
  enum windowHeight = 640;
  enum katSayı = 30;
  enum açı = 6;
  enum fps = katSayı * açı;

enum Boyut { X, Y, Z }
alias Painter = Çizici;

void main() {
  auto scr = new Painter(windowWidth, windowHeight, "3B Şekiller", Color.white);
  with(scr) window.eventLoop(fps, &çiz,
    delegate (KeyEvent event)
    {
      if(event.key == Key.Space)
      {
        auto rasgele = uniform(0, shapes.length);
        shapes[rasgele].ekseniDöndürüpUyarla(Boyut.X);
      }
      else if(event.key == Key.Escape)
      {
        window.close();
      }
    }
  );
}

"Graphic-version" kodunda ise sonsuz döngüyü yapan eventLoop() ama bir farkla: ilk parametre (fps) sıfır olsaydı window.close() yapana kadar devam edecekti. Bu kodda ise saniyenin belli bir oranında (genelde ms. ile hesaplanır) yardımcı sınıfa, yani scr.çiz() işlevine gitmesi ve hemen arkasından KeyEvent'lara bakarak tuşlarına basılıp basılmadığını tespit etmesi.

Bu temel kurulum pek fazla değişmeyecek ama bu kodları sonraki bölümdeki örneğe kendiniz uyarlayabilirsiniz...(her tuşa basıldığında çizgi çizsin, saniyede 10 çizgi değil vb.)

Kalın sağlıcakla...