简体   繁体   English

Javascript:随机绘制团块形状(遗传算法)

[英]Javascript: Randomly drawing shapes in clumps (Genetic Algorithm)

Problem 问题

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.j​​s包

Core Problem 核心问题

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

All Script 所有剧本

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM