@niahoo: Latitude/Longitude impliquent une carte sphérique, ce qui ne sera pas forcément le cas, d'où X/Y et altitude (et non Z car deux cases ne se superposent pas: l'altitude est une propriété de la case en XY plus qu'une coordonnée de la case).
Le générateur de carte travaillant à partir d'une image PNG, le résultat n'est pas parfaitement exact, et des cases terrestres se retrouvent sous le niveau de la mer, en étant voisine de celle-ci :\
@Ter Rowan: Oui, dans le cas d'une case sous le niveau de la mer, voisine d'une case également sous le niveau de la mer, voisine elle-même d'une case maritime, les deux cases sous le niveau de la mer seront inondées. Cela se fera très bien par réccurence: noyer les cases cotières sous le niveau de la mer, ce qui crée de nouvelles cases maritimes, modifier la liste des cases cotières sachant lesquelles viennent d'être noyées, puis noyer les cases cotières sous le niveau de la mer voisine d'une case qui vient d'être noyée.
Cette récurrence est en place, mais chaque "passage" (chaque tour de boucle) prend une dizaine de secondes, et comme le nombre de boucles peut monter à quelques centaines, cela fait vite très très long!
Oui, j'ai tenté de stocker un autre attribut indiquant qu'une case est cotière, mais la requête pour générer cet attribut est interminable (cf 2nd post, requête sans le "case0.altitude <=0).
@Akhyra: La carte contient environ 500k cases, dont 200k sont terrestres et 300k sont maritimes. Pour l'instant, l'inondation est réalisée uniquement au démarrage du jeu, pour l'initialiser.
J'ai eu la même idée en me levant, passer par un PHP avec un tableau 2D de booléens "mer" pour créer un autre tableau de booléens 2D "estCotiere". Je viens de tester, et le résultat est assez satisfaisant. Je vais essayer de faire le même procédé en SQL.
Pour information, en voici le code:
Temps (500k cases dont 24k cases côtières): 5secondes
Mémoire (carte 1440*720 contenant 500k cases): 165Mo
Merci du coup de main
Le générateur de carte travaillant à partir d'une image PNG, le résultat n'est pas parfaitement exact, et des cases terrestres se retrouvent sous le niveau de la mer, en étant voisine de celle-ci :\
@Ter Rowan: Oui, dans le cas d'une case sous le niveau de la mer, voisine d'une case également sous le niveau de la mer, voisine elle-même d'une case maritime, les deux cases sous le niveau de la mer seront inondées. Cela se fera très bien par réccurence: noyer les cases cotières sous le niveau de la mer, ce qui crée de nouvelles cases maritimes, modifier la liste des cases cotières sachant lesquelles viennent d'être noyées, puis noyer les cases cotières sous le niveau de la mer voisine d'une case qui vient d'être noyée.
Cette récurrence est en place, mais chaque "passage" (chaque tour de boucle) prend une dizaine de secondes, et comme le nombre de boucles peut monter à quelques centaines, cela fait vite très très long!
Oui, j'ai tenté de stocker un autre attribut indiquant qu'une case est cotière, mais la requête pour générer cet attribut est interminable (cf 2nd post, requête sans le "case0.altitude <=0).
@Akhyra: La carte contient environ 500k cases, dont 200k sont terrestres et 300k sont maritimes. Pour l'instant, l'inondation est réalisée uniquement au démarrage du jeu, pour l'initialiser.
J'ai eu la même idée en me levant, passer par un PHP avec un tableau 2D de booléens "mer" pour créer un autre tableau de booléens 2D "estCotiere". Je viens de tester, et le résultat est assez satisfaisant. Je vais essayer de faire le même procédé en SQL.
Pour information, en voici le code:
$r = $mysqli->query('SELECT `x`, `y`, `altitude`, `mer` FROM `cases`');
// Initialiser un tableau d'entiers type "flag", dont le premier bit indique s'il s'agit d'une case maritime (0x01)
// Le second bit (0x02) indique s'il s'agit d'une case cotière
$data = array_fill(0, 720, array_fill(0, 1440, 0));
// Insérer les données SQL dans ce tableau
foreach ($r as $c)
$data[(int)$c['y']][(int)$c['x']] = (int)$c['mer'];
foreach ($data as $j=>&$row)
{
foreach ($row as $i=>&$case) // Pour chaque case du tableau
{
// On teste si la case est terrestre et si l'un de ses voisins est maritime
// Effectivement, comme souligné par Akhyra, on pourra ajouter des traitements supplémentaires
// Comme le fait que la carte "boucle", exemple: les cases en X=0 sont voisines de celles en X=Xmax
// X=0 ($i==0) sont les cases du bord gauche, X=1439 ($i==1439) sont celles du bord droit
// Y=0 ($j==0) sont les cases du bord haut, Y=719 ($j==719) sont celles du bord bas
// Dans ce test, la carte ne boucle pas (pas encore!)
if ($case == 0
and (
($j > 0 and $i > 0 and $data[$j-1][$i-1] & 0x01)
or ($j > 0 and $i < 1439 and $data[$j-1][$i+1] & 0x01)
or ($j < 719 and $i > 0 and $data[$j+1][$i-1] & 0x01)
or ($j < 719 and $i < 1439 and $data[$j+1][$i+1] & 0x01)
)
)
$case |= 0x02; // Case cotière
}
}
// ($data[y][x] & 0x01) indique si la case est maritime
// ($data[y][x] & 0x02) indique si la case est cotière
Temps (500k cases dont 24k cases côtières): 5secondes
Mémoire (carte 1440*720 contenant 500k cases): 165Mo
Merci du coup de main