[英]Javascript: Randomly drawing shapes in clumps (Genetic Algorithm)
I'm trying to do graphic mimicking a bird's eye view of a forest, so I need to randomly generate green shapes on a canvas. 我正在试图模仿鸟瞰森林的图像,所以我需要在画布上随机生成绿色形状。 However, I want these shapes to be in randomized clumps to resemble a real forest more.
但是,我希望这些形状在随机丛中,更像真实的森林。 Is there a neat way to do this?
有一个巧妙的方法来做到这一点?
My code involves the basics of a genetic algorithm before the objective function gets really incorporated, with Javascript and p5.js package . 我的代码涉及到目标函数真正合并之前遗传算法的基础知识,使用Javascript和p5.js包 。
var settings = {
forestSize : 500,
rows : 124,
cols : 249,
};
function onCanvas(position){
return position*4+2;
}
var forest = new Forest(settings.forestSize);
function Tree(){
this.posx = Math.floor(Math.random()*settings.cols);
this.posy = Math.floor(Math.random()*settings.rows);
}
function Forest(f){
this.forSize = f;
this.trees = [];
for (var x = 0; x < this.forSize; x++) {
this.trees[x] = new Tree();
if(this.trees.length>1){
for(var y=0; y<x; y++){
while(this.trees[x].posx==this.trees[y].posx&&this.trees[x].posy==this.trees[y].posy){
this.trees[x] = new Tree();
}
}
}
}
}
//create world
function createWorld(){
background("lightblue");
fill(0,255,0);
for(var x=0; x<settings.forestSize; x++){
rect(onCanvas(forest.trees[x].posx), onCanvas(forest.trees[x].posy), 4, 4);
}
}
function setup() {
createCanvas(1000, 500);
}
function draw() {
createWorld();
}
var settings = {
populationSize : 25,
geneLength : 8,
mutationProbability : 0.05,
forestSize : 500,
rows : 124,
cols : 249,
year : 365,
};
function onCanvas(position){
return position*4+2;
}
function randombetween(min, max){
return Math.random()*max;
}
var population = new Population(settings.populationSize, settings.geneLength);
function Sheep(g, dna){
this.genLen = g;
this.fitness=0;
this.xpos = Math.floor(Math.random()*settings.cols);
this.ypos = Math.floor(Math.random()*settings.rows);
this.chromosome = new Array(this.genLen);
if (dna != null){
this.chromosome = dna;
} else{
for(var x=0; x<this.genLen; x+=4){
this.chromosome[x] = Math.random();
this.chromosome[x+1] = randombetween(0, 1-this.chromosome[x]);
this.chromosome[x+2] = randombetween(0, 1-this.chromosome[x]-this.chromosome[x+1]);
this.chromosome[x+3] = 1-this.chromosome[x]-this.chromosome[x+1]-this.chromosome[x+2];
}
}
}
function Population(p, g){
this.popSize = p;
this.sheep = [];
for (var x = 0; x < this.popSize; x++) {
this.sheep[x] = new Sheep(g, null);
}
}
var forest = new Forest(settings.forestSize);
function Tree(){
this.posx = Math.floor(Math.random()*settings.cols);
this.posy = Math.floor(Math.random()*settings.rows);
}
function Forest(f){
this.forSize = f;
this.trees = [];
for (var x = 0; x < this.forSize; x++) {
this.trees[x] = new Tree();
if(this.trees.length>1){
for(var y=0; y<x; y++){
while(this.trees[x].posx==this.trees[y].posx&&this.trees[x].posy==this.trees[y].posy){
this.trees[x] = new Tree();
}
}
}
}
}
//begin generation count
var generation=0;
//begin day count
var counter = 0;
function endRun(end){
if(end>=settings.year){
noLoop();
}
}
//create world
function createWorld(){
background("lightblue");
fill(0,255,0);
for(var x=0; x<settings.forestSize; x++){
rect(onCanvas(forest.trees[x].posx), onCanvas(forest.trees[x].posy), 4, 4);
}
fill(255,0,0);
for(var x=0; x<settings.populationSize; x++){
rect(onCanvas(population.sheep[x].xpos), onCanvas(population.sheep[x].ypos), 4, 4);
}
//remove eaten trees
for(var x=0; x<settings.populationSize; x++){
for(var y=0; y<settings.forestSize; y++){
if(population.sheep[x].xpos==forest.trees[y].posx && population.sheep[x].ypos==forest.trees[y].posy){
forest.trees[y].posx=null;
forest.trees[y].posy=null;
population.sheep[x].fitness++;
}
}
}
//move eaters based on chromosome
for(var x=0; x<settings.populationSize; x++){
var move = Math.random();
if(move<population.sheep[x].chromosome[0]){
//up
if(population.sheep[x].ypos>0){
population.sheep[x].ypos-=1;
}
}
else if(move-population.sheep[x].chromosome[0]<population.sheep[x].chromosome[1]){
//down
if(population.sheep[x].ypos<settings.rows-1){
population.sheep[x].ypos+=1;
}
}
else if(move-population.sheep[x].chromosome[0]-population.sheep[x].chromosome[1]<population.sheep[x].chromosome[2]){
//right
if(population.sheep[x].xpos<settings.cols-1){
population.sheep[x].xpos+=1;
}
}
else{
//left
if(population.sheep[x].xpos>0){
population.sheep[x].xpos-=1;
}
}
}
counter++;
endRun(counter);
}
function setup() {
createCanvas(1000, 500);
}
function draw() {
createWorld();
}
My idea would be to define a shape and a density within that shape and then generate that shape for specific random coordinates. 我的想法是在该形状内定义形状和密度,然后为特定的随机坐标生成该形状。
For example: 例如:
function radialTreePopulation(x,y,r,count){
let trees = []
for(let i = 0;i < count; i++){
trees.push({
posx : (x + (Math.random()* r * (Math.random() < 0.5 ? -1 : 1)))| 0,
posy : (y + (Math.random()* r * (Math.random() < 0.5 ? -1 : 1)))| 0
})
}
return trees
}
and than: 然后:
function Forest(f){
let segmentCount = (Math.random() * 75)| 0;
this.forSize = f ;
this.trees = [];
while(this.forSize){
this.trees.push(...radialTreePopulation(
(Math.random() *settings.cols)| 0,
(Math.random() *settings.rows)| 0,
(Math.random()*12) | 0 , // think squared > max segmentCount
segmentCount)
)
segmentCount = (Math.random() * 100)| 0
this.forSize -= this.forSize > segmentCount ?
segmentCount: this.forSize;
}
}
snippet: 片段:
var settings = { populationSize : 25, geneLength : 8, mutationProbability : 0.05, forestSize : 1500, rows : 124, cols : 249, year : 365, }; function onCanvas(position){ return position*4+2; } function randombetween(min, max){ return Math.random()*max; } var population = new Population(settings.populationSize, settings.geneLength); function Sheep(g, dna){ this.genLen = g; this.fitness=0; this.xpos = Math.floor(Math.random()*settings.cols); this.ypos = Math.floor(Math.random()*settings.rows); this.chromosome = new Array(this.genLen); if (dna != null){ this.chromosome = dna; } else{ for(var x=0; x<this.genLen; x+=4){ this.chromosome[x] = Math.random(); this.chromosome[x+1] = randombetween(0, 1-this.chromosome[x]); this.chromosome[x+2] = randombetween(0, 1-this.chromosome[x]-this.chromosome[x+1]); this.chromosome[x+3] = 1-this.chromosome[x]-this.chromosome[x+1]-this.chromosome[x+2]; } } } function Population(p, g){ this.popSize = p; this.sheep = []; for (var x = 0; x < this.popSize; x++) { this.sheep[x] = new Sheep(g, null); } } var forest = new Forest(settings.forestSize); function radialTreePopulation(x,y,r,count){ let trees = [] for(let i = 0;i < count; i++){ trees.push({ posx : (x + (Math.random()* r * (Math.random() < 0.5 ? -1 : 1)))| 0, posy : (y + (Math.random()* r * (Math.random() < 0.5 ? -1 : 1)))| 0 }) } return trees } function Tree(){ this.posx = Math.floor(Math.random()*settings.cols); this.posy = Math.floor(Math.random()*settings.rows); } function Forest(f){ let segmentCount = (Math.random() * 75)| 0; this.forSize = f ; this.trees = []; while(this.forSize){ this.trees.push(...radialTreePopulation( (Math.random() *settings.cols)| 0, (Math.random() *settings.rows)| 0, (Math.random()*12) | 0 , // think squared > max segmentCount segmentCount) ) segmentCount = (Math.random() * 75)| 0 this.forSize -= this.forSize > segmentCount ? segmentCount: this.forSize; } } //begin generation count var generation=0; //begin day count var counter = 0; function endRun(end){ if(end>=settings.year){ noLoop(); } } //create world function createWorld(){ background("lightblue"); fill(0,255,0); for(var x=0; x<settings.forestSize; x++){ rect(onCanvas(forest.trees[x].posx), onCanvas(forest.trees[x].posy), 4, 4); } fill(255,0,0); for(var x=0; x<settings.populationSize; x++){ rect(onCanvas(population.sheep[x].xpos), onCanvas(population.sheep[x].ypos), 4, 4); } //remove eaten trees for(var x=0; x<settings.populationSize; x++){ for(var y=0; y<settings.forestSize; y++){ if(population.sheep[x].xpos==forest.trees[y].posx && population.sheep[x].ypos==forest.trees[y].posy){ forest.trees[y].posx=null; forest.trees[y].posy=null; population.sheep[x].fitness++; } } } //move eaters based on chromosome for(var x=0; x<settings.populationSize; x++){ var move = Math.random(); if(move<population.sheep[x].chromosome[0]){ //up if(population.sheep[x].ypos>0){ population.sheep[x].ypos-=1; } } else if(move-population.sheep[x].chromosome[0]<population.sheep[x].chromosome[1]){ //down if(population.sheep[x].ypos<settings.rows-1){ population.sheep[x].ypos+=1; } } else if(move-population.sheep[x].chromosome[0]-population.sheep[x].chromosome[1]<population.sheep[x].chromosome[2]){ //right if(population.sheep[x].xpos<settings.cols-1){ population.sheep[x].xpos+=1; } } else{ //left if(population.sheep[x].xpos>0){ population.sheep[x].xpos-=1; } } } counter++; endRun(counter); } function setup() { createCanvas(1000, 500); } function draw() { createWorld(); }
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.3/p5.js"></script>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.