Wasserlauf

KeiWaran

Grünschnabel
Hi Leutz,

Also ich hab ne 2dimArray erstellt mit Höheninformationen. In jedem Feld ist die Höhe angegeben. Jetzt will ich von irgendeinem Punkt einen Fluss runterlaufen lassen.

Das ist eigentlich kein Problem. Man braucht nur ne rekursive Funktion zu erstellen die checkt welcher Punkt "tiefer" liegt als der Aktuelle.

Das kann aber zu einem Problem führen wenn man in einer Senke landet und es keinen "tieferen" Punkt gibt. Sprich das ein See entstehen muss.

Hmm. Mein Problem liegt jetzt daran das ich nicht weiß wie ich einen "See" programmieren soll....

Hat einer einen Tip für mich?

Kei
 
Also ich hab ne 2dimArray erstellt mit Höheninformationen.
Also ganz hab ich dich da nicht verstanden.
Zeig doch mal ganz grob auf, wie du das organisierst.
Aber ich denke am vernünftigsten wäre es, wenn du zu jedem Punkt, die Nachbarpunkte berechnen würdest und dann kannst du die Fließrichtung ermitteln.

Gruß Homer
 
also gut :) hier ein Beispiel

nimm an das die folgenden Zahlen Höhenangaben sind (zb in Meter).

9 9 9 9 9
9 8 5 5 7
9 7 4 3 9
9 8 6 7 9
9 9 9 9 9

Ok nehmen wir mal an ich will in der zweiten Zeile mit dem Fluss anfangen also bei der 9. Dann fließt der Fluss von der 9 zur 8 (bei mir gibts keine diagonale richtung) und von der 8 zur 5. von der 5 zur 4 und von der 4 zur 3. Bis jetzt ist alles in ordnung weil der Fluss ungehindert weiter "runterfließen" konnte.

Fluss durch "0" dargestellt:
9 9 9 9 9
0 0 0 5 7
9 7 0 0 9
9 8 6 7 9
9 9 9 9 9

Nun kann er das nicht mehr. Das Wasser staut sich (ein See entsteht).

Letztendlich kann der Fluss nur in der zweiten Zeile bei der 7 weiterfließen.

Also sollte zum schluss alle Felder unter Wasser stehen die kleiner als 7 sind:

Wasser wieder durch "0" dargestellt:
9 9 9 9 9
0 0 0 0 0
9 0 0 0 9
9 8 0 0 9
9 9 9 9 9

Hmm und das ist nun mal mein Problem. Ich weiß nicht wie ich das Realisieren kann.

@Daniel Toplak Also wenn ich den Flusslauf berechnen dann tu ich die Nebenpunkte checken und weiß auch ob das Nebenfeld "tiefer" oder "höher" liegt.

Wie gesagt ich weiß nicht wie ich das "stauen" des Wassers realisieren kann. Schließlich kann sich so ein "See" zimlich über eine große Fläche verbreiten.... eventuell über die halbe Karte...

Kei
 
Inwiefern realisieren? Das kannst du doch als zeitlichen Verlauf berechnen. Wenn das Wasser nachläuft, wird zuerst das Feld mit der 4 überflutet, dann die 5er usw. Zunächst sammelt sich das Wasser nur in den unteren Feldern (3). Denen wird ein Volumen zugeordnet und der Fluss muss eine festgelegte Wassermenge pro Zeit führen, damit das Volumen ansteigt. Näherungsweise sollten deinen Volumeneinheiten Quader sein (kann man sich später immer noch was passenderes überlegen, vielleicht ne Bodenfunktion, die du dann integrierst :-)). Dann brauchst du nur simulieren, wie der Wasserpegel steigt, irgendwann die 4 Meter erreicht, dann schwappt das Wasser ins nächste Feld, dein Sammelbecken vergrößert sich (entsprechend Volumen neu berechnen) und mit dem neuen Becken weitermachen.
Bsp.:
9 9 9 9 9
9 8 5 5 7
9 7 4 3 9
9 8 6 7 9
9 9 9 9 9

Volumen einer Einheit: Ve = 1m³
Wasser mit Geschw. v = 10l/s

Jetzt füllt sich zuerst das Feld 3 bis es voll ist:
1m³ -> in 100 Sek. voll,
jetzt füllen sich Becken 4 und Becken 3 -> V = 2m³, in 200 Sek. erreicht
weiter mit 5 V = 4m³ -> t = 400Sek.
usw.
Du brauchst nur, nachdem das aktuelle Volumen überschritten ist,
1. testen ob Felder der nächsthöheren Zahl angrenzen
2. neues Volumen festlegen, indem neue angrenzende Felder addiert werden

Es müssen allerdings Ausnahmen abgefangen werden, wenn z.B. das Wasser aus dem zugelaufenen See wieder irgendwo hinunterfließt. In diesem Fall würde ein neuer See entstehen und der alte füllt sich erst wieder, wenn der neue den gleichen Füllungsstand erreicht (irgendwie rekursiv rangehen).

Oder willst du irgendwas grafisch darstellen? Dann wär der algorithmische Ansatz trotzdem der selbe, musst halt noch ne visuelle Schnittstelle einbauen (die Position der Oberfläche vom Wasser hast du eh, dann halt noch darstellen).
 
Hi Leutz,

ich hab mich mal dran gesetzt und 2 Methoden ausgearbeitet die aber leider nicht so toll funktionieren. Beide kann man für verschiedene Zwecke einsetzen aber nicht für mein Problem (einen Fluss zu generieren - inklusive Seen).

Methode 1: Methode 1 tut den "Meeresspiegel erhöhen". Vom Programmablauf sollte es eigentlich weiterverwendbar sein. Das Problem liegt aber darin das ich nicht weiß wie Groß der "eventuelle" See wird...

Methode 2: Das ist eigentlich der Code der den Flusslauf berechnen soll. Problem ist das - wenn eine Senke kommt (also ein See entstehen soll) - nicht weiter berechnet werden kann... Im Beispiel hab ich 2 Flüsse machen lassen. Der erste fließt schön ins Meer der Zweite bricht ab wenn es nicht weitergeht...

Hab mir einer einen Vorschlag wie ich alles weitermachen kann?

Kei
______________________________________________________
Methode 1:
mail.cpp
PHP:
#include <iostream.h>
#include <stdlib.h>
#include "see.hpp"


using namespace std;

int main(int argc, char *argv[])
{
	see* wasser = new see();
	delete wasser;
	system("PAUSE");	
	return 0;
}

see.hpp
PHP:
class see {
	private:
		//See Koordinaten
		int sK[10][15];
		//Starte mit der Seeerstellung
		void createSee(void);
		//ausgabe des aktuellen Sees
		void showSee(void);
	public:
		see(void);
		~see(void);
};

see.cpp
PHP:
#include <iostream.h>
#include "see.hpp"


void see::showSee(){
	for(int k=0; k<10; k++){
		for(int j=0; j<15; j++){
			cout << sK[k][j] << " ";
		}
		cout << endl;
	}
}

void see::createSee(){
	//höhe
	int h=0;
	//umgebungen
	int xPl;
	int xMi;
	int yPl;
	int yMi;
	while(h < 6){
		for(int y=1; y<9; y++){
			yPl = y+1;
			yMi = y-1;
			for(int x=1; x<14; x++){
				xPl = x+1;
				xMi = x-1;
				
				if(sK[yMi][xMi] <= h){
					sK[yMi][xMi]++;
				}
				if(sK[yMi][x] <= h){
					sK[yMi][x]++;
				}
				if(sK[yMi][xPl] <= h){
					sK[yMi][xPl]++;
				}
				if(sK[y][xMi] <= h){
					sK[y][xMi]++;
				}
				if(sK[y][x] <= h){
					sK[y][x]++;
				}
				if(sK[y][xPl] <= h){
					sK[y][xPl]++;
				}
				if(sK[yPl][xMi] <= h){
					sK[yPl][xMi]++;
				}
				if(sK[yPl][x] <= h){
					sK[yPl][x]++;
				}
				if(sK[yPl][xPl] <= h){
					sK[yPl][xPl]++;
				} 
			}
		} 
		h++;
	}
}

see::see(){
	//see Ausgangsansicht
	int sA[10][15] = {
		{9,9,9,9,9,9,9,9,9,9,9,9,9,9,9},
		{8,1,1,1,1,1,1,1,1,1,1,1,1,1,9},
		{9,1,1,1,1,1,1,1,1,1,1,1,1,1,9},
		{9,1,1,1,1,1,1,1,6,6,6,1,1,1,7},
		{9,1,1,1,1,1,1,7,7,7,6,1,1,1,9},
		{9,1,1,1,1,1,1,7,8,7,1,1,1,1,9},
		{9,1,1,1,1,1,1,7,7,1,1,1,1,1,9},
		{9,1,1,1,1,1,1,1,1,1,1,1,1,1,9},
		{9,1,1,1,1,1,1,1,1,1,1,1,1,1,9},
		{9,9,9,9,9,9,9,9,9,9,9,9,9,9,9}
	};
	for(int k=0; k<10; k++){
		for(int j=0; j<15; j++){
			sK[k][j] = sA[k][j];
		}
	}
	createSee();
	showSee();
}

see::~see(){

}

______________________________________________________

Methode 2:
main.cpp
PHP:
#include <iostream.h>
#include <stdlib.h>
#include "see.hpp"

using namespace std;

int main(int argc, char *argv[])
{
	see* wasser = new see();
	delete wasser;
  	system("PAUSE");	
  	return 0;
}
see.hpp
PHP:
class see {
	private:
		//Map Koordinaten
		int map[9][9];
		//Fluss
		int fluss[9][9];
		//Starte mit der Flusserstellung
		int createFluss(int,int,int);
		//ausgabe der Karte
		void showMap(void);
	public:
		see(void);
		~see(void);
};

see.cpp
PHP:
#include <iostream.h>
#include "see.hpp"

void see::showMap(){
	cout << "Map" << endl;
	for(int k=0; k<9; k++){
		for(int j=0; j<9; j++){
			cout << map[k][j] << " ";
		}
		cout << endl;
	}
	cout << endl << "Map & Fluss" << endl;
	for(int k=0; k<9; k++){
		for(int j=0; j<9; j++){
			if(fluss[k][j] != 0){
				cout << "~" << " ";
			}else{
				cout << map[k][j] << " ";
			}
		}
		cout << endl;
	}
}

int see::createFluss(int x, int y, int flussNr){
	/*
		Tut einen Flusslauf entstehen lassen
	*/
 	//Wird das Meer erreicht ist der Flusslauf an sein Ende gelangt
	if(map[y][x] < 1){
		return 1;
    }
 	//Für das aktuelle Feld den Flusspunkt deffinieren
 	fluss[y][x] = flussNr;
	//Berechnet den nächsten Punkt an dem der Fluss weiterfließt
	
	//Flusslauf nach Norden
	if(
		map[y][x] >= map[y-1][x] &&
		fluss[y-1][x-1] == 0 &&
		fluss[y-1][x] == 0 &&
		fluss[y-1][x+1] == 0
		
      ){
	 	createFluss(x, y-1, flussNr);
	}
	//Flusslauf nach Osten
	if(
		map[y][x] >= map[y][x+1] &&
		fluss[y-1][x+1] == 0 &&
		fluss[y][x+1] == 0 &&
		fluss[y+1][x+1] == 0
		
      ){
		createFluss(x+1, y, flussNr);
	}
	
	//Flusslauf nach Süden
	if(
		map[y][x] >= map[y+1][x] &&
		fluss[y+1][x-1] == 0 &&
		fluss[y+1][x] == 0 &&
		fluss[y+1][x+1] == 0
		
      ){	
		createFluss(x, y+1, flussNr);
	}
	
	//Flusslauf nach Westen
	if(
		map[y][x] >= map[y][x-1] &&
		fluss[y-1][x-1] == 0 &&
		fluss[y][x-1] == 0 &&
		fluss[y+1][x-1] == 0
		
      ){
		createFluss(x-1, y, flussNr);
	}
	cout << "Senke - Hier müsste der Code für das entstehen eines Sees rein..." << endl;
	return 1;
}

see::see(){
	//Map
	int sA[9][9] = {
		{9,9,9,9,9,9,9,9,9},
		{9,7,8,7,9,9,8,7,9},
		{9,6,4,6,9,9,7,7,9},
		{9,5,3,3,9,9,7,6,9},
		{9,4,6,2,9,9,4,5,9},
		{9,3,1,1,9,9,3,7,9},
		{9,7,1,7,9,9,2,2,9},
		{9,7,1,7,9,9,9,9,9},
		{0,0,0,0,0,0,0,0,0}
	};
	for(int k=0; k<9; k++){
		for(int j=0; j<9; j++){
			map[k][j] = sA[k][j];
			fluss[k][j] = 0;
		}
	}
	//Fluss bei x=1; y=1 starten mit der FlussNummer 1
	createFluss(1,1,1);
	//Fluss bei x=6; y=1 starten mit der FlussNummer 2
	createFluss(6,1,2);
	//Endergebnis ausgeben
	showMap();
}

see::~see(){

}
 
Zurück