Concept:
In order to define fire suppression tactics and design fire risk management policies, it is important to simulate the propagation of wildfires. In my final project, I’ll be using cellular automata to model the spread of wind-driven fire across a grid-based terrain, demonstrating the dynamics of wildfires and exploring different scenarios and factors affecting their spread.
Users will be able to set the initial conditions (i.e. density of vegetation, vegetation type, ignition point), adjust parameters (i.e. wind speed, wind direction, temperature), monitor variables (i.e. frames per second, land proportion, water proportion, burned land), pause, and reset the simulation.
Final Sketch:
https://editor.p5js.org/bdr/full/2S_n0X2gV
Code:
https://editor.p5js.org/bdr/sketches/2S_n0X2gV
Initial sketches:
Papers to be used:
https://www.fs.usda.gov/rm/pubs_int/int_rp115.pdf
Code walkthrough:
Terrain generation:
The generateCells() function creates a terrain by dividing the map into cells to form a 2D grid (representing a cellular automata). Within each grid cell (defined by x and y coordinates), various noise functions are used to generate different aspects of the terrain.
generateCells() mainly defines the elevation of each cell in the grid through a combination of noise functions. Noise, Marks, Distortion, Bump, and Roughness are all variables employed with different scaling factors and combinations of input derived from the x and y coordinates. The noise functions were determined through trial and error.
roughness = noise(x / 600, y / 600) - 0.3; bumpdistort = noise(x / 20, y / 20); bumpnoise = noise(x / 50, y / 50, 2 * bumpdistort); h = noise1 + sq(sq(noise2)) + roughness * bumpnoise - 0.8;
The color of each point is determined based on its height and other noise values, influencing factors such as land type (e.g., vegetation or ocean) and terrain features.
Using HSB as the color mode, the hue component represents the color’s tone (e.g., red, green, blue) while the brightness component corresponds to the perceived elevation. This makes it intuitive to represent different elevations using a gradient of colors (e.g., blue for lower elevations to white for higher ones), making the terrain visually more coherent and natural-looking.
if (h > 0) { clr = color(20 + 10 * (marks1 - 4) + 10 * (marks2 - 4) + 20 * distort1 + 50 * distort2 + bumpnoise * 15, min(100, max(50, 100 - 500 * roughness)), 75 + 65 * h); veg = getColor(clr) pointData = { x: x, y: y, color: clr, vegetation: veg, fire: 0, elev: elevationClr, temp:null}; landCnt++; } else { clr = color(160, 100, 185 + max(-45, h * 500) + 65 * h + 75 * (noise2 - 0.75)); veg = getColor(clr) pointData = { x: x, y: y, color: clr, vegetation: veg, fire: 0, elev: elevationClr, temp:null}; oceanCnt++; }
The elevation/height is mapped as to the more the cell is in the middle of the ocean, the deeper it gets, and the more in the middle of the land, the higher it gets.
Initial step:
Simplified sketch: As the sketch needed around 3 seconds to render, and cellular automata required a constant update of the sketch, simplifying the sketch was crucial. So, instead of calculating the noise for every pixel, I skip one by predicting its color.
Vegetation:
Vegetation type propagation probability:
– No vegetation: -1
– Cultivated: -0.4
– Forests: 0.4
– Shrub: 0.4
Vegetation density propagation probability:
– No vegetation: -1
– Sparse: -0.3
– Normal: 0
– Dense: 0.3
Rules:
– R1: A cell that can’t be burned stays the same
– R2: A cell that is burning down at the present time will be completely burned in the next iteration.
– R3: A burned cell can’t be burned again.
– R4: If a cell is burned, and its neighbors contain vegetation fue, the fire can then propagate with a given probability (factors).
The fire propagation probabilities are:
P0: ignition point (user interaction)
P_veg: vegetation type
P_den: vegetation density
Ps: topography
Pw: wind speed and direction
with C1 and C2 are adjustable coefficients
V is the wind speed
O is the angle between the wind direction and the fire propagation (if aligned, Pw increases)
with a: adjustable coefficient
o: the slope angle of the terrain
with E: elevation of the cell
D: the size of the square cell if adjacent or sqrt(2*cellSize) if diagonal
Cellular Automata rules:
Implement rules governing the spread of fire: Fuel, topography, wind, and humidity.
– R1: A cell that can’t be burned stays the same
– R2: A cell that is burning down at the present time will be completely burned in the next iteration.
– R3: A burned cell can’t be burned again.
– R4: If a cell is burned, and its neighbors contain vegetation fue, the fire can then propagate with a given probability (factors).
function generateNextGeneration() { for (let i = 0; i < width; i+=2) { for (let j = 0; j < height; j+=2) { let neighbors = countNeighbors(i, j); let windAffectedProb = calculateWindEffect(i, j, windSpeed, windDirection); if (grid[i][j].fire==0 && neighbors==0){ // no fire, neighbors no fire nextGrid[i][j].fire=0; } if (grid[i][j].fire==0 && neighbors!=0 && grid[i][j].vegetation==0){ // water, neighbor fire, probability 0% nextGrid[i][j].fire=0; } probability = Math.floor(random(1,100)); windInfluence = random(0, 100); if (grid[i][j].fire==0 && neighbors!=0 && grid[i][j].vegetation==1 && probability<10 && windInfluence < windAffectedProb && temperature>0){ // sparse, neighbor fire, probability 10% nextGrid[i][j].fire=1; nextGrid[i][j].color=color(14, 252, 113); } probability = Math.floor(random(1,100)); windInfluence = random(0, 100); if (grid[i][j].fire==0 && neighbors!=0 && grid[i][j].vegetation==2 && probability<50 && windInfluence < windAffectedProb && temperature>0){ // no fire, neighbor fire, normal veg, probability 70% nextGrid[i][j].fire=1; nextGrid[i][j].color=color(14, 252, 113); } probability = Math.floor(random(1,100)); windInfluence = random(0, 100); if (grid[i][j].fire==0 && neighbors!=0 && grid[i][j].vegetation==3 && probability<30 && windInfluence < windAffectedProb && temperature>0){ // no fire, neighbor fire, dense veg, probability 100% nextGrid[i][j].fire=1; nextGrid[i][j].color=color(14, 252, 113); } else if (grid[i][j].fire==1){ // burning nextGrid[i][j].fire==-1; nextGrid[i][j].color=color(0, 0, 57); burnedCnt++; burnedBlocks[`${i}_${j}`] = true; } else if (grid[i][j].fire==-1){ // burned nextGrid[i][j].fire==-1; nextGrid[i][j].color=color(0, 0, 57); } } } swapGenerations(); }
Other Maps:
Elevation Map: Users are able to visualize the elevation of the terrain by using the button at the right of the screen.
Elevation type: Users are also able to visualize the tyoe of vegetation (forests, shrubs, cultivated…)
Wind: Users are also able to see the wind direction and modify it using the slider.
Challenges:
Improving the computation time was a rather challenging time. After optimizing it, it went from 3s to 0.35s.
IM Show Pictures: