[Xulu-commits] r56 - in trunk: dist src/edu/bonn/xulu/plugin/model src/edu/bonn/xulu/plugin/model/sleuth

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Thu Sep 10 16:02:23 CEST 2009


Author: rgoetzke
Date: 2009-09-10 16:02:19 +0200 (Thu, 10 Sep 2009)
New Revision: 56

Added:
   trunk/src/edu/bonn/xulu/plugin/model/sleuth/
   trunk/src/edu/bonn/xulu/plugin/model/sleuth/CopyUrbanInActualLU.java
   trunk/src/edu/bonn/xulu/plugin/model/sleuth/CopyUrbanInActualLUContentManager.java
   trunk/src/edu/bonn/xulu/plugin/model/sleuth/MultipleResolutionValidation.java
   trunk/src/edu/bonn/xulu/plugin/model/sleuth/MultipleResolutionValidationContentManager.java
   trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthContentManager.java
   trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModel.java
   trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelCalibration.java
   trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelCalibrationContentManager.java
   trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelCalibrationSelfModification.java
   trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelCalibrationSelfModificationContentManager.java
   trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelContentManager.java
   trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelSelfModifying.java
   trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelSelfModifyingContentManager.java
Modified:
   trunk/dist/xulu-doc.zip
Log:
SLEUTH 1. Version, wird noch geupdated

Modified: trunk/dist/xulu-doc.zip
===================================================================
(Binary files differ)

Added: trunk/src/edu/bonn/xulu/plugin/model/sleuth/CopyUrbanInActualLU.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/sleuth/CopyUrbanInActualLU.java	2009-09-07 12:15:20 UTC (rev 55)
+++ trunk/src/edu/bonn/xulu/plugin/model/sleuth/CopyUrbanInActualLU.java	2009-09-10 14:02:19 UTC (rev 56)
@@ -0,0 +1,94 @@
+package edu.bonn.xulu.plugin.model.sleuth;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.property.PropertyReadAccess;
+import schmitzm.data.property.PropertyWriteAccess;
+import schmitzm.data.property.ScalarProperty;
+import edu.bonn.xulu.model.AbstractStepModel;
+import appl.util.RasterUtil;
+
+public class CopyUrbanInActualLU extends AbstractStepModel {
+
+	
+	protected CopyUrbanInActualLUContentManager contManager;
+	
+	private PropertyReadAccess RA_ActualLuMap = null; 
+	private PropertyReadAccess RA_ActualUrbanMap = null;
+	private PropertyWriteAccess WA_ActualUrbanMap = null; // Output Grid
+	private PropertyReadAccess RA_UrbanLUClass = null;
+	
+	private WritableGrid ActualLuMap = null; 
+	private WritableGrid ActualUrbanMap = null;
+	private PropertyReadAccess UrbanLUClass = null;
+	
+	protected int	step = 0;
+	
+	public CopyUrbanInActualLU() {
+		super(new CopyUrbanInActualLUContentManager());
+		this.contManager = (CopyUrbanInActualLUContentManager) super.contManager;
+	}
+
+	@Override
+	public void performModelInit() {
+		// TODO Auto-generated method stub
+		if (contManager == null)
+			return;
+		RA_ActualLuMap = null;
+		if (contManager.getResource(0).getData() != null)
+			RA_ActualLuMap = ((ScalarProperty) contManager.getResource(0)
+					.getData()).getReadAccess(this);
+		RA_ActualUrbanMap = null;
+		if (contManager.getResource(1).getData() != null)
+			RA_ActualUrbanMap = ((ScalarProperty) contManager.getResource(1)
+					.getData()).getReadAccess(this);
+		WA_ActualUrbanMap = null;
+		if (contManager.getResource(1).getData() != null)
+			WA_ActualUrbanMap = ((ScalarProperty) contManager.getResource(1)
+					.getData()).getWriteAccess(this);
+		RA_UrbanLUClass = null;
+		if (contManager.getResource(2).getData() != null)
+			RA_UrbanLUClass = ((ScalarProperty) contManager.getResource(2).getData())
+					.getReadAccess(this);
+		
+		ActualLuMap = (WritableGrid) RA_ActualLuMap.getValue();
+		ActualUrbanMap = (WritableGrid) RA_ActualUrbanMap.getValue();
+		UrbanLUClass = RA_UrbanLUClass;
+		this.stepCount = 1;
+	}
+	
+	@Override
+	public void performModelDispose() {
+		// TODO Auto-generated method stub
+		releaseAccess(RA_ActualLuMap);
+		releaseAccess(RA_ActualUrbanMap);
+		releaseAccess(WA_ActualUrbanMap);
+	}
+	
+	
+	@Override
+	public void performModelStep(int stepNo) {
+		// TODO Auto-generated method stub
+		statusOut.println("Starting Copy ...");
+		
+		boolean[][] tmpGrid = new boolean[ActualLuMap.getWidth()][ActualLuMap.getHeight()];
+		
+		for (int x = 0; x < ActualLuMap.getWidth(); x++)
+			for (int y = 0; y < ActualLuMap.getHeight(); y++) {
+				float LU = ActualLuMap.getRasterSampleAsFloat(x, y);
+				float Urban = ActualUrbanMap.getRasterSampleAsFloat(x, y);
+				if (!Float.isNaN(LU) && !Float.isNaN(Urban)){
+					if ((int)Urban == 1){
+						tmpGrid[x][y] = true;
+						ActualLuMap.setRasterSample( tmpGrid[x][y] ? 1f : 0f ,x ,y);
+						}
+						
+					}	
+				}
+		
+		statusOut.println("Copy finished.");
+	}
+
+	
+
+	
+}
\ No newline at end of file

Added: trunk/src/edu/bonn/xulu/plugin/model/sleuth/CopyUrbanInActualLUContentManager.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/sleuth/CopyUrbanInActualLUContentManager.java	2009-09-07 12:15:20 UTC (rev 55)
+++ trunk/src/edu/bonn/xulu/plugin/model/sleuth/CopyUrbanInActualLUContentManager.java	2009-09-10 14:02:19 UTC (rev 56)
@@ -0,0 +1,26 @@
+package edu.bonn.xulu.plugin.model.sleuth;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.property.ScalarProperty;
+import edu.bonn.xulu.model.AbstractModelContentManager;
+import edu.bonn.xulu.model.ModelResource;
+import edu.bonn.xulu.model.ValuePropertyResource;
+
+public class CopyUrbanInActualLUContentManager extends AbstractModelContentManager {
+
+	  /**
+	   * Erzeugt einen neuen ContentManager fuer das Modell {@linkplain AverageNeighborhoodParallelDemoModel}.
+	   */
+	  public CopyUrbanInActualLUContentManager() {
+
+		  super(3);
+		    // ActualLU (CLUE-S)
+		    resource[0]	= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"ActualLU",ScalarProperty.class,WritableGrid.class,false);
+		    // ActualUrban (UGM)
+		    resource[1] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"ActualUrban",ScalarProperty.class,WritableGrid.class,false);
+		    // Urban LU Class
+		    resource[2] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"UrbanLUClass",ScalarProperty.class,Integer.class,false);
+	  }  
+
+}
+	  
\ No newline at end of file

Added: trunk/src/edu/bonn/xulu/plugin/model/sleuth/MultipleResolutionValidation.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/sleuth/MultipleResolutionValidation.java	2009-09-07 12:15:20 UTC (rev 55)
+++ trunk/src/edu/bonn/xulu/plugin/model/sleuth/MultipleResolutionValidation.java	2009-09-10 14:02:19 UTC (rev 56)
@@ -0,0 +1,286 @@
+package edu.bonn.xulu.plugin.model.sleuth;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.ListPropertyWriteAccess;
+import schmitzm.data.property.PropertyReadAccess;
+import schmitzm.data.property.PropertyWriteAccess;
+import schmitzm.data.property.ScalarProperty;
+import edu.bonn.xulu.model.AbstractStepModel;
+import edu.bonn.xulu.model.XuluModel;
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+import edu.bonn.xulu.plugin.model.parallel.demo.AVNTuned;
+import edu.bonn.xulu.plugin.model.parallel.demo.AverageNeighborhoodContentManager;
+import edu.bonn.xulu.plugin.model.parallel.demo.AverageNeighborhoodParallelDemoModel;
+
+/**
+ *  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}. 
+ * <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>
+ * 
+ * @see AverageNeighborhoodContentManager
+ * @author Dominik Appl
+ * @version 1.0
+ */
+public class MultipleResolutionValidation extends AbstractStepModel {
+
+	/**
+	 * the width/height of the neighborhood region over which the algorithm takes 
+	 * the average
+	 */
+	//private int neighborhoodRange = 8;
+	private int neighborhoodRange = 0;
+	private float[][] resultArray;
+	/**
+	 * Speichert den ContentManager fuer das Modell.
+	 * 
+	 * @see AverageNeighborhoodContentManager
+	 */
+	protected MultipleResolutionValidationContentManager contManager;
+
+	// ********** Lese/Schreibrechte, die fuer den gesamten ***********
+	// ********** Modellanlauf gehalten werden muessen ***********
+	private PropertyReadAccess RA_steps = null;
+	private PropertyReadAccess RA_referenceMap = null; // Reference Map
+	private PropertyReadAccess RA_simulationMap = null;	//Simulation Map
+	private PropertyWriteAccess WA_actualValidation = null; // Output Grid
+	private PropertyWriteAccess WA_outStep = null;	// Step Results
+	private ListPropertyWriteAccess WA_outResults = null;	//Output Validation Results
+
+	// **************** Variablen mit denen gearbeitet wird *******************
+	private PropertyReadAccess steps = null; // Number of steps
+	private WritableGrid referenceMap = null; // Reference Map
+	private WritableGrid simulationMap = null;	// Simulation Map
+	private WritableGrid actualValidation = null; // Output Grid
+	private MultiGrid outStep = null;	//Step Results
+	private ListPropertyWriteAccess outResults = null;	//Output Validation Results
+
+
+	/**
+	 * Erzeugt eine neue Instanz des Modells.
+	 */
+	public MultipleResolutionValidation() {
+		super(new MultipleResolutionValidationContentManager());
+		this.contManager = (MultipleResolutionValidationContentManager) super.contManager;
+	}
+
+	
+	/**
+	 * Initializes the model. Like in the init method of every {@link XuluModel}
+	 * the resources are initalized. 
+	 */
+	public void performModelInit() {
+		if (contManager == null)
+			return;
+		// Zugriffsrechte aus Ressourcen/Propertys holen
+		RA_steps = null;
+		if (contManager.getResource(0).getData() != null)
+			RA_steps = ((ScalarProperty) contManager.getResource(0).getData())
+					.getReadAccess(this);
+		RA_referenceMap = null;
+		if (contManager.getResource(1).getData() != null)
+			RA_referenceMap = ((ScalarProperty) contManager.getResource(1)
+					.getData()).getReadAccess(this);
+		RA_simulationMap = null;
+		if (contManager.getResource(2).getData() != null)
+			RA_simulationMap = ((ScalarProperty) contManager.getResource(2)
+					.getData()).getReadAccess(this);
+		WA_actualValidation = null;
+		if (contManager.getResource(3).getData() != null)
+			WA_actualValidation = ((ScalarProperty) contManager.getResource(3)
+					.getData()).getWriteAccess(this);
+		WA_outResults = null;
+		if (contManager.getResource(5).getData() != null)
+			WA_outResults = ((ListProperty) contManager.getResource(5)
+					.getData()).getWriteAccess(this);
+
+		// Variablen belegen mit denen gearbeitet wird
+		steps = RA_steps;
+		referenceMap = (WritableGrid) RA_referenceMap.getValue();
+		simulationMap = (WritableGrid) RA_simulationMap.getValue();
+		actualValidation = (WritableGrid) WA_actualValidation.getValue();
+
+		this.stepCount = steps.getValueAsInt();
+		outStep = (MultiGrid)contManager.getResource(4).getData();
+		outResults = WA_outResults;
+	}
+
+	/**
+	* like in every model: frees the resources
+	 */
+	public void performModelDispose() {
+
+		// Ressourcen wieder freigeben
+		releaseAccess(RA_steps);
+		releaseAccess(RA_referenceMap);
+		releaseAccess(RA_simulationMap);
+		releaseAccess(WA_actualValidation);
+		releaseAccess(WA_outStep);
+		releaseAccess(WA_outResults);
+	}
+
+	/**
+	 * This very simple model looks at every grid cell and takes the average
+	 * over a the surrounding cells in a specified neighborhood.
+	 * 
+	 * @param stepNo
+	 *            zu modellierender Schritt (beginnend bei 1!)
+	 */
+	public void performModelStep(int stepNo) {
+		
+		statusOut.println("Starting step " + stepNo + "...");
+		
+
+		/***********************************************************************
+		 * the overallsum is simply the sum over ALL grid elements. it can be used to
+		 * compare the result of this model with e.g. the parallel version of
+		 * this algorithm.
+		 **********************************************************************/ 
+		int RoverallSum = 0;
+		int RnumClasses = 0;
+		int SoverallSum = 0;
+		int SnumClasses = 0;
+		int correct = 0;
+		double fractionCorrect = 0f;
+		
+
+		long localStartTime = System.currentTimeMillis();
+		//iterate over all cells
+		
+		neighborhoodRange = (int) Math.sqrt(referenceMap.getWidth()*referenceMap.getHeight()); //maximal mögliche Zellengröße
+		statusOut.println(neighborhoodRange);
+		resultArray = new float[1][13];
+		//Fraction correct for original Resolution
+		for (int x = 0; x < referenceMap.getWidth(); x++)
+			for (int y = 0; y < referenceMap.getHeight(); y++) {
+				float Rtmp = referenceMap.getRasterSampleAsFloat(x, y);
+				float Stmp = simulationMap.getRasterSampleAsFloat(x, y);
+				if (!Float.isNaN(Rtmp) && !Float.isNaN(Stmp)){
+					RoverallSum ++;
+					SoverallSum ++;
+					if (Rtmp > RnumClasses)
+						RnumClasses = (int) Rtmp;
+					if (Stmp > SnumClasses)
+						SnumClasses = (int) Stmp;	
+					if (Rtmp == Stmp)
+						correct++;
+				}
+		}
+		fractionCorrect = (double) correct / (double) RoverallSum;
+		
+		//Anzahl der Pixel pro Klasse
+		for (int i = 1; i <= RnumClasses; i++){
+			int Rj = 0;
+			int Sj = 0;
+			for (int x = 0; x < referenceMap.getWidth(); x++)
+				for (int y = 0; y < referenceMap.getHeight(); y++){
+					float Rtmp = referenceMap.getRasterSampleAsFloat(x, y);
+					float Stmp = simulationMap.getRasterSampleAsFloat(x, y);
+					if (!Float.isNaN(Rtmp))
+						if ((int) Rtmp == i)
+							Rj++;
+					if (!Float.isNaN(Stmp))
+						if ((int) Stmp == i)
+							Sj++;
+				}
+			statusOut.println("Klasse "+i+": Referenz("+Rj+"), Simulation("+Sj+")");
+		}
+		
+		int ngrids = 0;
+		for (int r = 1; r <= neighborhoodRange; r = r+r){	//für Zellengröße 1 bis zur max. möglichen Zellengröße wird Statistik durchgeführt
+			statusOut.println(r);
+			ngrids++;
+			outStep.addGrid();
+			float SumWn = 0f;	//Summe der gewichteten Mittelwerte 
+			int SumCells = 0;	//Summe der Zellen
+			float totalAgreement = 0f;	//Endergebnis
+			for (int x = 0; x < referenceMap.getWidth(); x = x+r)	//für jeden größer werdenden Zellenbereich...
+				for (int y = 0; y < referenceMap.getHeight(); y = y+r){
+					int nCells = 0;		//Anzahl Zellen pro größerer Zelle
+					float SumMinRS = 0f;	//Summe der Min-Werte bei Vergleich zweier Raster
+					float Wn = 0;	//Gewichtete Zelle
+					for(int x2 = x; x2 < x+r; x2++)	//für jede kleinere Zelle innerhalb der größeren...
+						for(int y2 = y; y2 < y+r; y2++){
+							if ( x2 < referenceMap.getMinX() || y2 < referenceMap.getMinY() || x2 > referenceMap.getMinX()+referenceMap.getWidth()-1 || y2 > referenceMap.getMinY()+referenceMap.getHeight()-1 ||
+									Float.isNaN(referenceMap.getRasterSampleAsFloat(x2,y2)))
+								continue;
+							nCells++;	//zähle "positive" Zellen
+						}
+					for (int i = 0; i <= RnumClasses; i++){	//für jede Klasse i
+						int Rn = 0;	//Anzahl in Referenzkarte
+						int Sn = 0;	//Anzahl in Simulationskarte
+						float Rnj = 0f;	//Anteil in Referenzkarte
+						float Snj = 0f;	//Anteil in Simulationskarte
+						float MinRS = 0f;	//Min des Vergleichs zwischen beiden Karten
+						for(int x3 = x; x3 < x+r; x3++)	//für jede kleinere Zelle pro größerer Zelle...
+							for(int y3 = y; y3 < y+r; y3++){
+								if ( x3 < referenceMap.getMinX() || y3 < referenceMap.getMinY() || x3 > referenceMap.getMinX()+referenceMap.getWidth()-1 || y3 > referenceMap.getMinY()+referenceMap.getHeight()-1 ||
+										Float.isNaN(referenceMap.getRasterSampleAsFloat(x3,y3)))
+									continue;
+								float Rtmp = referenceMap.getRasterSampleAsFloat(x3, y3);	//hole Wert aus Referenz-Karte und
+								float Stmp = simulationMap.getRasterSampleAsFloat(x3, y3);	//Simulationskarte
+								if ((int) Rtmp == i)
+									Rn++;	//zähle in Referenzkarte Zellen, die zu Klasse i gehören 
+								if ((int) Stmp == i)
+									Sn++;	//und in Simulationskarte
+							}
+						if(nCells > 0){	//wenn positive Zellen vorhanden sind...
+							Rnj = (float)Rn / (float)nCells;	//berechne Anteile pro größerer Zelle
+							Snj = (float)Sn / (float)nCells;
+						}
+						MinRS = Math.min(Rnj, Snj);	//nehme Minimum-Wert des Vergleichs beider Karten
+						SumMinRS += MinRS;	//summiere die Minimum-Werte auf
+						//	statusOut.println(i+" Min"+MinRS+" Anzahl: "+nCells);
+						
+					}
+					Wn = (float)nCells * SumMinRS;
+					 
+					//	statusOut.println(SumMinRS+", gewichtet: "+Wn);
+					//Erstelle Output-Karten
+					float WnCell = 0f;
+					for(int x4 = x; x4 < x+r; x4++)	//für jede kleinere Zelle pro größerer Zelle...
+						for(int y4 = y; y4 < y+r; y4++){
+							if ( x4 < referenceMap.getMinX() || y4 < referenceMap.getMinY() || x4 > referenceMap.getMinX()+referenceMap.getWidth()-1 || y4 > referenceMap.getMinY()+referenceMap.getHeight()-1 ||
+									Float.isNaN(referenceMap.getRasterSampleAsFloat(x4,y4)))
+								continue;
+							WnCell = Wn / (float)nCells; //pro Zelle wird Mittelwert des Vergleichs genommen
+							actualValidation.setRasterSample( WnCell ,x4 ,y4);	
+							outStep.getGrid(ngrids-1).setRasterSample(WnCell,x4,y4);
+						}
+				
+					SumCells += (float)nCells;	//Summiere alle Zellen auf
+					SumWn += Wn;	//Summiere die gewichteten Anteile auf
+				}
+			//Total Agreement:
+			//siehe Pontius...
+			statusOut.println(SumWn+" / "+SumCells);
+			totalAgreement = SumWn / (float)SumCells;	//Ergebnisformel
+			statusOut.println(totalAgreement);	
+			outResults.addValue(totalAgreement);
+			resultArray[0][ngrids] = totalAgreement;
+	//	statusOut.println("Gesamt-Pixel: "+RoverallSum);
+	//	statusOut.println("Anzahl Klassen: "+RnumClasses);
+	//	statusOut.println("Fraction Correct: "+fractionCorrect);
+		}
+		
+		
+		System.out.println(resultArray[0][1]+","+resultArray[0][2]+","+resultArray[0][3]+","+
+				resultArray[0][4]+","+resultArray[0][5]+","+resultArray[0][6]+
+				","+resultArray[0][7]+","+resultArray[0][8]+","+resultArray[0][9]+","+resultArray[0][10]+","+resultArray[0][11]+","+resultArray[0][12]);
+		
+		System.out.print("Finished step " + (stepNo) + " in "
+				+ ((System.currentTimeMillis() - localStartTime)) + " ms");
+		localStartTime = System.currentTimeMillis();
+		System.out.println(" with sum (local calculated): " + RoverallSum);
+		
+	}
+}

Added: trunk/src/edu/bonn/xulu/plugin/model/sleuth/MultipleResolutionValidationContentManager.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/sleuth/MultipleResolutionValidationContentManager.java	2009-09-07 12:15:20 UTC (rev 55)
+++ trunk/src/edu/bonn/xulu/plugin/model/sleuth/MultipleResolutionValidationContentManager.java	2009-09-10 14:02:19 UTC (rev 56)
@@ -0,0 +1,47 @@
+package edu.bonn.xulu.plugin.model.sleuth;
+
+import edu.bonn.xulu.model.AbstractModelContentManager;
+import edu.bonn.xulu.model.DefaultModelResource;
+import edu.bonn.xulu.model.ModelResource;
+import edu.bonn.xulu.model.PropertiesResource;
+import edu.bonn.xulu.model.ValuePropertyResource;
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+import edu.bonn.xulu.plugin.model.clue.ClueModelContentManager;
+import schmitzm.data.WritableGrid;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.ScalarProperty;
+
+
+/**
+ * This class defines and handle the three resources for the models
+ * <ol> 
+ * <li><b> </li>
+ * <li><b> {@link AverageNeighborhoodSerialDemoModel}</b></li>
+ * <li><b> {@link AverageNeighborhoodParallelDemoModel}</b></li>
+ * <li><b> {@link AVNTuned}</b></li>
+ * </ol>
+ * @see ClueModelContentManager
+ * @author automatically generated using {@link edu.bonn.xulu.plugin.appl.GeoModelCodeGenerator}
+ * @version 1.0
+ */
+public class MultipleResolutionValidationContentManager extends AbstractModelContentManager {
+
+  /**
+   * Erzeugt einen neuen ContentManager fuer das Modell {@linkplain AverageNeighborhoodParallelDemoModel}.
+   */
+  public MultipleResolutionValidationContentManager() {
+    super(6);
+    // Steps
+    resource[0]	= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Number of steps",ScalarProperty.class,Integer.class,false);
+    // Reference Map
+    resource[1] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Reference Map",ScalarProperty.class,WritableGrid.class,false);
+    // Simulation Map
+    resource[2] = new ValuePropertyResource(ModelResource.CATEGORY_OUTPUT,"Simulation Map",ScalarProperty.class,WritableGrid.class,false);
+    // Actual Validation
+    resource[3]	= new ValuePropertyResource(ModelResource.CATEGORY_OUTPUT,"Actual Validation",ScalarProperty.class,WritableGrid.class,false);
+    // Map for every Resolution
+    resource[4]	= new DefaultModelResource(ModelResource.CATEGORY_OUTPUT,"Step Results",MultiGrid.class,false);
+    // Output Values
+    resource[5]	= new ValuePropertyResource(ModelResource.CATEGORY_OUTPUT,"Validation Results",ListProperty.class,Double.class,false);
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthContentManager.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthContentManager.java	2009-09-07 12:15:20 UTC (rev 55)
+++ trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthContentManager.java	2009-09-10 14:02:19 UTC (rev 56)
@@ -0,0 +1,37 @@
+package edu.bonn.xulu.plugin.model.sleuth;
+
+import edu.bonn.xulu.model.AbstractModelContentManager;
+import edu.bonn.xulu.model.ModelResource;
+import edu.bonn.xulu.model.ValuePropertyResource;
+import edu.bonn.xulu.plugin.model.clue.ClueModelContentManager;
+import schmitzm.data.WritableGrid;
+import schmitzm.data.property.ScalarProperty;
+
+
+/**
+ * This class defines and handle the three resources for the models
+ * <ol> 
+ * <li><b> </li>
+ * <li><b> {@link AverageNeighborhoodSerialDemoModel}</b></li>
+ * <li><b> {@link AverageNeighborhoodParallelDemoModel}</b></li>
+ * <li><b> {@link AVNTuned}</b></li>
+ * </ol>
+ * @see ClueModelContentManager
+ * @author automatically generated using {@link edu.bonn.xulu.plugin.appl.GeoModelCodeGenerator}
+ * @version 1.0
+ */
+public class UrbanGrowthContentManager extends AbstractModelContentManager {
+
+  /**
+   * Erzeugt einen neuen ContentManager fuer das Modell {@linkplain AverageNeighborhoodParallelDemoModel}.
+   */
+  public UrbanGrowthContentManager() {
+    super(3);
+    // Input Grid
+    resource[0] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Input Grid",ScalarProperty.class,WritableGrid.class,false);
+    // Output Grid
+    resource[1] = new ValuePropertyResource(ModelResource.CATEGORY_OUTPUT,"Output Grid",ScalarProperty.class,WritableGrid.class,false);
+    // Number of steps
+    resource[2] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Number of steps",ScalarProperty.class,Integer.class,false);
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModel.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModel.java	2009-09-07 12:15:20 UTC (rev 55)
+++ trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModel.java	2009-09-10 14:02:19 UTC (rev 56)
@@ -0,0 +1,839 @@
+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;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.property.PropertyReadAccess;
+import schmitzm.data.property.PropertyWriteAccess;
+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)}.
+ *  
+ *  
+ * <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>
+ * 
+ * @see AverageNeighborhoodContentManager
+ * @author Dominik Appl
+ * @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.
+	 * 
+	 * @see AverageNeighborhoodContentManager
+	 */
+	protected UrbanGrowthModelContentManager contManager;
+
+	// ********** Lese/Schreibrechte, die fuer den gesamten ***********
+	// ********** Modellanlauf gehalten werden muessen ***********
+	private PropertyReadAccess RA_inputGrid = null; // Input Grid
+	private PropertyWriteAccess WA_outputGrid = null; // Output Grid
+	private PropertyReadAccess RA_steps = null; // Number of steps
+	private PropertyReadAccess RA_areaRestr = null; //Area Restrictions
+	private PropertyReadAccess RA_spread = null;	//Spread-Koeffizient
+	private PropertyReadAccess RA_disp = null;		//Dispersions-Koeffizient
+	private PropertyReadAccess RA_breed = null;		//Breed-Koeffizient
+	private PropertyReadAccess RA_roadGravity = null;	//Road-Gravity-Koeffizient
+	private PropertyReadAccess RA_slope = null;	//Slope-Koeffizient
+	private PropertyReadAccess RA_criticalSlope = null;	//Critical Slope Value
+	private PropertyReadAccess RA_roadGrid = null;	//Road Grid
+	private PropertyReadAccess RA_slopeGrid = null;	//Slope Grid
+	private PropertyWriteAccess WA_outStep = null;	// Step Results
+
+	// **************** Variablen mit denen gearbeitet wird *******************
+	private WritableGrid inputGrid = null; // Input Grid
+	private WritableGrid outputGrid = null; // Output Grid
+	private PropertyReadAccess steps = null; // Number of steps
+	private WritableGrid areaRestr = null; //Area Restrictions
+	protected double spread = 0;	//Spread-Koeffizient
+	protected double disp = 0;	//Dispersions-Koeffizient
+	protected double breed = 0;	//Breed-Koeffizient
+	protected double roadGravity = 0;	//Road-Gravity-Koeffizient
+	protected double slope = 0;	//Slope-Koeffizient
+	protected double criticalSlope = 0;	//Critical Slope Value
+	private WritableGrid roadGrid = null;	//Road Grid
+	private WritableGrid slopeGrid = null;	//Slope Grid
+	private MultiGrid outStep = null;	//Step Results
+		
+	private  static final int[][] NEIGHBOR = new int[][] {
+	      {-1,-1}, {0,-1}, {1,-1},
+	      {-1, 0},         {1, 0},
+	      {-1, 1}, {0, 1}, {1, 1}
+	  };
+	
+	protected  HashMap<Number,Number> slopeLUT;
+	
+	/**
+	 * Erzeugt eine neue Instanz des Modells.
+	 */
+	public UrbanGrowthModel() {
+		super(new UrbanGrowthModelContentManager());
+		this.contManager = (UrbanGrowthModelContentManager) super.contManager;
+	}
+
+	
+	/**
+	 * Initializes the model. Like in the init method of every {@link XuluModel}
+	 * the resources are initalized. 
+	 */
+	public void performModelInit() {
+		if (contManager == null)
+			return;
+		// Zugriffsrechte aus Ressourcen/Propertys holen
+		RA_inputGrid = null;
+		if (contManager.getResource(0).getData() != null)
+			RA_inputGrid = ((ScalarProperty) contManager.getResource(0)
+					.getData()).getReadAccess(this);
+		WA_outputGrid = null;
+		if (contManager.getResource(1).getData() != null)
+			WA_outputGrid = ((ScalarProperty) contManager.getResource(1)
+					.getData()).getWriteAccess(this);
+		RA_steps = null;
+		if (contManager.getResource(2).getData() != null)
+			RA_steps = ((ScalarProperty) contManager.getResource(2).getData())
+					.getReadAccess(this);
+		RA_areaRestr = null;
+		if (contManager.getResource(3).getData() != null)
+			RA_areaRestr = ((ScalarProperty) contManager.getResource(3)
+					.getData()).getReadAccess(this);
+		RA_spread = null;
+		if (contManager.getResource(4).getData() != null)
+			RA_spread = ((ScalarProperty) contManager.getResource(4).getData())
+					.getReadAccess(this);
+		RA_disp = null;
+		if (contManager.getResource(5).getData() != null)
+			RA_disp = ((ScalarProperty) contManager.getResource(5).getData())
+					.getReadAccess(this);
+		RA_breed = null;
+		if (contManager.getResource(6).getData() != null)
+			RA_breed = ((ScalarProperty) contManager.getResource(6).getData())
+					.getReadAccess(this);
+		RA_roadGravity = null;
+		if (contManager.getResource(7).getData() != null)
+			RA_roadGravity = ((ScalarProperty) contManager.getResource(7).getData())
+					.getReadAccess(this);
+		RA_slope = null;
+		if (contManager.getResource(8).getData() != null)
+			RA_slope = ((ScalarProperty) contManager.getResource(8).getData())
+					.getReadAccess(this);
+		RA_criticalSlope = null;
+		if (contManager.getResource(9).getData() != null)
+			RA_criticalSlope = ((ScalarProperty) contManager.getResource(9).getData())
+					.getReadAccess(this);
+		RA_roadGrid = null;
+		if (contManager.getResource(10).getData() != null)
+			RA_roadGrid = ((ScalarProperty) contManager.getResource(10)
+					.getData()).getReadAccess(this);
+		RA_slopeGrid = null;
+		if (contManager.getResource(11).getData() != null)
+			RA_slopeGrid = ((ScalarProperty) contManager.getResource(11)
+					.getData()).getReadAccess(this);
+
+		// Variablen belegen mit denen gearbeitet wird
+		inputGrid = (WritableGrid) RA_inputGrid.getValue();
+		outputGrid = (WritableGrid) WA_outputGrid.getValue();
+		steps = RA_steps;
+		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();
+	    roadGravity = RA_roadGravity.getValueAsDouble();
+	    slope	= RA_slope.getValueAsDouble();
+	    criticalSlope = RA_criticalSlope.getValueAsDouble();
+	    roadGrid = (WritableGrid) RA_roadGrid.getValue();
+	    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);
+		
+		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);
+		
+		
+		//Erstellt einen Lookup-Table
+		slopeLUT = new HashMap<Number,Number>();
+		
+		int MaxSlopeResistance = 0;
+		double exp = 0.0;
+		MaxSlopeResistance = 100;
+		exp = (slope / (MaxSlopeResistance / 2));
+		double[] lookup = new double[slopeMax+1];
+		Number key = 0;
+		
+		for (int i = 0;i <= slopeMax;i++){
+			if (i <= criticalSlope){
+				double val = (criticalSlope - i) / criticalSlope;
+				lookup[i] = 1 - Math.pow(val,exp);
+				key = i;
+			} else{
+				lookup[i] = 1;
+				key = i;
+			}
+			slopeLUT.put(key,lookup[i]);
+			statusOut.println(slopeLUT.get(key));
+		}	
+	}
+
+	/**
+	* like in every model: frees the resources
+	 */
+	public void performModelDispose() {
+
+		// Ressourcen wieder freigeben
+		releaseAccess(RA_inputGrid);
+		releaseAccess(WA_outputGrid);
+		releaseAccess(RA_steps);
+		releaseAccess(RA_areaRestr);
+		releaseAccess(RA_spread);
+		releaseAccess(RA_disp);
+		releaseAccess(RA_breed);
+		releaseAccess(RA_roadGravity);
+		releaseAccess(RA_slope);
+		releaseAccess(RA_criticalSlope);
+		releaseAccess(RA_roadGrid);
+		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  
+	 * @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();
+		
+		long localStartTime = System.currentTimeMillis();
+		boolean anyBodyAlive = false;
+		
+		boolean[][] tmpGrid = new boolean[inputGrid.getWidth()][inputGrid.getHeight()];
+		Float actUrb = null;
+		
+		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;
+		
+		//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);
+		
+
+		/*****************************************************************
+		 * DISPERSION and BREED
+		 *****************************************************************/
+		
+		int p = 0;	//Verteile soviel neue Pixel zufällig in geeigneten Bereichen, bis disp_value erreicht ist
+		do{
+			dispRandX = Math.round((float) Math.random()*areaWidth);	//Zufallsposition in X-Richtung
+			dispRandY = Math.round((float) Math.random()*areaHeight);	//Zufallsposition in Y-Richtung
+			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
+	
+		/*********************************************************************
+		 * EDGE
+		 *********************************************************************/
+		
+		//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
+				
+				int areaMinXadd = areaMinX + x;								//Dimensionen des Rasters
+				int areaMinYadd = areaMinY + y;
+				
+				int anzNachbarn = 0;
+				int noNachbarn = 0;
+			
+				
+				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;	//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));
+					float RNEdgeSlope = 0;
+					int nbUrbanX = 0;
+					int nbUrbanY = 0;
+					for (int nbCellChange = 0; nbCellChange < NEIGHBOR.length; nbCellChange++){	//dann starte eine Schleife
+						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;
+						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++;
+								}
+							} 
+						}
+						nbCell = new int[] {nbX,nbY,(int) rasterSample};	
+					}
+				}
+				if (anzNachbarn>0) anyBodyAlive = true;		
+			}
+		
+		/*********************************************************************
+		 * 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;
+			int roadNeighborhoodRange = 0;
+			int RSearchNbRoad = 0;
+			for (int x = 0; x < inputGrid.getWidth();x++){		//gesamtes Raster wird durchsucht
+				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);
+												}
+											}
+										}
+							        	
+							        
+									}
+									
+								} else{
+									statusOut.println("Keine neue Zelle gefunden");
+								}
+							} else{
+								int anzRoadNb = 0;
+								
+								//HIER MIT FOR SCHLEIFE RECHTECK WACHSEN LASSEN!!!
+								for (int roadSearch = 0; roadSearch <= rg_value; roadSearch++){
+									if (anzRoadNb > 0)
+										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);
+										}
+									}
+									roadNeighborhoodRange++;
+									RSearchNbRoad = Math.round((float)Math.random()*anzRoadNb);
+									//statusOut.println("--> Zyklus "+roadNeighborhoodRange+"Nachbarn: "+anzRoadNb);
+									//statusOut.println(RSearchNbRoad);
+									int anzTempRoadNb = 0;
+									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))
+											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);
+																	}
+																}
+															}
+												        	
+												        
+														}
+													} else{
+														statusOut.println("Keine neue Zelle gefunden");
+													}
+												}
+											}
+										}
+									}
+								}
+							}
+						}
+					}	
+				}
+			}
+			
+		} 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();
+	}
+	
+	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;
+			int nbRoadY = 0;
+			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 roadNb = 0;
+			int roadNbTemp = 0;
+			int RN = 0;
+						
+			int[] nbCell = null;
+			for (int nbRoadCells = 0; nbRoadCells < NEIGHBOR.length; nbRoadCells++){
+				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++;
+			}
+	//		statusOut.println("Nachbarn von temporaerer Strassenzelle: "+roadNb);
+			
+			if (roadNb > 0){
+				RN = 1 + Math.round((float)Math.random()*(roadNb-1));
+			
+				for (int nbRoadCells = 0; nbRoadCells < NEIGHBOR.length; nbRoadCells++){
+					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++;
+							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){
+									int nbUrbanizeX = 0;
+									int nbUrbanizeY = 0;
+									int NbTemp = 0;
+									float RNRoadSlope = 0f;
+						//			statusOut.println(X+","+Y);
+									for (int urbanizeCells = 0; urbanizeCells < NEIGHBOR.length; urbanizeCells++){
+										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;
+										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]};
+											}
+										}	
+									}
+								
+							} else{
+								nbCellNew = null;
+							}	break;
+						}
+						
+					}
+					
+				}
+			}
+			
+			}
+		}
+		return nbCellNew;
+		}
+	
+	private int calculateNeighbors(int X, int Y, float NbValue){
+		int nbX = 0;
+		int nbY = 0;
+		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 Nb = 0;
+		for (int nbCells = 0; nbCells < NEIGHBOR.length; nbCells++){
+			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;
+			if (areaRestr.getRasterSampleAsFloat(nbX,nbY) != 0)
+	        	continue;
+			float rasterSample = outputGrid.getRasterSampleAsFloat(nbX,nbY);
+			if (rasterSample == NbValue)
+				Nb++;
+		}
+	//	statusOut.println("..."+Nb+"...");
+		return Nb;
+	}
+	
+	protected static boolean checkNoData(int x, int y, WritableGrid grid) {
+	    return Float.isNaN(grid.getRasterSampleAsFloat(x,y));
+	  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelCalibration.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelCalibration.java	2009-09-07 12:15:20 UTC (rev 55)
+++ trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelCalibration.java	2009-09-10 14:02:19 UTC (rev 56)
@@ -0,0 +1,1167 @@
+package edu.bonn.xulu.plugin.model.sleuth;
+
+import java.awt.Rectangle;
+import java.util.HashMap;
+
+import appl.util.RasterUtil;
+
+import edu.bonn.xulu.model.AbstractStepModel;
+import edu.bonn.xulu.model.XuluModel;
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.ListPropertyWriteAccess;
+import schmitzm.data.property.PropertyReadAccess;
+import schmitzm.data.property.PropertyWriteAccess;
+import schmitzm.data.property.ScalarProperty;
+
+/**
+ * @see AverageNeighborhoodContentManager
+ * @author Dominik Appl
+ * @version 1.0
+ */
+public class UrbanGrowthModelCalibration extends AbstractStepModel {
+
+	private int neighborhoodRange = 0;
+	private float[] resultArray;
+	private float[][] resultArrayFinal;
+	/**
+	 * Speichert den ContentManager fuer das Modell.
+	 */
+	protected UrbanGrowthModelCalibrationContentManager contManager;
+
+	// ********** Lese/Schreibrechte, die fuer den gesamten ***********
+	// ********** Modellanlauf gehalten werden muessen ***********
+	private PropertyReadAccess RA_steps = null; // Number of steps
+	private PropertyReadAccess RA_MonteCarlo = null;	//Number of MonteCarlo Iterations
+	private PropertyReadAccess RA_inputGrid = null; // Input Grid
+	private PropertyWriteAccess WA_outputGrid = null; // Output Grid
+	private PropertyReadAccess RA_areaRestr = null; //Area Restrictions
+	private PropertyReadAccess RA_spreadStart = null;	//Spread-Koeffizient
+	private PropertyReadAccess RA_spreadStep = null;	//Spread-Koeffizient
+	private PropertyReadAccess RA_spreadEnd = null;	//Spread-Koeffizient
+	private PropertyReadAccess RA_dispStart = null;		//Dispersions-Koeffizient
+	private PropertyReadAccess RA_dispStep = null;		//Dispersions-Koeffizient
+	private PropertyReadAccess RA_dispEnd = null;		//Dispersions-Koeffizient
+	private PropertyReadAccess RA_breedStart = null;		//Breed-Koeffizient
+	private PropertyReadAccess RA_breedStep = null;		//Breed-Koeffizient
+	private PropertyReadAccess RA_breedEnd = null;		//Breed-Koeffizient
+	private PropertyReadAccess RA_roadGravityStart = null;	//Road-Gravity-Koeffizient
+	private PropertyReadAccess RA_roadGravityStep = null;	//Road-Gravity-Koeffizient
+	private PropertyReadAccess RA_roadGravityEnd = null;	//Road-Gravity-Koeffizient
+	private PropertyReadAccess RA_slopeStart = null;	//Slope-Koeffizient
+	private PropertyReadAccess RA_slopeStep = null;	//Slope-Koeffizient
+	private PropertyReadAccess RA_slopeEnd = null;	//Slope-Koeffizient
+	private PropertyReadAccess RA_criticalSlope = null;	//Critical Slope Value
+	private PropertyReadAccess RA_roadGrid = null;	//Road Grid
+	private PropertyReadAccess RA_slopeGrid = null;	//Slope Grid
+	private PropertyReadAccess RA_referenceGrid = null;	//Observed Validation Grid
+	private ListPropertyWriteAccess WA_outResults = null;	//Output Validation Results
+
+	// **************** Variablen mit denen gearbeitet wird *******************
+	private WritableGrid inputGrid = null; // Input Grid
+	private WritableGrid outputGrid = null; // Output Grid
+	private int steps = 0; // Number of steps
+	private int MonteCarlo = 0;	//Number of Monte Carlo Iterations
+	private WritableGrid areaRestr = null; //Area Restrictions
+	protected double spreadStart = 0;	//Spread-Koeffizient
+	protected double spreadStep = 0;	//Spread-Koeffizient
+	protected double spreadEnd = 0;	//Spread-Koeffizient
+	protected double dispStart = 0;	//Dispersions-Koeffizient
+	protected double dispStep = 0;	//Dispersions-Koeffizient
+	protected double dispEnd = 0;	//Dispersions-Koeffizient
+	protected double breedStart = 0;	//Breed-Koeffizient
+	protected double breedStep = 0;	//Breed-Koeffizient
+	protected double breedEnd = 0;	//Breed-Koeffizient
+	protected double roadGravityStart = 0;	//Road-Gravity-Koeffizient
+	protected double roadGravityStep = 0;	//Road-Gravity-Koeffizient
+	protected double roadGravityEnd = 0;	//Road-Gravity-Koeffizient
+	protected double slopeStart = 0;	//Slope-Koeffizient
+	protected double slopeStep = 0;	//Slope-Koeffizient
+	protected double slopeEnd = 0;	//Slope-Koeffizient
+	protected double criticalSlope = 0;	//Critical Slope Value
+	private WritableGrid roadGrid = null;	//Road Grid
+	private WritableGrid slopeGrid = null;	//Slope Grid
+	private WritableGrid referenceGrid = null;	//Observed Validation Grid 
+	private ListPropertyWriteAccess outResults = null;	//Output Validation Results
+		
+	private  static final int[][] NEIGHBOR = new int[][] {
+	      {-1,-1}, {0,-1}, {1,-1},
+	      {-1, 0},         {1, 0},
+	      {-1, 1}, {0, 1}, {1, 1}
+	  };
+	
+	protected  HashMap<Number,Number> slopeLUT;
+	
+	/**
+	 * Erzeugt eine neue Instanz des Modells.
+	 */
+	public UrbanGrowthModelCalibration() {
+		super(new UrbanGrowthModelCalibrationContentManager());
+		this.contManager = (UrbanGrowthModelCalibrationContentManager) super.contManager;
+	}
+
+	
+	/**
+	 * Initializes the model. Like in the init method of every {@link XuluModel}
+	 * the resources are initalized. 
+	 */
+	public void performModelInit() {
+		if (contManager == null)
+			return;
+		// Zugriffsrechte aus Ressourcen/Propertys holen
+		RA_steps = null;
+		if (contManager.getResource(0).getData() != null)
+			RA_steps = ((ScalarProperty) contManager.getResource(0).getData())
+					.getReadAccess(this);
+		RA_MonteCarlo = null;
+		if (contManager.getResource(1).getData() != null)
+			RA_MonteCarlo = ((ScalarProperty) contManager.getResource(1).getData())
+					.getReadAccess(this);
+		RA_inputGrid = null;
+		if (contManager.getResource(2).getData() != null)
+			RA_inputGrid = ((ScalarProperty) contManager.getResource(2)
+					.getData()).getReadAccess(this);
+		WA_outputGrid = null;
+		if (contManager.getResource(3).getData() != null)
+			WA_outputGrid = ((ScalarProperty) contManager.getResource(3)
+					.getData()).getWriteAccess(this);
+		RA_areaRestr = null;
+		if (contManager.getResource(4).getData() != null)
+			RA_areaRestr = ((ScalarProperty) contManager.getResource(4)
+					.getData()).getReadAccess(this);
+		RA_roadGrid = null;
+		if (contManager.getResource(5).getData() != null)
+			RA_roadGrid = ((ScalarProperty) contManager.getResource(5)
+					.getData()).getReadAccess(this);
+		RA_slopeGrid = null;
+		if (contManager.getResource(6).getData() != null)
+			RA_slopeGrid = ((ScalarProperty) contManager.getResource(6)
+					.getData()).getReadAccess(this);
+		RA_referenceGrid = null;
+		if(contManager.getResource(7).getData() != null)
+			RA_referenceGrid = ((ScalarProperty) contManager.getResource(7)
+					.getData()).getReadAccess(this);
+		RA_spreadStart = null;
+		if (contManager.getResource(8).getData() != null)
+			RA_spreadStart = ((ScalarProperty) contManager.getResource(8).getData())
+					.getReadAccess(this);
+		RA_spreadStep = null;
+		if (contManager.getResource(9).getData() != null)
+			RA_spreadStep = ((ScalarProperty) contManager.getResource(9).getData())
+					.getReadAccess(this);
+		RA_spreadEnd = null;
+		if (contManager.getResource(10).getData() != null)
+			RA_spreadEnd = ((ScalarProperty) contManager.getResource(10).getData())
+					.getReadAccess(this);
+		RA_dispStart = null;
+		if (contManager.getResource(11).getData() != null)
+			RA_dispStart = ((ScalarProperty) contManager.getResource(11).getData())
+					.getReadAccess(this);
+		RA_dispStep = null;
+		if (contManager.getResource(12).getData() != null)
+			RA_dispStep = ((ScalarProperty) contManager.getResource(12).getData())
+					.getReadAccess(this);
+		RA_dispEnd = null;
+		if (contManager.getResource(13).getData() != null)
+			RA_dispEnd = ((ScalarProperty) contManager.getResource(13).getData())
+					.getReadAccess(this);
+		RA_breedStart = null;
+		if (contManager.getResource(14).getData() != null)
+			RA_breedStart = ((ScalarProperty) contManager.getResource(14).getData())
+					.getReadAccess(this);
+		RA_breedStep = null;
+		if (contManager.getResource(15).getData() != null)
+			RA_breedStep = ((ScalarProperty) contManager.getResource(15).getData())
+					.getReadAccess(this);
+		RA_breedEnd = null;
+		if (contManager.getResource(16).getData() != null)
+			RA_breedEnd = ((ScalarProperty) contManager.getResource(16).getData())
+					.getReadAccess(this);
+		RA_roadGravityStart = null;
+		if (contManager.getResource(17).getData() != null)
+			RA_roadGravityStart = ((ScalarProperty) contManager.getResource(17).getData())
+					.getReadAccess(this);
+		RA_roadGravityStep = null;
+		if (contManager.getResource(18).getData() != null)
+			RA_roadGravityStep = ((ScalarProperty) contManager.getResource(18).getData())
+					.getReadAccess(this);
+		RA_roadGravityEnd = null;
+		if (contManager.getResource(19).getData() != null)
+			RA_roadGravityEnd = ((ScalarProperty) contManager.getResource(19).getData())
+					.getReadAccess(this);
+		RA_slopeStart = null;
+		if (contManager.getResource(20).getData() != null)
+			RA_slopeStart = ((ScalarProperty) contManager.getResource(20).getData())
+					.getReadAccess(this);
+		RA_slopeStep = null;
+		if (contManager.getResource(21).getData() != null)
+			RA_slopeStep = ((ScalarProperty) contManager.getResource(21).getData())
+					.getReadAccess(this);
+		RA_slopeEnd = null;
+		if (contManager.getResource(22).getData() != null)
+			RA_slopeEnd = ((ScalarProperty) contManager.getResource(22).getData())
+					.getReadAccess(this);
+		RA_criticalSlope = null;
+		if (contManager.getResource(23).getData() != null)
+			RA_criticalSlope = ((ScalarProperty) contManager.getResource(23).getData())
+					.getReadAccess(this);
+		WA_outResults = null;
+		if (contManager.getResource(24).getData() != null)
+			WA_outResults = ((ListProperty) contManager.getResource(24)
+					.getData()).getWriteAccess(this);
+		
+		// Variablen belegen mit denen gearbeitet wird
+		steps = RA_steps.getValueAsInt();
+		MonteCarlo = RA_MonteCarlo.getValueAsInt();
+		inputGrid = (WritableGrid) RA_inputGrid.getValue();
+		outputGrid = (WritableGrid) WA_outputGrid.getValue();
+		areaRestr = (WritableGrid) RA_areaRestr.getValue();
+		
+		//this.stepCount = steps.getValueAsInt();
+		stepCount 		= 1;
+	    spreadStart  	= RA_spreadStart.getValueAsDouble();
+	    spreadStep  	= RA_spreadStep.getValueAsDouble();
+	    spreadEnd  		= RA_spreadEnd.getValueAsDouble();
+	    dispStart		= RA_dispStart.getValueAsDouble();
+	    dispStep		= RA_dispStep.getValueAsDouble();
+	    dispEnd			= RA_dispEnd.getValueAsDouble();
+	    breedStart		= RA_breedStart.getValueAsDouble();
+	    breedStep		= RA_breedStep.getValueAsDouble();
+	    breedEnd		= RA_breedEnd.getValueAsDouble();
+	    roadGravityStart= RA_roadGravityStart.getValueAsDouble();
+	    roadGravityStep = RA_roadGravityStep.getValueAsDouble();
+	    roadGravityEnd 	= RA_roadGravityEnd.getValueAsDouble();
+	    slopeStart		= RA_slopeStart.getValueAsDouble();
+	    slopeStep		= RA_slopeStep.getValueAsDouble();
+	    slopeEnd		= RA_slopeEnd.getValueAsDouble();
+	    criticalSlope 	= RA_criticalSlope.getValueAsDouble();	
+	    roadGrid 		= (WritableGrid) RA_roadGrid.getValue();
+	    slopeGrid 		= (WritableGrid) RA_slopeGrid.getValue();
+	    referenceGrid 	= (WritableGrid) RA_referenceGrid.getValue();
+		outResults 		= WA_outResults;
+
+		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);
+			}
+		}
+	}
+
+	/**
+	* like in every model: frees the resources
+	 */
+	public void performModelDispose() {
+
+		// Ressourcen wieder freigeben
+		releaseAccess(RA_steps);
+		releaseAccess(RA_MonteCarlo);
+		releaseAccess(RA_inputGrid);
+		releaseAccess(WA_outputGrid);
+		releaseAccess(RA_areaRestr);
+		releaseAccess(RA_spreadStart);
+		releaseAccess(RA_spreadStep);
+		releaseAccess(RA_spreadEnd);
+		releaseAccess(RA_dispStart);
+		releaseAccess(RA_dispStep);
+		releaseAccess(RA_dispEnd);
+		releaseAccess(RA_breedStart);
+		releaseAccess(RA_breedStep);
+		releaseAccess(RA_breedEnd);
+		releaseAccess(RA_roadGravityStart);
+		releaseAccess(RA_roadGravityStep);
+		releaseAccess(RA_roadGravityEnd);
+		releaseAccess(RA_slopeStart);
+		releaseAccess(RA_slopeStep);
+		releaseAccess(RA_slopeEnd);
+		releaseAccess(RA_criticalSlope);
+		releaseAccess(RA_roadGrid);
+		releaseAccess(RA_slopeGrid);
+		releaseAccess(WA_outResults);
+	}
+
+	
+	public void performModelStep(int stepNo) {
+		
+		/**
+		 * Ermitteln der maximalen Hangneigung
+		 */
+		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;		//Maximale Hangneigung im Slope-Bild
+				} 
+			}
+		}
+		
+		/**
+		 * Definition von Variablen, die als Output des gesamten Kalibrierungsdurchlaufs benötigt werden
+		 */
+		float MCtotalAgreementResult = 0f;
+		int ngrids = 0;
+		int slopeOut = 0;
+		int spreadOut = 0;
+		int dispOut = 0;
+		int breedOut = 0;
+		int roadGravityOut = 0;
+		
+		/**
+		 * Start des gesamten Kalibrierungsdurchlaufs:
+		 * 1. Für jeden Slope-Wert zwischen Start und End...
+		 * 2. Für jeden Spread-Wert zwischen Start und End...
+		 * 3. Für jeden Dispersion-Wert zwischen Start und End...
+		 * 4. Für jeden Breed-Wert zwischen Start und End...
+		 */
+		
+		for(int slope = (int)slopeStart;slope <= (int)slopeEnd; slope = slope+(int)slopeStep){
+			
+			//Variablendefinitionen bzgl. Slope-Berechnungen
+			slopeOut = slope;							//slopeOut wird als Ausgabewert benötigt und erhält am Anfang der Schleife den Wert von slope
+			slopeLUT = new HashMap<Number,Number>();	//Definition eines Lookup-Tables (HashMap --> jeder Indexwert bekommt einen Wert zugewiesen)
+			int MaxSlopeResistance = 100;				//Hangneigung kann maximal 100% betragen	
+			double exp = 0.0;							
+			exp = (slope / (MaxSlopeResistance / 2));
+			double[] lookup = new double[slopeMax+1];	//ein Array, das slopeMax+1 Stellen lang ist (+1, da Arrays mit der Zahl 0 beginnen)
+			Number key = 0;								//die Zahl key nimmt den Wert des Index für den Lookup-Table an
+		
+			//Aufbau des Lookup-Tables
+			for (int i = 0;i <= slopeMax;i++){							//Für jede Hangneigung zwischen 0% und dem maximal im Bild vorhandenen Wert
+				if (i <= criticalSlope){								//der kleiner als criticalSlope ist
+					double val = (criticalSlope - i) / criticalSlope;	//berechne den Wert val
+					lookup[i] = 1 - Math.pow(val,exp);					//und füge den Wert val hoch exp an der Stelle i in das Array lookup ein
+					key = i;											//Index-Wert ist key
+				} else{													//Ist der Wert größer als criticalSlope
+					lookup[i] = 1;										//wird der Wert 1 in das Array eingefügt
+					key = i;										
+				}
+				slopeLUT.put(key,lookup[i]);							//put platziert die Werte key und den entsprechenden Wert aus dem Array lookup in die HashMap-Tabelle
+//				statusOut.println(slopeLUT.get(key));
+			}	
+		
+
+			for(int spread = (int)spreadStart; spread <= (int)spreadEnd; spread = spread+(int)spreadStep){
+				spreadOut = spread;		//spreadOut wird als Ausgabewert benötigt und erhält am Anfang der Schleife den Wert von spread
+				for(int disp = (int)dispStart; disp <= (int)dispEnd; disp = disp+(int)dispStep){
+					dispOut = disp;		//dispOut wird als Ausgabewert benötigt und erhält am Anfang der Schleife den Wert von disp
+					for(int breed = (int)breedStart; breed <= (int)breedEnd+1; breed = breed+(int)breedStep){
+						breedOut = breed;	//breedOut wird als Ausgabewert benötigt und erhält am Anfang der Schleife den Wert von breed
+						for(int roadGravity = (int)roadGravityStart; roadGravity <=(int)roadGravityEnd; roadGravity = roadGravity+(int)roadGravityStep){
+							roadGravityOut = roadGravity;	//roadGravityOut wird als Ausgabewert benötigt und erhält am Anfang der Schleife den Wert von roadGravity
+							
+							/**
+							 * An dieser Stelle beginnt der eigentliche Modellalgorithmus des UrbanGrowth-Modells.
+							 * Da bei der Kalibrierung das Modell durch jede mögliche Kombination an Werten durchiteriert,
+							 * wird der Algorithmus x-mal durchlaufen.
+							 * Da häufig Zufallswerte in das Modell eingebaut sind, ist es sinnvoll jeden Iterationsschritt mehrfach durchzuführen
+							 * und die Ergebnisse zu mitteln. Dies geschieht "Monte-Carlo"-mal (Wert wird in Modellparametern angegeben).
+							 * Das bedeutet, dass der Modellalgorithmus zusätzlich in die folgende for-Schleife eingebunden ist.
+							 */
+							float pos1 = 0;	//das hier ist nicht optimal gelöst. Für jede Stelle im Result Array eine eigene Variable definiert, die später ausgelesen wird. Habs nur auf die Schnelle nicht besser hinbekommen
+							float pos2 = 0;
+							float pos3 = 0;
+							float pos4 = 0;
+							float pos5 = 0;
+							float pos6 = 0;
+							float pos7 = 0;
+							float pos8 = 0;
+							float pos9 = 0;
+							float pos10 = 0;
+							float pos11 = 0;
+							float pos12 = 0;
+							for(int MC = 1; MC <= MonteCarlo; MC++){	//führe den Modellalgorithmus 1 bis MC-mal durch
+								RasterUtil.copyInto(inputGrid, outputGrid);		//starte dabei aber mit dem Eingabebild (das Ausgabebild verändert sich nach jedem Modellschritt!!)
+//								statusOut.println("Starting step " + stepNo + "...");
+//								statusOut.println(steps);
+								
+								/**
+								 * Der Modelllauf muss so oft wiederholt werden, wie Jahre für den Kalibrierungsmodus angegeben wurden.
+								 * Für die anschließende Bewertung der Ergebnisse zählt nur das Bild des Schlussjahres
+								 */
+									for(int timeSteps = 1;timeSteps <=steps;timeSteps++){	
+										//Dimensionen des Rasters werden definiert
+										int areaMinX = outputGrid.getMinX();								
+										int areaMinY = outputGrid.getMinY();
+										int areaMaxX = outputGrid.getMinX() + outputGrid.getWidth() - 1;
+										int areaMaxY = outputGrid.getMinY() + outputGrid.getHeight() - 1;
+										int areaWidth = outputGrid.getWidth();
+										int areaHeight = outputGrid.getHeight();
+										
+										//weitere Variablendefinitionen
+										long localStartTime = System.currentTimeMillis();
+										boolean anyBodyAlive = false;
+		
+										boolean[][] tmpGrid = new boolean[outputGrid.getWidth()][outputGrid.getHeight()];	//temporäres Raster, in das true und false geschrieben wird, je nachdem ob Siedlung nach Modellschritt vorhanden ist oder nicht
+										Float actUrb = null;
+		
+										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;
+		
+										// Variablen, die für den DISPERSION Bereich benötigt werden
+										double disp_value = Math.round((disp*0.005)* Math.sqrt(Math.pow(outputGrid.getWidth(), 2)+(Math.pow(outputGrid.getHeight(), 2))));
+										int dispRandX = 0;
+										int dispRandY = 0;
+										float slopeRandDisp = 0;
+		
+										// Variablen, die für den ROAD GRAVITY Bereich benötigt werden
+										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);
+		
+
+										/*****************************************************************
+										 * DISPERSION and BREED
+										 *****************************************************************/
+										
+										//Verteile soviel neue Pixel zufällig in geeigneten Bereichen, bis disp_value erreicht ist
+										//-->Beginn einer do-while-Schleife
+										int p = 0;	
+										do{
+											dispRandX = Math.round((float) Math.random()*areaWidth);											//Zufallsposition in X-Richtung
+											dispRandY = Math.round((float) Math.random()*areaHeight);											//Zufallsposition in Y-Richtung
+											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){			//wenn der Slope-Wert kleiner als der Wert der Zufallszahl ist
+												tmpGrid[dispRandX][dispRandY] = true;	//wird "true" ins temporäre Raster geschrieben (neue Siedlung entsteht!!)
+												anzDispTreffer++;						//Anzahl der Disp-Treffer wird hochgezählt
+												
+												//
+												//hier beginnt der BREED Bereich
+												//
+												//Variablendefinitionen
+												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)	//wenn durch DISPERSION neue Zellen entstanden sind UND der Breed-Zufallswert kleiner als der Breed-Wert ist
+													breedNb = calculateNeighbors(dispRandX,dispRandY,NbValue);	//werden die Nachbarzellen dieser neuen Zellen gezählt, und zwar alle, die zur weiteren Besiedlung zur Verfügung stehen (--> Funktion calculateNeighbors)
+		        			       
+												int RNBreed1 = 0;
+												int RNBreed2 = 0;
+												float RNBreedSlope = 0f;
+		        
+												if (breedNb >= 2 && tmpGrid[dispRandX][dispRandY] == true){		//sind mehr als 2 Nachbarzellen verfügbar und die Koordinate X/Y true...
+													int anzBreedTemp = 0;
+													int[] nbPossibleBreedUrban = null;
+													RNBreed1 = 1 + Math.round((float)Math.random()*(breedNb-1));	//werden 2 Zufallszahlen zwischen 1 und breedNb erzeugt
+													RNBreed2 = 1 + Math.round((float)Math.random()*(breedNb-1));
+													if (RNBreed2 == RNBreed1)										//falls beide Zufallszahlen den gleichen Wert haben sollten, wird die zweite Zahl nochmal erzeugt
+														RNBreed2 = 1 + Math.round((float)Math.random()*(breedNb-1));	
+													for (int cellBreed = 0; cellBreed < NEIGHBOR.length; cellBreed++){	//die Nachbarn jeder Zelle müssen nochmal durchgezählt werden, um zu bestimmen, welche per Zufallswert in Siedlung umgewandelt werden soll
+														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();	 										//Zufallszahl zum Abgleich mit Slope-Koeffizient
+														int getSlopeNb = (int) slopeGrid.getRasterSampleAsFloat(nbBreedX,nbBreedY);		//holt sich den Slope-Wert aus dem Slope-Raster
+														Double doubleObjNb = (Double)slopeLUT.get(getSlopeNb);							//holt den Slope-Wert aus dem Lookup-Table (get) und konvertiert in Double
+														double slopeDoubleNb = doubleObjNb.doubleValue();								//konvertiert Double-Objekt in double-Wert
+														float breedSample = outputGrid.getRasterSampleAsFloat(nbBreedX,nbBreedY);		//holt den Wert aus dem Output-Raster
+														if (breedSample == 0f){													//ist der Wert aus dem Output-Raster 0
+															anzBreedTemp++;														//wird die Zahl der zur Verfügung stehenden Zellen hochgezählt
+															nbPossibleBreedUrban = new int[] {nbBreedX,nbBreedY,anzBreedTemp};	//und die Nummer und Koordinaten der jeweiligen Zellen in ein Array geschrieben 
+															if (nbPossibleBreedUrban[2] == RNBreed1 || nbPossibleBreedUrban[2] == RNBreed2 && slopeDoubleNb < RNBreedSlope){	//entspricht die Nummer einer der zuvor erstellten Zufallswerte...
+																tmpGrid[nbBreedX][nbBreedY] = true;								//wird in das temporäre Raster "true" geschrieben (--> neue Siedlung durch BREED entstanden!!)
+																anzBreedTreffer++;												//die Anzahl der BREED-Treffer wird gezählt
+															}	
+														}
+													}
+												} 
+											} p++;		//der Wert p wird hochgezählt, bis der Disp-Wert erreicht ist
+		       
+										} 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
+										//ENDE DISPERSION UND BREED WACHSTUM
+	
+										/*********************************************************************
+										 * EDGE
+										 *********************************************************************/
+		
+										//iterate over all cells
+										for (int x = 0; x < outputGrid.getWidth(); x++)
+											for (int y = 0; y < outputGrid.getHeight(); y++) {		//für jede Zelle in x/y-Richtung
+												
+												//Dimensionen des Rasters
+												int areaMinXadd = areaMinX + x;								
+												int areaMinYadd = areaMinY + y;
+												
+												//Variablendefinitionen
+												int anzNachbarn = 0;
+												int noNachbarn = 0;
+				
+												for (int nbCellIdx = 0; nbCellIdx < NEIGHBOR.length; nbCellIdx++) {	//zählt alle Nachbarn jeder Rasterzelle durch
+													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 als anzNachbarn gezählt
+														anzNachbarn++;
+													if (rasterSample == 0f)		//ist sie nicht urban (0), wird sie als noNachbarn gezählt		
+														noNachbarn++;
+												}
+				
+												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
+													
+													//Variablendefinitionen
+													int anzTemp = 0;
+													int[] nbPossibleUrban = null;
+													RN = 1 + Math.round((float)Math.random()*(noNachbarn-1));
+													float RNEdgeSlope = 0;
+													int nbUrbanX = 0;
+													int nbUrbanY = 0;
+													
+													for (int nbCellChange = 0; nbCellChange < NEIGHBOR.length; nbCellChange++){	//dann starte eine Schleife
+														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;
+														if (areaRestr.getRasterSampleAsFloat(nbX,nbY) != 0)
+															continue;
+														RNEdgeSlope = (float)Math.random();									//Zufallszahl zum Abgleich mit Slope-Koeffizient
+														int getSlopeNb = (int) slopeGrid.getRasterSampleAsFloat(nbX,nbY);	//holt sich den Slope-Wert aus dem Slope-Raster
+														Double doubleObjNb = (Double)slopeLUT.get(getSlopeNb);				//holt den Slope-Wert aus dem Lookup-Table (get) und konvertiert in Double
+														double slopeDoubleNb = doubleObjNb.doubleValue();					//konvertiert Double-Objekt in double-Wert
+														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++;			//und die Anzahl der Spread-Treffer gezählt
+																}
+															} 
+														}
+														nbCell = new int[] {nbX,nbY,(int) rasterSample};	//die Nummer und Koordinaten der jeweiligen Zellen wird in ein Array geschrieben
+													}
+												}
+												if (anzNachbarn>0) anyBodyAlive = true;		
+											}	//ENDE EDGE-WACHSTUM
+		
+										/*********************************************************************
+										 * ROAD
+										 *********************************************************************/
+										
+										//Variablendefinitionen
+										int anzGesamt = 0;
+										int[] cellValue = null;
+										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, outputGrid.getWidth(), outputGrid.getHeight()); //ein Rechteck wird definiert
+		
+										//For-Schleife zählt alle als true markierten Zellen im Temp-Raster
+										for (int x = 0; x < outputGrid.getWidth();x++)
+											for(int y = 0; y < outputGrid.getHeight();y++){
+												int X = outputGrid.getMinX() + x;
+												int Y = outputGrid.getMinY() + y;
+												if (tmpGrid[X][Y]==true){
+													anzGesamt++;
+												}		
+											}
+		
+										//Beginn einer do-while-Schleife
+										do{
+											//Variablendefinitionen
+											RSearchRoad = Math.round((float)Math.random()*anzGesamt);	//Zufallszahl zwischen 1 und Anzahl aller bisher neu hinzugekommener Pixel
+											int anzTruePixels = 0;
+											int roadNeighborhoodRange = 0;
+											int RSearchNbRoad = 0;
+												for (int x = 0; x < outputGrid.getWidth();x++){		//gesamtes Raster wird durchsucht
+													for(int y = 0; y < outputGrid.getHeight();y++){
+														int X = outputGrid.getMinX() + x;
+														int Y = outputGrid.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){	//eins der neu entstandenen Pixel wird nach Zufallsprinzip ausgewählt
+																//statusOut.println(cellValue[0]+","+cellValue[1]+","+cellValue[2]);
+																//statusOut.println(r+","+RSearchRoad);
+																r++;							//Anzahl der so gefundenen Zellen wird hochgezählt, bis Road-Koeffizient erreicht wird
+																//JETZT NACH STRAßE SUCHEN!!
+																float roadValue = roadGrid.getRasterSampleAsFloat(X,Y);	//An Koordinate X/Y wird Wert aus roadGrid geholt
+																//		statusOut.println(roadValue);
+																if (roadValue > 0.0){					//wenn Wert > 0 ist...
+																	tempRoadCell = new int[] {X,Y};		//wird an Koordinate X/Y eine temporäre Straßenzelle platziert (bzw. Koordinaten in Array geschrieben
+					//												statusOut.println("Strasse in Entfernung 0: "+tempRoadCell[0]+","+tempRoadCell[1]);
+																	int nbCellNew[] = roadWalk(tempRoadCell[0],tempRoadCell[1],disp);	//von dieser Koordinate aus wird ein Road-Walk gestartete (siehe Funktion roadWalk!!)
+																	if(nbCellNew != null){									//kommt nach roadWalk ein Wert zurück (d.h. wurde potenziell zu besiedelndes Pixel gefunden)...
+																		tmpGrid[nbCellNew[0]][nbCellNew[1]] = true;			//wird "true" ins temporäre Raster geschrieben (neue Siedlungszelle gefunden!!)
+					//													statusOut.println(nbCellNew.length);
+					//													statusOut.println("Neue Zelle: "+nbCellNew[0]+","+nbCellNew[1]);
+					//													statusOut.println("++++++++++++++++++++++++++++++++++++++++");
+																		
+																		//wenn per roadWalk eine neue Zelle gefunden wurde, kann sie auch noch als Ausbreitungszentrum fungieren. Daher geht von ihr 
+																		//nochmals ein "Breed" aus.
+																		
+																		//Variablendefinitionen
+																		float nbRoadBreed = 0f;
+																		int nbRoadBreedNeighbors = 0;
+																		nbRoadBreedNeighbors = calculateNeighbors(nbCellNew[0],nbCellNew[1],nbRoadBreed);	//Nachbarzellen der neuen Zelle werden gezählt
+																		int RNRoadBreed1 = 0;
+																		int RNRoadBreed2 = 0;
+																		int nbRoadBreedX = 0;
+																		int nbRoadBreedY = 0;
+																		int anzRoadBreedTreffer = 0;
+							        
+																		if (nbRoadBreedNeighbors >= 2){	//sind mehr als 2 potenzielle Nachbarzellen verfügbar
+																			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();											//Zufallszahl zum Abgleich mit Slope-Koeffizient
+																				int getSlopeNb = (int) slopeGrid.getRasterSampleAsFloat(nbRoadBreedX,nbRoadBreedY);	//holt sich den Slope-Wert aus dem Slope-Raster
+																				Double doubleObjNb = (Double)slopeLUT.get(getSlopeNb);								//holt den Slope-Wert aus dem Lookup-Table (get) und konvertiert in Double
+																				double slopeDoubleNb = doubleObjNb.doubleValue();									//konvertiert Double-Objekt in double-Wert
+																				float breedSample = outputGrid.getRasterSampleAsFloat(nbRoadBreedX,nbRoadBreedY);	//holt die Werte aus den jeweiligen Nachbarzellen
+																				if (breedSample == 0f){			//hat die Nachbarzelle den Wert 0 wird anzBreedTemp hochgezählt
+																					anzBreedTemp++;
+																					nbPossibleBreedUrban = new int[] {nbRoadBreedX,nbRoadBreedY,anzBreedTemp};		//und Koordinaten dieser Zelle in Array geschrieben
+																					if (nbPossibleBreedUrban[2] == RNRoadBreed1 || nbPossibleBreedUrban[2] == RNRoadBreed2 && slopeDoubleNb < RNRoadBreedSlope){	//stimmt der Wert mit einer der beiden Zufallszahlen überein und ist laut Slope-Wert Besiedlung erlaubt...
+																						tmpGrid[nbRoadBreedX][nbRoadBreedY] = true;					//..wird "true" ins temporäre Raster geschrieben (neue Siedlungszelle erstellt!)
+																						anzRoadBreedTreffer++;										//Anzahl der durch Breed nach RoadWalk erzeugten Zellen wird hochgezählt
+						//																statusOut.println("Road-Breed-Treffer: "+anzRoadBreedTreffer);
+																					}
+																				}
+																			}
+																		}
+																	} else{		//kommt nach Road-Walk nichts zurück...
+																		//	statusOut.println("Keine neue Zelle gefunden");
+																	}
+																//ist an der Stelle, an der eine neue Zelle entstanden war keine Straße, wird im Folgenden in ihrer Nähe danach gesucht...
+																} else{	
+																	
+																	int anzRoadNb = 0;
+								
+																	//HIER MIT FOR SCHLEIFE RECHTECK WACHSEN LASSEN!!!
+																	for (int roadSearch = 0; roadSearch <= rg_value; roadSearch++){		//vergrößere die Nachbarschaft, bis rg_value erreicht ist
+																		if (anzRoadNb > 0)		//höre auf, sobald Straße in der Nachbarschaft gefunden wurde
+																			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);	//hole Wert aus Straßenraster
+																				if (roadValueNb > 0f)	//ist der Wert im Straßen-Raster > 0 zähle den Wert anzRoadNb hoch
+																					anzRoadNb++;
+																				
+																				//statusOut.println("Strasse in Entfernung 1: "+anzRoadNb+","+nbRoadCellsX+","+nbRoadCellsY);
+																			}
+																		roadNeighborhoodRange++;	
+																		RSearchNbRoad = Math.round((float)Math.random()*anzRoadNb);
+																		//statusOut.println("--> Zyklus "+roadNeighborhoodRange+"Nachbarn: "+anzRoadNb);
+																		//statusOut.println(RSearchNbRoad);
+																		int anzTempRoadNb = 0;
+																		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))
+																				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);	//hole Wert aus Straßenraster
+																				if (roadValueNbTemp > 0f){									//ist der Wert im Straßen-Raster > 0 zähle den Wert anzRoadNbTemp hoch
+																					anzTempRoadNb++;
+																					tempNbRoadCell = new int[] {nbRoadCellsX,nbRoadCellsY,anzTempRoadNb};	//schreibe die Koordinaten in ein Array
+																					if (tempNbRoadCell[2]==RSearchNbRoad){					//Wenn der Wert im Array dem vorher definierten Zufallswert entspricht...
+																						//statusOut.println("Treffer: "+tempNbRoadCell[0]+","+tempNbRoadCell[1]+","+tempNbRoadCell[2]);
+																						tempRoadCell = tempNbRoadCell;						//...wird die temporäre Straßenzelle an diese Position verschoben
+											//											statusOut.println("Strasse in Entfernung "+roadSearch+": "+tempRoadCell[0]+","+tempRoadCell[1]+","+tempRoadCell[2]);
+																						int nbCellNew[] = roadWalk(tempRoadCell[0],tempRoadCell[1],disp);	//von dort aus wird ein Road-Walk durchgeführt (--> siehe Funktion roadWalk!)
+																						if(nbCellNew != null){												//kommt nach roadWalk ein Wert zurück (d.h. wurde potenziell zu besiedelndes Pixel gefunden)...
+																							tmpGrid[nbCellNew[0]][nbCellNew[1]] = true;						//wird "true" ins temporäre Raster geschrieben (neue Siedlungszelle gefunden!!)
+//																							statusOut.println(nbCellNew.length);
+//																							statusOut.println("Neue Zelle: "+nbCellNew[0]+","+nbCellNew[1]);
+//																							statusOut.println("++++++++++++++++++++++++++++++++++++++++");
+																							//Variablendefinitionen
+																							
+																							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;
+																						
+																							//wenn per roadWalk eine neue Zelle gefunden wurde, kann sie auch noch als Ausbreitungszentrum fungieren. Daher geht von ihr 
+																							//nochmals ein "Breed" aus. (GLEICHE FUNKTION WIE OBEN!!)
+												        
+																							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);
+																										}
+																									}
+																								}
+												        									}
+																						} else{			//sind nicht mind. 2 Nachbarzellen gefunden worden...
+																							//statusOut.println("Keine neue Zelle gefunden");
+																						}
+																					}
+																				}
+																			}
+																		}
+																	}
+																}
+															}
+														}	
+													}
+												}
+			
+										} 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();
+		
+
+										/**
+										 * Hier endet der eigentliche Modellalgorithmus des Urban Growth Modells.
+										 * Als nächstes wird das was ins temporäre grid geschrieben wurde ins outputGrid geschrieben.
+										 * Mit dem outputGrid wird dann im nächsten Zeitschritt weitergerechnet, bis die maximale Anzahl
+										 * an Jahren erreicht ist. Danach wird die nächste Kombination an Koeffizienten gewählt.
+										 */
+										
+										// TempGrid auf das echte Grid schreiben
+										for (int y = 1; y < outputGrid.getHeight()-1;y++ ) 
+											for (int x = 1; x < outputGrid.getWidth()-1; x++ ) {
+				
+												int X = outputGrid.getMinX() + x;
+												int Y = outputGrid.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!");
+										}
+		
+										//RasterUtil.copyInto(outputGrid, inputGrid);
+										//	System.out.println("Finished step " + (stepNo) + " in "
+										//			+ ((System.currentTimeMillis() - localStartTime)) + " ms\n");
+										localStartTime = System.currentTimeMillis();
+		
+									}	//HIER ENDET DER ZEITSCHRITT. DIE SCHLEIFE WIRD DURCHLAUFEN, BIS MAX JAHRE ERREICHT SIND.
+		
+									/**
+									 * +++++ MULTIPLE RESOLUTION VALIDATION ++++++
+									 * Sind alle Zeitschritte durchlaufen, wird das Endergebnis validiert.
+									 * Als Validierungsmethode wurde die Multiple Resolution Validation ausgewählt (siehe
+									 * Costanza(1989), Pontius (2002), Pontius et al. (2005), Lesschen et al. (2005),
+									 * Pontius et al. (2008a), Pontius et al. (2008b))
+									 * Für das SLEUTH-Modell werden eigentlich eine Reihe an Landschaftsmaßen zur Validierung
+									 * verwendet (siehe Clarke et al. (1997), Dietzel et al. (2007)), wie z.B. LeeSallee
+									 * oder OSM. Da für die spätere Validierung der Modellierungsergebnisse und zum Vergleich mit 
+									 * anderen Modelltypen die Multiple Resolution Validation verwendet wird, wird sie auch zur
+									 * Bewertung der Kalibrierungsschritte verwendet.
+									 */
+									
+									//Variablendefinitionen
+									int RoverallSum = 0;
+									int RnumClasses = 0;
+									int SoverallSum = 0;
+									int SnumClasses = 0;
+									int correct = 0;
+									double fractionCorrect = 0f;
+		
+
+									long localStartTime = System.currentTimeMillis();
+									neighborhoodRange = (int) Math.sqrt(referenceGrid.getWidth()*referenceGrid.getHeight()); //maximal mögliche Zellengröße
+									//statusOut.println(neighborhoodRange);
+									resultArray = new float[13];		//!!!!!!!!! Ergebnis-Array
+									resultArrayFinal = new float[MonteCarlo-1][10];	//?????????????
+									
+									//Für die Ausgangs-Auflösung wird berechnet, wieviel % der Pixel zwischen Modell und Referenz übereinstimmen
+									for (int x = 0; x < referenceGrid.getWidth(); x++)
+										for (int y = 0; y < referenceGrid.getHeight(); y++) {
+											float Rtmp = referenceGrid.getRasterSampleAsFloat(x, y);
+											float Stmp = outputGrid.getRasterSampleAsFloat(x, y);
+											if (!Float.isNaN(Rtmp) && !Float.isNaN(Stmp)){
+												RoverallSum ++;
+												SoverallSum ++;
+												if (Rtmp > RnumClasses)
+													RnumClasses = (int) Rtmp;
+												if (Stmp > SnumClasses)
+													SnumClasses = (int) Stmp;	
+												if (Rtmp == Stmp)
+													correct++;
+											}
+										}
+									fractionCorrect = (double) correct / (double) RoverallSum;
+		
+									//Anzahl der Pixel pro Klasse
+									for (int i = 1; i <= RnumClasses; i++){
+										int Rj = 0;
+										int Sj = 0;
+										for (int x = 0; x < referenceGrid.getWidth(); x++)
+											for (int y = 0; y < referenceGrid.getHeight(); y++){
+												float Rtmp = referenceGrid.getRasterSampleAsFloat(x, y);
+												float Stmp = outputGrid.getRasterSampleAsFloat(x, y);
+												if (!Float.isNaN(Rtmp))
+													if ((int) Rtmp == i)
+														Rj++;
+												if (!Float.isNaN(Stmp))
+													if ((int) Stmp == i)
+														Sj++;
+											}
+										//statusOut.println("Klasse "+i+": Referenz("+Rj+"), Simulation("+Sj+")");
+									}
+		
+									ngrids = 0;
+									
+									//Die eigentliche Validierung wird für alle Zellengrößen von 1 (Ausgangsauflösung) bis "neighborhoodRange" durchgeführt
+									for (int r1 = 1; r1 <= neighborhoodRange; r1 = r1+r1){	//für Zellengröße 1 bis zur max. möglichen Zellengröße wird Statistik durchgeführt
+										//statusOut.println(r1);	
+										ngrids++;
+										float SumWn = 0f;	//Summe der gewichteten Mittelwerte 
+										int SumCells = 0;	//Summe der Zellen
+										float totalAgreement = 0f;	//Endergebnis
+										for (int x = 0; x < referenceGrid.getWidth(); x = x+r1)	//für jeden größer werdenden Zellenbereich...
+											for (int y = 0; y < referenceGrid.getHeight(); y = y+r1){	//was folgt passiert innerhalb einer größeren Rasterzelle
+												int nCells = 0;		//Anzahl Zellen pro größerer Zelle
+												float SumMinRS = 0f;	//Summe der Min-Werte bei Vergleich zweier Raster
+												float Wn = 0;	//Gewichtete Zelle
+												for(int x2 = x; x2 < x+r1; x2++)	//für jede kleinere Zelle innerhalb der größeren...
+													for(int y2 = y; y2 < y+r1; y2++){
+														if ( x2 < referenceGrid.getMinX() || y2 < referenceGrid.getMinY() || x2 > referenceGrid.getMinX()+referenceGrid.getWidth()-1 || y2 > referenceGrid.getMinY()+referenceGrid.getHeight()-1 ||
+																Float.isNaN(referenceGrid.getRasterSampleAsFloat(x2,y2)))
+															continue;
+														nCells++;	//zähle "positive" Zellen
+													}
+												for (int i = 0; i <= RnumClasses; i++){	//für jede Klasse i
+													int Rn = 0;	//Anzahl in Referenzkarte
+													int Sn = 0;	//Anzahl in Simulationskarte
+													float Rnj = 0f;	//Anteil in Referenzkarte
+													float Snj = 0f;	//Anteil in Simulationskarte
+													float MinRS = 0f;	//Min des Vergleichs zwischen beiden Karten
+													for(int x3 = x; x3 < x+r1; x3++)	//für jede kleinere Zelle pro größerer Zelle...
+														for(int y3 = y; y3 < y+r1; y3++){
+															if ( x3 < referenceGrid.getMinX() || y3 < referenceGrid.getMinY() || x3 > referenceGrid.getMinX()+referenceGrid.getWidth()-1 || y3 > referenceGrid.getMinY()+referenceGrid.getHeight()-1 ||
+																	Float.isNaN(referenceGrid.getRasterSampleAsFloat(x3,y3)))
+																continue;
+															float Rtmp = referenceGrid.getRasterSampleAsFloat(x3, y3);	//hole Wert aus Referenz-Karte und
+															float Stmp = outputGrid.getRasterSampleAsFloat(x3, y3);	//Simulationskarte
+															if ((int) Rtmp == i)
+																Rn++;	//zähle in Referenzkarte Zellen, die zu Klasse i gehören 
+															if ((int) Stmp == i)
+																Sn++;	//und in Simulationskarte
+														}
+													if(nCells > 0){	//wenn positive Zellen vorhanden sind...
+														Rnj = (float)Rn / (float)nCells;	//berechne Anteile pro größerer Zelle
+														Snj = (float)Sn / (float)nCells;
+													}
+													MinRS = Math.min(Rnj, Snj);	//nehme Minimum-Wert des Vergleichs beider Karten
+													SumMinRS += MinRS;	//summiere die Minimum-Werte auf
+													//	statusOut.println(i+" Min"+MinRS+" Anzahl: "+nCells);	
+												}
+												
+												Wn = (float)nCells * SumMinRS;
+												//	statusOut.println(SumMinRS+", gewichtet: "+Wn);
+												//Erstelle Output-Karten
+												float WnCell = 0f;
+												for(int x4 = x; x4 < x+r1; x4++)	//für jede kleinere Zelle pro größerer Zelle...
+													for(int y4 = y; y4 < y+r1; y4++){
+														if ( x4 < referenceGrid.getMinX() || y4 < referenceGrid.getMinY() || x4 > referenceGrid.getMinX()+referenceGrid.getWidth()-1 || y4 > referenceGrid.getMinY()+referenceGrid.getHeight()-1 ||
+																Float.isNaN(referenceGrid.getRasterSampleAsFloat(x4,y4)))
+															continue;
+														WnCell = Wn / (float)nCells; //pro Zelle wird Mittelwert des Vergleichs genommen
+														//actualValidation.setRasterSample( WnCell ,x4 ,y4);	
+													}
+				
+												SumCells += (float)nCells;	//Summiere alle Zellen auf
+												SumWn += Wn;	//Summiere die gewichteten Anteile auf
+											}		//hier endet die Berechnung innerhalb einer größeren Rasterzelle
+										
+										
+										//Total Agreement:
+										//statusOut.println(SumWn+" / "+SumCells);
+										totalAgreement = SumWn / (float)SumCells;	//Ergebnisformel
+										//statusOut.println(totalAgreement);	
+
+										outResults.addValue(totalAgreement);
+										resultArray[ngrids] = totalAgreement;
+
+										//	statusOut.println("Gesamt-Pixel: "+RoverallSum);
+										//	statusOut.println("Anzahl Klassen: "+RnumClasses);
+										//	statusOut.println("Fraction Correct: "+fractionCorrect);
+										
+									}	//Hier endet die Berechnung pro Auflösung
+		
+								//	System.out.println("(Slope:"+slope+" Spread:"+spread+" Dispersion:"+disp+" Breed: "+breed+" RoadGravity: "+roadGravity+") "+
+								//			resultArray[1]+","+resultArray[2]+","+resultArray[3]+","+resultArray[4]+","+resultArray[5]+","+resultArray[6]+
+								//			","+resultArray[7]+","+resultArray[8]+","+resultArray[9]);
+																		
+									//Führe jede Position einzeln auf. Das sollte noch automatisiert werden !!!
+									pos1 += resultArray[1];
+									pos2 += resultArray[2];
+									pos3 += resultArray[3];
+									pos4 += resultArray[4];
+									pos5 += resultArray[5];
+									pos6 += resultArray[6];
+									pos7 += resultArray[7];
+									pos8 += resultArray[8];
+									pos9 += resultArray[9];
+									pos10 += resultArray[10];
+									pos11 += resultArray[11];
+									pos12 += resultArray[12];
+									//	System.out.print("Finished step " + (stepNo) + " in "
+									//			+ ((System.currentTimeMillis() - localStartTime)) + " ms");
+									localStartTime = System.currentTimeMillis();
+									//	System.out.println(" with sum (local calculated): " + RoverallSum);
+							}	//!!!!!!!!!! Hier endet ein Monte-Carlo-Schritt
+							
+							System.out.println("-->(Slope:"+slope+" Spread:"+spread+" Dispersion:"+disp+" Breed: "+breed+" RoadGravity: "+roadGravity+") "+
+									pos1/MonteCarlo+","+pos2/MonteCarlo+","+pos3/MonteCarlo+","+pos4/MonteCarlo+","+pos5/MonteCarlo+","+pos6/MonteCarlo+
+											","+pos7/MonteCarlo+","+pos8/MonteCarlo+","+pos9/MonteCarlo+","+pos10/MonteCarlo+","+pos11/MonteCarlo+","+pos12/MonteCarlo);
+						}	//Ende RoadGravity-Koeffizient
+					}	//Ende Breed-Koeffizient
+				}	//Ende Disp-Koeffizient
+			}	//Ende Spread-Koeffizient
+		}	//Ende Slope-Koeffizient
+	}	//Ende Model-Step
+	
+	private int[] roadWalk(int X,int Y,double disp){
+//		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;
+			int nbRoadY = 0;
+			int areaMinX = outputGrid.getMinX();								//Dimensionen des Rasters
+			int areaMinY = outputGrid.getMinY();
+			int areaMaxX = outputGrid.getMinX() + outputGrid.getWidth() - 1;
+			int areaMaxY = outputGrid.getMinY() + outputGrid.getHeight() - 1;
+			int roadNb = 0;
+			int roadNbTemp = 0;
+			int RN = 0;
+						
+			int[] nbCell = null;
+			for (int nbRoadCells = 0; nbRoadCells < NEIGHBOR.length; nbRoadCells++){
+				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++;
+			}
+	//		statusOut.println("Nachbarn von temporaerer Strassenzelle: "+roadNb);
+			
+			if (roadNb > 0){
+				RN = 1 + Math.round((float)Math.random()*(roadNb-1));
+			
+				for (int nbRoadCells = 0; nbRoadCells < NEIGHBOR.length; nbRoadCells++){
+					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++;
+							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){
+									int nbUrbanizeX = 0;
+									int nbUrbanizeY = 0;
+									int NbTemp = 0;
+									float RNRoadSlope = 0f;
+						//			statusOut.println(X+","+Y);
+									for (int urbanizeCells = 0; urbanizeCells < NEIGHBOR.length; urbanizeCells++){
+										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;
+										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]};
+											}
+										}	
+									}
+								
+							} else{
+								nbCellNew = null;
+							}	break;
+						}
+						
+					}
+					
+				}
+			}
+			
+			}
+		}
+		return nbCellNew;
+		}
+	
+	private int calculateNeighbors(int X, int Y, float NbValue){
+		int nbX = 0;
+		int nbY = 0;
+		int areaMinX = outputGrid.getMinX();								//Dimensionen des Rasters
+		int areaMinY = outputGrid.getMinY();
+		int areaMaxX = outputGrid.getMinX() + outputGrid.getWidth() - 1;
+		int areaMaxY = outputGrid.getMinY() + outputGrid.getHeight() - 1;
+		int Nb = 0;
+		for (int nbCells = 0; nbCells < NEIGHBOR.length; nbCells++){
+			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;
+			if (areaRestr.getRasterSampleAsFloat(nbX,nbY) != 0)
+	        	continue;
+			float rasterSample = outputGrid.getRasterSampleAsFloat(nbX,nbY);
+			if (rasterSample == NbValue)
+				Nb++;
+		}
+	//	statusOut.println("..."+Nb+"...");
+		return Nb;
+	}
+	
+	protected static boolean checkNoData(int x, int y, WritableGrid grid) {
+	    return Float.isNaN(grid.getRasterSampleAsFloat(x,y));
+	  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelCalibrationContentManager.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelCalibrationContentManager.java	2009-09-07 12:15:20 UTC (rev 55)
+++ trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelCalibrationContentManager.java	2009-09-10 14:02:19 UTC (rev 56)
@@ -0,0 +1,54 @@
+package edu.bonn.xulu.plugin.model.sleuth;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.ScalarProperty;
+import edu.bonn.xulu.data.XuluDataException;
+import edu.bonn.xulu.model.AbstractModelContentManager;
+import edu.bonn.xulu.model.DefaultModelResource;
+import edu.bonn.xulu.model.ModelResource;
+import edu.bonn.xulu.model.ValuePropertyResource;
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+
+
+public class UrbanGrowthModelCalibrationContentManager extends AbstractModelContentManager {
+	
+	public UrbanGrowthModelCalibrationContentManager() {
+		super(25);
+	    
+		resource[0] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Number of steps",ScalarProperty.class,Integer.class,false);
+		resource[1] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Number of MonteCarlo Iterations",ScalarProperty.class,Integer.class,false);
+		resource[2] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Input Grid",ScalarProperty.class,WritableGrid.class,false);
+		resource[3] = new ValuePropertyResource(ModelResource.CATEGORY_OUTPUT,"Output Grid",ScalarProperty.class,WritableGrid.class,false);
+	    resource[4] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Area Restrictions",ScalarProperty.class,WritableGrid.class,false);
+	    resource[5] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Road Grid",ScalarProperty.class,WritableGrid.class,false);
+	    resource[6] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Slope Grid",ScalarProperty.class,WritableGrid.class,false);
+	    resource[7] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Reference Grid",ScalarProperty.class,WritableGrid.class,false);
+	    resource[8] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Spread Coefficient Start",ScalarProperty.class,Double.class,false);
+	    resource[9] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Spread Coefficient Step",ScalarProperty.class,Double.class,false);
+	    resource[10] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Spread Coefficient End",ScalarProperty.class,Double.class,false);
+	    resource[11]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Dispersion Coefficient Start",ScalarProperty.class,Double.class,false);
+	    resource[12]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Dispersion Coefficient Step",ScalarProperty.class,Double.class,false);
+	    resource[13]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Dispersion Coefficient End",ScalarProperty.class,Double.class,false);
+	    resource[14]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Breed Coefficient Start",ScalarProperty.class,Double.class,false);
+	    resource[15]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Breed Coefficient Step",ScalarProperty.class,Double.class,false);
+	    resource[16]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Breed Coefficient End",ScalarProperty.class,Double.class,false);
+	    resource[17]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"RoadGravity Coefficient Start",ScalarProperty.class,Double.class,false);
+	    resource[18]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"RoadGravity Coefficient Step",ScalarProperty.class,Double.class,false);
+	    resource[19]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"RoadGravity Coefficient End",ScalarProperty.class,Double.class,false);
+	    resource[20]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Slope Coefficient Start",ScalarProperty.class,Double.class,false);
+	    resource[21]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Slope Coefficient Step",ScalarProperty.class,Double.class,false);
+	    resource[22]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Slope Coefficient End",ScalarProperty.class,Double.class,false);
+	    resource[23]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Critical Slope",ScalarProperty.class,Double.class,false);
+	    resource[24]= new ValuePropertyResource(ModelResource.CATEGORY_OUTPUT,"Validation Results",ListProperty.class,Float.class,false);
+	 	// ===== Ressourcen Bezeichnungen lokalisieren =====
+	    resetCaptions(null);
+	}
+	
+	
+	@Override
+	public void checkAndError() throws XuluDataException {
+		// TODO Auto-generated method stub
+		super.checkAndError();
+	}
+}

Added: trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelCalibrationSelfModification.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelCalibrationSelfModification.java	2009-09-07 12:15:20 UTC (rev 55)
+++ trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelCalibrationSelfModification.java	2009-09-10 14:02:19 UTC (rev 56)
@@ -0,0 +1,1290 @@
+package edu.bonn.xulu.plugin.model.sleuth;
+
+import java.awt.Rectangle;
+import java.util.HashMap;
+
+import appl.util.RasterUtil;
+
+import edu.bonn.xulu.model.AbstractStepModel;
+import edu.bonn.xulu.model.XuluModel;
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.ListPropertyWriteAccess;
+import schmitzm.data.property.PropertyReadAccess;
+import schmitzm.data.property.PropertyWriteAccess;
+import schmitzm.data.property.ScalarProperty;
+
+/**
+ * @see AverageNeighborhoodContentManager
+ * @author Dominik Appl
+ * @version 1.0
+ */
+public class UrbanGrowthModelCalibrationSelfModification extends AbstractStepModel {
+
+	private int neighborhoodRange = 0;
+	private float[] resultArray;
+	private float[][] resultArrayFinal;
+	/**
+	 * Speichert den ContentManager fuer das Modell.
+	 */
+	protected UrbanGrowthModelCalibrationSelfModificationContentManager contManager;
+
+	// ********** Lese/Schreibrechte, die fuer den gesamten ***********
+	// ********** Modellanlauf gehalten werden muessen ***********
+	private PropertyReadAccess RA_steps = null; // Number of steps
+	private PropertyReadAccess RA_MonteCarlo = null;	//Number of MonteCarlo Iterations
+	private PropertyReadAccess RA_inputGrid = null; // Input Grid
+	private PropertyWriteAccess WA_outputGrid = null; // Output Grid
+	private PropertyReadAccess RA_areaRestr = null; //Area Restrictions
+	private PropertyReadAccess RA_spreadStart = null;	//Spread-Koeffizient
+	private PropertyReadAccess RA_spreadStep = null;	//Spread-Koeffizient
+	private PropertyReadAccess RA_spreadEnd = null;	//Spread-Koeffizient
+	private PropertyReadAccess RA_dispStart = null;		//Dispersions-Koeffizient
+	private PropertyReadAccess RA_dispStep = null;		//Dispersions-Koeffizient
+	private PropertyReadAccess RA_dispEnd = null;		//Dispersions-Koeffizient
+	private PropertyReadAccess RA_breedStart = null;		//Breed-Koeffizient
+	private PropertyReadAccess RA_breedStep = null;		//Breed-Koeffizient
+	private PropertyReadAccess RA_breedEnd = null;		//Breed-Koeffizient
+	private PropertyReadAccess RA_roadGravityStart = null;	//Road-Gravity-Koeffizient
+	private PropertyReadAccess RA_roadGravityStep = null;	//Road-Gravity-Koeffizient
+	private PropertyReadAccess RA_roadGravityEnd = null;	//Road-Gravity-Koeffizient
+	private PropertyReadAccess RA_slopeStart = null;	//Slope-Koeffizient
+	private PropertyReadAccess RA_slopeStep = null;	//Slope-Koeffizient
+	private PropertyReadAccess RA_slopeEnd = null;	//Slope-Koeffizient
+	private PropertyReadAccess RA_criticalSlope = null;	//Critical Slope Value
+	private PropertyReadAccess RA_roadGrid = null;	//Road Grid
+	private PropertyReadAccess RA_slopeGrid = null;	//Slope Grid
+	private PropertyReadAccess RA_referenceGrid = null;	//Observed Validation Grid
+	private ListPropertyWriteAccess WA_outResults = null;	//Output Validation Results
+	private PropertyReadAccess RA_roadGravSens = null;	//RoadGravity Sensitivity
+	private PropertyReadAccess RA_slopeSens = null;	//Slope Sensitivity
+	private PropertyReadAccess RA_criticalLow = null;	//Critical Low
+	private PropertyReadAccess RA_criticalHigh = null;	//Critical High
+	private PropertyReadAccess RA_Boom = null;	//Boom
+	private PropertyReadAccess RA_Bust = null;	//Bust
+	
+	// **************** Variablen mit denen gearbeitet wird *******************
+	private WritableGrid inputGrid = null; // Input Grid
+	private WritableGrid outputGrid = null; // Output Grid
+	private int steps = 0; // Number of steps
+	private int MonteCarlo = 0;	//Number of Monte Carlo Iterations
+	private WritableGrid areaRestr = null; //Area Restrictions
+	protected double spreadStart = 0;	//Spread-Koeffizient
+	protected double spreadStep = 0;	//Spread-Koeffizient
+	protected double spreadEnd = 0;	//Spread-Koeffizient
+	protected double dispStart = 0;	//Dispersions-Koeffizient
+	protected double dispStep = 0;	//Dispersions-Koeffizient
+	protected double dispEnd = 0;	//Dispersions-Koeffizient
+	protected double breedStart = 0;	//Breed-Koeffizient
+	protected double breedStep = 0;	//Breed-Koeffizient
+	protected double breedEnd = 0;	//Breed-Koeffizient
+	protected double roadGravityStart = 0;	//Road-Gravity-Koeffizient
+	protected double roadGravityStep = 0;	//Road-Gravity-Koeffizient
+	protected double roadGravityEnd = 0;	//Road-Gravity-Koeffizient
+	protected double slopeStart = 0;	//Slope-Koeffizient
+	protected double slopeStep = 0;	//Slope-Koeffizient
+	protected double slopeEnd = 0;	//Slope-Koeffizient
+	protected double criticalSlope = 0;	//Critical Slope Value
+	private WritableGrid roadGrid = null;	//Road Grid
+	private WritableGrid slopeGrid = null;	//Slope Grid
+	private WritableGrid referenceGrid = null;	//Observed Validation Grid 
+	private ListPropertyWriteAccess outResults = null;	//Output Validation Results
+	protected double roadGravSens = 0;	//RoadGravity Sensitivity
+	protected double slopeSens = 0;	//Slope Sensitivity
+	protected double criticalLow = 0;	//critical Low
+	protected double criticalHigh = 0;	//critical High
+	protected double boom = 0;	//Boom
+	protected double bust = 0;	//Bust
+	
+	private  static final int[][] NEIGHBOR = new int[][] {
+	      {-1,-1}, {0,-1}, {1,-1},
+	      {-1, 0},         {1, 0},
+	      {-1, 1}, {0, 1}, {1, 1}
+	  };
+	
+	protected  HashMap<Number,Number> slopeLUT;
+	private int slopeMax = 0;
+	private int totalPixels = 0;
+	private int excldCount = 0;
+	
+	/**
+	 * Erzeugt eine neue Instanz des Modells.
+	 */
+	public UrbanGrowthModelCalibrationSelfModification() {
+		super(new UrbanGrowthModelCalibrationSelfModificationContentManager());
+		this.contManager = (UrbanGrowthModelCalibrationSelfModificationContentManager) super.contManager;
+	}
+
+	
+	/**
+	 * Initializes the model. Like in the init method of every {@link XuluModel}
+	 * the resources are initalized. 
+	 */
+	public void performModelInit() {
+		if (contManager == null)
+			return;
+		// Zugriffsrechte aus Ressourcen/Propertys holen
+		RA_steps = null;
+		if (contManager.getResource(0).getData() != null)
+			RA_steps = ((ScalarProperty) contManager.getResource(0).getData())
+					.getReadAccess(this);
+		RA_MonteCarlo = null;
+		if (contManager.getResource(1).getData() != null)
+			RA_MonteCarlo = ((ScalarProperty) contManager.getResource(1).getData())
+					.getReadAccess(this);
+		RA_inputGrid = null;
+		if (contManager.getResource(2).getData() != null)
+			RA_inputGrid = ((ScalarProperty) contManager.getResource(2)
+					.getData()).getReadAccess(this);
+		WA_outputGrid = null;
+		if (contManager.getResource(3).getData() != null)
+			WA_outputGrid = ((ScalarProperty) contManager.getResource(3)
+					.getData()).getWriteAccess(this);
+		RA_areaRestr = null;
+		if (contManager.getResource(4).getData() != null)
+			RA_areaRestr = ((ScalarProperty) contManager.getResource(4)
+					.getData()).getReadAccess(this);
+		RA_roadGrid = null;
+		if (contManager.getResource(5).getData() != null)
+			RA_roadGrid = ((ScalarProperty) contManager.getResource(5)
+					.getData()).getReadAccess(this);
+		RA_slopeGrid = null;
+		if (contManager.getResource(6).getData() != null)
+			RA_slopeGrid = ((ScalarProperty) contManager.getResource(6)
+					.getData()).getReadAccess(this);
+		RA_referenceGrid = null;
+		if(contManager.getResource(7).getData() != null)
+			RA_referenceGrid = ((ScalarProperty) contManager.getResource(7)
+					.getData()).getReadAccess(this);
+		RA_spreadStart = null;
+		if (contManager.getResource(8).getData() != null)
+			RA_spreadStart = ((ScalarProperty) contManager.getResource(8).getData())
+					.getReadAccess(this);
+		RA_spreadStep = null;
+		if (contManager.getResource(9).getData() != null)
+			RA_spreadStep = ((ScalarProperty) contManager.getResource(9).getData())
+					.getReadAccess(this);
+		RA_spreadEnd = null;
+		if (contManager.getResource(10).getData() != null)
+			RA_spreadEnd = ((ScalarProperty) contManager.getResource(10).getData())
+					.getReadAccess(this);
+		RA_dispStart = null;
+		if (contManager.getResource(11).getData() != null)
+			RA_dispStart = ((ScalarProperty) contManager.getResource(11).getData())
+					.getReadAccess(this);
+		RA_dispStep = null;
+		if (contManager.getResource(12).getData() != null)
+			RA_dispStep = ((ScalarProperty) contManager.getResource(12).getData())
+					.getReadAccess(this);
+		RA_dispEnd = null;
+		if (contManager.getResource(13).getData() != null)
+			RA_dispEnd = ((ScalarProperty) contManager.getResource(13).getData())
+					.getReadAccess(this);
+		RA_breedStart = null;
+		if (contManager.getResource(14).getData() != null)
+			RA_breedStart = ((ScalarProperty) contManager.getResource(14).getData())
+					.getReadAccess(this);
+		RA_breedStep = null;
+		if (contManager.getResource(15).getData() != null)
+			RA_breedStep = ((ScalarProperty) contManager.getResource(15).getData())
+					.getReadAccess(this);
+		RA_breedEnd = null;
+		if (contManager.getResource(16).getData() != null)
+			RA_breedEnd = ((ScalarProperty) contManager.getResource(16).getData())
+					.getReadAccess(this);
+		RA_roadGravityStart = null;
+		if (contManager.getResource(17).getData() != null)
+			RA_roadGravityStart = ((ScalarProperty) contManager.getResource(17).getData())
+					.getReadAccess(this);
+		RA_roadGravityStep = null;
+		if (contManager.getResource(18).getData() != null)
+			RA_roadGravityStep = ((ScalarProperty) contManager.getResource(18).getData())
+					.getReadAccess(this);
+		RA_roadGravityEnd = null;
+		if (contManager.getResource(19).getData() != null)
+			RA_roadGravityEnd = ((ScalarProperty) contManager.getResource(19).getData())
+					.getReadAccess(this);
+		RA_slopeStart = null;
+		if (contManager.getResource(20).getData() != null)
+			RA_slopeStart = ((ScalarProperty) contManager.getResource(20).getData())
+					.getReadAccess(this);
+		RA_slopeStep = null;
+		if (contManager.getResource(21).getData() != null)
+			RA_slopeStep = ((ScalarProperty) contManager.getResource(21).getData())
+					.getReadAccess(this);
+		RA_slopeEnd = null;
+		if (contManager.getResource(22).getData() != null)
+			RA_slopeEnd = ((ScalarProperty) contManager.getResource(22).getData())
+					.getReadAccess(this);
+		RA_criticalSlope = null;
+		if (contManager.getResource(23).getData() != null)
+			RA_criticalSlope = ((ScalarProperty) contManager.getResource(23).getData())
+					.getReadAccess(this);
+		WA_outResults = null;
+		if (contManager.getResource(24).getData() != null)
+			WA_outResults = ((ListProperty) contManager.getResource(24)
+					.getData()).getWriteAccess(this);
+		RA_roadGravSens = null;
+		if (contManager.getResource(25).getData() != null)
+			RA_roadGravSens = ((ScalarProperty) contManager.getResource(25).getData())
+					.getReadAccess(this);
+		RA_slopeSens = null;
+		if (contManager.getResource(26).getData() != null)
+			RA_slopeSens = ((ScalarProperty) contManager.getResource(26).getData())
+					.getReadAccess(this);
+		RA_criticalLow = null;
+		if (contManager.getResource(27).getData() != null)
+			RA_criticalLow = ((ScalarProperty) contManager.getResource(27).getData())
+					.getReadAccess(this);
+		RA_criticalHigh = null;
+		if (contManager.getResource(28).getData() != null)
+			RA_criticalHigh = ((ScalarProperty) contManager.getResource(28).getData())
+					.getReadAccess(this);
+		RA_Boom = null;
+		if (contManager.getResource(29).getData() != null)
+			RA_Boom = ((ScalarProperty) contManager.getResource(29).getData())
+					.getReadAccess(this);
+		RA_Bust = null;
+		if (contManager.getResource(30).getData() != null)
+			RA_Bust = ((ScalarProperty) contManager.getResource(30).getData())
+					.getReadAccess(this);
+		
+		// Variablen belegen mit denen gearbeitet wird
+		steps = RA_steps.getValueAsInt();
+		MonteCarlo = RA_MonteCarlo.getValueAsInt();
+		inputGrid = (WritableGrid) RA_inputGrid.getValue();
+		outputGrid = (WritableGrid) WA_outputGrid.getValue();
+		areaRestr = (WritableGrid) RA_areaRestr.getValue();
+		
+		//this.stepCount = steps.getValueAsInt();
+		stepCount 		= 1;
+	    spreadStart  	= RA_spreadStart.getValueAsDouble();
+	    spreadStep  	= RA_spreadStep.getValueAsDouble();
+	    spreadEnd  		= RA_spreadEnd.getValueAsDouble();
+	    dispStart		= RA_dispStart.getValueAsDouble();
+	    dispStep		= RA_dispStep.getValueAsDouble();
+	    dispEnd			= RA_dispEnd.getValueAsDouble();
+	    breedStart		= RA_breedStart.getValueAsDouble();
+	    breedStep		= RA_breedStep.getValueAsDouble();
+	    breedEnd		= RA_breedEnd.getValueAsDouble();
+	    roadGravityStart= RA_roadGravityStart.getValueAsDouble();
+	    roadGravityStep = RA_roadGravityStep.getValueAsDouble();
+	    roadGravityEnd 	= RA_roadGravityEnd.getValueAsDouble();
+	    slopeStart		= RA_slopeStart.getValueAsDouble();
+	    slopeStep		= RA_slopeStep.getValueAsDouble();
+	    slopeEnd		= RA_slopeEnd.getValueAsDouble();
+	    criticalSlope 	= RA_criticalSlope.getValueAsDouble();	
+	    roadGrid 		= (WritableGrid) RA_roadGrid.getValue();
+	    slopeGrid 		= (WritableGrid) RA_slopeGrid.getValue();
+	    referenceGrid 	= (WritableGrid) RA_referenceGrid.getValue();
+		outResults 		= WA_outResults;
+		roadGravSens = RA_roadGravSens.getValueAsDouble();
+	    slopeSens = RA_slopeSens.getValueAsDouble();
+	    criticalLow = RA_criticalLow.getValueAsDouble();
+	    criticalHigh = RA_criticalHigh.getValueAsDouble();
+	    boom = RA_Boom.getValueAsDouble();
+	    bust = RA_Bust.getValueAsDouble();
+
+		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);
+			}
+		}
+		
+		for (int x = 0; x < inputGrid.getWidth();x++ ) 
+			for (int y = 0; y < inputGrid.getHeight(); y++ ) {
+				if ( x < inputGrid.getMinX() || y < inputGrid.getMinY() || x > inputGrid.getMinX()+inputGrid.getWidth()-1 || y > inputGrid.getMinY()+inputGrid.getHeight()-1 ||
+			            Float.isNaN(outputGrid.getRasterSampleAsFloat(x,y)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
+			             continue;
+				totalPixels++;
+				if (areaRestr.getRasterSampleAsFloat(x,y) != 0 && !Float.isNaN(areaRestr.getRasterSampleAsFloat(x,y)))
+		        	//continue;	//wenn in Area Restriction oder wenn schon Siedlung da ist, mach weiter
+				//if (inputGrid.getRasterSampleAsFloat(i,ii) == 1f);
+					excldCount++;
+			}
+		
+	}
+
+	/**
+	* like in every model: frees the resources
+	 */
+	public void performModelDispose() {
+
+		// Ressourcen wieder freigeben
+		releaseAccess(RA_steps);
+		releaseAccess(RA_MonteCarlo);
+		releaseAccess(RA_inputGrid);
+		releaseAccess(WA_outputGrid);
+		releaseAccess(RA_areaRestr);
+		releaseAccess(RA_spreadStart);
+		releaseAccess(RA_spreadStep);
+		releaseAccess(RA_spreadEnd);
+		releaseAccess(RA_dispStart);
+		releaseAccess(RA_dispStep);
+		releaseAccess(RA_dispEnd);
+		releaseAccess(RA_breedStart);
+		releaseAccess(RA_breedStep);
+		releaseAccess(RA_breedEnd);
+		releaseAccess(RA_roadGravityStart);
+		releaseAccess(RA_roadGravityStep);
+		releaseAccess(RA_roadGravityEnd);
+		releaseAccess(RA_slopeStart);
+		releaseAccess(RA_slopeStep);
+		releaseAccess(RA_slopeEnd);
+		releaseAccess(RA_criticalSlope);
+		releaseAccess(RA_roadGrid);
+		releaseAccess(RA_slopeGrid);
+		releaseAccess(WA_outResults);
+		releaseAccess(RA_roadGravSens);
+		releaseAccess(RA_slopeSens);
+		releaseAccess(RA_criticalLow);
+		releaseAccess(RA_criticalHigh);
+		releaseAccess(RA_Boom);
+		releaseAccess(RA_Bust);
+	}
+
+	
+	public void performModelStep(int stepNo) {
+		
+		/**
+		 * Ermitteln der maximalen Hangneigung
+		 */
+		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;		//Maximale Hangneigung im Slope-Bild
+				} 
+			}
+		}
+		
+		/**
+		 * Definition von Variablen, die als Output des gesamten Kalibrierungsdurchlaufs benötigt werden
+		 */
+		float MCtotalAgreementResult = 0f;
+		int ngrids = 0;
+		double slopeF = 0;
+		double spreadF = 0;
+		double dispF = 0;
+		double breedF = 0;
+		double roadGravityF = 0;
+		
+		/**
+		 * Start des gesamten Kalibrierungsdurchlaufs:
+		 * 1. Für jeden Slope-Wert zwischen Start und End...
+		 * 2. Für jeden Spread-Wert zwischen Start und End...
+		 * 3. Für jeden Dispersion-Wert zwischen Start und End...
+		 * 4. Für jeden Breed-Wert zwischen Start und End...
+		 */
+		
+		for(int slope = (int)slopeStart;slope <= (int)slopeEnd; slope = slope+(int)slopeStep){
+			for(int spread = (int)spreadStart; spread <= (int)spreadEnd; spread = spread+(int)spreadStep){
+				for(int disp = (int)dispStart; disp <= (int)dispEnd; disp = disp+(int)dispStep){
+					for(int breed = (int)breedStart; breed <= (int)breedEnd+1; breed = breed+(int)breedStep){
+						for(int roadGravity = (int)roadGravityStart; roadGravity <=(int)roadGravityEnd; roadGravity = roadGravity+(int)roadGravityStep){
+														
+							/**
+							 * An dieser Stelle beginnt der eigentliche Modellalgorithmus des UrbanGrowth-Modells.
+							 * Da bei der Kalibrierung das Modell durch jede mögliche Kombination an Werten durchiteriert,
+							 * wird der Algorithmus x-mal durchlaufen.
+							 * Da häufig Zufallswerte in das Modell eingebaut sind, ist es sinnvoll jeden Iterationsschritt mehrfach durchzuführen
+							 * und die Ergebnisse zu mitteln. Dies geschieht "Monte-Carlo"-mal (Wert wird in Modellparametern angegeben).
+							 * Das bedeutet, dass der Modellalgorithmus zusätzlich in die folgende for-Schleife eingebunden ist.
+							 */
+							float pos1 = 0;	//das hier ist nicht optimal gelöst. Für jede Stelle im Result Array eine eigene Variable definiert, die später ausgelesen wird. Habs nur auf die Schnelle nicht besser hinbekommen
+							float pos2 = 0;
+							float pos3 = 0;
+							float pos4 = 0;
+							float pos5 = 0;
+							float pos6 = 0;
+							float pos7 = 0;
+							float pos8 = 0;
+							float pos9 = 0;
+							float pos10 = 0;
+							float pos11 = 0;
+							float pos12 = 0;
+							for(int MC = 1; MC <= MonteCarlo; MC++){	//führe den Modellalgorithmus 1 bis MC-mal durch
+								RasterUtil.copyInto(inputGrid, outputGrid);		//starte dabei aber mit dem Eingabebild (das Ausgabebild verändert sich nach jedem Modellschritt!!)
+//								statusOut.println("Starting step " + stepNo + "...");
+//								statusOut.println(steps);
+								
+								//Koeffizienten werden für jeden Iterationsschritt zurückgesetzt. Innerhalb eines MC-Laufs können die Koeffizienten modifiziert werden 
+								slopeF = (double)slope;		//slopeF erhält am Beginn der Schleife den Wert von slope und kann innerhalb der Schleife modifiziert werden
+								spreadF = (double)spread;		//spreadF erhält am Beginn der Schleife den Wert von spread und kann innerhalb der Schleife modifiziert werden
+								dispF = (double) disp;		//dispF erhält am Beginn der Schleife den Wert von disp und kann innerhalb der Schleife modifiziert werden
+								breedF = (double)breed;	//breedF erhält am Beginn der Schleife den Wert von breed und kann innerhalb der Schleife modifiziert werden
+								roadGravityF = (double) roadGravity;	//roadGravityF erhält am Beginn der Schleife den Wert von roadGravity und kann innerhalb der Schleife modifiziert werden
+								
+								/**
+								 * Der Modelllauf muss so oft wiederholt werden, wie Jahre für den Kalibrierungsmodus angegeben wurden.
+								 * Für die anschließende Bewertung der Ergebnisse zählt nur das Bild des Schlussjahres
+								 */
+									for(int timeSteps = 1;timeSteps <=steps;timeSteps++){	
+										//Dimensionen des Rasters werden definiert
+										int areaMinX = outputGrid.getMinX();								
+										int areaMinY = outputGrid.getMinY();
+										int areaMaxX = outputGrid.getMinX() + outputGrid.getWidth() - 1;
+										int areaMaxY = outputGrid.getMinY() + outputGrid.getHeight() - 1;
+										int areaWidth = outputGrid.getWidth();
+										int areaHeight = outputGrid.getHeight();
+										
+										//weitere Variablendefinitionen
+										long localStartTime = System.currentTimeMillis();
+										boolean anyBodyAlive = false;
+		
+										boolean[][] tmpGrid = new boolean[outputGrid.getWidth()][outputGrid.getHeight()];	//temporäres Raster, in das true und false geschrieben wird, je nachdem ob Siedlung nach Modellschritt vorhanden ist oder nicht
+										Float actUrb = null;
+		
+										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;
+										int anzGesamtTreffer = 0;
+										int anzRoadTreffer = 0;
+										double growthRate = 0;
+										int thisYear = 0;
+										int roadCount = 0;
+											
+										// Variablen, die für den DISPERSION Bereich benötigt werden
+										double disp_value = Math.round((dispF*0.005)* Math.sqrt(Math.pow(outputGrid.getWidth(), 2)+(Math.pow(outputGrid.getHeight(), 2))));
+										int dispRandX = 0;
+										int dispRandY = 0;
+										float slopeRandDisp = 0;
+		
+										// Variablen, die für den ROAD GRAVITY Bereich benötigt werden
+										double max_RG_value = 100.0;
+										double rg_value = Math.round((roadGravityF/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);
+		
+										//Variablendefinitionen bzgl. Slope-Berechnungen
+										
+										slopeLUT = new HashMap<Number,Number>();	//Definition eines Lookup-Tables (HashMap --> jeder Indexwert bekommt einen Wert zugewiesen)
+										int MaxSlopeResistance = 100;				//Hangneigung kann maximal 100% betragen	
+										double exp = 0.0;							
+										exp = (slopeF / (MaxSlopeResistance / 2));
+										double[] lookup = new double[slopeMax+1];	//ein Array, das slopeMax+1 Stellen lang ist (+1, da Arrays mit der Zahl 0 beginnen)
+										Number key = 0;								//die Zahl key nimmt den Wert des Index für den Lookup-Table an
+									
+										//Aufbau des Lookup-Tables
+										for (int i = 0;i <= slopeMax;i++){							//Für jede Hangneigung zwischen 0% und dem maximal im Bild vorhandenen Wert
+											if (i <= criticalSlope){								//der kleiner als criticalSlope ist
+												double val = (criticalSlope - i) / criticalSlope;	//berechne den Wert val
+												lookup[i] = 1 - Math.pow(val,exp);					//und füge den Wert val hoch exp an der Stelle i in das Array lookup ein
+												key = i;											//Index-Wert ist key
+											} else{													//Ist der Wert größer als criticalSlope
+												lookup[i] = 1;										//wird der Wert 1 in das Array eingefügt
+												key = i;										
+											}
+											slopeLUT.put(key,lookup[i]);							//put platziert die Werte key und den entsprechenden Wert aus dem Array lookup in die HashMap-Tabelle
+//											statusOut.println(slopeLUT.get(key));
+										}	
+										
+										/*****************************************************************
+										 * DISPERSION and BREED
+										 *****************************************************************/
+										
+										//Verteile soviel neue Pixel zufällig in geeigneten Bereichen, bis disp_value erreicht ist
+										//-->Beginn einer do-while-Schleife
+										int p = 0;	
+										do{
+											dispRandX = Math.round((float) Math.random()*areaWidth);											//Zufallsposition in X-Richtung
+											dispRandY = Math.round((float) Math.random()*areaHeight);											//Zufallsposition in Y-Richtung
+											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){			//wenn der Slope-Wert kleiner als der Wert der Zufallszahl ist
+												tmpGrid[dispRandX][dispRandY] = true;	//wird "true" ins temporäre Raster geschrieben (neue Siedlung entsteht!!)
+												anzDispTreffer++;						//Anzahl der Disp-Treffer wird hochgezählt
+												
+												//
+												//hier beginnt der BREED Bereich
+												//
+												//Variablendefinitionen
+												float breedRnd = (float) Math.random()*100;
+												int nbBreedX  = 0;
+												int nbBreedY  = 0;
+												int breedNb	  = 0;
+												float NbValue = 0f;
+												if (tmpGrid[dispRandX][dispRandY] == true && breedRnd < breedF)	//wenn durch DISPERSION neue Zellen entstanden sind UND der Breed-Zufallswert kleiner als der Breed-Wert ist
+													breedNb = calculateNeighbors(dispRandX,dispRandY,NbValue);	//werden die Nachbarzellen dieser neuen Zellen gezählt, und zwar alle, die zur weiteren Besiedlung zur Verfügung stehen (--> Funktion calculateNeighbors)
+		        			       
+												int RNBreed1 = 0;
+												int RNBreed2 = 0;
+												float RNBreedSlope = 0f;
+		        
+												if (breedNb >= 2 && tmpGrid[dispRandX][dispRandY] == true){		//sind mehr als 2 Nachbarzellen verfügbar und die Koordinate X/Y true...
+													int anzBreedTemp = 0;
+													int[] nbPossibleBreedUrban = null;
+													RNBreed1 = 1 + Math.round((float)Math.random()*(breedNb-1));	//werden 2 Zufallszahlen zwischen 1 und breedNb erzeugt
+													RNBreed2 = 1 + Math.round((float)Math.random()*(breedNb-1));
+													if (RNBreed2 == RNBreed1)										//falls beide Zufallszahlen den gleichen Wert haben sollten, wird die zweite Zahl nochmal erzeugt
+														RNBreed2 = 1 + Math.round((float)Math.random()*(breedNb-1));	
+													for (int cellBreed = 0; cellBreed < NEIGHBOR.length; cellBreed++){	//die Nachbarn jeder Zelle müssen nochmal durchgezählt werden, um zu bestimmen, welche per Zufallswert in Siedlung umgewandelt werden soll
+														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();	 										//Zufallszahl zum Abgleich mit Slope-Koeffizient
+														int getSlopeNb = (int) slopeGrid.getRasterSampleAsFloat(nbBreedX,nbBreedY);		//holt sich den Slope-Wert aus dem Slope-Raster
+														Double doubleObjNb = (Double)slopeLUT.get(getSlopeNb);							//holt den Slope-Wert aus dem Lookup-Table (get) und konvertiert in Double
+														double slopeDoubleNb = doubleObjNb.doubleValue();								//konvertiert Double-Objekt in double-Wert
+														float breedSample = outputGrid.getRasterSampleAsFloat(nbBreedX,nbBreedY);		//holt den Wert aus dem Output-Raster
+														if (breedSample == 0f){													//ist der Wert aus dem Output-Raster 0
+															anzBreedTemp++;														//wird die Zahl der zur Verfügung stehenden Zellen hochgezählt
+															nbPossibleBreedUrban = new int[] {nbBreedX,nbBreedY,anzBreedTemp};	//und die Nummer und Koordinaten der jeweiligen Zellen in ein Array geschrieben 
+															if (nbPossibleBreedUrban[2] == RNBreed1 || nbPossibleBreedUrban[2] == RNBreed2 && slopeDoubleNb < RNBreedSlope){	//entspricht die Nummer einer der zuvor erstellten Zufallswerte...
+																tmpGrid[nbBreedX][nbBreedY] = true;								//wird in das temporäre Raster "true" geschrieben (--> neue Siedlung durch BREED entstanden!!)
+																anzBreedTreffer++;												//die Anzahl der BREED-Treffer wird gezählt
+															}	
+														}
+													}
+												} 
+											} p++;		//der Wert p wird hochgezählt, bis der Disp-Wert erreicht ist
+		       
+										} 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
+										//ENDE DISPERSION UND BREED WACHSTUM
+	
+										/*********************************************************************
+										 * EDGE
+										 *********************************************************************/
+		
+										//iterate over all cells
+										for (int x = 0; x < outputGrid.getWidth(); x++)
+											for (int y = 0; y < outputGrid.getHeight(); y++) {		//für jede Zelle in x/y-Richtung
+												
+												//Dimensionen des Rasters
+												int areaMinXadd = areaMinX + x;								
+												int areaMinYadd = areaMinY + y;
+												
+												//Variablendefinitionen
+												int anzNachbarn = 0;
+												int noNachbarn = 0;
+				
+												for (int nbCellIdx = 0; nbCellIdx < NEIGHBOR.length; nbCellIdx++) {	//zählt alle Nachbarn jeder Rasterzelle durch
+													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 als anzNachbarn gezählt
+														anzNachbarn++;
+													if (rasterSample == 0f)		//ist sie nicht urban (0), wird sie als noNachbarn gezählt		
+														noNachbarn++;
+												}
+				
+												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 < spreadF) && (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
+													
+													//Variablendefinitionen
+													int anzTemp = 0;
+													int[] nbPossibleUrban = null;
+													RN = 1 + Math.round((float)Math.random()*(noNachbarn-1));
+													float RNEdgeSlope = 0;
+													int nbUrbanX = 0;
+													int nbUrbanY = 0;
+													
+													for (int nbCellChange = 0; nbCellChange < NEIGHBOR.length; nbCellChange++){	//dann starte eine Schleife
+														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;
+														if (areaRestr.getRasterSampleAsFloat(nbX,nbY) != 0)
+															continue;
+														RNEdgeSlope = (float)Math.random();									//Zufallszahl zum Abgleich mit Slope-Koeffizient
+														int getSlopeNb = (int) slopeGrid.getRasterSampleAsFloat(nbX,nbY);	//holt sich den Slope-Wert aus dem Slope-Raster
+														Double doubleObjNb = (Double)slopeLUT.get(getSlopeNb);				//holt den Slope-Wert aus dem Lookup-Table (get) und konvertiert in Double
+														double slopeDoubleNb = doubleObjNb.doubleValue();					//konvertiert Double-Objekt in double-Wert
+														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++;			//und die Anzahl der Spread-Treffer gezählt
+																}
+															} 
+														}
+														nbCell = new int[] {nbX,nbY,(int) rasterSample};	//die Nummer und Koordinaten der jeweiligen Zellen wird in ein Array geschrieben
+													}
+												}
+												if (anzNachbarn>0) anyBodyAlive = true;		
+											}	//ENDE EDGE-WACHSTUM
+		
+										/*********************************************************************
+										 * ROAD
+										 *********************************************************************/
+										
+										//Variablendefinitionen
+										int anzGesamt = 0;
+										int[] cellValue = null;
+										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, outputGrid.getWidth(), outputGrid.getHeight()); //ein Rechteck wird definiert
+		
+										//For-Schleife zählt alle als true markierten Zellen im Temp-Raster
+										for (int x = 0; x < outputGrid.getWidth();x++)
+											for(int y = 0; y < outputGrid.getHeight();y++){
+												int X = outputGrid.getMinX() + x;
+												int Y = outputGrid.getMinY() + y;
+												if (tmpGrid[X][Y]==true){
+													anzGesamt++;
+												}		
+											}
+		
+										//Beginn einer do-while-Schleife
+										do{
+											//Variablendefinitionen
+											RSearchRoad = Math.round((float)Math.random()*anzGesamt);	//Zufallszahl zwischen 1 und Anzahl aller bisher neu hinzugekommener Pixel
+											int anzTruePixels = 0;
+											int roadNeighborhoodRange = 0;
+											int RSearchNbRoad = 0;
+												for (int x = 0; x < outputGrid.getWidth();x++){		//gesamtes Raster wird durchsucht
+													for(int y = 0; y < outputGrid.getHeight();y++){
+														int X = outputGrid.getMinX() + x;
+														int Y = outputGrid.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){	//eins der neu entstandenen Pixel wird nach Zufallsprinzip ausgewählt
+																//statusOut.println(cellValue[0]+","+cellValue[1]+","+cellValue[2]);
+																//statusOut.println(r+","+RSearchRoad);
+																r++;							//Anzahl der so gefundenen Zellen wird hochgezählt, bis Road-Koeffizient erreicht wird
+																//JETZT NACH STRAßE SUCHEN!!
+																float roadValue = roadGrid.getRasterSampleAsFloat(X,Y);	//An Koordinate X/Y wird Wert aus roadGrid geholt
+																//		statusOut.println(roadValue);
+																if (roadValue > 0.0){					//wenn Wert > 0 ist...
+																	tempRoadCell = new int[] {X,Y};		//wird an Koordinate X/Y eine temporäre Straßenzelle platziert (bzw. Koordinaten in Array geschrieben
+					//												statusOut.println("Strasse in Entfernung 0: "+tempRoadCell[0]+","+tempRoadCell[1]);
+																	int nbCellNew[] = roadWalk(tempRoadCell[0],tempRoadCell[1],dispF);	//von dieser Koordinate aus wird ein Road-Walk gestartete (siehe Funktion roadWalk!!)
+																	if(nbCellNew != null){									//kommt nach roadWalk ein Wert zurück (d.h. wurde potenziell zu besiedelndes Pixel gefunden)...
+																		tmpGrid[nbCellNew[0]][nbCellNew[1]] = true;			//wird "true" ins temporäre Raster geschrieben (neue Siedlungszelle gefunden!!)
+					//													statusOut.println(nbCellNew.length);
+					//													statusOut.println("Neue Zelle: "+nbCellNew[0]+","+nbCellNew[1]);
+					//													statusOut.println("++++++++++++++++++++++++++++++++++++++++");
+																		
+																		//wenn per roadWalk eine neue Zelle gefunden wurde, kann sie auch noch als Ausbreitungszentrum fungieren. Daher geht von ihr 
+																		//nochmals ein "Breed" aus.
+																		
+																		//Variablendefinitionen
+																		float nbRoadBreed = 0f;
+																		int nbRoadBreedNeighbors = 0;
+																		nbRoadBreedNeighbors = calculateNeighbors(nbCellNew[0],nbCellNew[1],nbRoadBreed);	//Nachbarzellen der neuen Zelle werden gezählt
+																		int RNRoadBreed1 = 0;
+																		int RNRoadBreed2 = 0;
+																		int nbRoadBreedX = 0;
+																		int nbRoadBreedY = 0;
+																		int anzRoadBreedTreffer = 0;
+							        
+																		if (nbRoadBreedNeighbors >= 2){	//sind mehr als 2 potenzielle Nachbarzellen verfügbar
+																			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();											//Zufallszahl zum Abgleich mit Slope-Koeffizient
+																				int getSlopeNb = (int) slopeGrid.getRasterSampleAsFloat(nbRoadBreedX,nbRoadBreedY);	//holt sich den Slope-Wert aus dem Slope-Raster
+																				Double doubleObjNb = (Double)slopeLUT.get(getSlopeNb);								//holt den Slope-Wert aus dem Lookup-Table (get) und konvertiert in Double
+																				double slopeDoubleNb = doubleObjNb.doubleValue();									//konvertiert Double-Objekt in double-Wert
+																				float breedSample = outputGrid.getRasterSampleAsFloat(nbRoadBreedX,nbRoadBreedY);	//holt die Werte aus den jeweiligen Nachbarzellen
+																				if (breedSample == 0f){			//hat die Nachbarzelle den Wert 0 wird anzBreedTemp hochgezählt
+																					anzBreedTemp++;
+																					nbPossibleBreedUrban = new int[] {nbRoadBreedX,nbRoadBreedY,anzBreedTemp};		//und Koordinaten dieser Zelle in Array geschrieben
+																					if (nbPossibleBreedUrban[2] == RNRoadBreed1 || nbPossibleBreedUrban[2] == RNRoadBreed2 && slopeDoubleNb < RNRoadBreedSlope){	//stimmt der Wert mit einer der beiden Zufallszahlen überein und ist laut Slope-Wert Besiedlung erlaubt...
+																						tmpGrid[nbRoadBreedX][nbRoadBreedY] = true;					//..wird "true" ins temporäre Raster geschrieben (neue Siedlungszelle erstellt!)
+																						anzRoadBreedTreffer++;										//Anzahl der durch Breed nach RoadWalk erzeugten Zellen wird hochgezählt
+																						anzRoadTreffer++;
+						//																statusOut.println("Road-Breed-Treffer: "+anzRoadBreedTreffer);
+																					}
+																				}
+																			}
+																		}
+																	} else{		//kommt nach Road-Walk nichts zurück...
+																		//	statusOut.println("Keine neue Zelle gefunden");
+																	}
+																//ist an der Stelle, an der eine neue Zelle entstanden war keine Straße, wird im Folgenden in ihrer Nähe danach gesucht...
+																} else{	
+																	
+																	int anzRoadNb = 0;
+								
+																	//HIER MIT FOR SCHLEIFE RECHTECK WACHSEN LASSEN!!!
+																	for (int roadSearch = 0; roadSearch <= rg_value; roadSearch++){		//vergrößere die Nachbarschaft, bis rg_value erreicht ist
+																		if (anzRoadNb > 0)		//höre auf, sobald Straße in der Nachbarschaft gefunden wurde
+																			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);	//hole Wert aus Straßenraster
+																				if (roadValueNb > 0f)	//ist der Wert im Straßen-Raster > 0 zähle den Wert anzRoadNb hoch
+																					anzRoadNb++;
+																				
+																				//statusOut.println("Strasse in Entfernung 1: "+anzRoadNb+","+nbRoadCellsX+","+nbRoadCellsY);
+																			}
+																		roadNeighborhoodRange++;	
+																		RSearchNbRoad = Math.round((float)Math.random()*anzRoadNb);
+																		//statusOut.println("--> Zyklus "+roadNeighborhoodRange+"Nachbarn: "+anzRoadNb);
+																		//statusOut.println(RSearchNbRoad);
+																		int anzTempRoadNb = 0;
+																		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))
+																				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);	//hole Wert aus Straßenraster
+																				if (roadValueNbTemp > 0f){									//ist der Wert im Straßen-Raster > 0 zähle den Wert anzRoadNbTemp hoch
+																					anzTempRoadNb++;
+																					tempNbRoadCell = new int[] {nbRoadCellsX,nbRoadCellsY,anzTempRoadNb};	//schreibe die Koordinaten in ein Array
+																					if (tempNbRoadCell[2]==RSearchNbRoad){					//Wenn der Wert im Array dem vorher definierten Zufallswert entspricht...
+																						//statusOut.println("Treffer: "+tempNbRoadCell[0]+","+tempNbRoadCell[1]+","+tempNbRoadCell[2]);
+																						tempRoadCell = tempNbRoadCell;						//...wird die temporäre Straßenzelle an diese Position verschoben
+											//											statusOut.println("Strasse in Entfernung "+roadSearch+": "+tempRoadCell[0]+","+tempRoadCell[1]+","+tempRoadCell[2]);
+																						int nbCellNew[] = roadWalk(tempRoadCell[0],tempRoadCell[1],dispF);	//von dort aus wird ein Road-Walk durchgeführt (--> siehe Funktion roadWalk!)
+																						if(nbCellNew != null){												//kommt nach roadWalk ein Wert zurück (d.h. wurde potenziell zu besiedelndes Pixel gefunden)...
+																							tmpGrid[nbCellNew[0]][nbCellNew[1]] = true;						//wird "true" ins temporäre Raster geschrieben (neue Siedlungszelle gefunden!!)
+//																							statusOut.println(nbCellNew.length);
+//																							statusOut.println("Neue Zelle: "+nbCellNew[0]+","+nbCellNew[1]);
+//																							statusOut.println("++++++++++++++++++++++++++++++++++++++++");
+																							//Variablendefinitionen
+																							
+																							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;
+																						
+																							//wenn per roadWalk eine neue Zelle gefunden wurde, kann sie auch noch als Ausbreitungszentrum fungieren. Daher geht von ihr 
+																							//nochmals ein "Breed" aus. (GLEICHE FUNKTION WIE OBEN!!)
+												        
+																							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++;
+																											anzRoadTreffer++;
+																											//statusOut.println("Road-Breed-Treffer: "+anzRoadBreedTreffer);
+																										}
+																									}
+																								}
+												        									}
+																						} else{			//sind nicht mind. 2 Nachbarzellen gefunden worden...
+																							//statusOut.println("Keine neue Zelle gefunden");
+																						}
+																					}
+																				}
+																			}
+																		}
+																	}
+																}
+															}
+														}	
+													}
+												}
+			
+										} while (r <= breedF);
+		
+										//		statusOut.println("Spread-Treffer: "+anzSpreadTreffer);
+										//		statusOut.println("Dispersion-Treffer: "+anzDispTreffer);
+										//		statusOut.println("Breed-Treffer: "+anzBreedTreffer);
+										//		statusOut.println("Treffer gesamt: "+anzGesamt);
+										anzGesamtTreffer = anzSpreadTreffer+anzDispTreffer+anzBreedTreffer+anzRoadTreffer;
+										//		outStep.addGrid();
+										
+
+										/**
+										 * Hier endet der eigentliche Modellalgorithmus des Urban Growth Modells.
+										 * Als nächstes wird das was ins temporäre grid geschrieben wurde ins outputGrid geschrieben.
+										 * Mit dem outputGrid wird dann im nächsten Zeitschritt weitergerechnet, bis die maximale Anzahl
+										 * an Jahren erreicht ist. Danach wird die nächste Kombination an Koeffizienten gewählt.
+										 */
+										
+										// TempGrid auf das echte Grid schreiben
+										for (int y = 1; y < outputGrid.getHeight()-1;y++ ) 
+											for (int x = 1; x < outputGrid.getWidth()-1; x++ ) {
+				
+												int X = outputGrid.getMinX() + x;
+												int Y = outputGrid.getMinY() + y;
+				
+												boolean lebt = outputGrid.getRasterSampleAsFloat(X , Y ) > 0f;	//eine Zelle lebt, wenn sie 1 ist
+												boolean road = roadGrid.getRasterSampleAsFloat(X, Y) > 0f;	//eine Zelle beinhaltet eine Straße...
+												if (tmpGrid[x][y] == false)	//wenn im temporären Raster nichts drinsteht...
+													tmpGrid[x][y] = lebt;	//wird der Wert aus dem Ausgangsraster übernommen
+												if(lebt == true)
+													thisYear++;
+												if(road == true)
+													roadCount++;
+
+												outputGrid.setRasterSample( tmpGrid[x][y] ? 1f : 0f ,X ,Y);	
+												actUrb  = (Float)outputGrid.getRasterSample(x,y);
+												// outStep.getGrid(stepNo-1).setRasterSample(actUrb,x,y);
+											}
+										
+										//SELF-MODIFICATION
+										growthRate = ((float)anzGesamtTreffer / (float)thisYear)*100;
+									//	statusOut.println("Wachstumsrate: "+growthRate+", Urban: "+anzGesamtTreffer);
+										double percent_urban = (100.0 *(thisYear+roadCount) / (totalPixels-roadCount-excldCount));
+									//	statusOut.println("1. Slope-Sensitivity: "+slopeF+", RoadGravity-Sensitivity: "+roadGravityF+", Diffusion-Sensitivity: "+dispF+", Breed-Sensitivity: "+breedF+", Spread-Sensitivity: "+spreadF);
+										//Boom-Year
+										if(growthRate > criticalHigh){
+											slopeF -= (float)percent_urban * (float)slopeSens;
+											if(slopeF <= 0.01)
+												slopeF = 1.0;
+											roadGravityF += (float)percent_urban * roadGravSens;
+											if(roadGravityF > 100.0)
+												roadGravityF = 100.0;
+											if(dispF < 100.0){
+												dispF *= boom;
+												if(dispF > 100.0)
+													dispF = 100.0;
+												breedF *= boom;
+												if(breedF > 100.0)
+													breedF = 100.0;
+												spreadF *= boom;
+												if(spreadF > 100.0)
+													spreadF = 100.0;
+											}
+										}
+										//Bust-Year
+										if(growthRate < criticalLow){
+											slopeF += (float)percent_urban * (float)slopeSens;
+											if(slopeF > MaxSlopeResistance)
+												slopeF = MaxSlopeResistance;
+											roadGravityF -= (float)percent_urban * roadGravSens;
+											if(roadGravityF <= 0.01)
+												roadGravityF = 1.0;
+											if(growthRate < criticalLow && dispF > 0){
+												dispF *= bust;
+												if(dispF <= 0.01)
+													dispF = 1.0;
+												spreadF *= bust;
+												if(spreadF <= 0.01)
+													spreadF = 1.0;
+												breedF *= bust;
+												if(breedF <= 0.01)
+													breedF = 1.0;
+											}
+										}
+										//statusOut.println("thisYear: "+thisYear+", roadCount: "+roadCount+", excldCount: "+excldCount+", percent_urban: "+percent_urban);
+										statusOut.println("Slope-Sensitivity: "+slopeF+", RoadGravity-Sensitivity: "+roadGravityF+", Diffusion-Sensitivity: "+dispF+", Breed-Sensitivity: "+breedF+", Spread-Sensitivity: "+spreadF);
+										
+										
+										if (!anyBodyAlive) {
+											stepCount = stepNo;
+											//statusOut.println("Lebt keiner mehr... höre hier auf!");
+										}
+		
+										//RasterUtil.copyInto(outputGrid, inputGrid);
+										//	System.out.println("Finished step " + (stepNo) + " in "
+										//			+ ((System.currentTimeMillis() - localStartTime)) + " ms\n");
+										localStartTime = System.currentTimeMillis();
+		
+									}	//HIER ENDET DER ZEITSCHRITT. DIE SCHLEIFE WIRD DURCHLAUFEN, BIS MAX JAHRE ERREICHT SIND.
+		
+									/**
+									 * +++++ MULTIPLE RESOLUTION VALIDATION ++++++
+									 * Sind alle Zeitschritte durchlaufen, wird das Endergebnis validiert.
+									 * Als Validierungsmethode wurde die Multiple Resolution Validation ausgewählt (siehe
+									 * Costanza(1989), Pontius (2002), Pontius et al. (2005), Lesschen et al. (2005),
+									 * Pontius et al. (2008a), Pontius et al. (2008b))
+									 * Für das SLEUTH-Modell werden eigentlich eine Reihe an Landschaftsmaßen zur Validierung
+									 * verwendet (siehe Clarke et al. (1997), Dietzel et al. (2007)), wie z.B. LeeSallee
+									 * oder OSM. Da für die spätere Validierung der Modellierungsergebnisse und zum Vergleich mit 
+									 * anderen Modelltypen die Multiple Resolution Validation verwendet wird, wird sie auch zur
+									 * Bewertung der Kalibrierungsschritte verwendet.
+									 */
+									
+									//Variablendefinitionen
+									int RoverallSum = 0;
+									int RnumClasses = 0;
+									int SoverallSum = 0;
+									int SnumClasses = 0;
+									int correct = 0;
+									double fractionCorrect = 0f;
+		
+
+									long localStartTime = System.currentTimeMillis();
+									neighborhoodRange = (int) Math.sqrt(referenceGrid.getWidth()*referenceGrid.getHeight()); //maximal mögliche Zellengröße
+									//statusOut.println(neighborhoodRange);
+									resultArray = new float[13];		//!!!!!!!!! Ergebnis-Array
+									resultArrayFinal = new float[MonteCarlo-1][13];	//?????????????
+									
+									//Für die Ausgangs-Auflösung wird berechnet, wieviel % der Pixel zwischen Modell und Referenz übereinstimmen
+									for (int x = 0; x < referenceGrid.getWidth(); x++)
+										for (int y = 0; y < referenceGrid.getHeight(); y++) {
+											float Rtmp = referenceGrid.getRasterSampleAsFloat(x, y);
+											float Stmp = outputGrid.getRasterSampleAsFloat(x, y);
+											if (!Float.isNaN(Rtmp) && !Float.isNaN(Stmp)){
+												RoverallSum ++;
+												SoverallSum ++;
+												if (Rtmp > RnumClasses)
+													RnumClasses = (int) Rtmp;
+												if (Stmp > SnumClasses)
+													SnumClasses = (int) Stmp;	
+												if (Rtmp == Stmp)
+													correct++;
+											}
+										}
+									fractionCorrect = (double) correct / (double) RoverallSum;
+		
+									//Anzahl der Pixel pro Klasse
+									for (int i = 1; i <= RnumClasses; i++){
+										int Rj = 0;
+										int Sj = 0;
+										for (int x = 0; x < referenceGrid.getWidth(); x++)
+											for (int y = 0; y < referenceGrid.getHeight(); y++){
+												float Rtmp = referenceGrid.getRasterSampleAsFloat(x, y);
+												float Stmp = outputGrid.getRasterSampleAsFloat(x, y);
+												if (!Float.isNaN(Rtmp))
+													if ((int) Rtmp == i)
+														Rj++;
+												if (!Float.isNaN(Stmp))
+													if ((int) Stmp == i)
+														Sj++;
+											}
+										//statusOut.println("Klasse "+i+": Referenz("+Rj+"), Simulation("+Sj+")");
+									}
+		
+									ngrids = 0;
+									
+									//Die eigentliche Validierung wird für alle Zellengrößen von 1 (Ausgangsauflösung) bis "neighborhoodRange" durchgeführt
+									for (int r1 = 1; r1 <= neighborhoodRange; r1 = r1+r1){	//für Zellengröße 1 bis zur max. möglichen Zellengröße wird Statistik durchgeführt
+										//statusOut.println(r1);	
+										ngrids++;
+										float SumWn = 0f;	//Summe der gewichteten Mittelwerte 
+										int SumCells = 0;	//Summe der Zellen
+										float totalAgreement = 0f;	//Endergebnis
+										for (int x = 0; x < referenceGrid.getWidth(); x = x+r1)	//für jeden größer werdenden Zellenbereich...
+											for (int y = 0; y < referenceGrid.getHeight(); y = y+r1){	//was folgt passiert innerhalb einer größeren Rasterzelle
+												int nCells = 0;		//Anzahl Zellen pro größerer Zelle
+												float SumMinRS = 0f;	//Summe der Min-Werte bei Vergleich zweier Raster
+												float Wn = 0;	//Gewichtete Zelle
+												for(int x2 = x; x2 < x+r1; x2++)	//für jede kleinere Zelle innerhalb der größeren...
+													for(int y2 = y; y2 < y+r1; y2++){
+														if ( x2 < referenceGrid.getMinX() || y2 < referenceGrid.getMinY() || x2 > referenceGrid.getMinX()+referenceGrid.getWidth()-1 || y2 > referenceGrid.getMinY()+referenceGrid.getHeight()-1 ||
+																Float.isNaN(referenceGrid.getRasterSampleAsFloat(x2,y2)))
+															continue;
+														nCells++;	//zähle "positive" Zellen
+													}
+												for (int i = 0; i <= RnumClasses; i++){	//für jede Klasse i
+													int Rn = 0;	//Anzahl in Referenzkarte
+													int Sn = 0;	//Anzahl in Simulationskarte
+													float Rnj = 0f;	//Anteil in Referenzkarte
+													float Snj = 0f;	//Anteil in Simulationskarte
+													float MinRS = 0f;	//Min des Vergleichs zwischen beiden Karten
+													for(int x3 = x; x3 < x+r1; x3++)	//für jede kleinere Zelle pro größerer Zelle...
+														for(int y3 = y; y3 < y+r1; y3++){
+															if ( x3 < referenceGrid.getMinX() || y3 < referenceGrid.getMinY() || x3 > referenceGrid.getMinX()+referenceGrid.getWidth()-1 || y3 > referenceGrid.getMinY()+referenceGrid.getHeight()-1 ||
+																	Float.isNaN(referenceGrid.getRasterSampleAsFloat(x3,y3)))
+																continue;
+															float Rtmp = referenceGrid.getRasterSampleAsFloat(x3, y3);	//hole Wert aus Referenz-Karte und
+															float Stmp = outputGrid.getRasterSampleAsFloat(x3, y3);	//Simulationskarte
+															if ((int) Rtmp == i)
+																Rn++;	//zähle in Referenzkarte Zellen, die zu Klasse i gehören 
+															if ((int) Stmp == i)
+																Sn++;	//und in Simulationskarte
+														}
+													if(nCells > 0){	//wenn positive Zellen vorhanden sind...
+														Rnj = (float)Rn / (float)nCells;	//berechne Anteile pro größerer Zelle
+														Snj = (float)Sn / (float)nCells;
+													}
+													MinRS = Math.min(Rnj, Snj);	//nehme Minimum-Wert des Vergleichs beider Karten
+													SumMinRS += MinRS;	//summiere die Minimum-Werte auf
+													//	statusOut.println(i+" Min"+MinRS+" Anzahl: "+nCells);	
+												}
+												
+												Wn = (float)nCells * SumMinRS;
+												//	statusOut.println(SumMinRS+", gewichtet: "+Wn);
+												//Erstelle Output-Karten
+												float WnCell = 0f;
+												for(int x4 = x; x4 < x+r1; x4++)	//für jede kleinere Zelle pro größerer Zelle...
+													for(int y4 = y; y4 < y+r1; y4++){
+														if ( x4 < referenceGrid.getMinX() || y4 < referenceGrid.getMinY() || x4 > referenceGrid.getMinX()+referenceGrid.getWidth()-1 || y4 > referenceGrid.getMinY()+referenceGrid.getHeight()-1 ||
+																Float.isNaN(referenceGrid.getRasterSampleAsFloat(x4,y4)))
+															continue;
+														WnCell = Wn / (float)nCells; //pro Zelle wird Mittelwert des Vergleichs genommen
+														//actualValidation.setRasterSample( WnCell ,x4 ,y4);	
+													}
+				
+												SumCells += (float)nCells;	//Summiere alle Zellen auf
+												SumWn += Wn;	//Summiere die gewichteten Anteile auf
+											}		//hier endet die Berechnung innerhalb einer größeren Rasterzelle
+										
+										
+										//Total Agreement:
+										//statusOut.println(SumWn+" / "+SumCells);
+										totalAgreement = SumWn / (float)SumCells;	//Ergebnisformel
+										//statusOut.println(totalAgreement);	
+
+										outResults.addValue(totalAgreement);
+										resultArray[ngrids] = totalAgreement;
+
+										//	statusOut.println("Gesamt-Pixel: "+RoverallSum);
+										//	statusOut.println("Anzahl Klassen: "+RnumClasses);
+										//	statusOut.println("Fraction Correct: "+fractionCorrect);
+										
+									}	//Hier endet die Berechnung pro Auflösung
+		
+								//	System.out.println("(Slope:"+slope+" Spread:"+spread+" Dispersion:"+disp+" Breed: "+breed+" RoadGravity: "+roadGravity+") "+
+								//			resultArray[1]+","+resultArray[2]+","+resultArray[3]+","+resultArray[4]+","+resultArray[5]+","+resultArray[6]+
+								//			","+resultArray[7]+","+resultArray[8]+","+resultArray[9]);
+																		
+									pos1 += resultArray[1];
+									pos2 += resultArray[2];
+									pos3 += resultArray[3];
+									pos4 += resultArray[4];
+									pos5 += resultArray[5];
+									pos6 += resultArray[6];
+									pos7 += resultArray[7];
+									pos8 += resultArray[8];
+									pos9 += resultArray[9];
+									pos10 += resultArray[10];
+									pos11 += resultArray[11];
+									pos12 += resultArray[12];
+									//	System.out.print("Finished step " + (stepNo) + " in "
+									//			+ ((System.currentTimeMillis() - localStartTime)) + " ms");
+									localStartTime = System.currentTimeMillis();
+									//	System.out.println(" with sum (local calculated): " + RoverallSum);
+							}	//!!!!!!!!!! Hier endet ein Monte-Carlo-Schritt
+							
+							System.out.println("-->(Slope:"+slope+" Spread:"+spread+" Dispersion:"+disp+" Breed: "+breed+" RoadGravity: "+roadGravity+") "+
+									pos1/MonteCarlo+","+pos2/MonteCarlo+","+pos3/MonteCarlo+","+pos4/MonteCarlo+","+pos5/MonteCarlo+","+pos6/MonteCarlo+
+											","+pos7/MonteCarlo+","+pos8/MonteCarlo+","+pos9/MonteCarlo+","+pos10/MonteCarlo+","+pos11/MonteCarlo+","+pos12/MonteCarlo);
+						}	//Ende RoadGravity-Koeffizient
+					}	//Ende Breed-Koeffizient
+				}	//Ende Disp-Koeffizient
+			}	//Ende Spread-Koeffizient
+		}	//Ende Slope-Koeffizient
+	}	//Ende Model-Step
+	
+	private int[] roadWalk(int X,int Y,double dispF){
+//		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;
+			int nbRoadY = 0;
+			int areaMinX = outputGrid.getMinX();								//Dimensionen des Rasters
+			int areaMinY = outputGrid.getMinY();
+			int areaMaxX = outputGrid.getMinX() + outputGrid.getWidth() - 1;
+			int areaMaxY = outputGrid.getMinY() + outputGrid.getHeight() - 1;
+			int roadNb = 0;
+			int roadNbTemp = 0;
+			int RN = 0;
+						
+			int[] nbCell = null;
+			for (int nbRoadCells = 0; nbRoadCells < NEIGHBOR.length; nbRoadCells++){
+				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++;
+			}
+	//		statusOut.println("Nachbarn von temporaerer Strassenzelle: "+roadNb);
+			
+			if (roadNb > 0){
+				RN = 1 + Math.round((float)Math.random()*(roadNb-1));
+			
+				for (int nbRoadCells = 0; nbRoadCells < NEIGHBOR.length; nbRoadCells++){
+					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++;
+							X = nbRoadX;
+							Y = nbRoadY;
+							float roadSample2 = roadGrid.getRasterSampleAsFloat(X,Y);
+							run_value = (int) (roadSample2 / 100 * dispF);
+					//		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){
+									int nbUrbanizeX = 0;
+									int nbUrbanizeY = 0;
+									int NbTemp = 0;
+									float RNRoadSlope = 0f;
+						//			statusOut.println(X+","+Y);
+									for (int urbanizeCells = 0; urbanizeCells < NEIGHBOR.length; urbanizeCells++){
+										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;
+										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]};
+											}
+										}	
+									}
+								
+							} else{
+								nbCellNew = null;
+							}	break;
+						}
+						
+					}
+					
+				}
+			}
+			
+			}
+		}
+		return nbCellNew;
+		}
+	
+	private int calculateNeighbors(int X, int Y, float NbValue){
+		int nbX = 0;
+		int nbY = 0;
+		int areaMinX = outputGrid.getMinX();								//Dimensionen des Rasters
+		int areaMinY = outputGrid.getMinY();
+		int areaMaxX = outputGrid.getMinX() + outputGrid.getWidth() - 1;
+		int areaMaxY = outputGrid.getMinY() + outputGrid.getHeight() - 1;
+		int Nb = 0;
+		for (int nbCells = 0; nbCells < NEIGHBOR.length; nbCells++){
+			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;
+			if (areaRestr.getRasterSampleAsFloat(nbX,nbY) != 0)
+	        	continue;
+			float rasterSample = outputGrid.getRasterSampleAsFloat(nbX,nbY);
+			if (rasterSample == NbValue)
+				Nb++;
+		}
+	//	statusOut.println("..."+Nb+"...");
+		return Nb;
+	}
+	
+	protected static boolean checkNoData(int x, int y, WritableGrid grid) {
+	    return Float.isNaN(grid.getRasterSampleAsFloat(x,y));
+	  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelCalibrationSelfModificationContentManager.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelCalibrationSelfModificationContentManager.java	2009-09-07 12:15:20 UTC (rev 55)
+++ trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelCalibrationSelfModificationContentManager.java	2009-09-10 14:02:19 UTC (rev 56)
@@ -0,0 +1,61 @@
+package edu.bonn.xulu.plugin.model.sleuth;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.ScalarProperty;
+import edu.bonn.xulu.data.XuluDataException;
+import edu.bonn.xulu.model.AbstractModelContentManager;
+import edu.bonn.xulu.model.DefaultModelResource;
+import edu.bonn.xulu.model.ModelResource;
+import edu.bonn.xulu.model.ValuePropertyResource;
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+
+
+public class UrbanGrowthModelCalibrationSelfModificationContentManager extends AbstractModelContentManager {
+	
+	public UrbanGrowthModelCalibrationSelfModificationContentManager() {
+		super(31);
+	    
+		resource[0] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Number of steps",ScalarProperty.class,Integer.class,false);
+		resource[1] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Number of MonteCarlo Iterations",ScalarProperty.class,Integer.class,false);
+		resource[2] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Input Grid",ScalarProperty.class,WritableGrid.class,false);
+		resource[3] = new ValuePropertyResource(ModelResource.CATEGORY_OUTPUT,"Output Grid",ScalarProperty.class,WritableGrid.class,false);
+	    resource[4] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Area Restrictions",ScalarProperty.class,WritableGrid.class,false);
+	    resource[5] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Road Grid",ScalarProperty.class,WritableGrid.class,false);
+	    resource[6] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Slope Grid",ScalarProperty.class,WritableGrid.class,false);
+	    resource[7] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Reference Grid",ScalarProperty.class,WritableGrid.class,false);
+	    resource[8] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Spread Coefficient Start",ScalarProperty.class,Double.class,false);
+	    resource[9] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Spread Coefficient Step",ScalarProperty.class,Double.class,false);
+	    resource[10] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Spread Coefficient End",ScalarProperty.class,Double.class,false);
+	    resource[11]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Dispersion Coefficient Start",ScalarProperty.class,Double.class,false);
+	    resource[12]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Dispersion Coefficient Step",ScalarProperty.class,Double.class,false);
+	    resource[13]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Dispersion Coefficient End",ScalarProperty.class,Double.class,false);
+	    resource[14]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Breed Coefficient Start",ScalarProperty.class,Double.class,false);
+	    resource[15]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Breed Coefficient Step",ScalarProperty.class,Double.class,false);
+	    resource[16]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Breed Coefficient End",ScalarProperty.class,Double.class,false);
+	    resource[17]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"RoadGravity Coefficient Start",ScalarProperty.class,Double.class,false);
+	    resource[18]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"RoadGravity Coefficient Step",ScalarProperty.class,Double.class,false);
+	    resource[19]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"RoadGravity Coefficient End",ScalarProperty.class,Double.class,false);
+	    resource[20]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Slope Coefficient Start",ScalarProperty.class,Double.class,false);
+	    resource[21]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Slope Coefficient Step",ScalarProperty.class,Double.class,false);
+	    resource[22]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Slope Coefficient End",ScalarProperty.class,Double.class,false);
+	    resource[23]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Critical Slope",ScalarProperty.class,Double.class,false);
+	    resource[24]= new ValuePropertyResource(ModelResource.CATEGORY_OUTPUT,"Validation Results",ListProperty.class,Float.class,false);
+	    resource[25]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Road Gravity Sensitivity",ScalarProperty.class,Double.class,false);
+	    resource[26]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Slope Sensitivity",ScalarProperty.class,Double.class,false);
+	    resource[27]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Critical Low",ScalarProperty.class,Double.class,false);
+	    resource[28]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Critical High",ScalarProperty.class,Double.class,false);
+	    resource[29]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Boom",ScalarProperty.class,Double.class,false);
+	    resource[30]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Bust",ScalarProperty.class,Double.class,false);
+
+	 	// ===== Ressourcen Bezeichnungen lokalisieren =====
+	    resetCaptions(null);
+	}
+	
+	
+	@Override
+	public void checkAndError() throws XuluDataException {
+		// TODO Auto-generated method stub
+		super.checkAndError();
+	}
+}

Added: trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelContentManager.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelContentManager.java	2009-09-07 12:15:20 UTC (rev 55)
+++ trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelContentManager.java	2009-09-10 14:02:19 UTC (rev 56)
@@ -0,0 +1,44 @@
+package edu.bonn.xulu.plugin.model.sleuth;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.property.ScalarProperty;
+import edu.bonn.xulu.data.XuluDataException;
+import edu.bonn.xulu.model.AbstractModelContentManager;
+import edu.bonn.xulu.model.DefaultModelResource;
+import edu.bonn.xulu.model.ModelResource;
+import edu.bonn.xulu.model.ValuePropertyResource;
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+
+
+public class UrbanGrowthModelContentManager extends AbstractModelContentManager {
+	
+	public UrbanGrowthModelContentManager() {
+		super(13);
+
+		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);
+	    // Number of steps
+	    resource[2] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Number of steps",ScalarProperty.class,Integer.class,false);
+	    // Spread Coefficient
+	    resource[3] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Area Restrictions",ScalarProperty.class,WritableGrid.class,false);
+	    resource[4] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Spread Coefficient",ScalarProperty.class,Double.class,false);
+	    resource[5]	= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Dispersion Coefficient",ScalarProperty.class,Double.class,false);
+	    resource[6]	= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Breed Coefficient",ScalarProperty.class,Double.class,false);
+	    resource[7] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"RoadGravity Coefficient",ScalarProperty.class,Double.class,false);
+	    resource[8]	= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Slope Coefficient",ScalarProperty.class,Double.class,false);
+	    resource[9]	= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Critical Slope",ScalarProperty.class,Double.class,false);
+	    resource[10]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Road Grid",ScalarProperty.class,WritableGrid.class,false);
+	    resource[11]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Slope Grid",ScalarProperty.class,WritableGrid.class,false);
+	    resource[12]= new DefaultModelResource(ModelResource.CATEGORY_OUTPUT,"Step Results",MultiGrid.class,false);
+	    
+	 	// ===== Ressourcen Bezeichnungen lokalisieren =====
+	    resetCaptions(null);
+	}
+	
+	
+	@Override
+	public void checkAndError() throws XuluDataException {
+		// TODO Auto-generated method stub
+		super.checkAndError();
+	}
+}

Added: trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelSelfModifying.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelSelfModifying.java	2009-09-07 12:15:20 UTC (rev 55)
+++ trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelSelfModifying.java	2009-09-10 14:02:19 UTC (rev 56)
@@ -0,0 +1,951 @@
+package edu.bonn.xulu.plugin.model.sleuth;
+
+import java.awt.Rectangle;
+import java.util.HashMap;
+
+import edu.bonn.xulu.model.AbstractStepModel;
+import edu.bonn.xulu.model.XuluModel;
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.property.PropertyReadAccess;
+import schmitzm.data.property.PropertyWriteAccess;
+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}. 
+ * <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>
+ * 
+ * @see AverageNeighborhoodContentManager
+ * @author Dominik Appl
+ * @version 1.0
+ */
+public class UrbanGrowthModelSelfModifying extends AbstractStepModel {
+
+	protected UrbanGrowthModelSelfModifyingContentManager contManager;
+
+	// ********** Lese/Schreibrechte, die fuer den gesamten ***********
+	// ********** Modellanlauf gehalten werden muessen ***********
+	private PropertyReadAccess RA_inputGrid = null; // Input Grid
+	private PropertyWriteAccess WA_outputGrid = null; // Output Grid
+	private PropertyReadAccess RA_steps = null; // Number of steps
+	private PropertyReadAccess RA_areaRestr = null; //Area Restrictions
+	private PropertyReadAccess RA_spread = null;	//Spread-Koeffizient
+	private PropertyReadAccess RA_disp = null;		//Dispersions-Koeffizient
+	private PropertyReadAccess RA_breed = null;		//Breed-Koeffizient
+	private PropertyReadAccess RA_roadGravity = null;	//Road-Gravity-Koeffizient
+	private PropertyReadAccess RA_slope = null;	//Slope-Koeffizient
+	private PropertyReadAccess RA_criticalSlope = null;	//Critical Slope Value
+	private PropertyReadAccess RA_roadGrid = null;	//Road Grid
+	private PropertyReadAccess RA_slopeGrid = null;	//Slope Grid
+	private PropertyWriteAccess WA_outStep = null;	// Step Results
+	private PropertyReadAccess RA_roadGravSens = null;	//RoadGravity Sensitivity
+	private PropertyReadAccess RA_slopeSens = null;	//Slope Sensitivity
+	private PropertyReadAccess RA_criticalLow = null;	//Critical Low
+	private PropertyReadAccess RA_criticalHigh = null;	//Critical High
+	private PropertyReadAccess RA_Boom = null;	//Boom
+	private PropertyReadAccess RA_Bust = null;	//Bust
+
+	// **************** Variablen mit denen gearbeitet wird *******************
+	private WritableGrid inputGrid = null; // Input Grid
+	private WritableGrid outputGrid = null; // Output Grid
+	private PropertyReadAccess steps = null; // Number of steps
+	private WritableGrid areaRestr = null; //Area Restrictions
+	protected double spread = 0;	//Spread-Koeffizient
+	protected double disp = 0;	//Dispersions-Koeffizient
+	protected double breed = 0;	//Breed-Koeffizient
+	protected double roadGravity = 0;	//Road-Gravity-Koeffizient
+	protected double slope = 0;	//Slope-Koeffizient
+	protected double criticalSlope = 0;	//Critical Slope Value
+	private WritableGrid roadGrid = null;	//Road Grid
+	private WritableGrid slopeGrid = null;	//Slope Grid
+	private MultiGrid outStep = null;	//Step Results
+	protected double roadGravSens = 0;	//RoadGravity Sensitivity
+	protected double slopeSens = 0;	//Slope Sensitivity
+	protected double criticalLow = 0;	//critical Low
+	protected double criticalHigh = 0;	//critical High
+	protected double boom = 0;	//Boom
+	protected double bust = 0;	//Bust
+		
+	private  static final int[][] NEIGHBOR = new int[][] {
+	      {-1,-1}, {0,-1}, {1,-1},
+	      {-1, 0},         {1, 0},
+	      {-1, 1}, {0, 1}, {1, 1}
+	  };
+	
+	protected  HashMap<Number,Number> slopeLUT;
+	private int slopeMax = 0;
+	private int totalPixels = 0;
+	private int excldCount = 0;
+	
+	/**
+	 * Erzeugt eine neue Instanz des Modells.
+	 */
+	public UrbanGrowthModelSelfModifying() {
+		super(new UrbanGrowthModelSelfModifyingContentManager());
+		this.contManager = (UrbanGrowthModelSelfModifyingContentManager) super.contManager;
+	}
+
+	
+	/**
+	 * Initializes the model. Like in the init method of every {@link XuluModel}
+	 * the resources are initalized. 
+	 */
+	public void performModelInit() {
+		if (contManager == null)
+			return;
+		// Zugriffsrechte aus Ressourcen/Propertys holen
+		RA_inputGrid = null;
+		if (contManager.getResource(0).getData() != null)
+			RA_inputGrid = ((ScalarProperty) contManager.getResource(0)
+					.getData()).getReadAccess(this);
+		WA_outputGrid = null;
+		if (contManager.getResource(1).getData() != null)
+			WA_outputGrid = ((ScalarProperty) contManager.getResource(1)
+					.getData()).getWriteAccess(this);
+		RA_steps = null;
+		if (contManager.getResource(2).getData() != null)
+			RA_steps = ((ScalarProperty) contManager.getResource(2).getData())
+					.getReadAccess(this);
+		RA_areaRestr = null;
+		if (contManager.getResource(3).getData() != null)
+			RA_areaRestr = ((ScalarProperty) contManager.getResource(3)
+					.getData()).getReadAccess(this);
+		RA_spread = null;
+		if (contManager.getResource(4).getData() != null)
+			RA_spread = ((ScalarProperty) contManager.getResource(4).getData())
+					.getReadAccess(this);
+		RA_disp = null;
+		if (contManager.getResource(5).getData() != null)
+			RA_disp = ((ScalarProperty) contManager.getResource(5).getData())
+					.getReadAccess(this);
+		RA_breed = null;
+		if (contManager.getResource(6).getData() != null)
+			RA_breed = ((ScalarProperty) contManager.getResource(6).getData())
+					.getReadAccess(this);
+		RA_roadGravity = null;
+		if (contManager.getResource(7).getData() != null)
+			RA_roadGravity = ((ScalarProperty) contManager.getResource(7).getData())
+					.getReadAccess(this);
+		RA_slope = null;
+		if (contManager.getResource(8).getData() != null)
+			RA_slope = ((ScalarProperty) contManager.getResource(8).getData())
+					.getReadAccess(this);
+		RA_criticalSlope = null;
+		if (contManager.getResource(9).getData() != null)
+			RA_criticalSlope = ((ScalarProperty) contManager.getResource(9).getData())
+					.getReadAccess(this);
+		RA_roadGrid = null;
+		if (contManager.getResource(10).getData() != null)
+			RA_roadGrid = ((ScalarProperty) contManager.getResource(10)
+					.getData()).getReadAccess(this);
+		RA_slopeGrid = null;
+		if (contManager.getResource(11).getData() != null)
+			RA_slopeGrid = ((ScalarProperty) contManager.getResource(11)
+					.getData()).getReadAccess(this);
+		RA_roadGravSens = null;
+		if (contManager.getResource(13).getData() != null)
+			RA_roadGravSens = ((ScalarProperty) contManager.getResource(13).getData())
+					.getReadAccess(this);
+		RA_slopeSens = null;
+		if (contManager.getResource(14).getData() != null)
+			RA_slopeSens = ((ScalarProperty) contManager.getResource(14).getData())
+					.getReadAccess(this);
+		RA_criticalLow = null;
+		if (contManager.getResource(15).getData() != null)
+			RA_criticalLow = ((ScalarProperty) contManager.getResource(15).getData())
+					.getReadAccess(this);
+		RA_criticalHigh = null;
+		if (contManager.getResource(16).getData() != null)
+			RA_criticalHigh = ((ScalarProperty) contManager.getResource(16).getData())
+					.getReadAccess(this);
+		RA_Boom = null;
+		if (contManager.getResource(17).getData() != null)
+			RA_Boom = ((ScalarProperty) contManager.getResource(17).getData())
+					.getReadAccess(this);
+		RA_Bust = null;
+		if (contManager.getResource(18).getData() != null)
+			RA_Bust = ((ScalarProperty) contManager.getResource(18).getData())
+					.getReadAccess(this);
+
+		// Variablen belegen mit denen gearbeitet wird
+		inputGrid = (WritableGrid) RA_inputGrid.getValue();
+		outputGrid = (WritableGrid) WA_outputGrid.getValue();
+		steps = RA_steps;
+		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();
+	    roadGravity = RA_roadGravity.getValueAsDouble();
+	    slope	= RA_slope.getValueAsDouble();
+	    criticalSlope = RA_criticalSlope.getValueAsDouble();
+	    roadGrid = (WritableGrid) RA_roadGrid.getValue();
+	    slopeGrid = (WritableGrid) RA_slopeGrid.getValue();
+	    outStep = (MultiGrid)contManager.getResource(12).getData();
+	    roadGravSens = RA_roadGravSens.getValueAsDouble();
+	    slopeSens = RA_slopeSens.getValueAsDouble();
+	    criticalLow = RA_criticalLow.getValueAsDouble();
+	    criticalHigh = RA_criticalHigh.getValueAsDouble();
+	    boom = RA_Boom.getValueAsDouble();
+	    bust = RA_Bust.getValueAsDouble();
+
+		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);
+			}
+		}
+		for (int x = 0; x < inputGrid.getWidth();x++ ) 
+			for (int y = 0; y < inputGrid.getHeight(); y++ ) {
+				if ( x < inputGrid.getMinX() || y < inputGrid.getMinY() || x > inputGrid.getMinX()+inputGrid.getWidth()-1 || y > inputGrid.getMinY()+inputGrid.getHeight()-1 ||
+			            Float.isNaN(outputGrid.getRasterSampleAsFloat(x,y)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
+			             continue;
+				totalPixels++;
+				if (areaRestr.getRasterSampleAsFloat(x,y) != 0 && !Float.isNaN(areaRestr.getRasterSampleAsFloat(x,y)))
+		        	//continue;	//wenn in Area Restriction oder wenn schon Siedlung da ist, mach weiter
+				//if (inputGrid.getRasterSampleAsFloat(i,ii) == 1f);
+					excldCount++;
+			}
+		
+		statusOut.println("Anzahl der startenden Individuen: "+startAnz);
+		statusOut.println(NEIGHBOR.length);
+		statusOut.println("Total: "+totalPixels+", Excluded: "+excldCount);
+		
+		
+		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);
+		
+	}
+
+	/**
+	* like in every model: frees the resources
+	 */
+	public void performModelDispose() {
+
+		// Ressourcen wieder freigeben
+		releaseAccess(RA_inputGrid);
+		releaseAccess(WA_outputGrid);
+		releaseAccess(RA_steps);
+		releaseAccess(RA_areaRestr);
+		releaseAccess(RA_spread);
+		releaseAccess(RA_disp);
+		releaseAccess(RA_breed);
+		releaseAccess(RA_roadGravity);
+		releaseAccess(RA_slope);
+		releaseAccess(RA_criticalSlope);
+		releaseAccess(RA_roadGrid);
+		releaseAccess(RA_slopeGrid);
+		releaseAccess(WA_outStep);
+		releaseAccess(RA_roadGravSens);
+		releaseAccess(RA_slopeSens);
+		releaseAccess(RA_criticalLow);
+		releaseAccess(RA_criticalHigh);
+		releaseAccess(RA_Boom);
+		releaseAccess(RA_Bust);
+	}
+
+	/**
+	 * This very simple model looks at every grid cell and takes the average
+	 * over a the surrounding cells in a specified neighborhood.
+	 * 
+	 * @param stepNo
+	 *            zu modellierender Schritt (beginnend bei 1!)
+	 */
+	public void performModelStep(int stepNo) {
+		
+		statusOut.println("Starting step " + stepNo + "...");
+		
+		//Erstellt einen Lookup-Table
+		slopeLUT = new HashMap<Number,Number>();
+		
+		int MaxSlopeResistance = 0;
+		double exp = 0.0;
+		MaxSlopeResistance = 100;
+		exp = (slope / (MaxSlopeResistance / 2));
+		double[] lookup = new double[slopeMax+1];
+		Number key = 0;
+		
+		for (int i = 0;i <= slopeMax;i++){
+			if (i <= criticalSlope){
+				double val = (criticalSlope - i) / criticalSlope;
+				lookup[i] = 1 - Math.pow(val,exp);
+				key = i;
+			} else{
+				lookup[i] = 1;
+				key = i;
+			}
+			slopeLUT.put(key,lookup[i]);
+			statusOut.println(slopeLUT.get(key));
+		}	
+		
+		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();
+		
+		long localStartTime = System.currentTimeMillis();
+		boolean anyBodyAlive = false;
+		
+		boolean[][] tmpGrid = new boolean[inputGrid.getWidth()][inputGrid.getHeight()];
+		Float actUrb = null;
+		
+		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;
+		int anzRoadTreffer = 0;
+		int anzGesamtTreffer = 0;
+		double growthRate = 0;
+		int thisYear = 0;
+		int roadCount = 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;
+		
+		//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);
+		
+
+		/*****************************************************************
+		 * DISPERSION and BREED
+		 *****************************************************************/
+		
+		int p = 0;	//Verteile soviel neue Pixel zufällig in geeigneten Bereichen, bis disp_value erreicht ist
+		do{
+			dispRandX = Math.round((float) Math.random()*areaWidth);	//Zufallsposition in X-Richtung
+			dispRandY = Math.round((float) Math.random()*areaHeight);	//Zufallsposition in Y-Richtung
+			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
+	
+		/*********************************************************************
+		 * EDGE
+		 *********************************************************************/
+		
+		//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
+				
+				int areaMinXadd = areaMinX + x;								//Dimensionen des Rasters
+				int areaMinYadd = areaMinY + y;
+				
+				int anzNachbarn = 0;
+				int noNachbarn = 0;
+			
+				
+				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;	//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));
+					float RNEdgeSlope = 0;
+					int nbUrbanX = 0;
+					int nbUrbanY = 0;
+					for (int nbCellChange = 0; nbCellChange < NEIGHBOR.length; nbCellChange++){	//dann starte eine Schleife
+						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;
+						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++;
+								}
+							} 
+						}
+						nbCell = new int[] {nbX,nbY,(int) rasterSample};	
+					}
+				}
+				if (anzNachbarn>0) anyBodyAlive = true;		
+			}
+		
+		/*********************************************************************
+		 * 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;
+			int roadNeighborhoodRange = 0;
+			int RSearchNbRoad = 0;
+			for (int x = 0; x < inputGrid.getWidth();x++){		//gesamtes Raster wird durchsucht
+				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 anzRoadBreedTreffer1 = 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;
+													anzRoadBreedTreffer1++;
+													anzRoadTreffer++;
+													statusOut.println("Road-Breed-Treffer: "+anzRoadBreedTreffer1);
+												}
+											}
+										}
+							        	
+							        
+									}
+									
+								} else{
+//									statusOut.println("Keine neue Zelle gefunden");
+								}
+							} else{
+								int anzRoadNb = 0;
+								
+								//HIER MIT FOR SCHLEIFE RECHTECK WACHSEN LASSEN!!!
+								for (int roadSearch = 0; roadSearch <= rg_value; roadSearch++){
+									if (anzRoadNb > 0)
+										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);
+										}
+									}
+									roadNeighborhoodRange++;
+									RSearchNbRoad = Math.round((float)Math.random()*anzRoadNb);
+									//statusOut.println("--> Zyklus "+roadNeighborhoodRange+"Nachbarn: "+anzRoadNb);
+									//statusOut.println(RSearchNbRoad);
+									int anzTempRoadNb = 0;
+									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))
+											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 anzRoadBreedTreffer2 = 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;
+																		anzRoadBreedTreffer2++;
+																		anzRoadTreffer++;
+																		statusOut.println("Road-Breed-Treffer: "+anzRoadBreedTreffer2);
+																	}
+																}
+															}
+												        	
+												        
+														}
+													} else{
+//														statusOut.println("Keine neue Zelle gefunden");
+													}
+												}
+											}
+										}
+									}
+								}
+							}
+						}
+					}	
+				}
+			}
+			
+		} while (r <= breed);
+		
+		statusOut.println("Spread-Treffer: "+anzSpreadTreffer);
+		statusOut.println("Dispersion-Treffer: "+anzDispTreffer);
+		statusOut.println("Breed-Treffer: "+anzBreedTreffer);
+		statusOut.println("Treffer gesamt: "+anzGesamt);
+		statusOut.println("Anzahl Road-Treffer: "+anzRoadTreffer);
+		anzGesamtTreffer = anzSpreadTreffer+anzDispTreffer+anzBreedTreffer+anzRoadTreffer;
+		
+		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
+				boolean road = roadGrid.getRasterSampleAsFloat(X, Y) > 0f;	//eine Zelle beinhaltet eine Straße...
+				if (tmpGrid[x][y] == false)	//wenn im temporären Raster nichts drinsteht...
+					tmpGrid[x][y] = lebt;	//wird der Wert aus dem Ausgangsraster übernommen
+				if(lebt == true)
+					thisYear++;
+				if(road == true)
+					roadCount++;
+
+				outputGrid.setRasterSample( tmpGrid[x][y] ? 1f : 0f ,X ,Y);	
+				actUrb  = (Float)outputGrid.getRasterSample(x,y);
+				outStep.getGrid(stepNo-1).setRasterSample(actUrb,x,y);
+			}
+		}
+		
+		//SELF-MODIFICATION
+		growthRate = ((float)anzGesamtTreffer / (float)thisYear)*100;
+		statusOut.println("Wachstumsrate: "+growthRate+", Urban: "+anzGesamtTreffer);
+		double percent_urban = (100.0 *(thisYear+roadCount) / (totalPixels-roadCount-excldCount));
+		
+		//Boom-Year
+		if(growthRate > criticalHigh){
+			slope -= (float)percent_urban * (float)slopeSens;
+			if(slope <= 0.01)
+				slope = 1.0;
+			roadGravity += (float)percent_urban * roadGravSens;
+			if(roadGravity > 100.0)
+				roadGravity = 100.0;
+			if(disp < 100.0){
+				disp *= boom;
+				if(disp > 100.0)
+					disp = 100.0;
+				breed *= boom;
+				if(breed > 100.0)
+					breed = 100.0;
+				spread *= boom;
+				if(spread > 100.0)
+					spread = 100.0;
+			}
+		}
+		//Bust-Year
+		if(growthRate < criticalLow){
+			slope += (float)percent_urban * (float)slopeSens;
+			if(slope > MaxSlopeResistance)
+				slope = MaxSlopeResistance;
+			roadGravity -= (float)percent_urban * roadGravSens;
+			if(roadGravity <= 0.01)
+				roadGravity = 1.0;
+			if(growthRate < criticalLow && disp > 0){
+				disp *= bust;
+				if(disp <= 0.01)
+					disp = 1.0;
+				spread *= bust;
+				if(spread <= 0.01)
+					spread = 1.0;
+				breed *= bust;
+				if(breed <= 0.01)
+					breed = 1.0;
+			}
+		}
+		statusOut.println("thisYear: "+thisYear+", roadCount: "+roadCount+", excldCount: "+excldCount+", percent_urban: "+percent_urban);
+		statusOut.println("Slope-Sensitivity: "+slope+", RoadGravity-Sensitivity: "+roadGravity+", Diffusion-Sensitivity: "+disp+", Breed-Sensitivity: "+breed+", Spread-Sensitivity: "+spread);
+		
+		
+		
+		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();
+	}
+	
+	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;
+			int nbRoadY = 0;
+			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 roadNb = 0;
+			int roadNbTemp = 0;
+			int RN = 0;
+						
+			int[] nbCell = null;
+			for (int nbRoadCells = 0; nbRoadCells < NEIGHBOR.length; nbRoadCells++){
+				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++;
+			}
+	//		statusOut.println("Nachbarn von temporaerer Strassenzelle: "+roadNb);
+			
+			if (roadNb > 0){
+				RN = 1 + Math.round((float)Math.random()*(roadNb-1));
+			
+				for (int nbRoadCells = 0; nbRoadCells < NEIGHBOR.length; nbRoadCells++){
+					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++;
+							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){
+									int nbUrbanizeX = 0;
+									int nbUrbanizeY = 0;
+									int NbTemp = 0;
+									float RNRoadSlope = 0f;
+						//			statusOut.println(X+","+Y);
+									for (int urbanizeCells = 0; urbanizeCells < NEIGHBOR.length; urbanizeCells++){
+										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;
+										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]};
+											}
+										}	
+									}
+								
+							} else{
+								nbCellNew = null;
+							}	break;
+						}
+						
+					}
+					
+				}
+			}
+			
+			}
+		}
+		return nbCellNew;
+		}
+	
+	private int calculateNeighbors(int X, int Y, float NbValue){
+		int nbX = 0;
+		int nbY = 0;
+		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 Nb = 0;
+		for (int nbCells = 0; nbCells < NEIGHBOR.length; nbCells++){
+			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;
+			if (areaRestr.getRasterSampleAsFloat(nbX,nbY) != 0)
+	        	continue;
+			float rasterSample = outputGrid.getRasterSampleAsFloat(nbX,nbY);
+			if (rasterSample == NbValue)
+				Nb++;
+		}
+	//	statusOut.println("..."+Nb+"...");
+		return Nb;
+	}
+	
+	protected static boolean checkNoData(int x, int y, WritableGrid grid) {
+	    return Float.isNaN(grid.getRasterSampleAsFloat(x,y));
+	  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelSelfModifyingContentManager.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelSelfModifyingContentManager.java	2009-09-07 12:15:20 UTC (rev 55)
+++ trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelSelfModifyingContentManager.java	2009-09-10 14:02:19 UTC (rev 56)
@@ -0,0 +1,50 @@
+package edu.bonn.xulu.plugin.model.sleuth;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.property.ScalarProperty;
+import edu.bonn.xulu.data.XuluDataException;
+import edu.bonn.xulu.model.AbstractModelContentManager;
+import edu.bonn.xulu.model.DefaultModelResource;
+import edu.bonn.xulu.model.ModelResource;
+import edu.bonn.xulu.model.ValuePropertyResource;
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+
+
+public class UrbanGrowthModelSelfModifyingContentManager extends AbstractModelContentManager {
+	
+	public UrbanGrowthModelSelfModifyingContentManager() {
+		super(19);
+
+		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);
+	    // Number of steps
+	    resource[2] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Number of steps",ScalarProperty.class,Integer.class,false);
+	    // Spread Coefficient
+	    resource[3] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Area Restrictions",ScalarProperty.class,WritableGrid.class,false);
+	    resource[4] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Spread Coefficient",ScalarProperty.class,Double.class,false);
+	    resource[5]	= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Dispersion Coefficient",ScalarProperty.class,Double.class,false);
+	    resource[6]	= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Breed Coefficient",ScalarProperty.class,Double.class,false);
+	    resource[7] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"RoadGravity Coefficient",ScalarProperty.class,Double.class,false);
+	    resource[8]	= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Slope Coefficient",ScalarProperty.class,Double.class,false);
+	    resource[9]	= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Critical Slope",ScalarProperty.class,Double.class,false);
+	    resource[10]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Road Grid",ScalarProperty.class,WritableGrid.class,false);
+	    resource[11]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Slope Grid",ScalarProperty.class,WritableGrid.class,false);
+	    resource[12]= new DefaultModelResource(ModelResource.CATEGORY_OUTPUT,"Step Results",MultiGrid.class,false);
+	    resource[13]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Road Gravity Sensitivity",ScalarProperty.class,Double.class,false);
+	    resource[14]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Slope Sensitivity",ScalarProperty.class,Double.class,false);
+	    resource[15]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Critical Low",ScalarProperty.class,Double.class,false);
+	    resource[16]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Critical High",ScalarProperty.class,Double.class,false);
+	    resource[17]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Boom",ScalarProperty.class,Double.class,false);
+	    resource[18]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Bust",ScalarProperty.class,Double.class,false);
+	    
+	 	// ===== Ressourcen Bezeichnungen lokalisieren =====
+	    resetCaptions(null);
+	}
+	
+	
+	@Override
+	public void checkAndError() throws XuluDataException {
+		// TODO Auto-generated method stub
+		super.checkAndError();
+	}
+}



More information about the Xulu-commits mailing list