küçük elmas kare algoritması


12

Elmas kare algoritması bir fraktal arazi (yükseklik haritası) üreten algoritmadır. Burada nasıl çalıştığını gösteren güzel bir açıklama bulabilirsiniz:

http://www.gameprogrammer.com/fractal.html (Referans olarak kullanılır.)

http://www.playfuljs.com/realistic-terrain-in-130-lines/ (Büyük JS uygulaması, belki de oluşturucusunu çalmak isteyebilirsiniz. Bu algoritmanın http: // demolar için neler yapabileceğini bir göz atın . playfuljs.com/terrain/ .)

Genel fikir, tohumlar (a) olarak 4 köşeye sahip olmanız ve bu dört köşeyi ortalayarak ve rastgele bir değer ekleyerek (-0.5 ile 0.5 (b) arasında) merkez noktasının yüksekliğini hesaplamanızdır. Bunu ızgaraya uygularsanız tekrar bir elmas ızgarası alırsınız (kareler 45 ° kareler) ve aynı şeyi tekrarlarsınız (c, d), ancak rastgele aralık küçülür, örneğin -0.125 ila 0.125 vb. resim açıklamasını buraya girin

Programınız bir dizi girişi kabul etmelidir:

  • l=1,2,3,...Kenar uzunluğu olan kare ızgara boyutunu belirleyen bir tam sayı 2^l+1. At l=10yaklaşık bir milyon sayı depolamak zorunda kalacak.
  • Her köşe için dört tohum (kayan nokta)
  • 0<h<1Pürüzlülüğü ( Hbağlantıda) belirleyen ve rastgele aralığın başlangıçta ne kadar büyük olduğu anlamına gelen bir parametre
  • a,bRastgele aralık için başlangıç ​​alt ve üst sınırlarını temsil eden ve hher ayrıntılandırma adımında çarpılan parametreler . (Rastgele sayı ave arasında eşit olarak seçilir b.

Çıktı bitmiş 2d ızgarasından oluşmalıdır.

Kaba algoritma şöyle görünecektir:

Create a square grid with sidelength 2^l+1
Place seed values in the corners
Repeat:
  |  Perform square steps
  |  Refine Range: a = a*h; b=b*h;
  |  Perform diamond steps
  |  Refine Range

Dikkat etmeniz gereken bir ayrıntı var: Izgara sınırında, elmasın sadece üç köşesi olacak , bu yüzden sadece bu üç noktanın ortalamasını hesaplamanız gerekir.

Bazı örneklerin görselleştirilmesi (lütfen bize hangi parametreleri kullandığınızı söyleyin) isteğe bağlıdır ancak takdir edilir ve elbette bayt sayısına eklenmez.

Bu algoritmanın biraz farklı bir uygulaması burada bulunabilir: Paralel izdüşümlü voksel arazi jeneratörü

Javascript'te 2d'de yükseklik haritalarını gri tonlamalı görüntü olarak dağıtmak için küçük bir çizim işlevi oluşturdum. http://jsfiddle.net/flawr/oy9kxpsx/

Eğer herhangi biri süslü 3d içine ve 3d haritaları görüntülemek için bir komut dosyası yapabilirsiniz bana bildirin! =)

Yanıtlar:


8

Java, 1017 bayt

Girdi bir boşluk şöyle ayrılmış listesi ise: l s1 s2 s3 s4 h a b.

Çıktı, sayıları içeren bir 2d dizisidir.

Programı:

import java.util.*;import static java.lang.Math.*;class C{public static void main(String[]a){int b=a.length,d=0;float[]c=new float[b];for(;d<b;){c[d]=Float.parseFloat(a[d++]);}e=(int)(pow(2,c[0])+1);f=new float[e][e];f[0][0]=c[1];f[0][e-1]=c[2];f[e-1][0]=c[3];f[e-1][e-1]=c[4];g=c[5];float h=c[6],i=c[7];s(0,0,e-1,e-1,h,i);System.out.print(Arrays.deepToString(f));}static int e;static float[][]f;static float g;static void s(int q,int r,int s,int t,float h,float i){if(s-q<2|t-r<2|q<0|r<0|s>=e|t>=e)return;float o,p;int m=(q+s)/2,n=(r+t)/2;f[m][n]=(float)(a(q,r,s,r,q,t,s,t)+random()*(i-h)-h);d(m,r,m-q,o=h*g,p=i*g);d(q,n,m-q,o,p);d(m,t,m-q,o,p);d(s,n,m-q,o,p);}static void d(int x,int y,int e,float h,float i){float o,p;f[x][y]=(float)(a(x,y-e,x+e,y,x,y+e,x-e,y)+random()*(i-h)-h);s(x-e,y-e,x,y,o=h*g,p=i*g);s(x,y-e,x+e,y,o,p);s(x-e,y,x,y+e,o,p);s(x,y,x+e,y+e,o,p);}static float a(int...j){float k=0,l=0;for(int d=0;d<j.length;d+=2){if(j[d]<0|j[d+1]<0|j[d]>=e|j[d+1]>=e)continue;l++;k+=f[j[d]][j[d+1]];}return k/l;}}

Girintili ve haritayı görüntüleyen program:

import java.util.*;
import java.awt.image.*;
import java.awt.*;
import javax.swing.*;
import static java.lang.Math.*;

class D{

    public static void main(String[]a){
        int b=a.length,d=0;
        float[]c=new float[b];
        for(;d<b;){
            c[d]=Float.parseFloat(a[d++]);
        }
        e=(int)(pow(2,c[0])+1);
        f=new float[e][e];
        f[0][0]=c[1];
        f[0][e-1]=c[2];
        f[e-1][0]=c[3];
        f[e-1][e-1]=c[4];
        g=c[5];
        float h=c[6],i=c[7];
        s(0,0,e-1,e-1,h,i);
        showImage(f);
    }

    static int e;
    static float[][]f;
    static float g;

    static void s(int q,int r,int s,int t,float h,float i){
        if(s-q<2|t-r<2|q<0|r<0|s>=e|t>=e)
            return;
        float o,p;
        int m=(q+s)/2,n=(r+t)/2;
        f[m][n]=(float)(a(q,r,s,r,q,t,s,t)+random()*(i+h)-h);
        d(m,r,m-q,o=h*g,p=i*g);
        d(q,n,m-q,o,p);
        d(m,t,m-q,o,p);
        d(s,n,m-q,o,p);
    }

    static void d(int x,int y,int e,float h,float i){
        float o,p;
        f[x][y]=(float)(a(x,y-e,x+e,y,x,y+e,x-e,y)+random()*(i-h)+h);
        s(x-e,y-e,x,y,o=h*g,p=i*g);
        s(x,y-e,x+e,y,o,p);
        s(x-e,y,x,y+e,o,p);
        s(x,y,x+e,y+e,o,p);
    }

    static float a(int...j){
        float k=0,l=0;
        for(int d=0;d<j.length;d+=2){
            if(j[d]<0|j[d+1]<0|j[d]>=e|j[d+1]>=e)
                continue;
            l++;
            k+=f[j[d]][j[d+1]];
        }
        return k/l;
    }

    public static void showImage(float[][] f){
        float maxHeight = Float.MIN_VALUE;
        float minHeight = Float.MAX_VALUE;
        for (float[] row : f){
            for (float height : row){
                if (height > maxHeight){
                    maxHeight = height;
                }
                if (height < minHeight){
                    minHeight = height;
                }
            }
        }
        int e = f.length;
        BufferedImage image = new BufferedImage(e, e, BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < e; x++){
            for (int y = 0; y < e; y++){
                Color color = Color.getHSBColor((float)((f[x][y] - minHeight)/(maxHeight - minHeight)), 1, 1);
                image.setRGB(x,y,color.getRGB());
            }
        }
        JFrame frame = new JFrame("Picture");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new JComponent(){

            @Override
            public void paint(Graphics g){
                g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
            }

        });
        frame.setVisible(true);
        frame.setBounds(0,0,e,e);
    }

}

Java'da bir haritayı gösteren bir işlev şunlardır:

public static void showImage(float[][] map){
    float maxHeight = Float.MIN_VALUE;
    float minHeight = Float.MAX_VALUE;
    for (float[] row : map){
        for (float height : row){
            if (height > maxHeight){
                maxHeight = height;
            }
            if (height < minHeight){
                minHeight = height;
            }
        }
    }
    int size = map.length;
    BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_RGB);
    for (int x = 0; x < size; x++){
        for (int y = 0; y < size; y++){
            Color color = Color.getHSBColor((float)((map[x][y] - minHeight)/(maxHeight - minHeight)), 1, 1);
            image.setRGB(x,y,color.getRGB());
        }
    }
    JFrame frame = new JFrame("Picture");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(new JComponent(){

        @Override
        public void paint(Graphics g){
            g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
        }

    });
    frame.setVisible(true);
    frame.setBounds(0,0,size,size);
}

Tüm bu görüntülerin boyutu 7. 4 tohumlardır 5, 10, 15, ve 20.

ave bvardır -10ve 10sırasıyla.

Pürüzlülük de başlar .1ve artışlarla tarafından .1kadar 1.

BirİkiÜçdörtBeşAltıYediSekizDokuzOn

Arazi üreten kodu yakında !!!

Görüntüler çok yakında !!!


Çok teşekkür ederim! Belki de gerekli tüm ithalatları içeren bir sınıf sağlayabilir misiniz? Bu harika olurdu!
flawr

@flawr Üzerinde çalışıyorum.
TheNumberOne

Sadece işe yaradı, nasıl yapılacağını biliyorsanız, pencerenin 'harmanlanmamış' görünmesini sağlamak harika olurdu. En azından makinemde, her başlattığınızda onu açmanız gerekiyor. Sınıfı şu şekilde tamamladım: pastebin.com/pRAMst4d
flawr

Harika görünüyor! Özellikle bir
tepe noktanın

@flawr Şimdi açtığınızda pencere daraltılmayacak.
TheNumberOne
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.