algorytm małego kwadratu diamentowego

12

Algorytm kwadratu diamentowego jest algorytmem generującym obszar fraktalny (mapa wysokości). Możesz znaleźć ładny opis, jak to działa:

http://www.gameprogrammer.com/fractal.html (Używany jako odniesienie.)

http://www.playfuljs.com/realistic-terrain-in-130-lines/ (Świetna implementacja JS, być może możesz chcieć ukraść jego renderer. Spójrz tutaj, do czego ten algorytm może http: // dema. playfuljs.com/terrain/ .)

Ogólna idea jest taka, że ​​masz 4 rogi jako nasiona (a) i oblicz wysokość punktu środkowego, uśredniając te cztery rogi i dodając losową wartość, np. Od -0,5 do 0,5 (b). Jeśli zastosujesz to do siatki, ponownie otrzymujesz siatkę diamentów (kwadraty i 45 °) i powtarzasz to samo (c, d), ale zakres losowy zmniejsza się, np. -0,125 do 0,125 itd. wprowadź opis zdjęcia tutaj

Twój program musi zaakceptować szereg danych wejściowych:

  • Liczba całkowita l=1,2,3,...określająca rozmiar kwadratowej siatki o długości boku 2^l+1. Co l=10trzeba będzie przechowywać około miliona cyfr.
  • Cztery nasiona (zmiennoprzecinkowe) dla każdego rogu
  • Parametr 0<h<1określający chropowatość ( Hw łączu), który oznacza początkowo zakres losowy
  • Parametry a,breprezentujące początkowe dolne i górne granice dla zakresu losowego i mnożone przez hna każdym etapie udoskonalania. (Liczba losowa jest jednolicie wybierana pomiędzy ai b.

Wyjście musi składać się z gotowej siatki 2d.

Z grubsza algorytm wyglądałby tak:

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

Jest jeden szczegół, o którym powinieneś wiedzieć: na granicy siatki będziesz mieć tylko trzy wierzchołki diamentu , więc powinieneś także obliczyć tylko średnią z tych trzech punktów.

Wizualizacja niektórych przykładów (powiedz nam, jakich parametrów użyłeś) jest opcjonalna, ale doceniona i oczywiście nie dodaje się do liczby bajtów.

Nieco zróżnicowaną implementację tego algorytmu można znaleźć tutaj: Równolegle rzutowany generator terenu wokseli

Stworzyłem małą funkcję rysowania w javascript do wyświetlania map wysokości w 2D w obrazie w skali szarości. http://jsfiddle.net/flawr/oy9kxpsx/

Jeśli ktoś z was lubi fantazyjne 3D i może napisać skrypt do przeglądania map w 3D, dajcie znać! =)

wada
źródło

Odpowiedzi:

8

Java, 1017 bajtów

Wejście jest przestrzeń oddzielona listy tak: l s1 s2 s3 s4 h a b.

Dane wyjściowe to tablica 2d zawierająca liczby.

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;}}

Program, który jest wcięty i wyświetla mapę:

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);
    }

}

Oto funkcja w Javie do wyświetlania mapy:

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);
}

Wszystkie te obrazy mają rozmiar 7. W 4 nasiona 5, 10, 15, i 20.

aa b-10i 10odpowiednio.

Chropowatość zaczyna się od .1i .1rośnie o maksymalnie 1.

JedenDwaTrzyCzteryPięćSześćSiedemOsiemDziewięćDziesięć

Kod generowania terenu już wkrótce !!!

Obrazy już wkrótce !!!

Numer jeden
źródło
Dziękuję Ci bardzo! Czy możesz zapewnić klasę ze wszystkimi niezbędnymi importami, więc nie jest wymagana żadna duża modyfikacja? To byłoby niesamowite!
flawr
@flawr Pracuję nad tym.
TheNumberOne
Po prostu działało, jeśli wiesz, jak to zrobić, byłoby wspaniale, gdybyś mógł sprawić, że okno pokaże się jako „nierozwinięte”. Przynajmniej na mojej maszynie musisz ją otworzyć przy każdym uruchomieniu. Oto jak ukończyłem klasę: pastebin.com/pRAMst4d
flawr
To wygląda niesamowicie! Szczególnie podoba mi się elegancki sposób radzenia sobie z granicami, w których brakuje jednego wierzchołka =)
flawr
@flawr Okno nie zwinie się, gdy je teraz otworzysz.
TheNumberOne