<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://wiki-de.moshellshocker.dns64.de/index.php?action=history&amp;feed=atom&amp;title=Diamond-square_Algorithmus</id>
	<title>Diamond-square Algorithmus - Versionsgeschichte</title>
	<link rel="self" type="application/atom+xml" href="https://wiki-de.moshellshocker.dns64.de/index.php?action=history&amp;feed=atom&amp;title=Diamond-square_Algorithmus"/>
	<link rel="alternate" type="text/html" href="https://wiki-de.moshellshocker.dns64.de/index.php?title=Diamond-square_Algorithmus&amp;action=history"/>
	<updated>2026-06-10T10:02:09Z</updated>
	<subtitle>Versionsgeschichte dieser Seite in Wikipedia (Deutsch) – Lokale Kopie</subtitle>
	<generator>MediaWiki 1.43.8</generator>
	<entry>
		<id>https://wiki-de.moshellshocker.dns64.de/index.php?title=Diamond-square_Algorithmus&amp;diff=2591471&amp;oldid=prev</id>
		<title>2001:16B8:8144:3B00:D172:9519:9BFA:4C11: Typo.</title>
		<link rel="alternate" type="text/html" href="https://wiki-de.moshellshocker.dns64.de/index.php?title=Diamond-square_Algorithmus&amp;diff=2591471&amp;oldid=prev"/>
		<updated>2024-06-17T03:39:22Z</updated>

		<summary type="html">&lt;p&gt;Typo.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Neue Seite&lt;/b&gt;&lt;/p&gt;&lt;div&gt;Der &amp;#039;&amp;#039;&amp;#039;Diamond-square Algorithmus&amp;#039;&amp;#039;&amp;#039; ist ein Verfahren, das in der [[Computergrafik]] eingesetzt wird, um [[Höhenfeld]]er zu erzeugen. Er stellt eine [[zweidimensional|2-dimensionale]] Verallgemeinerung der [[Mittelpunktverschiebung]] dar. Der Algorithmus wurde erstmals 1982 von [[Alain Fournier (Informatiker)|Fournier]], Fussell und Carpenter auf der [[SIGGRAPH]] 1982 vorgestellt&amp;lt;ref name=&amp;quot;fournier1982computer&amp;quot;&amp;gt;A. Fournier,D. Fussell und L. Carpenter: &amp;#039;&amp;#039;Computer rendering of stochastic models&amp;#039;&amp;#039; In: Communications of the ACM, Band 25, Nr. 6, 1982, S. 371–384&amp;lt;/ref&amp;gt;. Der Name geht zurück auf Gavin S. P. Miller&amp;lt;ref name=&amp;quot;miller1986definition&amp;quot;&amp;gt;Gavin S. P. Miller: &amp;#039;&amp;#039;The definition and rendering of terrain maps&amp;#039;&amp;#039; In: ACM SIGGRAPH Computer Graphics, Band 20, Nr. 4, 1986, S. 39–48&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Funktionsweise ==&lt;br /&gt;
Ausgangspunkt für die Generierung einer fraktalen Landschaft auf Basis des Diamond-square Algorithmus ist ein Quadrat. Jeder Ecke des Quadrats wird ein Höhenwert zugeordnet. Der Algorithmus zerlegt das Quadrat [[rekursiv]] in kleinere Quadrate, wobei der Höhenwert des Mittelpunkts als Mittelwert der vier Eckpunkte, plus einer zufälligen Verschiebung, definiert wird. Analog wird der Höhenwert der [[Seitenhalbierende]]n eines Quadrats als Mittelwert der vier horizontal umgebenden Punkte, plus einer zufälligen Verschiebung, definiert. Die Verschiebung ist [[Normalverteilung|Normalverteilt]] mit einem [[Mittelwert]] von 0 und nimmt mit der Größe der Rechtecke ab. Die Mittelpunkte und Seitenhalbierende bilden die Eckpunkte der neuen Rechtecke. Ausnahme von der Regel zur Generierung der neuen Punkte bilden die vier Außenseiten des ursprünglichen Rechtecks, die jeweils nach der eindimensionalen Mittelpunktverschiebung generiert werden&amp;lt;ref name=&amp;quot;fournier1982computer&amp;quot; /&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Für den Diamond-square Algorithmus kommt ein 3x3-Raster, ein 5x5-Raster, ein 9x9-Raster, ein 17x17-Raster oder allgemein ein [[Quadratisch|quadratisches]] Raster infrage, wo die Breite und Höhe gleich &amp;lt;math&amp;gt;2^n + 1&amp;lt;/math&amp;gt; mit einer positiven [[Ganze Zahl|ganzen Zahl]] &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; ist. Jede [[Iteration]] unterteilt jedes Quadrat in 4 gleich große Quadrate mit halber Seitenlänge und besteht aus 2 Schritten:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;Karoschritt&amp;#039;&amp;#039;: Für jedes Quadrat des Rasters wird ein zufälliger Wert im Mittelpunkt erzeugt, wo sich die beiden Diagonalen des Quadrats schneiden. Der Wert für den Mittelpunkt wird berechnet, indem der Durchschnitt der Werte der 4 Ecken des Quadrats gebildet und ein zufälliger Betrag addiert wird. Dadurch entstehen Quadrate, die auf der Ecke stehen (&amp;#039;&amp;#039;Karos&amp;#039;&amp;#039;).&lt;br /&gt;
* &amp;#039;&amp;#039;Quadratschritt&amp;#039;&amp;#039;: Für jedes quadratische Karo wird ein zufälliger Wert im Mittelpunkt erzeugt, wo sich die beiden Diagonalen des Karos schneiden. Der Wert für den Mittelpunkt wird berechnet, indem der Durchschnitt der Werte der 4 Ecken des Karos gebildet und ein zufälliger Betrag addiert wird, der im gleichen Bereich liegt wie im Karoschritt. Dadurch entstehen wieder Quadrate, die parallel zum Raster sind.&lt;br /&gt;
&lt;br /&gt;
Jede [[Iteration]] unterteilt jedes Quadrat also in 4 gleich große Quadrate mit halber Seitenlänge. Wenn die Prozedur 2-mal ausgeführt wird, entstehen aus jedem Quadrat &amp;lt;math&amp;gt;4^2 = 16&amp;lt;/math&amp;gt; kleinere Quadrate mit gleicher Seitenlänge. Wenn die Prozedur &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-mal ausgeführt wird, entstehen aus jedem Quadrat &amp;lt;math&amp;gt;4^k&amp;lt;/math&amp;gt; kleinere Quadrate mit gleicher Seitenlänge.&amp;lt;ref&amp;gt;Robert C. Pendleton: [https://web.archive.org/web/20060420054134/http://www.gameprogrammer.com/fractal.html#diamond Generating Random Fractal Terrain]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Folgende Abbildung zeigt die ersten zwei Iterationen des Algorithmus für ein 5x5-Raster:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Diamond Square.svg|rahmenlos|800x800px]]&lt;br /&gt;
&lt;br /&gt;
Dabei werden vier Schritte in der Reihenfolge &amp;#039;&amp;#039;Karoschritt, Quadratschritt, Karoschritt, Quadratschritt&amp;#039;&amp;#039; ausgeführt. Schon vorhandene Punkte sind schwarz, neu erzeugte Punkte sind gelb dargestellt.&lt;br /&gt;
&lt;br /&gt;
== Programmierung ==&lt;br /&gt;
Das folgende Beispiel in der [[Programmiersprache]] [[C-Sharp|C#]] zeigt die Implementierung des Diamond-square Algorithmus. Das Höhenfeld wird als [[Zweidimensional|zweidimensionales]] Hintergrundbild des Hauptfensters dargestellt. Die berechneten Werte entsprechen den Farbwerten der [[Pixel]] einer &amp;#039;&amp;#039;Bitmap&amp;#039;&amp;#039;.&amp;lt;ref&amp;gt;GitHub: [https://gist.github.com/awilki01/83b65ad852a0ab30192af07cda3d7c0b Diamond-Square Algorithm for Generating Terrain (C#)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable left mw-collapsible mw-collapsed font-size: 105.3%;&amp;quot;&lt;br /&gt;
|style=&amp;quot;text-align:left; font-size: 95%;&amp;quot;| &amp;#039;&amp;#039;&amp;#039;Code-Schnipsel&amp;#039;&amp;#039;&amp;#039;&amp;amp;nbsp;&amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c#&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Drawing;&lt;br /&gt;
using System.Windows.Forms;&lt;br /&gt;
&lt;br /&gt;
namespace DiamondSquare&lt;br /&gt;
{&lt;br /&gt;
	public class DiamondSquare&lt;br /&gt;
	{&lt;br /&gt;
		// Diese Methode berechnet die Werte mit dem Diamond-square Algorithmus&lt;br /&gt;
		// Gegen ist die Seitenlänge des Quadrats, der Bereich für die zufälligen Werte und der Wert für die 4 Ecken des Quadrats&lt;br /&gt;
		public double[,] CalculateValues(int length, double roughness, double seed)&lt;br /&gt;
		{&lt;br /&gt;
			// Initialisiert den Wert der 4 Ecken des Quadrats&lt;br /&gt;
			double[,] values = new double[length, length]; // Initialisiert das zweidimensionale Array für die Werte des quadratischen Rasters&lt;br /&gt;
			values[0, 0] = seed; // Wert der Ecke links oben&lt;br /&gt;
			values[0, length - 1] = seed; // Wert der Ecke links unten&lt;br /&gt;
			values[length - 1, 0] = seed; // Wert der Ecke rechts oben&lt;br /&gt;
			values[length - 1, length - 1] = seed; // Wert der Ecke rechts unten&lt;br /&gt;
			Random random = new Random(); // Initialisiert den Zufallsgenerator&lt;br /&gt;
			// Diese for-Schleife definiert die Iterationsschritte des Algorithmus&lt;br /&gt;
			// In jedem Iterationsschritt wird die Seitenlänge der Teilquadrate und der Bereich für die zufälligen Werte halbiert, bis die Seitenlänge kleiner als 2 ist&lt;br /&gt;
			for (int sideLength = length - 1; sideLength &amp;gt;= 2; sideLength /= 2, roughness /= 2.0)&lt;br /&gt;
			{&lt;br /&gt;
				int halfLength = sideLength / 2;&lt;br /&gt;
				// In diesen zwei for-Schleifen werden die Werte für den Karoschritt berechnet&lt;br /&gt;
				for (int x = 0; x &amp;lt; length - 1; x += sideLength)&lt;br /&gt;
				{&lt;br /&gt;
					for (int y = 0; y &amp;lt; length - 1; y += sideLength)&lt;br /&gt;
					{&lt;br /&gt;
						// Berechnet den Mittelwert der 4 Ecken des Teilquadrats&lt;br /&gt;
						double average = (values[x, y] // Wert der Ecke links oben&lt;br /&gt;
						                  + values[x, y + sideLength] // Wert der Ecke links unten&lt;br /&gt;
						                  + values[x + sideLength, y] // Wert der Ecke rechts oben&lt;br /&gt;
						                  + values[x + sideLength, y + sideLength]) / 4.0; // Wert der Ecke rechts unten&lt;br /&gt;
						average += (2 * roughness * random.NextDouble()) - roughness; // Addiert einen zufälligen Wert im Bereich von -roughness bis +roughness zum Mittelwert&lt;br /&gt;
						values[x + halfLength, y + halfLength] = average; // Setzt den Wert für den Mittelpunkt des Teilquadrats&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				// In diesen zwei for-Schleifen werden die Werte für den Quadratschritt berechnet&lt;br /&gt;
				for (int x = 0; x &amp;lt; length - 1; x += halfLength)&lt;br /&gt;
				{&lt;br /&gt;
					for (int y = (x + halfLength) % sideLength; y &amp;lt; length - 1; y += sideLength)&lt;br /&gt;
					{&lt;br /&gt;
						// Berechnet den Mittelwert der 4 Ecken des Karos&lt;br /&gt;
						double average = (values[(x - halfLength + length) % length, y] // Wert der linken Ecke&lt;br /&gt;
						                  + values[(x + halfLength) % length, y] // Wert der rechten Ecke&lt;br /&gt;
						                  + values[x, (y - halfLength + length) % length] // Wert der oberen Ecke&lt;br /&gt;
						                  + values[x, (y + halfLength) % length]) / 4.0; // Wert der unteren Ecke&lt;br /&gt;
						average += (2 * roughness * random.NextDouble()) - roughness; // Addiert einen zufälligen Wert im Bereich von -roughness bis +roughness zum Mittelwert&lt;br /&gt;
						values[x, y] = average; // Setzt den Wert für den Mittelpunkt des Karos&lt;br /&gt;
						if (x == 0) // Sonderfall für die linke Kante des Quadrats&lt;br /&gt;
						{&lt;br /&gt;
							values[length - 1, y] = average; // Setzt den entsprechenden Punkt auf der rechten Kante auf denselben Wert&lt;br /&gt;
						}&lt;br /&gt;
						if (y == 0) // Sonderfall für die obere Kante des Quadrats&lt;br /&gt;
						{&lt;br /&gt;
							values[x, length - 1] = average; // Setzt den entsprechenden Punkt auf der unteren Kante auf denselben Wert&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return values;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// Klasse für das Hauptfenster&lt;br /&gt;
	public partial class MainForm : Form&lt;br /&gt;
	{&lt;br /&gt;
		private Bitmap bitmap;&lt;br /&gt;
		&lt;br /&gt;
		private int length;&lt;br /&gt;
		private double[,] values; // Zweidimensionales Array für die Werte des quadratischen Rasters&lt;br /&gt;
		&lt;br /&gt;
		public MainForm()&lt;br /&gt;
		{&lt;br /&gt;
			Random random = new Random(); // Initialisiert den Zufallsgenerator&lt;br /&gt;
			length = 257; // Seitenlänge des Quadrats, es ist 2^8 + 1 = 257&lt;br /&gt;
			int roughness = 64; // Bereich für die zufälligen Werte&lt;br /&gt;
			int seed = 128; // Wert für die 4 Ecken des Quadrats&lt;br /&gt;
			&lt;br /&gt;
			DiamondSquare diamondSquare = new DiamondSquare(); // Erzeugt ein Objekt der Klasse DiamondSquare&lt;br /&gt;
			values = diamondSquare.CalculateValues(length, roughness, seed); // Aufruf der Methode, die die Werte für das quadratische Raster berechnet und zurückgibt&lt;br /&gt;
			bitmap = new Bitmap(length, length); // Erzeugt ein quadratisches Bitmap mit der gegebenen Seitenlänge&lt;br /&gt;
			BackgroundImage = bitmap; // Setzt die Bitmap als Hintergrundbild des Hauptfensters.&lt;br /&gt;
			&lt;br /&gt;
			InitializeComponent();&lt;br /&gt;
			Text = &amp;quot;Diamond-square Algorithmus&amp;quot;;&lt;br /&gt;
			Width = 800;&lt;br /&gt;
			Height = 800;&lt;br /&gt;
			Paint += OnPaint; // Verknüpft die Ereignisbehandlungsmethode mit dem Paint Ereignis des Hauptfensters.&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		// Diese Methode wird aufgerufen, wenn das Hauptfenster gezeichnet wird und setzt die Pixel des Bitmaps&lt;br /&gt;
		private void OnPaint(object sender, PaintEventArgs e)&lt;br /&gt;
		{&lt;br /&gt;
			// Diese for-Schleifen durchlaufen die Pixel des Bitmaps&lt;br /&gt;
			for (int x = 0; x &amp;lt; length; x++)&lt;br /&gt;
			{&lt;br /&gt;
				for (int y = 0; y &amp;lt; length; y++)&lt;br /&gt;
				{&lt;br /&gt;
					bitmap.SetPixel(x, y, Color.FromArgb(0, (int) values[x, y], 0)); // Setzt den Farbwert des Pixels&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Mögliche Implementierung in unterschiedlichen Dimensionen ==&lt;br /&gt;
Es ist möglich, den Algorithmus in verschiedene Dimensionen zu übertragen und somit unterschiedliche Resultate zu erzielen. Hierbei wird eine n-dimensionale Einheit mit Tiefe versehen. Das heißt, dass für jede berechnete n-dimensionale Koordinate ein Wert, meist von 0 bis 1, vorhanden ist. Die optische Darstellung kann man entweder mit einer Verschiebung in der nächsten Dimensionsachse oder eine Farbe bzw. Transparenz realisieren. Hierbei ist die zweidimensionale Implementierung namensgebend.&lt;br /&gt;
;Beispiele:&lt;br /&gt;
Bei einer dreidimensionalen Implementierung kann man sich zum Beispiel eine Karte für die Dichte von Nebel vorstellen. Hierbei werden unterschiedliche Areale unterschiedlich viel Licht absorbieren.&lt;br /&gt;
&lt;br /&gt;
== Kritik ==&lt;br /&gt;
Gavin S. P. Miller hat den Diamond-square Algorithmus kritisiert, da er, im Gegensatz zu dem von ihm vorgestellten [[Square-square Algorithmus]], zu auffälligen Artefakten in der generierten Landschaft führt&amp;lt;ref name=&amp;quot;miller1986definition&amp;quot; /&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Fraktale Landschaften im Allgemeinen stehen in der Kritik, da sie zwar eine gute Approximation für Bergzüge liefern, die Landschaften jedoch – stellt man sie auf den Kopf – [[statistisch identisch]] sind&amp;lt;ref&amp;gt;F.K. Musgrave, C.E. Kolb und R.S. Mace: &amp;#039;&amp;#039;The synthesis and rendering of eroded fractal terrains&amp;#039;&amp;#039; In: ACM SIGGRAPH Computer Graphics, Band 23, Nr. 3, 1989, S. 41–50&amp;lt;/ref&amp;gt;. In der Realität lagern sich jedoch beispielsweise Sedimente in Talsenken ab, wodurch diese abflachen. Unter anderem haben Musgrave, Kolb und Mace unter Berücksichtigung von [[Erosion (Geologie)|Erosion]]&amp;lt;nowiki /&amp;gt;seffekten eine Weiterentwicklung fraktaler Landschaften entwickelt, die in der Lage ist, Landschaften zu erzeugen, die wesentlich realitätsnäher sind.&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
* Async Drink: [https://asyncdrink.com/blog/diamond-square-algorithm Generating landscapes with the Diamond Square algorithm]&lt;br /&gt;
* Robert C. Martin, The Clean Code Blog [https://blog.cleancoder.com/uncle-bob/2017/01/09/DiamondSquare.html TDD Lesson - Terrain Generation]&lt;br /&gt;
* [https://gist.github.com/awilki01/83b65ad852a0ab30192af07cda3d7c0b Diamond-square Implementierung in C#]&lt;br /&gt;
* [https://github.com/A1essandro/Diamond-And-Square Diamond-square Implementierung in PHP]&lt;br /&gt;
* Fractal terrain generator: [https://spbooth.github.io/xmountains/ Xmountains]&lt;br /&gt;
&lt;br /&gt;
== Einzelnachweise ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Algorithmus (Computergrafik)]]&lt;/div&gt;</summary>
		<author><name>2001:16B8:8144:3B00:D172:9519:9BFA:4C11</name></author>
	</entry>
</feed>