Smooth 3d camembert

Soyez le premier à donner votre avis sur cette source.

Vue 19 437 fois - Téléchargée 1 862 fois

Description

Suite à la remarque de BADOUX concernant le "camembert" de la source N°34131 d'adresse :
http://www.phpcs.com/codes/CAMEMBERTS-3D_34131.aspx
et dont les bords lui semblaient "un peux pixellisé", j'ai décidé de revoir tout le code avec la ferme intention de faire disparaître ces vilains petits défauts (d'où cette nouvelle publication et non pas une simple mise à jour).
Un mot-clé à retenir : Anti-Aliasing (AA pour les connaisseurs)
Sa définition : "algorithme appliqué sur le contour des formes pour en rendre l'aspect plus agréable, et éviter de voir la structure grillagée de l'image."

La méthode "bourrin" consiste à créer une image plus grande (par exemple 3 fois plus grande)que l'on réduit à la bonne taille une fois le travail effectué. L'AA est réalisé par la fonction de réduction "ImageCopyResampled()", qui se charge de trouver un compromis satisfaisant entre les pixels constituant chaque carré de 3x3. Cette technique est efficace, l'image finale qu'elle produit acceptable (pour un camembert!), le code l'implémentant court et facile à comprendre, son seul défaut est de requérir un temps d'exécution important (que je n'ai pas mesuré, mais bon...). On peut trouver un code de ce type en allant sur "http://www.phpclasses.org" (y rechercher quelque chose comme "EQ_Smooth_3D_Pie_Graph").

On peut aussi attaquer le problème par la face nord, en partant d'une image à l'échelle 1, et gérer les transitions entre les zones de couleurs différentes.
Cette technique suppose en fait la réécriture des fonctions de gd2 impliquées dans l'image, et l'utilisation intensive d'algorithmes qui ont pour nom : Bresenham, Gupta-Sproull, point-milieu, ainsi que la mise à contribution de la transparence alpha.

C'est cette deuxième méthode qui est traitée ici.
Le code ci-dessous est entièrement fonctionnel, on peut donc en faire un copier-coller et l'exécuter immédiatement (php5 et gd2 requis).
Pour ceux qui veulent approfondir, ils trouveront dans le zip une version plus aboutie utilisant une véritable police de caractères et donnant le choix entre trois tailles de camembert différentes et trois types de fonds différents.

La démo en ligne :
http://michel.vanthodiep.free.fr/smooth3dcamembert/

Source / Exemple :


<?php
header ('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header ('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header ('Cache-Control: no-cache, must-revalidate');
header ('Pragma: no-cache');

/*
 - Date de création : 27/01/2008
 - Nom : aacamembert.php, version simplifiée à "copier-coller"
 - Auteur : opossum_farceur
 - Object : Camembert, 3D, Antialiasing, Bresenham, Statistiques 

  • /
define('coef',M_PI/180); class aacamembert { private $img; private $a,$b,$cx,$cy,$aa,$bb,$aabb; /* ellipse */ private $data,$sort,$ellipse; /* tableaux */ private $quarter,$pivot; /* autres */ private $num,$linecolor; /* algorithme de Gupta-Sproull */ /* constructeur ---------------------------------------------------------------------------------------*/ function __construct($title,$arr) { $width=500; $head=35; /* 15+15+5 : réservés pour le titre */ $height=300; $w=240; /* grand axe horizontal */ $h=$w/2; /* 120 : petit axe vertical */ $thickness=$w/4; /* 60 : "épaisseur" du camembert */ $topcolor=0xFFFF00; /* dégradé : couleur du haut */ $bottomcolor=0x00FFFF; /* dégradé : couleur du bas */ $fontsize=3; /* attributs calculés */ $this->a=$w/2; /* 1/2 grand axe : 120 */ $this->b=$h/2; /* 1/2 petit axe : 60 */ $this->cx=$width/2; /* abscisse et ordonnée du "centre" du camembert */ $this->cy=($height+$head-$thickness)/2; $this->aa=$this->a*$this->a; $this->bb=$this->b*$this->b; $this->aabb=$this->aa*$this->bb; /* attributs renseignés en cours de route */ $this->data=array(); $this->sort=array(); $this->ellipse=array(); /* antialiasing ligne droite */ $this->num=10; /* à choisir pair */ $this->linecolor=array(); /* taille du tableau : 1+3/2*$this->num, soit 16 (suffisant) */ /* préliminaires */ $this->img=imagecreatetruecolor($width,$height); $this->mybackground($width-1,$height-1,$topcolor,$bottomcolor); $textcolor=imagecolorallocate($this->img,0x00,0x00,0x00); imagestring($this->img,5,($width-imagefontwidth(5)*strlen($title))/2,15,$title,$textcolor); $this->aaellipse(); $this->gupta_sproull(); $specialcase=$this->init($arr,$thickness); /* tracés */ $this->aadraw($thickness,$fontsize,$textcolor,$specialcase); /* affichage */ header('Content-type: image/png'); imagepng($this->img); imagedestroy($this->img); } /* "splite" une couleur en ses 3 composantes ----------------------------------------------------------*/ private function hex2rgb($hex) { return array(($hex>>16)& 0xFF,($hex>>8)& 0xFF,$hex & 0xFF); } /* mise en place du fond ------------------------------------------------------------------------------*/ private function mybackground($w,$h,$topcolor,$bottomcolor) { list($red,$green,$blue)=$this->hex2rgb($topcolor); $bc=$this->hex2rgb($bottomcolor); $incr=($bc[0]-$red)/$h; $incg=($bc[1]-$green)/$h; $incb=($bc[2]-$blue)/$h; for($j=0;$j<=$h;$j++,$red+=$incr,$green+=$incg,$blue+=$incb) imageline($this->img,0,$j,$w,$j,imagecolorallocate($this->img,$red,$green,$blue)); } /* à partir de l'angle donné en argument retourne l'index correspondant du tableau de l'ellipse -------*/ private function index($v) { /* formulation du sinus à partir du cosinus, en principe + rapide */ $cosv=cos(coef*$v); $sinv= ($v>180)? -sqrt(1-$cosv*$cosv) : sqrt(1-$cosv*$cosv); $x=round($this->a*abs($cosv)); $y=round($this->b*abs($sinv)); $case=floor($v/90); $p=($case+$case%2)*$this->quarter; $sign= ($case%2)? -1 : 1; $q= ($this->aa*$y-$this->bb*$x<0)? $y : $this->quarter-$x; return $p+$sign*$q; } /* traitement des données fournies dans le tableau ----------------------------------------------------*/ private function init($arr,$e) { /* calcul de la somme des données */ for ($j=$sum=0,$n=count($arr);$j<$n;$j++) $sum+=$arr[$j][0]; /* analyse du tableau */ for ($j=$k=$v1=0;$j<$n;$j++) if ($arr[$j][0]) { /* cas non traité si donnée nulle */ /* extraction des composantes red, green et blue */ list($red,$green,$blue)=$this->hex2rgb($arr[$j][1]); $this->data[$k]['color']=imagecolorallocate($this->img,$red,$green,$blue); /* traitement des angles */ $v2=$v1+$arr[$j][0]*360/$sum; if ($v1<=270 && $v2>=270) $first=$k; if ($v1<=90 && $v2>=90) $last=$k; $this->data[$k]['v']=$v2; /* détermine la couleur ombrée */ $this->data[$k]['shade']=imagecolorallocate($this->img,max(0,$red-50),max(0,$green-50),max(0,$blue-50)); /* préparation du texte */ $this->data[$k]['legend']=$arr[$j][2]; $this->data[$k]['value']=number_format(100*$arr[$j][0]/$sum,2,',','').'%'; $this->data[$k]['xploded']=$arr[$j][3]; $v1=$v2; $k++; } $m=count($this->data); /* différent de $n si une ou plusieurs donnée(s) sont nulles */ if ($first!=$last) { for ($j=0,$k=$first;$k!=$last;$j++,$k=($k+1)%$m) $this->sort[$j]=$k; $this->pivot=$j; for ($k=$first-1;$k>=$last;$j++,$k--) $this->sort[$j]=$k; return false; } else { /* cas particulier préoccupant : une grosse portion présente à la fois à 12h et à 18h */ for ($j=0,$k=($first+1)%$m;$j<$m;$j++,$k=($k+1)%$m) $this->sort[$j]=$k; $this->pivot=$m-1; /* mise en place du 2ème panneau de la dernière portion (origine du code : méthode "aadraw()") */ $j=$this->sort[$m-1]; $xploded=$this->data[$j]['xploded']; if ($this->data[$this->sort[0]]['xploded'] || $xploded) { $shade=$this->data[$j]['shade']; $v1= ($j)? $this->data[$j-1]['v'] : 0; $v2=$this->data[$j]['v']; $vm=($v1+$v2)/2; if ($xploded) { $ox=round($this->cx+$this->a*cos(coef*$vm)/6); /* a/6, b/6 : "offsets" des portions */ $oy=round($this->cy+$this->b*sin(coef*$vm)/6); } else { $ox=$this->cx; $oy=$this->cy; } $index2=$this->index($v2); $x2=$ox+$this->ellipse[$index2]['x']; $y2=$oy+$this->ellipse[$index2]['y']; imageline($this->img,$ox,$oy,$ox,$oy+$e,$shade); imageline($this->img,$x2,$y2,$x2,$y2+$e,$shade); $this->aaborder($ox,$oy,$x2,$y2,0,$backup2,$shade); /* ligne du haut */ $this->aaborder($x2,$y2+$e,$ox,$oy+$e,1,$backup2,$shade);/* ligne du bas (attention à l'ordre!) */ if ($x2-$ox>1) imagefilltoborder($this->img,round(($ox+$x2)/2),round(($oy+$y2+$e)/2),$shade,$shade); $this->aaborder($x2,$y2+$e,$ox,$oy+$e,2,$backup2); /* aa ligne du bas */ } return true; } } /* calcul des 16 tons de gris utiles au dessin des lignes droites antialiassées -----------------------*/ private function gupta_sproull() { /* cette fonction crée une table allant de 0 à 1.5*$this->num */ $col=array(); $numdiv2=$this->num/2; /* calcul du volume interceptant chaque colonne, i et j parcourent un quart du cône */ for ($i=$this->num,$total=0;$i>=0;$i--) { for ($j=$this->num,$k=0,$ii=$i*$i;$j>=0;$j--) { $d=sqrt($ii+$j*$j); if ($d<$this->num) $k+=$this->num-$d; } $col[$this->num-$i]=2*$k; $total+=4*$k; } /* calcul de la table : 1ere partie correspondant à une intersection d'épaisseur inférieure à 1 */ $max=$this->num+$numdiv2; for ($i=$k=0;$i<=$this->num;$i++) { $k+=$col[$i]; $this->linecolor[$max-$i]=imagecolorexactalpha($this->img,0,0,0,round(127*(1-$k/$total))); } /* calcul de la table : 2eme partie correspondant à une intersection d'épaisseur supérieure à 1 */ for ($i=1;$i<=$numdiv2;$i++) { $k+=$col[$this->num-$i]-$col[$i]; $this->linecolor[$numdiv2-$i]=imagecolorexactalpha($this->img,0,0,0,round(127*(1-$k/$total))); } } /* "allume" le pixel avec une intensité fonction de la distance à la droite ---------------------------*/ private function plot($x,$y,$d) { if ($d<0) $d=-$d; if ($d>1.5) return; /* rien à allumer si le pixel est trop loin */ imagesetpixel($this->img,$x,$y,$this->linecolor[round($d*$this->num)]); } /* tracé de droite "antialiassée" ---------------------------------------------------------------------*/ private function aaline($x1,$y1,$x2,$y2) { $dx=abs($x2-$x1); $dy=abs($y2-$y1); $incj= (($x2-$x1)*($y2-$y1)>0)? 1 : -1; $K=1/(2*sqrt($dx*$dx+$dy*$dy)); if ($dx>$dy) { /* tendance "horizontale" */ if ($x2>$x1) { $y=$y1; $begin=$x1; $end=$x2; } else { $y=$y2; $begin=$x2; $end=$x1; } $p=2*$dy; $delta=$dx; $incx=0; $incy=$incj; $i=&$x; $j=&$y; } else { /* tendance "verticale" */ if ($y2>$y1) { $x=$x1; $begin=$y1; $end=$y2; } else { $x=$x2; $begin=$y2; $end=$y1; } $p=2*$dx; $delta=$dy; $incx=$incj; $incy=0; $i=&$y; $j=&$x; } /* tronc commun */ for ($i=$begin,$e=$p-$delta,$q=$e-$delta,$D=0,$R=2*$K*$delta;$i<=$end;$i++) { $this->plot($x,$y,$D); $this->plot($x+$incx,$y+$incy,$R-$D); $this->plot($x-$incx,$y-$incy,$R+$D); if ($e>=0) { $D=$K*($e-$delta); $j+=$incj; $e+=$q; } else { $D=$K*($e+$delta); $e+=$p; } } } /* traitement de l'aa des "bordures" ------------------------------------------------------------------*/ private function aaborder($x1,$y1,$x2,$y2,$mode,&$backup,$mycolor=0) { $dx=$x2-$x1; $dy=$y2-$y1; $incj= ($dx*$dy>0)? 1 : -1; if ($mode==1) $backup=array(); elseif ($mode==2) $const=$dx*$y1-$dy*$x1; if (abs($dx)>abs($dy)) { /* tendance "horizontale" */ if ($dx>0) { $y=$y1; $begin=$x1; $end=$x2; } else { $y=$y2; $begin=$x2; $end=$x1; } $p=2*abs($dy); $e=$p-abs($dx); $q=$e-abs($dx); $i=&$x; $j=&$y; } else { /* tendance "verticale" */ if ($dy>0) { $x=$x1; $begin=$y1; $end=$y2; } else { $x=$x2; $begin=$y2; $end=$y1; } $p=2*abs($dx); $e=$p-abs($dy); $q=$e-abs($dy); $i=&$y; $j=&$x; } /* tronc commun */ for ($i=$begin,$t=0;$i<=$end;$i++,$t++) { if ($mode==1) $backup[]=imagecolorat($this->img,$x,$y); /* mode "sauvegarde" */ elseif ($mode==2) { /* mode "antialiasing" */ for ($f=$x-0.2,$g1=$y-0.2,$g3=$y+0.2,$alpha=0;$f<=$x+0.2;$f+=0.2) { $k=$const+$dy*$f; for ($g=$g1;$g<=$g3;$g+=0.2) if ($dx*$g>$k) $alpha++; } list($red,$green,$blue)=$this->hex2rgb($backup[$t]); $mycolor=imagecolorexactalpha($this->img,$red,$green,$blue,11*$alpha+28); } imagesetpixel($this->img,$x,$y,$mycolor); if ($e>=0) { $j+=$incj; $e+=$q; } else $e+=$p; } } /* tracé du camembert ---------------------------------------------------------------------------------*/ private function aadraw($e,$fontsize,$textcolor,$specialcase) { $A=$this->a*21/16; /* 1/2 grand axe de l'ellipse "englobante" */ $B=3*$A/4; /* bien que dépendant de $e, mais bon... */ $dy=-$e/2; /* "centre" du camembert à celui de l'ellipse "englobante" */ $AA=$A*$A; $BB=$B*$B; $ifw=imagefontwidth($fontsize); /* "grande boucle" */ for ($i=0,$m=count($this->data);$i<$m;$i++) { $j=$this->sort[$i]; /* initialisations */ $color=$this->data[$j]['color']; $shade=$this->data[$j]['shade']; $v1= ($j)? $this->data[$j-1]['v'] : 0; $v2=$this->data[$j]['v']; $vm=($v1+$v2)/2; $index1=$this->index($v1); $index2=$this->index($v2); $xploded=$this->data[$j]['xploded']; $panel1=$panel2=false; $flag=0; if ($xploded) { $px=$this->a*cos(coef*$vm); $py=$this->b*sin(coef*$vm); $ox=round($this->cx+$px/6); /* a/6, b/6 : "offsets" des portions */ $oy=round($this->cy+$py/6); } else { $px=5*$this->a*cos(coef*$vm)/6; $py=5*$this->b*sin(coef*$vm)/6; $ox=$this->cx; $oy=$this->cy; switch ($i) { /* cumulations possibles */ case 0: $flag=$this->data[$this->sort[$this->pivot]]['xploded']; case $this->pivot-1: $flag|=$this->data[$this->sort[$m-1]]['xploded']; default: $flag|=$this->data[$this->sort[$i+1]]['xploded']; } } $x1=$ox+$this->ellipse[$index1]['x']; $y1=$oy+$this->ellipse[$index1]['y']; $x2=$ox+$this->ellipse[$index2]['x']; $y2=$oy+$this->ellipse[$index2]['y']; $gx=round($this->cx+$px); /* sans arrondi, problème raccordement segment en size 1 */ $gy=round($this->cy+$py); /* traitement secteur du bas + paravent vertical */ if ($v1<180) { if ($v2<180) { $indexmax=$index2; $x=$x2; $y=$y2; } else { /* le traitement s'arrête à 180° */ $indexmax=2*$this->quarter; /* aussi : $this->index(180); */ $x=$ox-$this->a; /* aussi : $ox+$this->ellipse[$indexmax]['x']; */ $y=$oy; /* aussi : $oy+$this->ellipse[$indexmax]['y'] */ } /* dessin des secteurs hauts et bas de l'ellipse */ for ($k=$index1,$backup0=array();$k<=$indexmax;$k++) { $xk=$ox+$this->ellipse[$k]['x']; $yk=$oy+$this->ellipse[$k]['y']; $backup0[]=imagecolorat($this->img,$xk,$yk+$e); imagesetpixel($this->img,$xk,$yk,$shade); imagesetpixel($this->img,$xk,$yk+$e,$shade); } /* lignes verticales */ imageline($this->img,$x1,$y1,$x1,$y1+$e,$shade); imageline($this->img,$x,$y,$x,$y+$e,$shade); /* "remplissage" peu optimisé mais valable dans tous les cas de figures */ if ($x1-$x>1) imagefilltoborder($this->img,$x+1,$y+$e/2,$shade,$shade); /* antialiasing secteur ellipse du bas */ $this->aaarc($index1,$indexmax,$ox,$oy+$e,$backup0); } if ($xploded || $flag) { /* dessine les "panneaux" verticaux */ if ($v1>90 && $v1<270) { imageline($this->img,$ox,$oy,$ox,$oy+$e,$shade); imageline($this->img,$x1,$y1,$x1,$y1+$e,$shade); /* parfois inutile, mais bon... */ $this->aaborder($x1,$y1,$ox,$oy,0,$backup1,$shade); /* ligne du haut, backup inutile */ $this->aaborder($ox,$oy+$e,$x1,$y1+$e,1,$backup1,$shade);/* ligne du bas, backup parfois inutile */ if ($ox-$x1>1) imagefilltoborder($this->img,round(($ox+$x1)/2),round(($oy+$y1+$e)/2),$shade,$shade); $this->aaborder($ox,$oy+$e,$x1,$y1+$e,2,$backup1); /* aa ligne du bas */ if ($v1<180) imageline($this->img,$x1,$y1,$x1,$y1+$e,$color); /* séparation verticale */ $panel1=true; } if ($v2<90 ||($v2>270 &&!($specialcase && $i==$m-1))) { /* $specialcase n'apparait qu'ici */ imageline($this->img,$ox,$oy,$ox,$oy+$e,$shade); imageline($this->img,$x2,$y2,$x2,$y2+$e,$shade); $this->aaborder($ox,$oy,$x2,$y2,0,$backup2,$shade); /* ligne du haut, backup inutile */ $this->aaborder($x2,$y2+$e,$ox,$oy+$e,1,$backup2,$shade);/* ligne du bas */ if ($x2-$ox>1) imagefilltoborder($this->img,round(($ox+$x2)/2),round(($oy+$y2+$e)/2),$shade,$shade); $this->aaborder($x2,$y2+$e,$ox,$oy+$e,2,$backup2); /* aa ligne du bas */ if ($v2<90) imageline($this->img,$x2,$y2,$x2,$y2+$e,$color); /* séparation verticale */ $panel2=true; } if ($panel1 && $panel2) imageline($this->img,$ox,$oy,$ox,$oy+$e,$color);/* séparation verticale */ } /* dessine le dessus de la portion */ for ($k=$index1,$backup0=array();$k<=$index2;$k++) { $xk=$ox+$this->ellipse[$k]['x']; $yk=$oy+$this->ellipse[$k]['y']; $backup0[]=imagecolorat($this->img,$xk,$yk); imagesetpixel($this->img,$xk,$yk,$color); } /* tracé des "rayons", sauvegarde parfois inutile, mais bon... */ $this->aaborder($ox,$oy,$x1,$y1,1,$backup1,$color); /* centre -> extrémité */ $this->aaborder($x2,$y2,$ox,$oy,1,$backup2,$color); /* extrémité -> centre */ /* "remplissage" du secteur en partant du "germe" */ imagefilltoborder($this->img,$gx,$gy,$color,$color); /* correction du défaut du "secteur trop étroit" (pas toujours nécessaire) */ imageline($this->img,$ox,$oy,$gx,$gy,$color); /* antialiasing secteur ellipse du haut */ $this->aaarc($index1,$index2,$ox,$oy,$backup0); /* antialiasing des "rayons" du secteur elliptique */ if ($xploded || $flag) { $this->aaborder($ox,$oy,$x1,$y1,2,$backup1); /* centre -> extrémité */ $this->aaborder($x2,$y2,$ox,$oy,2,$backup2); /* extrémité -> centre */ } else if ($i) { /* centre -> extrémité */ if ($i<$this->pivot) $this->aaborder($ox,$oy,$x1,$y1,2,$backup1); else { /* extrémité -> centre */ $this->aaborder($x2,$y2,$ox,$oy,2,$backup2); if ($i==$m-1) $this->aaborder($ox,$oy,$x1,$y1,2,$backup1); } } /* traitement des légendes */ $ka=$AA*$py*$py+$BB*$px*$px; $kb=$AA*$dy*$px*$py; $kc=$AA*$px*$px*($dy*$dy-$BB); if ($vm<=90 || $vm>270) { $root=(-$kb+sqrt($kb*$kb-$ka*$kc))/$ka; $qx=round($this->cx+$root); $qy=round($this->cy+$root*$py/$px); $this->aaline($gx,$gy,$qx,$qy); $this->aaline($qx+1,$qy,$qx+10,$qy); imagestring($this->img,$fontsize,$qx+14,$qy-12,$this->data[$j]['legend'],$textcolor); imagestring($this->img,$fontsize,$qx+14,$qy-2,$this->data[$j]['value'],$textcolor); } else { $root=(-$kb-sqrt($kb*$kb-$ka*$kc))/$ka; $qx=round($this->cx+$root); $qy=round($this->cy+$root*$py/$px); $this->aaline($gx,$gy,$qx,$qy); $this->aaline($qx-1,$qy,$qx-10,$qy); $legendposx=$qx-12-$ifw*strlen($this->data[$j]['legend']); $valueposx=$qx-12-$ifw*strlen($this->data[$j]['value']); imagestring($this->img,$fontsize,$legendposx,$qy-12,$this->data[$j]['legend'],$textcolor); imagestring($this->img,$fontsize,$valueposx,$qy-2,$this->data[$j]['value'],$textcolor); } } } /* dessine un arc avec l'aa ---------------------------------------------------------------------------*/ private function aaarc($begin,$end,$dx,$dy,&$backup) { for ($j=$begin,$i=0;$j<=$end;$j++,$i++) { list($red,$green,$blue)=$this->hex2rgb($backup[$i]); $mix=imagecolorexactalpha($this->img,$red,$green,$blue,$this->ellipse[$j]['alpha']); imagesetpixel($this->img,$dx+$this->ellipse[$j]['x'],$dy+$this->ellipse[$j]['y'],$mix); } } /* calcul de la transparence du point, intégration de l'enregistrement au tableau ---------------------*/ private function add($x,$y) { /* 9 échantillons sont suffisants */ for ($f=$x-0.2,$g1=$y-0.2,$g3=$y+0.2,$alpha=0;$f<=$x+0.2;$f+=0.2) { $k=$this->aabb-$this->bb*$f*$f; for ($g=$g1;$g<=$g3;$g+=0.2) if ($this->aa*$g*$g<$k) $alpha++; } return array('x'=>$x,'y'=>$y,'alpha'=>11*$alpha+28); } /* calcul d'un quart de l'ellipse, généralisation à l'ellipse entière ---------------------------------*/ private function aaellipse() { $temp=array(); /* algorithme volontairement non optimisé, pour ne pas le rendre encore plus hermétique ! */ for ($x=0,$y=$this->b,$e=4*$this->bb+$this->aa*(1-4*$y);$this->bb*$x<$this->aa*$y;$x++) { $temp[2][]=$this->add($x,$y); /* octant n°2 */ $e+= ($e<0)? $this->bb*(8*$x+12) : $this->bb*(8*$x+12)+8*$this->aa*(1-$y--); } for ($x=$this->a,$y=0,$e=4*$this->aa+$this->bb*(1-4*$x);$this->aa*$y<$this->bb*$x;$y++) { $temp[1][]=$this->add($x,$y); /* octant n° 1 */ $e+= ($e<0)? $this->aa*(8*$y+12) : $this->aa*(8*$y+12)+8*$this->bb*(1-$x--); } /* on remet tout dans l'ordre qui convient */ $this->ellipse=array_merge($temp[1],array_reverse($temp[2])); unset($temp); /* généralisation aux 3 autres quadrants */ for ($i=0,$n=count($this->ellipse),$p=2*$n-2,$q=4*$n-4;$i<$n;$i++) { $x=$this->ellipse[$i]['x']; $y=$this->ellipse[$i]['y']; $alpha=$this->ellipse[$i]['alpha']; $this->ellipse[$p-$i]=array('x'=>-$x,'y'=>$y,'alpha'=>$alpha); $this->ellipse[$p+$i]=array('x'=>-$x,'y'=>-$y,'alpha'=>$alpha); $this->ellipse[$q-$i]=array('x'=>$x,'y'=>-$y,'alpha'=>$alpha); } $this->quarter=(count($this->ellipse)-1)/4; } /* fin de la classe -----------------------------------------------------------------------------------*/ } $title='CodeS-SourceS : 33620 sources publiées!'; $arr=array( /* donnée couleur légende xploded */ array(2072, 0x969696, 'Divers', 0), array(1003, 0xFF9900, 'JAVA/J2EE', 0), array(1038, 0xFFCB03, 'C#', 0), array(1623, 0x99CC00, 'Flash', 0), array(1854, 0x339966, 'IRC', 0), array(1873, 0x33CCCC, 'Javascript/DHTML', 0), array(2208, 0x0091C3, 'PHP', 1), array(2624, 0xAA44AA, 'Delphi', 0), array(4971, 0xFF99CC, 'C/C++', 0), array(14354, 0xFF4C4C, 'Visual Basic', 0) ); $mon_caprice_des_dieux=new aacamembert($title,$arr); ?>

Codes Sources

A voir également

Ajouter un commentaire Commentaires
Messages postés
2
Date d'inscription
mardi 9 juin 2009
Statut
Membre
Dernière intervention
23 mai 2013

Bonjour,

Je voudrais tout d'abord vous remercier pour ce script qui est tout simplement génial !
En effet, j'avais trouvé d'autres camemberts, mais sans antialiasing, le rendu était plutôt très moche...
Cependant, une question me trotte toujours en tête: Est-il possible de faire démarrer le camembert non pas à l'horizontale comme c'est actuellement le cas, mais à la verticale, ou alors de lui faire faire uns fois tracé une rotation de -90° ?

Merci à vous.
Messages postés
1
Date d'inscription
mardi 7 août 2012
Statut
Membre
Dernière intervention
8 août 2012

Bonjour,
Je viens de découvrir et d'installer votre script, et même si je ne suis pas le premier à vous le dire : "Félicitations ! Une vraie merveille !
Ceci dit, j'aurais aimé savoir si il serait possible de faire en sorte que certaines portions du camembert puissent être mises, individuellement, en semi-transparent. Qu'en pensez-vous ?
Messages postés
147
Date d'inscription
lundi 16 août 2004
Statut
Membre
Dernière intervention
14 novembre 2009

Hi!

La classe "smooth3dcamembert" du zip génère un fichier de nom "~temp.png"
Messages postés
2
Date d'inscription
mardi 16 novembre 2010
Statut
Membre
Dernière intervention
11 mai 2011

Bonjour,

Je ne comprend pas une chose s'il vous plais ...
Tous les scripts GD pour générer un graphe sur le net tel que celui-ci finissent par un ECHO pour afficher celui-ci.

Moi je voudrais enregistrer l'image dans un fichier image sur le ddur pour la re-utiliser derrière dans un pdf ou autre ...
Comment faire pour enregistrer cet echo ?

Merci
Messages postés
147
Date d'inscription
lundi 16 août 2004
Statut
Membre
Dernière intervention
14 novembre 2009

Hi!,

Je te signale que t'es sur un site de développeurs, et qu'il faut parfois mettre les mains dans le cambouis. Si le support FreeType t'est refusé, tu peux utiliser la fonction "imagestring" pour afficher du texte dans une image.
Quant à l'autre source, sur laquelle tu as déposé aussi un commentaire, elle ne fait que 120 lignes de code et l'étudier peut représenter un bon exercice si tu veux qu'elle ne traite pas les valeurs nulles.
Amicalement.
Afficher les 108 commentaires

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.