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 (à 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.
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 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.
En plus, je vais devoir faire quelque chose d'assez proche (mais qui générera du HTML + CSS).
Sephi-Chan
|