algoritma berlian persegi kecil


12

Algoritma diamond square adalah algoritma yang menghasilkan fractal terrain (heightmap). Anda dapat menemukan deskripsi yang bagus tentang cara kerjanya di sini:

http://www.gameprogrammer.com/fractal.html (Digunakan sebagai referensi.)

http://www.playfuljs.com/realistic-terrain-in-130-lines/ (Implementasi JS yang hebat, mungkin Anda mungkin ingin mencuri renderernya. Lihatlah di sini apa yang mampu dilakukan algoritma ini dari http: // demo. playfuljs.com/terrain/ .)

Gagasan umum adalah bahwa Anda memiliki 4 sudut sebagai biji (a), dan menghitung ketinggian titik pusat dengan rata-rata keempat sudut dan menambahkan nilai acak misalnya antara -0,5 dan 0,5 (b). Jika Anda menerapkan ini ke grid Anda mendapatkan lagi grid berlian (kuadrat turend 45 °) dan Anda ulangi yang sama (c, d), tetapi rentang acak semakin kecil, misalnya -0,125 ke 0,125 dll. masukkan deskripsi gambar di sini

Program Anda harus menerima sejumlah input:

  • Bilangan bulat l=1,2,3,...yang menentukan ukuran kotak persegi dengan panjang sisi 2^l+1. Pada l=10Anda harus menyimpan sekitar satu juta nomor.
  • Empat biji (floating point) untuk setiap sudut
  • Parameter 0<h<1yang menentukan kekasaran ( Hdalam tautan) yang berarti seberapa besar rentang acak awalnya
  • Parameter a,byang mewakili batas bawah dan atas awal untuk rentang acak dan dikalikan dengan hdi setiap langkah penyempurnaan. (Nomor acak dipilih secara seragam antara adan b.

Output harus terdiri dari grid 2d yang sudah jadi.

Jadi algoritma kasar akan terlihat seperti ini:

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

Ada satu detail yang harus Anda perhatikan: Pada batas kisi, Anda hanya akan memiliki tiga simpul berlian , jadi Anda juga harus hanya menghitung rata-rata dari ketiga titik tersebut.

Visualisasi beberapa contoh (beri tahu kami parameter apa yang Anda gunakan) adalah opsional tetapi dihargai, dan tentu saja tidak menambah jumlah byte.

Implementasi yang sedikit bervariasi dari algoritma ini dapat ditemukan di sini: Generator medan voxel yang diproyeksikan paralel

Saya membuat fungsi menggambar kecil dalam javascript untuk memindahkan ketinggian peta dalam 2d sebagai gambar skala abu-abu. http://jsfiddle.net/flawr/oy9kxpsx/

Jika ada di antara Anda yang menyukai 3d mewah dan dapat membuat skrip untuk melihat peta dalam 3d beri tahu saya! =)

Jawaban:


8

Java, 1017 byte

Input adalah ruang daftar dipisahkan seperti: l s1 s2 s3 s4 h a b.

Output adalah array 2d yang berisi angka-angka.

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 yang diberi indentasi dan menampilkan peta:

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

}

Berikut adalah fungsi di Jawa untuk menampilkan peta:

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

Semua gambar ini memiliki ukuran 7. 4 biji 5, 10, 15, dan 20.

adan byang -10dan 10masing-masing.

Kekasaran dimulai pada .1dan meningkat .1hingga 1.

SatuDuaTigaEmpatLimaEnamTujuhDelapanSembilanSepuluh

Terrain menghasilkan kode segera !!!

Gambar segera hadir !!!


Terima kasih banyak! Bisakah Anda memberikan kelas sekitar dengan semua impor yang diperlukan sehingga tidak ada modifikasi besar yang diperlukan? Itu akan luar biasa!
flawr

@ flawr saya sedang mengerjakannya.
TheNumberOne

Baru saja berfungsi, jika Anda tahu cara melakukannya, alangkah baiknya jika Anda bisa membuat jendela muncul 'tidak terkumpul'. Setidaknya di mesin saya, Anda harus menariknya terbuka setiap kali Anda memulainya. Inilah cara saya menyelesaikan kelas: pastebin.com/pRAMst4d
flawr

Ini terlihat luar biasa! Saya terutama menyukai cara elegan Anda berurusan dengan batas-batas di mana satu simpul hilang =)
flawr

@ flawr Jendela tidak akan diciutkan saat Anda membukanya sekarang.
TheNumberOne
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.