JeuWeb - Crée ton jeu par navigateur
[Résolu] Génération d'un graphe respectant un visuel - Version imprimable

+- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org)
+-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38)
+--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51)
+--- Sujet : [Résolu] Génération d'un graphe respectant un visuel (/showthread.php?tid=4580)

Pages : 1 2 3


RE: Génération d'un graphe respectant un visuel - Harparine - 11-02-2010

Salut, je te propose un calcul avec moins de conditions (pas de repérage de "coin"). Si tu veux des explications, n'hésite pas Wink (à copier-coller dans un fichier pour le test).

Code PHP :
<?php
function getNeighbours($n, $c) {
$return = array();
if(
$n == 0) { // Si le centre
for($i = 0; $i < 4; $i++) {
$return[] = array(1, $i);
}
} else {
if(
$c%$n == 0) { // Si sur un axe
$return[] = validIndex($n + 1, $c + floor($c / $n) - 1);
} else {
$return[] = validIndex($n - 1, $c - floor($c / $n) - 1 );
}
$return[] = validIndex($n - 1, $c - floor($c / $n));
$return[] = validIndex($n, $c - 1);
$return[] = validIndex($n, $c + 1);
$return[] = validIndex($n + 1, $c - floor($c / $n));
$return[] = validIndex($n + 1, $c - floor($c / $n) + 1);
}

usort($return, '_sort1');

return
$return;
}

// Première fonction de tri (du plus petit cercle au plus grand)
function _sort1($a,$b) {
if (
$a[0] == $b[0])
return
_sort2($a,$b);
return (
$a[0] < $b[0]) ? -1 : 1;
}

// Deuxième fonction de tri (si égalité, du plus petit index au plus grand)
function _sort2($a,$b) {
if (
$a[1] == $b[1])
return
0;
return (
$a[1] < $b[1]) ? -1 : 1;
}

// Vérifie que l'index calculé ne soit pas trop grand ou trop petit
function validIndex($n, $c) {
if(
$c < 0) $c = $n * 4 - 1;
if(
$c >= $n * 4) $c = 0;

return array(
$n, $c);
}

//On définit le maillage de sphères
$spheres = array();
$spheres[] = array(0,0);
for(
$i = 1; $i < 4; $i++) {
for(
$j = 0; $j < 4 * $i; $j++) {
$spheres[] = array($i, $j);
}
}

//On affiche les résultats

foreach($spheres as $sphere) {
$neighbours = getNeighbours($sphere[0],$sphere[1]);
echo
"Sphère ", $sphere[0], "-", $sphere[1], " : ";
foreach(
$neighbours as $elem) {
echo
"", $elem[0], "-", $elem[1], " | ";
}
echo
"<br />";
}


?>

Par contre, il faut juste limiter les voisins pour le dernier cercle : je n'ai pas mis de limites au maillage.

@+


RE: Génération d'un graphe respectant un visuel - Sephi-Chan - 12-02-2010

Je dois avouer que tel quel, je n'arrive pas à lire le code (à cause du nommage des variables/fonctions, essentiellement) et à comprendre l'intention. Je retenterai ma chance demain. Cependant, si tu as le temps, je ne suis pas contre une explication. Smile

En tout cas, merci à tous pour l'aide apportée et merci aussi pour ce code. L'approche a l'air plus mathématique que la mienne (ça se voit tant que ça, que je suis une burne en maths ?).


Sephi-Chan


RE: Génération d'un graphe respectant un visuel - Harparine - 12-02-2010

Pour les variables, j'ai repris celles que tu avais utilisées pour tes explications en début de post (N : niveau, C : coefficient).
La seule fonction vraiment utile est la fonction getNeighbours qui prend les valeurs N et C d'une sphère. La fonction renvoie un tableau contenant les sphères voisines.

Les fonctions _sort1 et _sort2 sont utilisées par usort (ce qui permet de renvoyer un tableau trié du plus petit cercle au plus grand, classé par coefficient). La fonction validIndex s'assure juste que l'on n'aie pas de valeurs de C négatives ou supérieur au nombre de sphères sur un cercle.

Sinon, pour l'explication de getNeighbours, à part pour l'origine, il y a des récurrences :
- toujours les voisins de gauche et droite sur le cercle.
- toujours une sphère du cercle inférieur dont l'index de coef est C - arrondi.inf(C / N). Par exemple pour N = 3 et C = 10, on peut calculer qu'une sphère de niveau N-1 (3 - 1 = 2) et de coef. C - arrondi.inf(C / N) (10 - arrondi.inf(10 / 3) = 7) est sa voisine (2,7 est voisine de 3, 10).
- inverse pour le cercle supérieur.
-etc.

Toutes les autres formules sont vérifiables avec un plan de ton graphe sous les yeux. En notant les formules, j'ai finalement constaté que seule une voisine n'était pas la même pour les sphères sur les axes X et Y (il n'y a qu'une voisine sur le cercle inférieur et trois sur le cercle supérieur).

Bref, je ne pense pas être trop clair mais j'allais me coucher et je ne me sens pas de me lancer dans des schémas à cette heure-ci Wink J'espère que tu capteras.


RE: Génération d'un graphe respectant un visuel - jo_link_noir - 12-02-2010

Salut,
Harparine, je croit qu'il y a une erreur avec les 3 derniers points, quand n est supérieur ou égal à 2, ils se décalent.
Code :
Sphère 2-2 : 1-1 | 2-1 | 2-3 | 3-1 | 3-2 | 3-2 |
Sphère 3-7 : 2-4 | 2-5 | 3-6 | 3-8 | 4-5 | 4-6 |
Sphère 3-8 : 2-5 | 2-6 | 3-7 | 3-9 | 4-6 | 4-7 |
Sphère 3-9 : 2-6 | 3-8 | 3-10 | 4-6 | 4-7 | 4-11 |
Si je ne me trompe pas, normalement ça donne
Code :
Sphère 2-2 : 1-1 | 2-1 | 2-3 | 3-2 | 3-3 | 3-4 |
Sphère 3-7 : 2-4 | 2-5 | 3-6 | 3-8 | 4-10 | 4-9 |
Sphère 3-8 : 2-5 | 2-6 | 3-7 | 3-9 | 4-11 | 4-10 |
Sphère 3-9 : 2-6 | 3-8 | 3-10 | 4-13 | 4-12 | 4-11 |

En fait, l'algo que j'ai fait ne marche que pour c=4 '^^

Bonne nuit


RE: Génération d'un graphe respectant un visuel - Harparine - 12-02-2010

Merde, j'ai zappé deux moins en faisant mon copié-collé. Les deux derniers calculs de getNeighbours sont bien sûr :
$return[] = validIndex($n + 1, $c + floor($c / $n));
$return[] = validIndex($n + 1, $c + floor($c / $n) + 1);
@+


RE: [Résolu] Génération d'un graphe respectant un visuel - jo_link_noir - 13-02-2010

Vu que j'avais que ça à faire, -et histoire de ne pas l'avoir fait pour rien (xD)- je vous passe le svg pour visualiser le tout.
On peut passer dans l'url les valeurs n, c, space (espace entre cercle) et r (rayon).
Par défaut n=5, c=4, space=10, r=50

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">


<svg xml:lang="fr" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1500px" height="1500px">
<title>Nœuds adjacents pour un cercle</title>

<script type="text/javascript">
<![CDATA[
function event(el, type, fn)
{
if (el.addEventListener)
el.addEventListener(type, fn, true);
else if (el.attachEvent)
el.attachEvent("on"+type, fn);
else
el["on"+type] = fn;
}

Uri = {
get : function()
{
var params = new Array(),
first = window.location.search.slice(1,window.location.search.length).split("&");

for(var i in first)
{
var second = first[i].split("=");
if (second[0])
params[second[0]] = second[1] | "" ;
}

return params;
}
};

function intval(v, d)
{
if ("undefined" !== typeof v)
{
v = parseInt(v);
return (v == "NaN") ? d?d:0 : v;
}
return d?d:0;
}

event(window, "load", function(){
var get = Uri.get(),
n = intval(get["n"], 5), //nombre de spirale
c = intval(get["c"], 4), //nombre de cercle dans la première spirale
space = intval(get["space"], 10), //espace entre les cercles
r = intval(get["r"], 50), //rayon d'un cercle
d = space + r, //distance qui sépare un cercle à un autre
o = r + n*(r+d), //position x et y de l'origine
svg = document.documentElement;

svg.setAttribute("width", o*2);
svg.setAttribute("height", o*2);

var id = function(x,y)
{
return "circle-"+x+"-"+y;
}

var adjacent = function(x, y)
{
//origine
if (x === 0 && y === 0)
{
var circles = new Array();
for (var i=0; i<c; ++i)
circles[i] = id(x+1, y+i);
}
else
{
var y1 = Math.floor(y * (1 + 1/x)),
y2 = Math.floor(y * (1 - 1/x)),
cn = c*x - 1,
circles = new Array(
id(x, (y+1 > cn) ? 0 : y+1), //condition sur fin de cercle
id(x, y ? y-1 : cn), //condition sur début de cercle
id(x+1, y1),
id(x-1, y2),
id(x+1, y1+1)
);

//axe
if (y === 0 || y%x === 0)
{
circles[5] = id(x+1, y ? y * (1 + 1/x) -1 : cn+c); //condition sur début de cercle
}
else
{
circles[5] = id(x-1, (y2+c+1 > cn) ? 0 : y2+1); //condition sur fin de cercle
}
}

for (var i in circles)
circles[i] = document.getElementById(circles[i]);

return circles;
}

var circleInit = function(x, y, cx, cy)
{
circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
circle.setAttribute("cx", cx);
circle.setAttribute("cy", cy);
circle.setAttribute("r", r);
circle.setAttribute("id", id(x,y));

event(circle, "mouseover", function(){
var c = adjacent(x,y);
for (var i in c)
{
if (c[i])
c[i].setAttribute("fill","red");
}
});
event(circle, "mouseout", function(){
var c = adjacent(x,y);
for (var i in c)
{
if (c[i])
c[i].removeAttribute("fill");
}
});

return circle;
}

//nœud d'origine
svg.appendChild(circleInit(0, 0, o, o));

for (var x = 1; x <= n; ++x)
{
var maxY = c*x, //4 équivaut au nombre cercle à la première spirale
p = Math.PI/maxY*2, //distance d'angle séparant les points
op = x * (r+d), //distance entre origine et point
a = -Math.PI/2; //angle de début pour que les y=0 soit diriger vers le haut

for (var y = 0; y < maxY; ++y)
{
var cx = o + op * Math.cos(a),
cy = o + op * Math.sin(a);
svg.appendChild(circleInit(x, y, cx, cy));

//affiche du texte
var text = document.createElementNS("http://www.w3.org/2000/svg", "text");
text.setAttribute("x", cx);
text.setAttribute("y", cy);
text.setAttribute("fill", "yellow");
text.appendChild(document.createTextNode(x+";"+y));
svg.appendChild(text);

a += p;
}
}
});
]]>
</script>
</svg>



RE: [Résolu] Génération d'un graphe respectant un visuel - Sephi-Chan - 13-02-2010

Merci beaucoup ! C'est bien rigolow. Smile
En plus, je vais devoir faire quelque chose d'assez proche (mais qui générera du HTML + CSS).


Sephi-Chan