[Xulu-commits] r62 - in trunk: dist src/edu/bonn/xulu/plugin/model/sleuth
scm-commit@wald.intevation.org
scm-commit at wald.intevation.org
Wed Oct 21 10:43:44 CEST 2009
Author: rgoetzke
Date: 2009-10-21 10:43:39 +0200 (Wed, 21 Oct 2009)
New Revision: 62
Modified:
trunk/dist/xulu-doc.zip
trunk/src/edu/bonn/xulu/plugin/model/sleuth/MultipleResolutionValidation.java
trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModel.java
trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelContentManager.java
Log:
Modified: trunk/dist/xulu-doc.zip
===================================================================
(Binary files differ)
Modified: trunk/src/edu/bonn/xulu/plugin/model/sleuth/MultipleResolutionValidation.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/sleuth/MultipleResolutionValidation.java 2009-10-14 08:31:55 UTC (rev 61)
+++ trunk/src/edu/bonn/xulu/plugin/model/sleuth/MultipleResolutionValidation.java 2009-10-21 08:43:39 UTC (rev 62)
@@ -11,7 +11,7 @@
import edu.bonn.xulu.plugin.data.grid.MultiGrid;
/**
- * <b>MULTIPLE RESOLUTION COMPARISON</b>
+ * <b>MULTIPLE RESOLUTION COMPARISON</b><br>
* The Multiple Resolution Comparison is a Xulu-plugin that can be used in order to validate modelling results.
* In general, the Multiple Resolution Comparison is a method to quantify the agreement between two maps,
* whereby it averages neighbouring pixels of both maps into coarser pixels in order to quantify the agreement between maps at coarser resolutions.
@@ -19,12 +19,28 @@
* a Multiple Resolution Comparison of a NULL-Model (no change has taken place between t1 and t2), the NULL-Resolution can be identified,
* which indicates the resolution at which the modelling result is more accurate than the NULL-Model.<br>
* For details refer to:<br>
- * Costanza,R. (1989): Model Goodness of Fit - A Multiple Resolution Procedure. In: Ecological Modelling, vol. 47, no. 3-4, pp. 199-215.<br>
- * Pontius Jr, R.G. (2002): Statistical Methods to Partition Effects of Quantity and Location During Comparison of Categorical Maps at Multiple Resolutions.
+ * <i>Costanza,R. (1989)</i>: Model Goodness of Fit - A Multiple Resolution Procedure. In: Ecological Modelling, vol. 47, no. 3-4, pp. 199-215.<br>
+ * <i>Pontius Jr, R.G. (2002)</i>: Statistical Methods to Partition Effects of Quantity and Location During Comparison of Categorical Maps at Multiple Resolutions.
* In: Photogrammetric Engineering & Remote Sensing, vol. 68, no. 10, pp. 1041-1049.<br>
- * Pontius Jr, R.G., Huffaker, D. & K. Denman (2004): Useful Techniques of Validation for Spatially Explicit Land-Change Models.
+ * <i>Pontius Jr, R.G., Huffaker, D. & K. Denman (2004)</i>: Useful Techniques of Validation for Spatially Explicit Land-Change Models.
* In: Ecological Modelling, vol. 179, no. 4, pp. 445-461.<br>
*
+ * The following input parameters/images are required:<br>
+ * <ul>
+ * <li><b>Number of Steps ({@code steps})</b>: Because this plugin is built as a step model, the number of (time) steps always has to be 1.</li>
+ * <li><b>Reference Map ({@code referenceMap})</b>: A raster containing the reference (observed) land cover.</li>
+ * <li><b>Simulation Map ({@code simulationMap})</b>: A raster containing the simulated land cover.</li>
+ * </ul>
+ *
+ * Furthermore the following outputs are created:<br>
+ * <ul>
+ * <li><b>Actual Validation (@code actualValidation)</b>: A raster containing the actual resolution grid with the fraction correct in every cell</li>
+ * <li><b>Out Step ({@code outStep})</b>: A Grid List containing a grid (Actual Validation) for every resolution.</li>
+ * <li><b>Out Results ({@code outResults})</b>: A list containing the total agreement for every resolution.</li>
+ * </ul>
+ *
+ * Other important values are written to the status output window!<br>
+ *
* @see MultipleResolutionValidationContentManager
* @author <a href="mailto:goetzke at uni-bonn.de">Roland Goetzke</a>
* @version 1.0
@@ -42,14 +58,14 @@
private float[][] resultArray;
/**
- * Speichert den ContentManager fuer das Modell.
+ * Saves the ContentManager for the model.
*
* @see MultipleResolutionValidationContentManager
*/
protected MultipleResolutionValidationContentManager contManager;
- // ********** Lese/Schreibrechte, die fuer den gesamten ***********
- // ********** Modellanlauf gehalten werden muessen ***********
+ // ********** Read/Write access, that has to be maintained ***
+ // ********** through the whole model run ********************
private PropertyReadAccess RA_steps = null; //Number of Steps
private PropertyReadAccess RA_referenceMap = null; // Reference Map
private PropertyReadAccess RA_simulationMap = null; //Simulation Map
@@ -57,7 +73,7 @@
private PropertyWriteAccess WA_outStep = null; // Step Results
private ListPropertyWriteAccess WA_outResults = null; //Output Validation Results
- // **************** Variablen mit denen gearbeitet wird *******************
+ // **************** Variables to work with *******************
private PropertyReadAccess steps = null; // Number of steps
private WritableGrid referenceMap = null; // Reference Map
private WritableGrid simulationMap = null; // Simulation Map
@@ -120,7 +136,7 @@
*/
public void performModelDispose() {
- // Ressourcen wieder freigeben
+ // free resources
releaseAccess(RA_steps);
releaseAccess(RA_referenceMap);
releaseAccess(RA_simulationMap);
Modified: trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModel.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModel.java 2009-10-14 08:31:55 UTC (rev 61)
+++ trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModel.java 2009-10-21 08:43:39 UTC (rev 62)
@@ -1,10 +1,7 @@
package edu.bonn.xulu.plugin.model.sleuth;
-import java.awt.Rectangle;
import java.util.HashMap;
-import org.geotools.feature.Feature;
-
import edu.bonn.xulu.model.AbstractStepModel;
import edu.bonn.xulu.model.XuluModel;
import edu.bonn.xulu.plugin.data.grid.MultiGrid;
@@ -15,42 +12,71 @@
import schmitzm.data.property.ScalarProperty;
/**
- * This very simple model looks at every grid cell and takes the average
- * over a the surrounding cells in a specified neighborhood. It was implemented
- * as demonstration of the Xulu / V functionality. You can see the parallel version
- * of this model in {@link AverageNeighborhoodParallelDemoModel} and also a tuned
- * version using late-merging support in {@link AVNTuned}. Beachte die Methode {@link #calculateNeighbors(int, int, float)}.
+ * <b>Urban Growth Model</b><br>
+ * This Model simulates urban growth. It is based on the algorithm of the SLEUTH-Model, which has originally been written in C code and could
+ * be run under UNIX. The SLEUTH-Model has been developed by Keith Clarke at the UC Santa Barbara, CA, within the Gigalopolis Project, funded by the
+ * USGS. Therefore it is under public domain. The name SLEUTH has been derived from the image input requirements of the model:
+ * Slope, Land cover, Exclusion, Urbanization, Transportation, and Hillshade.<br>
+ * In the original SLEUTH-Model the core Urban Growth Model (UGM) calls and drives an additional land cover deltatron model (LCD). Both models are
+ * tightly coupled, but the UGM can be run separately. Here, only the UGM part of the SLEUTH-Model has been translated into JAVA. Minor changes
+ * in the code have been necessary. Those changes are explained within the code. In general, the UGM is a Cellular Automaton (CA). All CA elements
+ * in the code have been untouched and are the same as in the original UGM.<br>
+ * This is the basic UGM code, a plain Cellular Automaton. Additional functions are implemented in other models, like:<br>
+ * <ul>
+ * <li><b>UGM Calibration ({@link UrbanGrowthModelCalibration})</b>: The same model algorithm like this, but in order to calibrate the model by finding the correct parameter values with the method of Multiple Resolution Comparison (@link MultipleResolutionValidation)</li>
+ * <li><b>UGM SelfModifying({@link UrbanGrowthModelSelfModifying})</b>: The same model algorithm like this, but with the possibility of self-modification of the parameter values.</li>
+ * <li><b>UGM CalibrationSelfModifying({@link UrbanGrowthModelCalibrationSelfModification})</b>: The same model algorithm like this, but in order to calibrate the model by finding the correct parameter values with the method of Multiple Resolution Comparison (@link MultipleResolutionValidation)
+ * While calibrating the model modifies the parameter values.</li>
+ * </ul>
+ * <br>
+ * The original SLEUTH-Model can be downloaded via the <a href="http://www.ncgia.ucsb.edu/projects/gig/">Gigalopolis Website</a>. To run it, a
+ * UNIX environment with the GNU C compiler (gcc) are required.<br>
+ * For details refer to:<br>
+ * <i>Clarke, K.C., Hoppen, S. & L.J. Gaydos (1997)</i>: A self-modifying cellular automaton model of historical urbanization in the San Francisco Bay area.
+ * In: Environment and Planning B: Planning and Design, vol. 24, pp. 247-261.<br>
+ * <i>Clarke, K.C. & L.J. Gaydos (1998)</i>: Loose-coupling a cellular automaton model and GIS: long-term urban growth prediction for San Francisco
+ * and Washington/Baltimore. In: International Journal of Geographical Information Science, vol. 12, no. 7, pp. 699-714.<br>
+ * <i>Jantz, C.A., Goetz, S.J. & M.K. Shelley (2003)</i>: Using the SLEUTH urban growth model to simulate the impacts of future policy scenarios
+ * on urban land use in the Baltimore-Washington metropolitan area. In: Environment and Planning B: Planning and Design, vol: 30, pp. 251-271.<br>
*
- *
- * <ol>
- * <li><b>Input Grid ({@code inputGrid}):</b> A grid with input values </li>
- * <li><b>Output Grid ({@code outputGrid}):</b> A grid where the output is
- * stored </li>
- * <li><b>Number of steps ({@code steps}):</b> the number of steps to
- * compute. </li>
- * </ol>
+ * <br>
+ * The following input parameters/images are required:<br>
+ * <ul>
+ * <li><b>Input Grid ({@code inputGrid})</b>: A grid containing the input (initial) urban land cover.</li>
+ * <li><b>Area Restriction ({@code areaRestr})</b>: A grid containing the area restrictions (e.g. water, natural reserves, areas with lower probability, etc.).</li>
+ * <li><b>Transportation Grid ({@code roadGrid})</b>: A grid containing the road network.</li>
+ * <li><b>Slope Grid ({@code slopeGrid})</b>: A grid containing the slope.</li>
+ * <li><b>Number of steps ({@code steps})</b>: The number of time steps to compute.</li>
+ * <li><b>Spread ({@code spread})</b>: The Spread-Coefficient.</li>
+ * <li><b>Disp ({@code disp})</b>: The Dispersion(Diffusion)-Coefficient.</li>
+ * <li><b>Breed ({@code breed})</b>: The Breed-Coefficient.</li>
+ * <li><b>Road Gravity ({@code roadGravity})</b>: The Road Gravity-Coefficient.</li>
+ * <li><b>Slope ({@code slope})</b>: The Slope-Coefficient.</li>
+ * <li><b>Critical Slope ({@code criticalSlope})</b>: The Percentage at which urbanization on steep slopes is not possible.</li>
+ * </ul>
*
- * @see AverageNeighborhoodContentManager
- * @author Dominik Appl
+ * <br>
+ * Furthermore the following outputs are created:<br>
+ * <ul>
+ * <li><b>Output Grid ({@code outputGrid})</b>: A grid containing the output, that is actualized in every time step.</li>
+ * <li><b>outStep ({@code outStep})</b>: A Grid List containing the results for every time step.</li>
+ * </ul>
+ *
+ * @see UrbanGrowthModelContentManager
+ * @author <a href="mailto:goetzke at uni-bonn.de">Roland Goetzke</a>
* @version 1.0
*/
public class UrbanGrowthModel extends AbstractStepModel {
/**
- * the width/height of the neighborhood region over which the algorithm takes
- * the average
- */
-// private int neighborhoodRange = 1;
-
- /**
- * Speichert den ContentManager fuer das Modell.
+ * Saves the ContentManager for the model.
*
- * @see AverageNeighborhoodContentManager
+ * @see UrbanGrowthModelContentManager
*/
protected UrbanGrowthModelContentManager contManager;
- // ********** Lese/Schreibrechte, die fuer den gesamten ***********
- // ********** Modellanlauf gehalten werden muessen ***********
+ // ********** Read/Write access, that has to be maintained ***
+ // ********** through the whole model run ********************
private PropertyReadAccess RA_inputGrid = null; // Input Grid
private PropertyWriteAccess WA_outputGrid = null; // Output Grid
private PropertyReadAccess RA_steps = null; // Number of steps
@@ -80,16 +106,34 @@
private WritableGrid slopeGrid = null; //Slope Grid
private MultiGrid outStep = null; //Step Results
+ /**
+ * Moore Neighborhood as a two dimensional array. It's the central element of a Cellular Automaton.
+ */
private static final int[][] NEIGHBOR = new int[][] {
{-1,-1}, {0,-1}, {1,-1},
{-1, 0}, {1, 0},
{-1, 1}, {0, 1}, {1, 1}
};
+ /**
+ * A Lookup-Table which relates actual slope values to slope coefficient influenced probabilities.
+ */
protected HashMap<Number,Number> slopeLUT;
+ protected int areaMinX = 0;
+ protected int areaMinY = 0;
+ protected int areaMaxX = 0;
+ protected int areaMaxY = 0;
+ protected int areaWidth = 0;
+ protected int areaHeight = 0;
+
+ protected double disp_value = 0; //Dispersion Value
+ protected double max_RG_value = 0; //Maximum RoadGravity Value
+ protected double rg_value = 0; //RoadGravity Value
+ protected double max_search_index = 0; //Maximum search index for road
+
/**
- * Erzeugt eine neue Instanz des Modells.
+ * Creates a new model instance.
*/
public UrbanGrowthModel() {
super(new UrbanGrowthModelContentManager());
@@ -102,9 +146,10 @@
* the resources are initalized.
*/
public void performModelInit() {
+
if (contManager == null)
return;
- // Zugriffsrechte aus Ressourcen/Propertys holen
+ // Get access authorisation of resource/properties
RA_inputGrid = null;
if (contManager.getResource(0).getData() != null)
RA_inputGrid = ((ScalarProperty) contManager.getResource(0)
@@ -154,14 +199,12 @@
RA_slopeGrid = ((ScalarProperty) contManager.getResource(11)
.getData()).getReadAccess(this);
- // Variablen belegen mit denen gearbeitet wird
+ // Assign variables to work with
inputGrid = (WritableGrid) RA_inputGrid.getValue();
outputGrid = (WritableGrid) WA_outputGrid.getValue();
steps = RA_steps;
+ this.stepCount = steps.getValueAsInt();
areaRestr = (WritableGrid) RA_areaRestr.getValue();
-
- this.stepCount = steps.getValueAsInt();
- // this.spread = RA_spread.getValueAsFloat();
spread = RA_spread.getValueAsDouble();
disp = RA_disp.getValueAsDouble();
breed = RA_breed.getValueAsDouble();
@@ -172,47 +215,30 @@
slopeGrid = (WritableGrid) RA_slopeGrid.getValue();
outStep = (MultiGrid)contManager.getResource(12).getData();
-
- int startAnz = 0;
- for (int i = 0; i < inputGrid.getWidth();i++ ) {
- for (int ii = 0; ii < inputGrid.getHeight(); ii++ ) {
- //if (inputGrid.getRasterSampleAsFloat(i,ii) == 1f);
- float val = inputGrid.getRasterSampleAsFloat(i,ii);
- if (val == 1.0 ) {
- val = 1f;
- startAnz++;
- }
- else val = 0f;
-
- //inputGrid.setRasterSample(val, inputGrid.getMinX() + i, inputGrid.getMinY() + ii);
- outputGrid.setRasterSample(val, inputGrid.getMinX() + i, inputGrid.getMinY() + ii);
- }
- }
- statusOut.println("Anzahl der startenden Individuen: "+startAnz);
- statusOut.println(NEIGHBOR.length);
+ //count the number of starting individuals
+ int startAnz = 0;
+ startAnz = countIndividuals();
+ statusOut.println("Number of starting cells: "+startAnz);
+ statusOut.println("Neighborhood size: "+NEIGHBOR.length);
+
+ //calculate the maximum slope
int slopeMax = 0;
- for (int s = 0; s < inputGrid.getWidth();s++){
- for(int ss = 0; ss < inputGrid.getHeight();ss++){
- float slopeVal = slopeGrid.getRasterSampleAsFloat(s,ss);
- if (slopeVal > slopeMax){
- slopeMax = (int) slopeVal;
- }
- }
- }
- statusOut.println("Maximale Hangneigung: "+slopeMax);
+ slopeMax = getSlopeMax();
-
- //Erstellt einen Lookup-Table
+ statusOut.println("Max. Slope: "+slopeMax+" %");
+
+ //Creates a new Lookup-table
slopeLUT = new HashMap<Number,Number>();
+ //assigns for every slope value between 0 and the maximum slope that is below the critical slope the value calculated for the variable "lookup".
+ //all values higher than the critical slope become 1
int MaxSlopeResistance = 0;
double exp = 0.0;
- MaxSlopeResistance = 100;
- exp = (slope / (MaxSlopeResistance / 2));
+ MaxSlopeResistance = 100; //Max slope resistance is 100%
+ exp = (slope / (MaxSlopeResistance / 2.0));
double[] lookup = new double[slopeMax+1];
Number key = 0;
-
for (int i = 0;i <= slopeMax;i++){
if (i <= criticalSlope){
double val = (criticalSlope - i) / criticalSlope;
@@ -223,8 +249,24 @@
key = i;
}
slopeLUT.put(key,lookup[i]);
- statusOut.println(slopeLUT.get(key));
}
+
+ //raster dimensions
+ areaMinX = inputGrid.getMinX();
+ areaMinY = inputGrid.getMinY();
+ areaMaxX = inputGrid.getMinX() + inputGrid.getWidth() - 1;
+ areaMaxY = inputGrid.getMinY() + inputGrid.getHeight() - 1;
+ areaWidth = inputGrid.getWidth();
+ areaHeight = inputGrid.getHeight();
+
+ //coefficient calculations of for growth rules
+ disp_value = Math.round((disp*0.005)* Math.sqrt(Math.pow(inputGrid.getWidth(), 2)+(Math.pow(inputGrid.getHeight(), 2)))); //Dispersion value (Number of cells to select spontaneously)
+ statusOut.println("Dispersion-Value: "+disp_value);
+ max_RG_value = 100.0; //Maximum possible road gravity value
+ rg_value = Math.round((roadGravity/max_RG_value)*((areaWidth + areaHeight)/16)); //calculation of the road gravity value
+ statusOut.println("RoadGravity-Value: "+rg_value);
+ max_search_index = Math.round(4*((int)rg_value*(1+(int)rg_value))); //area in which to look for a road cell
+ statusOut.println("MaxSearchIndex: "+max_search_index);
}
/**
@@ -232,7 +274,7 @@
*/
public void performModelDispose() {
- // Ressourcen wieder freigeben
+ // free resources
releaseAccess(RA_inputGrid);
releaseAccess(WA_outputGrid);
releaseAccess(RA_steps);
@@ -247,406 +289,437 @@
releaseAccess(RA_slopeGrid);
releaseAccess(WA_outStep);
}
-
+
/**
- * This very simple model looks at every grid cell and takes the average
- * over a the surrounding cells in a specified neighborhood.
- * @exception IllegalArgumentException wenn das dadad
+ * This is the main run of the Urban Growth Model. Depending on the input parameters the cellular automaton looks in the neighborhood of individual cells for specific conditions
+ * and turns them from non-urban into urban, following certain growth rules. Those growth rules are:<br>
+ * <ol>
+ * <li><b>spontaneous growth</b>: controlled by dispersion (@code disp): Randomly selects potential new growth cells.</li>
+ * <li><b>new spreading centers</b>: controlled by breed (@code breed): Growing urban centers from spontaneous growth.</li>
+ * <li><b>edge</b>: controlled by spread (@code spread): Old or new urban centers spawn additional growth.</li>
+ * <li><b>road influenced</b>: controlled by road-gravity(@code roadGravity), dispersion (@code disp), breed (@code breed): Newly urbanized cell spawns growth along transportation network.</li>
+ * </ol>
+ * @exception IllegalArgumentException
* @param stepNo
- * zu modellierender Schritt (beginnend bei 1!)
*/
public void performModelStep(int stepNo) {
statusOut.println("Starting step " + stepNo + "...");
- Number number = slopeLUT.get(79);
- statusOut.println(number);
-
- int areaMinX = inputGrid.getMinX(); //Dimensionen des Rasters
- int areaMinY = inputGrid.getMinY();
- int areaMaxX = inputGrid.getMinX() + inputGrid.getWidth() - 1;
- int areaMaxY = inputGrid.getMinY() + inputGrid.getHeight() - 1;
- int areaWidth = inputGrid.getWidth();
- int areaHeight = inputGrid.getHeight();
+ //time measure
long localStartTime = System.currentTimeMillis();
- boolean anyBodyAlive = false;
- boolean[][] tmpGrid = new boolean[inputGrid.getWidth()][inputGrid.getHeight()];
- Float actUrb = null;
+ //cells to be created
+ boolean[][] tmpGrid = new boolean[inputGrid.getWidth()][inputGrid.getHeight()]; //a temporary raster
+ Float actUrb = null; //urban cell in the raster
+
+
+ /*****************************************************************
+ * DISPERSION and BREED (Growth Phase 1 and 2)
+ *****************************************************************/
+ boolean[][] tmpGridDisp = new boolean[inputGrid.getWidth()][inputGrid.getHeight()]; //a temporary raster
+ tmpGridDisp = DispersionGrowth(); //calls the method "DispersionBreed" to perform the Dispersion and Breed Growth Phase
+ int anzDispBreed = 0; //number of cells urbanized by Dispersion and Breed
+ for (int x = 0; x < inputGrid.getWidth();x++)
+ for(int y = 0; y < inputGrid.getHeight();y++){
+ int X = inputGrid.getMinX() + x;
+ int Y = inputGrid.getMinY() + y;
+ if (tmpGridDisp[X][Y]==true){
+ anzDispBreed++;
+ tmpGrid[X][Y] = true; //write the temporary Dispersion and Breed Cells to the overall temporary Cell array
+ }
+ }
+ statusOut.println("Number of Spontaneous and New Spreading Center Cells: "+anzDispBreed);
+ writeToGrid(tmpGrid); //calls the method "writeToGrid" to write the new urbanized cells to the output grid
- int nbX = 0; // X-Koordinate einer Nachbarzelle
- int nbY = 0; // Y-Koordinate einer Nachbarzelle
- int[] nbCell = null;
-
- int anzSpreadTreffer = 0;
- int anzDispTreffer = 0;
- int anzBreedTreffer = 0;
-
- //DISPERSION
- double disp_value = Math.round((disp*0.005)* Math.sqrt(Math.pow(inputGrid.getWidth(), 2)+(Math.pow(inputGrid.getHeight(), 2))));
- int dispRandX = 0;
- int dispRandY = 0;
- float slopeRandDisp = 0;
+ /*********************************************************************
+ * EDGE
+ *********************************************************************/
+ boolean[][] tmpGridSpread = new boolean[inputGrid.getWidth()][inputGrid.getHeight()]; //a temporary raster
+ tmpGridSpread = EdgeGrowth(); //calls the method "EdgeGrowth" to perform the Spread (Edge Growth) Phase
+ int anzSpread = 0; //number of cells urbanized by Spread
+ for (int x = 0; x < inputGrid.getWidth();x++)
+ for(int y = 0; y < inputGrid.getHeight();y++){
+ int X = inputGrid.getMinX() + x;
+ int Y = inputGrid.getMinY() + y;
+ if (tmpGridSpread[X][Y]==true){
+ anzSpread++;
+ tmpGrid[X][Y] = true; //write the temporary Spread cells to the overall temporary Cell array
+ }
+ }
+ statusOut.println("Number of Edge Growth Cells: "+anzSpread);
+ writeToGrid(tmpGrid); //calls the method "writeToGrid" to write the new urbanized cells to the output grid
+
+ /*********************************************************************
+ * ROAD
+ *********************************************************************/
- //ROAD GRAVITY
- double max_RG_value = 100.0;
- double rg_value = Math.round((roadGravity/max_RG_value)*((areaWidth + areaHeight)/16));
- double max_search_index = Math.round(4*((int)rg_value*(1+(int)rg_value)));
- statusOut.println("RG-Value:"+rg_value);
- statusOut.println("Max-SearchIndex"+max_search_index);
+ boolean[][] tmpGridRoad = new boolean[inputGrid.getWidth()][inputGrid.getHeight()]; //a temporary raster
+ tmpGridRoad = RoadGrowth(tmpGrid); //calls the method "RoadGrowth" to perform the Road weighted growth
+ int anzRoad = 0; //number of cells urbanized by Road Growth
+ for (int x = 0; x < inputGrid.getWidth();x++)
+ for(int y = 0; y < inputGrid.getHeight();y++){
+ int X = inputGrid.getMinX() + x;
+ int Y = inputGrid.getMinY() + y;
+ if (tmpGridRoad[X][Y]==true){
+ anzRoad++;
+ tmpGrid[X][Y] = true; //write the temporary Road Growth cells to the overall temporary Cell array
+ }
+ }
+ statusOut.println("Number of Road Growth Cells: "+anzRoad);
+ writeToGrid(tmpGrid); //calls the method "writeToGrid" to write the new urbanized cells to the output grid
+
+ outStep.addGrid();
+ int anzGesamt = 0;
+
+ // Write the temporary Grid to the Output Grid
+ for (int y = 1; y < inputGrid.getHeight()-1;y++ ) {
+ for (int x = 1; x < inputGrid.getWidth()-1; x++ ) {
+
+ int X = inputGrid.getMinX() + x;
+ int Y = inputGrid.getMinY() + y;
+
+ if (tmpGrid[x][y] == true)
+ anzGesamt++;
+
+ boolean lebt = outputGrid.getRasterSampleAsFloat(X , Y ) > 0f; //a cell is alive, when it is 1
+ if (tmpGrid[x][y] == false) //if there is nothing in the temporary raster
+ tmpGrid[x][y] = lebt; //take the values from the current output raster
+
- /*****************************************************************
- * DISPERSION and BREED
- *****************************************************************/
+ outputGrid.setRasterSample( tmpGrid[x][y] ? 1f : 0f ,X ,Y); //write the results in the output raster
+ actUrb = (Float)outputGrid.getRasterSample(x,y); //the actual urban extent
+ outStep.getGrid(stepNo-1).setRasterSample(actUrb,x,y); //put the layer in the raster list containing the step results
+ }
+ }
- int p = 0; //Verteile soviel neue Pixel zufällig in geeigneten Bereichen, bis disp_value erreicht ist
+ statusOut.println("Urban pixels at step "+stepNo+": "+anzGesamt);
+
+ System.out.println("Finished step " + (stepNo) + " in "
+ + ((System.currentTimeMillis() - localStartTime)) + " ms\n");
+ localStartTime = System.currentTimeMillis();
+ }
+
+ /**
+ * This function counts the starting individual cells for the urban growth model run.<br>
+ * It only works for a binary classification with urban cells having the value 1 and non-urban
+ * cells the value 0.
+ * @return startAnz
+ */
+ public int countIndividuals(){
+ int startAnz = 0;
+ for (int i = 0; i < inputGrid.getWidth();i++ ) {
+ for (int ii = 0; ii < inputGrid.getHeight(); ii++ ) {
+ float val = inputGrid.getRasterSampleAsFloat(i,ii);
+ if (val == 1.0 ) {
+ val = 1f;
+ startAnz++; //count if value is 1
+ }
+ else val = 0f;
+ }
+ }
+ return startAnz;
+ }
+
+ /**
+ * Calculates the maximum slope from the Slope Raster.
+ * @return slopeMax
+ */
+ public int getSlopeMax(){
+ int slopeMax = 0;
+ for (int s = 0; s < inputGrid.getWidth();s++){
+ for(int ss = 0; ss < inputGrid.getHeight();ss++){
+ float slopeVal = slopeGrid.getRasterSampleAsFloat(s,ss);
+ if (slopeVal > slopeMax){
+ slopeMax = (int) slopeVal; //if the actual slope is larger than the highest measured slope up to now, increase the maximum value to that point
+ }
+ }
+ }
+ return slopeMax;
+
+ }
+
+ /**
+ * Takes a slope value from the slope lookup-table depending on the given cell in the slope raster.
+ * @return slopeDoubleNb
+ */
+ public double getSlopeValue(int X,int Y){
+ int getSlopeNb = (int) slopeGrid.getRasterSampleAsFloat(X, Y); //takes a slope value from the slope raster
+ Double doubleObjNb = (Double)slopeLUT.get(getSlopeNb); //looks for that slope value in the Lookup-Table and takes it as a double number
+ double slopeDoubleNb = doubleObjNb.doubleValue(); //converts the double object into a double value.
+ return slopeDoubleNb; //returns the slope value
+ }
+
+ /**
+ * This is phase 1 of the growth cycle, where spontaneous growth occurs (DISPERSION). Those new cells can turn out to be
+ * new spreading centers by urbanizing neighboring pixels (BREED {@link BreedGrowth}).
+ * @return tmpGridDispBreed
+ */
+ public boolean[][] DispersionGrowth(){
+ //DISPERSION
+ int dispRandX = 0; //x-coordinate for randomly created cell
+ int dispRandY = 0; //y-coordinate for randomly created cell
+ float slopeRandDisp = 0; //random value in order to compare the selected dispersion cell with the slope in that cell
+ int anzDispTreffer = 0; //Dispersion
+ int anzBreedTreffer = 0;
+ boolean[][] tmpGridDispBreed = new boolean[inputGrid.getWidth()][inputGrid.getHeight()]; //a temporary raster
+ int p = 0; //Distribute so many new cells randomly in suitable places, until disp_value is reached.
do{
- dispRandX = Math.round((float) Math.random()*areaWidth); //Zufallsposition in X-Richtung
- dispRandY = Math.round((float) Math.random()*areaHeight); //Zufallsposition in Y-Richtung
+ dispRandX = Math.round((float) Math.random()*areaWidth); //Random position in x-direction
+ dispRandY = Math.round((float) Math.random()*areaHeight); //Random position in y-direction
if ( dispRandX < areaMinX || dispRandY < areaMinY || dispRandX > areaMaxX || dispRandY > areaMaxY ||
- Float.isNaN(outputGrid.getRasterSampleAsFloat(dispRandX,dispRandY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
- continue;
- if (areaRestr.getRasterSampleAsFloat(dispRandX,dispRandY) != 0 || outputGrid.getRasterSampleAsFloat(dispRandX,dispRandY) == 1)
- continue; //wenn in Area Restriction oder wenn schon Siedlung da ist, mach weiter
- slopeRandDisp = (float) Math.random(); //Zufallszahl zum Abgleich mit Slope-Koeffizient
- int getSlope = (int) slopeGrid.getRasterSampleAsFloat(dispRandX,dispRandY); //holt sich den Slope-Wert aus dem Slope-Raster
- Double doubleObj = (Double)slopeLUT.get(getSlope); //holt den Slope-Wert aus dem Lookup-Table (get) und konvertiert in Double
- double slopeDouble = doubleObj.doubleValue(); //konvertiert Double-Objekt in double-Wert
- statusOut.println(getSlope+","+slopeDouble+"----Random: "+slopeRandDisp);
- if(slopeDouble < slopeRandDisp){
- tmpGrid[dispRandX][dispRandY] = true; //true wird ins temporäre Raster geschrieben
- anzDispTreffer++;
- //BREED
- float breedRnd = (float) Math.random()*100;
- int nbBreedX = 0;
- int nbBreedY = 0;
- int breedNb = 0;
- float NbValue = 0f;
- if (tmpGrid[dispRandX][dispRandY] == true && breedRnd < breed)
- breedNb = calculateNeighbors(dispRandX,dispRandY,NbValue);
-
- int RNBreed1 = 0;
- int RNBreed2 = 0;
- float RNBreedSlope = 0f;
-
- if (breedNb >= 2 && tmpGrid[dispRandX][dispRandY] == true){
- int anzBreedTemp = 0;
- int[] nbPossibleBreedUrban = null;
- RNBreed1 = 1 + Math.round((float)Math.random()*(breedNb-1));
- RNBreed2 = 1 + Math.round((float)Math.random()*(breedNb-1));
- if (RNBreed2 == RNBreed1)
- RNBreed2 = 1 + Math.round((float)Math.random()*(breedNb-1));
- for (int cellBreed = 0; cellBreed < NEIGHBOR.length; cellBreed++){
- nbBreedX = dispRandX+NEIGHBOR[cellBreed][0];
- nbBreedY = dispRandY+NEIGHBOR[cellBreed][1];
- if ( nbBreedX < areaMinX || nbBreedY < areaMinY || nbBreedX > areaMaxX || nbBreedY > areaMaxY ||
- Float.isNaN(outputGrid.getRasterSampleAsFloat(nbBreedX,nbBreedY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
- continue;
- if (areaRestr.getRasterSampleAsFloat(nbBreedX,nbBreedY) != 0)
- continue;
- RNBreedSlope = (float)Math.random();
- int getSlopeNb = (int) slopeGrid.getRasterSampleAsFloat(nbBreedX,nbBreedY);
- Double doubleObjNb = (Double)slopeLUT.get(getSlopeNb);
- double slopeDoubleNb = doubleObjNb.doubleValue();
- float breedSample = outputGrid.getRasterSampleAsFloat(nbBreedX,nbBreedY);
- if (breedSample == 0f){
- anzBreedTemp++;
- nbPossibleBreedUrban = new int[] {nbBreedX,nbBreedY,anzBreedTemp};
- if (nbPossibleBreedUrban[2] == RNBreed1 || nbPossibleBreedUrban[2] == RNBreed2 && slopeDoubleNb < RNBreedSlope){
- tmpGrid[nbBreedX][nbBreedY] = true;
- anzBreedTreffer++;
- }
- }
- }
- }
- }
- p++;
-
- } while (p < disp_value); //while, statt for-Schleife, da Überprüfung erst am Ende vorgenommen werden kann
- //am Anfang der Schleife ist noch nicht klar, ob alle Pixel verteilt werden können
- //da ein Teil in Ausschlussflächen etc. landen würde
+ Float.isNaN(outputGrid.getRasterSampleAsFloat(dispRandX,dispRandY)) )
+ continue; //if a cell is outside the raster (NaN), break and continue loop from the beginning
+ if (areaRestr.getRasterSampleAsFloat(dispRandX,dispRandY) != 0 || outputGrid.getRasterSampleAsFloat(dispRandX,dispRandY) == 1)
+ continue; //if a cell is inside an excluded area or already exists, break and continue loop from the beginning
+ slopeRandDisp = (float) Math.random(); //a random slope value between 0.0 and 1.0
+ double slopeDouble = getSlopeValue(dispRandX,dispRandY); //returns the slope value for the cell
+ if(slopeDouble < slopeRandDisp){ //if the slope value of the pixel is smaller than the slope value
+ tmpGridDispBreed[dispRandX][dispRandY] = true; //true is written in the temporary raster
+ anzDispTreffer++; //count number of dispersion cells
+
+ //BREED
+ float breedRnd = (float) Math.random()*100; //Breed Random value
+ if (tmpGridDispBreed[dispRandX][dispRandY] == true && breedRnd < breed){ //if there is a new dispersion cell and you pass the Breed-Test
+ int[][] tmpBreedArray = new int[2][2]; //an array containing the two x and y coordinates of two urbanized cells by breed
+ tmpBreedArray = BreedGrowth(dispRandX,dispRandY); //perform a breed for this cell
+ int x1 = tmpBreedArray[0][0]; //x-coordinate of first cell
+ int y1 = tmpBreedArray[0][1]; //y-coordinate of first cell
+ int x2 = tmpBreedArray[1][0]; //x-coordinate of second cell
+ int y2 = tmpBreedArray[1][1]; //y-coordinate of second cell
+ tmpGridDispBreed[x1][y1] = true; //make the temporary grid true at that position
+ tmpGridDispBreed[x2][y2] = true;
+ anzBreedTreffer += 2; //count the hits
+ }
+ } p++;
+ } while (p < disp_value); //while instead of for-loop, because it can only be checked in the end
+ //if all cells could be distributed, which is not known at the beginning of the loop.
+ //a part of the cells falls in excluded areas, etc.
+ statusOut.println("Dispersion-Treffer: "+anzDispTreffer);
+ statusOut.println("Breed-Treffer: "+anzBreedTreffer);
+ return tmpGridDispBreed; //returns a temporary Array containing the newly urbanized cells by the dispersion and breed growth rules
+ }
- /*********************************************************************
- * EDGE
- *********************************************************************/
+ /**
+ * This is phase 2 of the growth cycle. New spreading centers can induce new growth right in the neighborhood,
+ * which is calles "breed". This method is fired by new dispersion cells (@link DispersionGrowth), as well as
+ * by new road cells ({@link RoadGrowth}).
+ * @param X
+ * @param Y
+ * @return tmpBreedArray
+ */
+ public int[][] BreedGrowth(int X,int Y){
+ boolean[][] tmpGridBreed = new boolean[inputGrid.getWidth()][inputGrid.getHeight()]; //a temporary raster
+ int[][] tmpBreedArray = new int[2][2]; //an array containing the x and y coordinates of two cells
+ int anzBreedTreffer = 0; //Breed
+ int breedNb = calculateNeighbors(X,Y,0f); //calculate number of neighbors of a new spreading center cell
+ int nbBreedX = 0; //x-coordinate of neighbouring cells of new spreading center cell
+ int nbBreedY = 0; //y-coordinate of neighbouring cells of new spreading center cell
+ int RNBreed1 = 0; //1st Random number for breed
+ int RNBreed2 = 0; //2nd Random number for breed
+ float RNBreedSlope = 0f; //Slope value of the randomly selected breed cell
+ if (breedNb >= 2){ //if 2 or more neighbor cells are available around a new dispersion cell
+ int anzBreedTemp = 0; //number of temporary breed cells
+ int[] nbPossibleBreedUrban = null; //Array of possible breed cells
+ RNBreed1 = 1 + Math.round((float)Math.random()*(breedNb-1)); //take the first neighbor cell by random (between 1 and the Sum of neighbor cells)
+ RNBreed2 = 1 + Math.round((float)Math.random()*(breedNb-1)); //take the second neighbor cell by random (between 1 and the Sum of neighbor cells)
+ do{
+ RNBreed2 = 1 + Math.round((float)Math.random()*(breedNb-1));
+ } while (RNBreed2 == RNBreed1);//if the second cell is the same as the first cell try again until the second random number is different from the first
+
+ for (int cellBreed = 0; cellBreed < NEIGHBOR.length; cellBreed++){ //for every cell in the neighborhood...
+ nbBreedX = X+NEIGHBOR[cellBreed][0];
+ nbBreedY = Y+NEIGHBOR[cellBreed][1];
+ if ( nbBreedX < areaMinX || nbBreedY < areaMinY || nbBreedX > areaMaxX || nbBreedY > areaMaxY ||
+ Float.isNaN(outputGrid.getRasterSampleAsFloat(nbBreedX,nbBreedY)) )
+ continue; //if a cell is outside the raster (NaN), break and continue loop from the beginning
+ if (areaRestr.getRasterSampleAsFloat(nbBreedX,nbBreedY) != 0)
+ continue; //if a cell is inside an excluded area, break and continue loop from the beginning
+ RNBreedSlope = (float)Math.random(); //a random slope value between 0.0 and 1.0
+ double slopeDoubleNb = getSlopeValue(nbBreedX,nbBreedY); //returns the slope value for the neighboring cells which are available for breed
+ float breedSample = outputGrid.getRasterSampleAsFloat(nbBreedX,nbBreedY); //takes the value from the input grid
+ if (breedSample == 0f){ //if it is free for urbanization...
+ anzBreedTemp++; //increase the number of temporary breed cells
+ nbPossibleBreedUrban = new int[] {nbBreedX,nbBreedY,anzBreedTemp}; //create a new array containing the x and y coordinates and the number of the breed pixel
+ if (nbPossibleBreedUrban[2] == RNBreed1 || nbPossibleBreedUrban[2] == RNBreed2 && slopeDoubleNb < RNBreedSlope){ //if the cell has the same value as the first or second random value and its slope value is smaller than the random slope value...
+ tmpBreedArray[anzBreedTreffer][0] = nbBreedX; //x-coordinate
+ tmpBreedArray[anzBreedTreffer][1] = nbBreedY; //y-coordinate
+ tmpGridBreed[nbBreedX][nbBreedY] = true; //urbanize the cell in the temporary grid
+ anzBreedTreffer++; //and increase the number of breed cells
+ }
+ }
+ }
+ }
+ return tmpBreedArray;
+ }
+
+
+ /**
+ * This is phase 3 of the growth cycle, where edge growth appears based on the urban pixels that exist at
+ * this time (including the new spontaneous and spreading center pixels).
+ * @return tmpGridSpread
+ */
+ public boolean[][] EdgeGrowth(){
+ boolean[][] tmpGridSpread = new boolean[inputGrid.getWidth()][inputGrid.getHeight()]; //a temporary raster
+ //definitions for neighborhood cells
+ int nbX = 0; // X-Coordinate of a neighboring cell
+ int nbY = 0; // Y-Coordinate of a neighboring cell
+
+ int anzSpreadTreffer = 0; //Number of Spread cells
+
//iterate over all cells
for (int x = 0; x < inputGrid.getWidth(); x++)
- for (int y = 0; y < inputGrid.getHeight(); y++) { //für jede Zelle in x/y-Richtung
+ for (int y = 0; y < inputGrid.getHeight(); y++) { //for every cell in x/y direction...
- int areaMinXadd = areaMinX + x; //Dimensionen des Rasters
- int areaMinYadd = areaMinY + y;
+ int areaMinXadd = areaMinX + x; //x-coordinate cell in the raster
+ int areaMinYadd = areaMinY + y; //y-coordinate cell in the raster
- int anzNachbarn = 0;
- int noNachbarn = 0;
-
+ int anzNachbarn = calculateNeighbors(x,y,1f); //number of urban neighbors
- for (int nbCellIdx = 0; nbCellIdx < NEIGHBOR.length; nbCellIdx++) {
- checkBreakingCommands();
- nbX = x+NEIGHBOR[nbCellIdx][0]; //Nachbarschaft der Zellen
- nbY = y+NEIGHBOR[nbCellIdx][1];
- nbCell = new int[] {nbX,nbY}; //jede Nachbarzelle
- if ( nbX < areaMinX || nbY < areaMinY || nbX > areaMaxX || nbY > areaMaxY ||
- Float.isNaN(outputGrid.getRasterSampleAsFloat(nbX,nbY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
- continue;
- if (areaRestr.getRasterSampleAsFloat(nbX,nbY) != 0)
- continue;
- float rasterSample = outputGrid.getRasterSampleAsFloat(nbX,nbY);
- if (rasterSample > 0f) //ist Nachbarzelle urban (1), wird sie gezählt
- anzNachbarn++;
- if (rasterSample == 0f)
- noNachbarn++;
- }
+ boolean lebt = outputGrid.getRasterSampleAsFloat(areaMinXadd, areaMinYadd ) > 0f; //a cell is alive if it is 1
- boolean lebt = outputGrid.getRasterSampleAsFloat(areaMinXadd , areaMinYadd ) > 0f; //eine Zelle lebt, wenn sie 1 ist
-
- //hier ist die Abfrage wieviele Nachbarzellen am Leben sind
- //daraus ergibt sich, ob im tmpGrid die entsprechende Zelle
- //true oder false ist
-
- float SpR = (float) Math.random()*100; //eine Zufallszahl zwischen 0 und 1
- int RN = 0; //hier wird eine Integer-Zufallszahl reingeschrieben
-
- if (lebt && (anzNachbarn>=2) && (SpR < spread) && (noNachbarn >=1)) { //wenn eine Zelle lebt, mindestens 2 lebende Nachbarzellen hat, der Spread-Koeffizient größer als die für die Zelle berechnete Zufallszahl und mindestens einen nicht lebenden Nachbarn hat
- int anzTemp = 0;
- int[] nbPossibleUrban = null;
- RN = 1 + Math.round((float)Math.random()*(noNachbarn-1));
+ int SpR = Math.round((float) Math.random()*100); //a random number to compare with the spread coefficient
+ if (lebt && (anzNachbarn>=2) && (SpR < spread) && (anzNachbarn < 8)) { //if a cell is alive, it has more or equal than two urban neighbors and less than 8 urban neighbors (at least 1 non-urban neighbor) and we pass the spread coefficient test...
+ int anzTemp = 0; //temporary possible cells for urbanization
+ int[] nbPossibleUrban = null; //array with coordinates of possible cells for urbanization
+ //int RN = 1 + Math.round((float)Math.random()*(8-anzNachbarn-1)); //this is an option to distribute the ranom number only between the possible cells for urbanization
+ int RN = (int) Math.round(8*Math.random()); //a random number between 0 and 8
float RNEdgeSlope = 0;
- int nbUrbanX = 0;
- int nbUrbanY = 0;
- for (int nbCellChange = 0; nbCellChange < NEIGHBOR.length; nbCellChange++){ //dann starte eine Schleife
+ for (int nbCellChange = 0; nbCellChange < NEIGHBOR.length; nbCellChange++){ //loop over all neighbor cells
checkBreakingCommands();
nbX = x+NEIGHBOR[nbCellChange][0];
nbY = y+NEIGHBOR[nbCellChange][1];
if ( nbX < areaMinX || nbY < areaMinY || nbX > areaMaxX || nbY > areaMaxY ||
- Float.isNaN(outputGrid.getRasterSampleAsFloat(nbX,nbY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
- continue;
+ Float.isNaN(outputGrid.getRasterSampleAsFloat(nbX,nbY)))
+ continue; //if a cell is outside the raster (NaN), break and continue loop from the beginning
if (areaRestr.getRasterSampleAsFloat(nbX,nbY) != 0)
- continue;
- RNEdgeSlope = (float)Math.random();
- int getSlopeNb = (int) slopeGrid.getRasterSampleAsFloat(nbX,nbY);
- Double doubleObjNb = (Double)slopeLUT.get(getSlopeNb);
- double slopeDoubleNb = doubleObjNb.doubleValue();
- float rasterSample = outputGrid.getRasterSampleAsFloat(nbX,nbY); //holt die Werte aus den jeweiligen Nachbarzellen
- if (rasterSample == 0f){ //wenn der Wert 0 ist
- anzTemp++; //wird Anzahl der möglichen Zellen erhöht
- nbPossibleUrban = new int[] {nbX,nbY,anzTemp}; //Koordinaten und Nummern dieser Zellen werden in Array geschrieben
- int urbanNbTemp = 0;
- float NbValueEdge = 1f;
- if (nbPossibleUrban[2] == RN){ //wenn Nummer im "PossibleUrban"-Array der Zufallszahl entspricht, die zwischen 1 und Anzahl der möglichen Zellen liegt...
- //damit die Städte nicht zu sehr "ausfransen" steht eine Zelle nur zur Umwandlung zur Verfügung, wenn auch sie mind. 2 urbane Nachbarn hat
- urbanNbTemp = calculateNeighbors(nbX,nbY,NbValueEdge);
- if (urbanNbTemp >= 2 && tmpGrid[nbX][nbY]==false && slopeDoubleNb < RNEdgeSlope){
- tmpGrid[nbX][nbY] = true; //wird true ins temporäre Raster geschrieben
- anzSpreadTreffer++;
+ continue; //if a cell is inside an excluded area, break and continue loop from the beginning
+ RNEdgeSlope = (float)Math.random(); //a random number to be compared with the slope value
+ double slopeDoubleNb = getSlopeValue(nbX,nbY); //returns the slope value for the neighboring cells which are available for breed
+ float rasterSample = outputGrid.getRasterSampleAsFloat(nbX,nbY); //takes the value from the input gridn
+ if (rasterSample == 0f){ //if the value is 0 and thus is possible for urbanization
+ anzTemp++; //count it
+ nbPossibleUrban = new int[] {nbX,nbY,anzTemp}; //write it with its coordinates in an array
+ //float NbValueEdge = 1f;
+ if (nbPossibleUrban[2] == RN){ //if the number in the "possible for urbanization" array is the same as the random number...
+ //int urbanNbTemp = calculateNeighbors(nbX,nbY,NbValueEdge); //to reduce the effect of edge growth here could be included an option that allows only growth when a new urban cell has at least 2 urban neighbors
+ if (tmpGridSpread[nbX][nbY]==false && slopeDoubleNb < RNEdgeSlope){ // if the cell is non-urban and it passes the slope test //urbanNbTemp >= 2 &&
+ tmpGridSpread[nbX][nbY] = true; //write it in the temporary raster
+ anzSpreadTreffer++; //count the hits
}
}
}
- nbCell = new int[] {nbX,nbY,(int) rasterSample};
}
}
- if (anzNachbarn>0) anyBodyAlive = true;
}
+ return tmpGridSpread; //returns the temporary array
+ }
+
+ /**
+ * This is phase 4 of the growth cycle, where growth along roads appears. Every newly developed cell can induce road growth.
+ * Therefore for a defined number of new cells (by the breed-coeffient) the algorithm looks for a road in the neighborhood.
+ * If the new cell is located directly on a road, the algorithm starts a "road walk" ({@link roadWalk}), and moves a new cell along the road
+ * to a defined distance. If the new cell is not on a road, it looks for a road in a defined neighborhood (by {@code rg_value}).
+ * If a road is found, it starts a "road walk" from there.
+ * @param tmpGrid
+ * @return tmpGridRoad
+ */
+ public boolean[][] RoadGrowth(boolean[][] tmpGrid){
+ boolean[][] tmpGridRoad = new boolean[inputGrid.getWidth()][inputGrid.getHeight()]; //a temporary raster
+ int anzGesamt = countTempUrbanCells(tmpGrid); //number of urban cells in the temporary cell array
+ int anzRoadTreffer = 0;
+ int[] cellValue = null; //array of cell values
+ int RSearchRoad = 0; //Random Road Search Index
+ int r = 1; //number between 1 and the disp-Value, whih is increased during the follwing while-loop. It determines how many pixels are selected randomly for a possible road trip
- /*********************************************************************
- * ROAD
- *********************************************************************/
-
- int anzGesamt = 0;
- int[] cellValue = null;
-
- //For-Schleife zählt alle als true markierten Zellen im Temp-Raster
- for (int x = 0; x < inputGrid.getWidth();x++)
- for(int y = 0; y < inputGrid.getHeight();y++){
- int X = inputGrid.getMinX() + x;
- int Y = inputGrid.getMinY() + y;
- if (tmpGrid[X][Y]==true){
- anzGesamt++;
- }
- }
-
- int RSearchRoad = 0;
- int r = 1; //Verteile soviel neue Pixel zufällig in geeigneten Bereichen, bis disp_value erreicht ist
-
- Rectangle gridBounds = new Rectangle(0, 0, inputGrid.getWidth(), inputGrid.getHeight()); //ein Rechteck wird definiert
do{
- RSearchRoad = Math.round((float)Math.random()*anzGesamt); //Zufallszahl zwischen 1 und Anzahl aller bisher neu hinzugekommener Pixel
- int anzTruePixels = 0;
+ RSearchRoad = Math.round((float)Math.random()*anzGesamt); //a random value between 1 and the total amount of newly urbanized pixels
+ int anzTruePixels = 0;
int roadNeighborhoodRange = 0;
int RSearchNbRoad = 0;
- for (int x = 0; x < inputGrid.getWidth();x++){ //gesamtes Raster wird durchsucht
+ for (int x = 0; x < inputGrid.getWidth();x++){ //for every cell in the raster...
for(int y = 0; y < inputGrid.getHeight();y++){
- int X = inputGrid.getMinX() + x;
- int Y = inputGrid.getMinY() + y;
- if (tmpGrid[X][Y]==true){
- anzTruePixels++; //wird true-Pixel gefunden, wird anzTruePixels hochgezählt
- cellValue = new int[] {X,Y,anzTruePixels}; //und Koordinaten in Array geschrieben
- int tempRoadCell[] = null;
- int tempNbRoadCell[] = null;
- if (cellValue[2] == RSearchRoad){
- //statusOut.println(cellValue[0]+","+cellValue[1]+","+cellValue[2]);
- //statusOut.println(r+","+RSearchRoad);
- r++;
- //JETZT NACH STRAßE SUCHEN!!
- float roadValue = roadGrid.getRasterSampleAsFloat(X,Y);
- statusOut.println(roadValue);
- if (roadValue > 0.0){
- tempRoadCell = new int[] {X,Y};
- statusOut.println("Strasse in Entfernung 0: "+tempRoadCell[0]+","+tempRoadCell[1]);
- //roadWalk(tempRoadCell[0],tempRoadCell[1]);
- int nbCellNew[] = roadWalk(tempRoadCell[0],tempRoadCell[1]);
- if(nbCellNew != null){
- tmpGrid[nbCellNew[0]][nbCellNew[1]] = true;
- statusOut.println(nbCellNew.length);
- statusOut.println("Neue Zelle: "+nbCellNew[0]+","+nbCellNew[1]);
- statusOut.println("++++++++++++++++++++++++++++++++++++++++");
- float nbRoadBreed = 0f;
- int nbRoadBreedNeighbors = 0;
- nbRoadBreedNeighbors = calculateNeighbors(nbCellNew[0],nbCellNew[1],nbRoadBreed);
- int RNRoadBreed1 = 0;
- int RNRoadBreed2 = 0;
- int nbRoadBreedX = 0;
- int nbRoadBreedY = 0;
- int anzRoadBreedTreffer = 0;
-
- if (nbRoadBreedNeighbors >= 2){
- int anzBreedTemp = 0;
- int[] nbPossibleBreedUrban = null;
- RNRoadBreed1 = 1 + Math.round((float)Math.random()*(nbRoadBreedNeighbors-1));
- RNRoadBreed2 = 1 + Math.round((float)Math.random()*(nbRoadBreedNeighbors-1));
- float RNRoadBreedSlope = 0f;
-
- if (RNRoadBreed2 == RNRoadBreed1)
- RNRoadBreed2 = 1 + Math.round((float)Math.random()*(nbRoadBreedNeighbors-1));
- for (int cellBreed = 0; cellBreed < NEIGHBOR.length; cellBreed++){
- nbRoadBreedX = nbCellNew[0]+NEIGHBOR[cellBreed][0];
- nbRoadBreedY = nbCellNew[1]+NEIGHBOR[cellBreed][1];
- if ( nbRoadBreedX < areaMinX || nbRoadBreedY < areaMinY || nbRoadBreedX > areaMaxX || nbRoadBreedY > areaMaxY ||
- Float.isNaN(outputGrid.getRasterSampleAsFloat(nbRoadBreedX,nbRoadBreedY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
- continue;
- if (areaRestr.getRasterSampleAsFloat(nbRoadBreedX,nbRoadBreedY) != 0)
- continue;
- RNRoadBreedSlope = (float)Math.random();
- int getSlopeNb = (int) slopeGrid.getRasterSampleAsFloat(nbRoadBreedX,nbRoadBreedY);
- Double doubleObjNb = (Double)slopeLUT.get(getSlopeNb);
- double slopeDoubleNb = doubleObjNb.doubleValue();
- float breedSample = outputGrid.getRasterSampleAsFloat(nbRoadBreedX,nbRoadBreedY);
- if (breedSample == 0f){
- anzBreedTemp++;
- nbPossibleBreedUrban = new int[] {nbRoadBreedX,nbRoadBreedY,anzBreedTemp};
- if (nbPossibleBreedUrban[2] == RNRoadBreed1 || nbPossibleBreedUrban[2] == RNRoadBreed2 && slopeDoubleNb < RNRoadBreedSlope){
- tmpGrid[nbRoadBreedX][nbRoadBreedY] = true;
- anzRoadBreedTreffer++;
- statusOut.println("Road-Breed-Treffer: "+anzRoadBreedTreffer);
- }
- }
- }
-
-
- }
-
+ int X = inputGrid.getMinX() + x; //x-coordinate cell in the raster
+ int Y = inputGrid.getMinY() + y; //y-coordinate cell in the raster
+ if (tmpGrid[X][Y]==true){ //if a new urbanized cell is found
+ anzTruePixels++; //count the number of urban pixels, and...(and this is different to "countTempUrbanCells")
+ cellValue = new int[] {X,Y,anzTruePixels}; //write them with their coordinates in an array
+ int tempRoadCell[] = null; //an array of temporary road cells
+ int tempNbRoadCell[] = null; //an array of temporary neighboring cells of these road cells
+ if (cellValue[2] == RSearchRoad){ //randomly select a growth pixel to start search for road (by comparing the cell number with the generated random number between 1 and total amount of new cells)
+ r++; //increase r, because a potential road trip pixel has been selected
+ float roadValue = roadGrid.getRasterSampleAsFloat(X,Y); //take the value from the road map for that pixel
+ if (roadValue > 0.0){ //if the value is greater than 0 and thus is a road...
+ tempRoadCell = new int[] {X,Y}; //add its coordinates to the temporary road grid
+ //statusOut.println("Strasse in Entfernung 0: "+tempRoadCell[0]+","+tempRoadCell[1]);
+ int nbCellNew[] = roadWalk(tempRoadCell[0],tempRoadCell[1]); //perform a road walk
+ if(nbCellNew != null){ //if the result of the road walk is positive,...
+ tmpGridRoad[nbCellNew[0]][nbCellNew[1]] = true; //place a new urban pixel in the temporary Grid
+ anzRoadTreffer++;
+ int[][] tmpBreedArray = new int[2][2]; //an array containing the x and y coordinates of two breed cells
+ tmpBreedArray = BreedGrowth(nbCellNew[0],nbCellNew[1]); //this new urban cell can act as a new spreading center:
+ int x1 = tmpBreedArray[0][0]; //x-coordinate of first cell
+ int y1 = tmpBreedArray[0][1]; //y-coordinate of first cell
+ int x2 = tmpBreedArray[1][0]; //x-coordinate of second cell
+ int y2 = tmpBreedArray[1][1]; //y-coordinate of second cell
+ tmpGridRoad[x1][y1] = true; //make the temporary grid true at that position
+ tmpGridRoad[x2][y2] = true;
+ anzRoadTreffer += 2;
} else{
- statusOut.println("Keine neue Zelle gefunden");
+ // statusOut.println("No new RoadBreedCells found directly");
}
- } else{
+ } else{ //if the selected pixel has not been a road pixel search in the neighborhood for a road
int anzRoadNb = 0;
- //HIER MIT FOR SCHLEIFE RECHTECK WACHSEN LASSEN!!!
+ //With a loop look in the neighborhood for a road in an increasing radius until you reach the road gravity value
for (int roadSearch = 0; roadSearch <= rg_value; roadSearch++){
- if (anzRoadNb > 0)
+ if (anzRoadNb > 0) //if a road is found break and continue from the beginning (the next loops will end here as well until it stops when rg_value ist reached)
continue;
for (int nbRoadCellsX = X - roadNeighborhoodRange; nbRoadCellsX <= X + roadNeighborhoodRange; nbRoadCellsX++){
- for (int nbRoadCellsY = Y - roadNeighborhoodRange; nbRoadCellsY <= Y + roadNeighborhoodRange; nbRoadCellsY++){
- if (gridBounds.contains(nbRoadCellsX, nbRoadCellsY))
- if ( nbRoadCellsX < areaMinX || nbRoadCellsY < areaMinY || nbRoadCellsX > areaMaxX || nbRoadCellsY > areaMaxY ||
- Float.isNaN(outputGrid.getRasterSampleAsFloat(nbRoadCellsX,nbRoadCellsY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
- continue;
- if (areaRestr.getRasterSampleAsFloat(nbRoadCellsX,nbRoadCellsY) != 0)
- continue;
- float roadValueNb = roadGrid.getRasterSampleAsFloat(nbRoadCellsX,nbRoadCellsY);
- if (roadValueNb > 0f){
- anzRoadNb++;
- }
- //statusOut.println("Strasse in Entfernung 1: "+anzRoadNb+","+nbRoadCellsX+","+nbRoadCellsY);
+ for (int nbRoadCellsY = Y - roadNeighborhoodRange; nbRoadCellsY <= Y + roadNeighborhoodRange; nbRoadCellsY++){ //increase the neighborhood in every loop
+ if ( nbRoadCellsX < areaMinX || nbRoadCellsY < areaMinY || nbRoadCellsX > areaMaxX || nbRoadCellsY > areaMaxY ||
+ Float.isNaN(outputGrid.getRasterSampleAsFloat(nbRoadCellsX,nbRoadCellsY)) )
+ continue; //if a cell is outside the raster (NaN), break and continue loop from the beginning
+ float roadValueNb = roadGrid.getRasterSampleAsFloat(nbRoadCellsX,nbRoadCellsY); //take the value from the road map for that pixel
+ if (roadValueNb > 0f){ //if the value is greater than 0 and thus is a road...
+ anzRoadNb++; //increase the number of road neighbors
+ }
}
}
- roadNeighborhoodRange++;
- RSearchNbRoad = Math.round((float)Math.random()*anzRoadNb);
- //statusOut.println("--> Zyklus "+roadNeighborhoodRange+"Nachbarn: "+anzRoadNb);
- //statusOut.println(RSearchNbRoad);
- int anzTempRoadNb = 0;
+ roadNeighborhoodRange++; //increase the road neighborhood range
+ RSearchNbRoad = Math.round((float)Math.random()*anzRoadNb); //a random value between 0 and the number of road neighbors
+ int anzTempRoadNb = 0; //number of temporary road neighbors
for (int nbRoadCellsX = X - roadNeighborhoodRange; nbRoadCellsX <= X + roadNeighborhoodRange; nbRoadCellsX++){
- for (int nbRoadCellsY = Y - roadNeighborhoodRange; nbRoadCellsY <= Y + roadNeighborhoodRange; nbRoadCellsY++){
- statusOut.println("TEST-ROAD: "+nbRoadCellsX+","+nbRoadCellsY);
- if (gridBounds.contains(nbRoadCellsX, nbRoadCellsY))
+ for (int nbRoadCellsY = Y - roadNeighborhoodRange; nbRoadCellsY <= Y + roadNeighborhoodRange; nbRoadCellsY++){ //again increase the neighborhood in every loop
+ // statusOut.println("TEST-ROAD: "+nbRoadCellsX+","+nbRoadCellsY);
if ( nbRoadCellsX < areaMinX || nbRoadCellsY < areaMinY || nbRoadCellsX > areaMaxX || nbRoadCellsY > areaMaxY ||
Float.isNaN(outputGrid.getRasterSampleAsFloat(nbRoadCellsX,nbRoadCellsY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
- continue;
- if (areaRestr.getRasterSampleAsFloat(nbRoadCellsX,nbRoadCellsY) != 0)
- continue;
- float roadValueNbTemp = roadGrid.getRasterSampleAsFloat(nbRoadCellsX,nbRoadCellsY);
- if (roadValueNbTemp > 0f){
- anzTempRoadNb++;
- tempNbRoadCell = new int[] {nbRoadCellsX,nbRoadCellsY,anzTempRoadNb};
- if (tempNbRoadCell[2]==RSearchNbRoad){
- //statusOut.println("Treffer: "+tempNbRoadCell[0]+","+tempNbRoadCell[1]+","+tempNbRoadCell[2]);
- tempRoadCell = tempNbRoadCell;
- statusOut.println("Strasse in Entfernung "+roadSearch+": "+tempRoadCell[0]+","+tempRoadCell[1]+","+tempRoadCell[2]);
- //roadWalk(tempRoadCell[0],tempRoadCell[1]);
- int nbCellNew[] = roadWalk(tempRoadCell[0],tempRoadCell[1]);
- if(nbCellNew != null){
- tmpGrid[nbCellNew[0]][nbCellNew[1]] = true;
- statusOut.println(nbCellNew.length);
- statusOut.println("Neue Zelle: "+nbCellNew[0]+","+nbCellNew[1]);
- statusOut.println("++++++++++++++++++++++++++++++++++++++++");
-
- float nbRoadBreed = 0f;
- int nbRoadBreedNeighbors = 0;
- nbRoadBreedNeighbors = calculateNeighbors(nbCellNew[0],nbCellNew[1],nbRoadBreed);
- int RNRoadBreed1 = 0;
- int RNRoadBreed2 = 0;
- int nbRoadBreedX = 0;
- int nbRoadBreedY = 0;
- int anzRoadBreedTreffer = 0;
-
- if (nbRoadBreedNeighbors >= 2){
- int anzBreedTemp = 0;
- int[] nbPossibleBreedUrban = null;
- RNRoadBreed1 = 1 + Math.round((float)Math.random()*(nbRoadBreedNeighbors-1));
- RNRoadBreed2 = 1 + Math.round((float)Math.random()*(nbRoadBreedNeighbors-1));
- float RNRoadBreedSlope = 0f;
- if (RNRoadBreed2 == RNRoadBreed1)
- RNRoadBreed2 = 1 + Math.round((float)Math.random()*(nbRoadBreedNeighbors-1));
- for (int cellBreed = 0; cellBreed < NEIGHBOR.length; cellBreed++){
- nbRoadBreedX = nbCellNew[0]+NEIGHBOR[cellBreed][0];
- nbRoadBreedY = nbCellNew[1]+NEIGHBOR[cellBreed][1];
- if ( nbRoadBreedX < areaMinX || nbRoadBreedY < areaMinY || nbRoadBreedX > areaMaxX || nbRoadBreedY > areaMaxY ||
- Float.isNaN(outputGrid.getRasterSampleAsFloat(nbRoadBreedX,nbRoadBreedY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
- continue;
- if (areaRestr.getRasterSampleAsFloat(nbRoadBreedX,nbRoadBreedY) != 0)
- continue;
- RNRoadBreedSlope = (float)Math.random();
- int getSlopeNb = (int) slopeGrid.getRasterSampleAsFloat(nbRoadBreedX,nbRoadBreedY);
- Double doubleObjNb = (Double)slopeLUT.get(getSlopeNb);
- double slopeDoubleNb = doubleObjNb.doubleValue();
- float breedSample = outputGrid.getRasterSampleAsFloat(nbRoadBreedX,nbRoadBreedY);
- if (breedSample == 0f){
- anzBreedTemp++;
- nbPossibleBreedUrban = new int[] {nbRoadBreedX,nbRoadBreedY,anzBreedTemp};
- if (nbPossibleBreedUrban[2] == RNRoadBreed1 || nbPossibleBreedUrban[2] == RNRoadBreed2 && slopeDoubleNb < RNRoadBreedSlope){
- tmpGrid[nbRoadBreedX][nbRoadBreedY] = true;
- anzRoadBreedTreffer++;
- statusOut.println("Road-Breed-Treffer: "+anzRoadBreedTreffer);
- }
- }
- }
-
-
- }
+ continue; //if a cell is outside the raster (NaN), break and continue loop from the beginning
+ float roadValueNbTemp = roadGrid.getRasterSampleAsFloat(nbRoadCellsX,nbRoadCellsY); //take the road value from that pixel
+ if (roadValueNbTemp > 0f){ //if the value is greater than 0 and thus is a road...
+ anzTempRoadNb++; //increase the number of temporary road neighbors
+ tempNbRoadCell = new int[] {nbRoadCellsX,nbRoadCellsY,anzTempRoadNb}; //build an array of neighboring road cells with its coordinates
+ if (tempNbRoadCell[2]==RSearchNbRoad){ //check the position in that array with the random number
+ tempRoadCell = tempNbRoadCell; //the main temporary road cell is moved to this position
+ //statusOut.println("Strasse in Entfernung "+roadSearch+": "+tempRoadCell[0]+","+tempRoadCell[1]+","+tempRoadCell[2]);
+ int nbCellNew[] = roadWalk(tempRoadCell[0],tempRoadCell[1]); //perform a road walk
+ if(nbCellNew != null){ //if the result of the road walk is positive,...
+ tmpGridRoad[nbCellNew[0]][nbCellNew[1]] = true; //place a new urban cell in the temporary grid
+ anzRoadTreffer++;
+ int[][] tmpBreedArray = new int[2][2];
+ tmpBreedArray = BreedGrowth(nbCellNew[0],nbCellNew[1]);
+ int x1 = tmpBreedArray[0][0];
+ int y1 = tmpBreedArray[0][1];
+ int x2 = tmpBreedArray[1][0];
+ int y2 = tmpBreedArray[1][1];
+ tmpGridRoad[x1][y1] = true;
+ tmpGridRoad[x2][y2] = true;
+ anzRoadTreffer += 2;
} else{
- statusOut.println("Keine neue Zelle gefunden");
+ // statusOut.println("No new road cell found after road search.");
}
}
}
@@ -660,142 +733,98 @@
}
} while (r <= breed);
-
- statusOut.println("Spread-Treffer: "+anzSpreadTreffer);
- statusOut.println("Dispersion-Treffer: "+anzDispTreffer);
- statusOut.println("Breed-Treffer: "+anzBreedTreffer);
- statusOut.println("Treffer gesamt: "+anzGesamt);
-
- outStep.addGrid();
-
-
- // TempGrid auf das echte Grid schreiben
- for (int y = 1; y < inputGrid.getHeight()-1;y++ ) {
- for (int x = 1; x < inputGrid.getWidth()-1; x++ ) {
-
- int X = inputGrid.getMinX() + x;
- int Y = inputGrid.getMinY() + y;
-
- boolean lebt = outputGrid.getRasterSampleAsFloat(X , Y ) > 0f; //eine Zelle lebt, wenn sie 1 ist
- if (tmpGrid[x][y] == false) //wenn im temporären Raster nichts drinsteht...
- tmpGrid[x][y] = lebt; //wird der Wert aus dem Ausgangsraster übernommen
-
-
- outputGrid.setRasterSample( tmpGrid[x][y] ? 1f : 0f ,X ,Y);
- actUrb = (Float)outputGrid.getRasterSample(x,y);
- outStep.getGrid(stepNo-1).setRasterSample(actUrb,x,y);
- }
- }
-
-
- if (!anyBodyAlive) {
- stepCount = stepNo;
- statusOut.println("Lebt keiner mehr... höre hier auf!");
- }
-
-
- System.out.println("Finished step " + (stepNo) + " in "
- + ((System.currentTimeMillis() - localStartTime)) + " ms\n");
- localStartTime = System.currentTimeMillis();
+ statusOut.println("Road-Treffer: "+anzRoadTreffer);
+ return tmpGridRoad;
}
- private int[] roadWalk(int X,int Y){
-// statusOut.println(X+","+Y);
- boolean end_of_road;
- end_of_road = false;
- int run = 0;
- int run_value = 0;
- int[] nbCellNew = null;
- int[] nbCellTemp = null;
- while(!end_of_road){
- end_of_road = true;
- int nbRoadX = 0;
+ /**
+ * This method performs a walk along a road starting from an initial cell with the coordinates X, Y.
+ * It returns the position of the final cell after the road walk, which than can start a new urbanization.
+ * @param X
+ * @param Y
+ * @return nbCellNew
+ */
+ public int[] roadWalk(int X,int Y){
+ boolean end_of_road = false; //start with the assumption that the end of the road trip is not completed yet
+ int run = 0; //distance a cell is moving
+ int run_value = 0; //maximum moving distance
+ int[] nbCellNew = null; //Array containing the coordinates of the new urbanized cells after the road walk
+ int[] nbCellTemp = null; //Array containing the neighbors of the end cell
+ while(!end_of_road){ //until the end of the road is not reached...
+ end_of_road = true; //say that this is so
+ int nbRoadX = 0; //neighborhood of the cell
int nbRoadY = 0;
- int areaMinX = inputGrid.getMinX(); //Dimensionen des Rasters
+ int areaMinX = inputGrid.getMinX(); //raster dimensions
int areaMinY = inputGrid.getMinY();
int areaMaxX = inputGrid.getMinX() + inputGrid.getWidth() - 1;
int areaMaxY = inputGrid.getMinY() + inputGrid.getHeight() - 1;
- int roadNb = 0;
- int roadNbTemp = 0;
- int RN = 0;
+ int roadNb = 0; //number of neighboring cells
+ int roadNbTemp = 0; //number of neighboring cells
+ int RN = 0; //a random number
- int[] nbCell = null;
- for (int nbRoadCells = 0; nbRoadCells < NEIGHBOR.length; nbRoadCells++){
- nbRoadX = X+NEIGHBOR[nbRoadCells][0];
+ int[] nbCell = null; //Array containing a neighboring cell
+ for (int nbRoadCells = 0; nbRoadCells < NEIGHBOR.length; nbRoadCells++){ //for every neighbor of the starting cell...
+ nbRoadX = X+NEIGHBOR[nbRoadCells][0];
nbRoadY = Y+NEIGHBOR[nbRoadCells][1];
if ( nbRoadX < areaMinX || nbRoadY < areaMinY || nbRoadX > areaMaxX || nbRoadY > areaMaxY ||
- Float.isNaN(outputGrid.getRasterSampleAsFloat(nbRoadX,nbRoadY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
- continue;
- //if (areaRestr.getRasterSampleAsFloat(nbRoadX,nbRoadY) != 0)
- // continue;
- float roadSample = roadGrid.getRasterSampleAsFloat(nbRoadX,nbRoadY);
- if (roadSample > 0f)
- roadNb++;
+ Float.isNaN(outputGrid.getRasterSampleAsFloat(nbRoadX,nbRoadY)) )
+ continue; //if a cell is outside the raster (NaN), break and continue loop from the beginning
+ float roadSample = roadGrid.getRasterSampleAsFloat(nbRoadX,nbRoadY); //take the value
+ if (roadSample > 0f) //if a road is present (>1),
+ roadNb++; //count it
}
- // statusOut.println("Nachbarn von temporaerer Strassenzelle: "+roadNb);
- if (roadNb > 0){
- RN = 1 + Math.round((float)Math.random()*(roadNb-1));
+ if (roadNb > 0){ //if neighbors are available
+ RN = 1 + Math.round((float)Math.random()*(roadNb-1)); //select a random one
- for (int nbRoadCells = 0; nbRoadCells < NEIGHBOR.length; nbRoadCells++){
+ for (int nbRoadCells = 0; nbRoadCells < NEIGHBOR.length; nbRoadCells++){ //for every neighbor of the starting cell...
nbRoadX = X+NEIGHBOR[nbRoadCells][0];
nbRoadY = Y+NEIGHBOR[nbRoadCells][1];
if ( nbRoadX < areaMinX || nbRoadY < areaMinY || nbRoadX > areaMaxX || nbRoadY > areaMaxY ||
- Float.isNaN(outputGrid.getRasterSampleAsFloat(nbRoadX,nbRoadY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
- continue;
- float roadSample = roadGrid.getRasterSampleAsFloat(nbRoadX,nbRoadY);
- if (roadSample > 0f){
- roadNbTemp++;
- nbCell = new int[] {nbRoadX,nbRoadY,roadNbTemp};
- if (nbCell[2] == RN){
- statusOut.println("Nachbarzelle gefunden: "+nbCell[0]+","+nbCell[1]+","+nbCell[2]);
- end_of_road = false;
- run++;
+ Float.isNaN(outputGrid.getRasterSampleAsFloat(nbRoadX,nbRoadY)) )
+ continue; //if a cell is outside the raster (NaN), break and continue loop from the beginning
+ float roadSample = roadGrid.getRasterSampleAsFloat(nbRoadX,nbRoadY); //take the value
+ if (roadSample > 0f){ //if a road is present (>1),
+ roadNbTemp++; //count it
+ nbCell = new int[] {nbRoadX,nbRoadY,roadNbTemp}; //write it in an array
+ if (nbCell[2] == RN){ //if the number in the array is the same as the randomly selected number
+ end_of_road = false; //the end of the road is not reached
+ run++; //increase the run value
X = nbRoadX;
Y = nbRoadY;
- float roadSample2 = roadGrid.getRasterSampleAsFloat(X,Y);
- run_value = (int) (roadSample2 / 100 * disp);
- // statusOut.println("Run: "+run);
- // statusOut.println("Run_Value: "+run_value);
- // statusOut.println(X+","+Y+","+roadSample2);
- if (run > run_value){
- end_of_road = true;
- // statusOut.println("Endzelle erreicht!! Run:"+run+"RunValue: "+run_value);
- float NbValue = 0f;
- int Nb = calculateNeighbors(X,Y,NbValue);
- // statusOut.println("moegliche Nachbarzellen nach RoadWalk: "+Nb);
- RN = 1 + Math.round((float)Math.random()*(Nb-1));
- // statusOut.println("Random: "+RN);
- if (Nb > 0){
+ float roadSample2 = roadGrid.getRasterSampleAsFloat(X,Y); //take the value of the road
+ run_value = (int) (roadSample2 / 100 * disp); //calculate how far the cell can be moved along the road
+ if (run > run_value){ //if the run-value exceeds the maximum value...
+ end_of_road = true; //end the road walk
+ int Nb = calculateNeighbors(X,Y,0f); //find the neighbors of the cell found
+ RN = 1 + Math.round((float)Math.random()*(Nb-1)); //select a random number between 1 and the number of neighbors
+ if (Nb > 0){ //if a neighbor is found...
int nbUrbanizeX = 0;
int nbUrbanizeY = 0;
int NbTemp = 0;
float RNRoadSlope = 0f;
- // statusOut.println(X+","+Y);
- for (int urbanizeCells = 0; urbanizeCells < NEIGHBOR.length; urbanizeCells++){
+ for (int urbanizeCells = 0; urbanizeCells < NEIGHBOR.length; urbanizeCells++){ //look at every neighbor cell
nbUrbanizeX = X+NEIGHBOR[urbanizeCells][0];
nbUrbanizeY = Y+NEIGHBOR[urbanizeCells][1];
if ( nbUrbanizeX < areaMinX || nbUrbanizeY < areaMinY || nbUrbanizeX > areaMaxX || nbUrbanizeY > areaMaxY ||
- Float.isNaN(outputGrid.getRasterSampleAsFloat(nbUrbanizeX,nbUrbanizeY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
- continue;
+ Float.isNaN(outputGrid.getRasterSampleAsFloat(nbUrbanizeX,nbUrbanizeY)) )
+ continue; //if a cell is outside the raster (NaN), break and continue loop from the beginning
if (areaRestr.getRasterSampleAsFloat(nbUrbanizeX,nbUrbanizeY) != 0)
- continue;
- float rasterSample = outputGrid.getRasterSampleAsFloat(nbUrbanizeX,nbUrbanizeY);
- RNRoadSlope = (float)Math.random();
- int getSlopeNb = (int) slopeGrid.getRasterSampleAsFloat(nbUrbanizeX,nbUrbanizeY);
- Double doubleObjNb = (Double)slopeLUT.get(getSlopeNb);
- double slopeDoubleNb = doubleObjNb.doubleValue();
- if (rasterSample == 0f){
- NbTemp++;
- nbCellTemp = new int[] {nbUrbanizeX,nbUrbanizeY,NbTemp};
- if (nbCellTemp[2] == RN && slopeDoubleNb < RNRoadSlope){
- nbCellNew = new int[] {nbCellTemp[0],nbCellTemp[1],nbCellTemp[2]};
+ continue; //if a cell is inside an excluded area, break and continue loop from the beginning
+ float rasterSample = outputGrid.getRasterSampleAsFloat(nbUrbanizeX,nbUrbanizeY); //take the raster value
+ RNRoadSlope = (float)Math.random(); //generate a random number in order to compare it with the slope
+ double slopeDoubleNb = getSlopeValue(nbUrbanizeX,nbUrbanizeY); //returns the slope value for the neighboring cells which are available for breed
+ if (rasterSample == 0f){ //if the raster sample is available for urbanization...
+ NbTemp++; //count it
+ nbCellTemp = new int[] {nbUrbanizeX,nbUrbanizeY,NbTemp}; //create an array holding the coordinates and the number of that neighbor cell
+ if (nbCellTemp[2] == RN && slopeDoubleNb < RNRoadSlope){ //if its number is the same as the random number and it passes the slope-test..
+ nbCellNew = new int[] {nbCellTemp[0],nbCellTemp[1],nbCellTemp[2]}; //write its coordinates in the array to be returned
}
}
}
} else{
- nbCellNew = null;
+ nbCellNew = null;
} break;
}
@@ -806,13 +835,22 @@
}
}
- return nbCellNew;
+ return nbCellNew; //return the result array
}
- private int calculateNeighbors(int X, int Y, float NbValue){
+ /**
+ * This method returns the number of neighbors of a cell X/Y. The input for this method are the coordinates of the center cell
+ * and the value that the neighboring cells must have in order to be counted. In general this is 0 for non-urban cells and 1
+ * for urban cells.
+ * @param X
+ * @param Y
+ * @param NbValue
+ * @return Nb
+ */
+ public int calculateNeighbors(int X, int Y, float NbValue){
int nbX = 0;
int nbY = 0;
- int areaMinX = inputGrid.getMinX(); //Dimensionen des Rasters
+ int areaMinX = inputGrid.getMinX(); //raster dimensions
int areaMinY = inputGrid.getMinY();
int areaMaxX = inputGrid.getMinX() + inputGrid.getWidth() - 1;
int areaMaxY = inputGrid.getMinY() + inputGrid.getHeight() - 1;
@@ -821,19 +859,52 @@
nbX = X+NEIGHBOR[nbCells][0];
nbY = Y+NEIGHBOR[nbCells][1];
if ( nbX < areaMinX || nbY < areaMinY || nbX > areaMaxX || nbY > areaMaxY ||
- Float.isNaN(outputGrid.getRasterSampleAsFloat(nbX,nbY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
- continue;
+ Float.isNaN(outputGrid.getRasterSampleAsFloat(nbX,nbY)))
+ continue; //if a cell is outside the raster (NaN), break and continue loop from the beginning
if (areaRestr.getRasterSampleAsFloat(nbX,nbY) != 0)
- continue;
- float rasterSample = outputGrid.getRasterSampleAsFloat(nbX,nbY);
- if (rasterSample == NbValue)
- Nb++;
+ continue; //if a cell is inside an excluded area, break and continue loop from the beginning
+ float rasterSample = outputGrid.getRasterSampleAsFloat(nbX,nbY); //take the raster value
+ if (rasterSample == NbValue) //if it is the same as the value we look for...
+ Nb++; //count it
}
- // statusOut.println("..."+Nb+"...");
return Nb;
}
- protected static boolean checkNoData(int x, int y, WritableGrid grid) {
- return Float.isNaN(grid.getRasterSampleAsFloat(x,y));
- }
+ /**
+ * Returns the number of urban cells in the temporary cell array.
+ * @return anzGesamt
+ */
+ public int countTempUrbanCells(boolean[][] tmpGrid){
+ int anzGesamt = 0;
+ for (int x = 0; x < outputGrid.getWidth();x++)
+ for(int y = 0; y < outputGrid.getHeight();y++){
+ if (tmpGrid[x][y]==true){
+ anzGesamt++;
+ }
+ }
+ return anzGesamt;
+ }
+
+ /**
+ * Writes a temporary grid array with boolean values to the outputGrid.
+ * @param tmpGrid
+ */
+ public void writeToGrid(boolean tmpGrid[][]){
+ int t = 0;
+ for (int y = 1; y < inputGrid.getHeight()-1;y++ ) {
+ for (int x = 1; x < inputGrid.getWidth()-1; x++ ) {
+
+ int X = inputGrid.getMinX() + x;
+ int Y = inputGrid.getMinY() + y;
+
+ boolean lebt = outputGrid.getRasterSampleAsFloat(X , Y ) > 0f; //a cell is alive when it is 1
+ if (tmpGrid[x][y] == false) //if there is nothing in the temporary raster
+ tmpGrid[x][y] = lebt; //take the information from the current output grid
+ if(tmpGrid[x][y] == true)
+ t++;
+ outputGrid.setRasterSample( tmpGrid[x][y] ? 1f : 0f ,X ,Y); //write the result to the output grid
+ }
+ }
+ statusOut.println("Temporary Urban Cells: "+t);
+ }
}
Modified: trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelContentManager.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelContentManager.java 2009-10-14 08:31:55 UTC (rev 61)
+++ trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelContentManager.java 2009-10-21 08:43:39 UTC (rev 62)
@@ -11,9 +11,12 @@
public class UrbanGrowthModelContentManager extends AbstractModelContentManager {
+ public UrbanGrowthModelContentManager() {
+ this(13);
+ }
- public UrbanGrowthModelContentManager() {
- super(13);
+ protected UrbanGrowthModelContentManager(int resourceCount) {
+ super(resourceCount);
resource[0] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Input Grid",ScalarProperty.class,WritableGrid.class,false);
resource[1] = new ValuePropertyResource(ModelResource.CATEGORY_OUTPUT,"Output Grid",ScalarProperty.class,WritableGrid.class,false);
More information about the Xulu-commits
mailing list