imagearc

(PHP 3, PHP 4, PHP 5)

imagearc -- 画椭圆弧

说明

bool imagearc ( resource image, int cx, int cy, int w, int h, int s, int e, int color )

imagearc()cxcy(图像左上角为 0, 0)为中心在 image 所代表的图像中画一个椭圆弧。wh 分别指定了椭圆的宽度和高度,起始和结束点以 se 参数以角度指定。0°位于三点钟位置,以顺时针方向绘画。

例子 1. 用 imagearc() 画一个圆

<?php
// 创建一个 200X200 的图像
$img = imagecreatetruecolor(200, 200);
// 分配颜色
$white = imagecolorallocate($img, 255, 255, 255);
$black = imagecolorallocate($img, 0, 0, 0);
// 画一个黑色的圆
imagearc($img, 100, 100, 150, 150, 0, 360, $black);
// 将图像输出到浏览器
header("Content-type: image/png");
imagepng($img);
// 释放内存
imagedestroy($img);
?>

参见 imageellipse()imagefilledellipse()imagefilledarc()


add a note add a note User Contributed Notes
mojiro at awmn dot net
14-Dec-2005 04:28
A previous for the Rotated (Filled)Ellipse note from(nojer2 at yahoo dot com, 02-Apr-2001 12:06) has a mistake, at the second arc. Replace them with the following listing.

if ($filled) {
   triangle($im, $cx, $cy, $cx+$px, $cy+$py, $cx+$x, $cy+$y, $colour);
   triangle($im, $cx, $cy, $cx-$px, $cy-$py, $cx-$x, $cy-$y, $colour);
} else {
   imageline($im, $cx+$px, $cy+$py, $cx+$x, $cy+$y, $colour);
   imageline($im, $cx-$px, $cy-$py, $cx-$x, $cy-$y, $colour);
}
hans at lintoo dot dk
18-Jul-2004 10:19
When doing a pie chart... you really should not use imagearc, use imagefilledarc instead... it is much much easier...(and I guess every hosting company should support it by now)

3D Piechart:
Se my modified code at: http://dk.php.net/manual/en/function.imagefilledarc.php

For a quick sample see the online demo at:
http://webstatistik.lintoo.dk/
ruturaj_v at yahoo dot com
17-May-2004 09:32
this is another piechart eg. very simple ...

<?php
global $deg;

function
get_polar($xrel, $yrel, $ang, $radius) {
  
$i = $ang;
  
$ang = ($ang * pi())/ 180;
  
  
$ix = abs($radius*cos($ang));
  
$iy = abs($radius*sin($ang));
  
   if (
$i>=0 && $i<=90) {
      
$ix = $xrel + $ix;
      
$iy = $yrel - $iy;
   }
   if (
$i>90 && $i<=180) {
      
$ix = $xrel - $ix;
      
$iy = $yrel - $iy;
   }
   if (
$i>180 && $i<=270) {
      
$ix = $xrel - $ix;
      
$iy = $yrel + $iy;
   }
   if (
$i>270 && $i<=360) {
      
$ix = $xrel + $ix;
      
$iy = $yrel + $iy;
   }

  
$ix = floor($ix);
  
$iy = floor($iy);
  
//echo ($ix . " $iy<br>");
  
$returnvals = array (
                      
'x1' => $xrel,
                      
'y1' => $yrel,
                      
'x2' => $ix,
                      
'y2' => $iy
                      
);
   return
$returnvals;
}

function
get_degtotal($degindex)
{
   global
$deg;
   if (
$degindex == 0 ) {
       return ( 
$deg[$degindex] );
   }
   else {       
       return (
$deg[$degindex] + get_degtotal($degindex-1) );
   }   
}

$im  = imagecreate (400, 400);
$w  = imagecolorallocate ($im, 255, 255, 255);
$black  = imagecolorallocate ($im, 0, 0, 0);
$red = imagecolorallocate ($im, 255, 0, 0);
$green = imagecolorallocate ($im, 0, 180, 0);

$randcolor[0] = imagecolorallocate($im, 243, 54, 163);
$randcolor[1] = imagecolorallocate($im, 179, 51, 247);
$randcolor[2] = imagecolorallocate($im, 103, 48, 250);
$randcolor[3] = imagecolorallocate($im, 53, 145, 244);
$randcolor[4] = imagecolorallocate($im, 54, 243, 243);
$randcolor[5] = imagecolorallocate($im, 107, 245, 180);
$randcolor[6] = imagecolorallocate($im, 203, 242, 111);
$randcolor[7] = imagecolorallocate($im, 248, 201, 105);

$data[0] = 30;
$data[1] = 20;
$data[2] = 15;
$data[3] = 10;
$data[4] = 8;
$data[5] = 7;
$data[6] = 5;
$data[7] = 5;

$datasum = array_sum($data);

$deg[0] = number_format((30 / $datasum * 360), 2, ".", "");
$deg[1] = number_format((20 / $datasum * 360), 2, ".", "");
$deg[2] = number_format((15 / $datasum * 360), 2, ".", "");
$deg[3] = number_format((10 / $datasum * 360), 2, ".", "");
$deg[4] = number_format((8 / $datasum * 360), 2, ".", "");
$deg[5] = number_format((7 / $datasum * 360), 2, ".", "");
$deg[6] = number_format((5 / $datasum * 360), 2, ".", "");
$deg[7] = number_format((5 / $datasum * 360), 2, ".", "");
echo (
'<pre>');

//print_r($deg);

$datadeg = array();
$datapol = array();
$degbetween = array();
$databetweenpol = array();

for (
$i=0; $i < count($deg) ; $i++) {
  
$datadeg[$i] = get_degtotal($i);
  
$datapol[$i] = get_polar(200, 200, $datadeg[$i], 100);
}

for (
$i=0; $i < count($datadeg) ; $i++) {
  
/*this is a trick where you take 2deg angle before
   and get the smaller radius so that you can have a pt to
   `imagefill` the chartboundary
   */
  
$degbetween[$i] = ($datadeg[$i]-2);
  
$databetweenpol[$i] = get_polar(200, 200, $degbetween[$i], 50);
}

print_r($datadeg);
print_r($degbetween);
print_r($databetweenpol);
//exit;

for ($i=0; $i<count($deg); $i++) {
  
imageline ($im, 200, 200, $datapol[$i]['x2'], $datapol[$i]['y2'], $black);
}
imagearc($im, 200, 200, 200, 200, 0, 360, $black);

for (
$i=0; $i<count($deg); $i++) {
  
imagefill ($im, $databetweenpol[$i]['x2'], $databetweenpol[$i]['y2'], $randcolor[$i]);

}

//header ("Content-type: image/png");
imagepng($im, 'piechart.png');
?>
<img src='piechart.png'>
jerryscript at aol dot com
26-Dec-2003 06:05
[note-Apache/1.3.29 (Win32) PHP/4.3.4]

The imagearc (and imageellipse) functions do not accept line thicknesses when drawn from 0 to 360 degrees.

Drawing from 0 to 359 and again from 359 to 360 does create an ellipse with the current line thickness.

Jerry
eamon at hostelworld dot com
17-Dec-2003 11:24
Right...
possibly the easiest way of drawing a filled circle:
Loop through the imagearc function incrementing the diameter by one pixel:
<?
 
// --- code fragment --- //

for($i=1; $i<$Diameter; $i++){
 
imagearc($Image, $CenterX, $CenterY, $i, $i, $Start, $End, $Color);
}

// --------------------- //

?>

This works great for circles with diameters up to about 60 or 70 pixels wide. After that, you start to get pixle gaps.
logang at deltatee dot com
05-Aug-2003 11:19
Heres a function to make a curve between two points... This will be a downward curve but it wouldn't be hard to make a similar function to make an upward curve. The first point has to be to the left of the second point ($x1 < $x2), and height is actually backwards. The larger height is the less of a crest the curve has. I imagine with a few modifications this functions could make upward curves as well.

function ImageCurveDown ($image, $x1, $y1, $x2, $y2, $height, $color) {
   $presicion = 1;

   for ($left = ($x1-$x2); $left < 0; $left++){
       if ($y1 < $y2) {
           $cy = $y2 + $height;
           $cx = $x1 - $left;
       } else {
           $cy = $y1 + $height;
           $cx = $x2 + $left;
       }
       $nx1 = abs($x1 - $cx);
       $ny1 = abs($y1 - $cy);
       $nx2 = abs($x2 - $cx);
       $ny2 = abs($y2 - $cy);

       if ($y1 < $y2) {
           if ($nx2 == 0 || $ny1 == 0) continue;
           $angle1 = atan($height/$nx2);
           $A1 = $nx2/cos ($angle1);
           $B1 = $ny2/sin ($angle1);
           $angle2 = pi()/2 +atan($left/$ny1);
           $A2 = $nx1/cos ($angle2);
           $B2 = $ny1/sin ($angle2);
       } else {
           if ($ny2 == 0 || $nx1 == 0) continue;
           $angle1 = atan($ny2/$nx2);
           $A1 = abs($nx2/cos ($angle1));
           $B1 = abs($ny2/sin ($angle1));
           $angle2 = atan($height/$nx1);
           $A2 = abs ($nx1/cos ($angle2));
           $B2 = abs($ny1/sin ($angle2));
       }

       if (abs($A1 - $A2) < $presicion && abs ($B1 - $B2) < $presicion) {
           ImageArc($image, $cx, $cy, $A1*2, $B1*2, 180+rad2deg($angle2), 360-rad2deg($angle1), $color);
       }
   }
}
24-Jan-2003 12:55
Please note that in order to draw a complete circle or ellipse (without using the imageellipse) you mustn't use 0 for both s and e. If you do this you will get, umm, nothing. Instead set s to 0 and e to 360 to get a complete circle or ellipse.
jinny at 263 dot net
14-May-2002 01:27
imagesetstyle() sets the style to be used by all line drawing functions when drawing with the special color .

Here goes a example of drawing a dashed-line circle.enjoy!

<?php

header
("Content-type: image/jpeg");
$im = imagecreate(100,100);

$b  = imagecolorallocate ($im, 0, 0, 0);
$w  = imagecolorallocate ($im, 255, 255, 255);

$style = array ($b,$b,$b,$b,$b,$w,$w,$w,$w,$w);

imagesetstyle ($im, $style);

imagearc($im,50,50,100,100,0,360,IMG_COLOR_STYLED);

imagejpeg($im);
imagedestroy($im);
?>
arve at skogvold dot as
01-Dec-2001 05:04
I found a better way for drawing a pie chart:

header ("Content-type: image/png");
$diameter = 100;
$radius = $diameter / 2;
$centerX = $radius;
$centerY = $radius;

$im = @ImageCreate ($diameter, $diameter)
   or die ("Cannot Initialize new GD image stream");

$background = ImageColorAllocate ($im, 0, 0, 0);
$red = ImageColorAllocate ($im, 176, 0, 0);

function fill_arc($start, $end, $color) {
   global $diameter, $centerX, $centerY, $im, $radius;
   imagearc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color);
   imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start)) * $radius, $centerY + sin(deg2rad($start)) * $radius, $color);
   imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end)) * $radius, $centerY + sin(deg2rad($end)) * $radius, $color);
   imagefill ($im,$centerX + $radius * 0.5 *cos(deg2rad($start+($end-$start)/2)), $centerY + $radius * 0.5 * sin(deg2rad($start+($end-$start)/2)), $color);
   }


fill_arc(0,30,$red);
// Will make a red filled arc, starting at 0 degrees, ending at 30 degrees

ImagePng ($im);
marc at resiteit dot com
09-Nov-2001 05:04
Round cornered anti-aliased dynamically sized button.

$w=40;
$h=20;
$im = ImageCreate($w,$h);
$white=ImageColorAllocate($im,255,255,255);
ImageFilledRectangle($im,0,0,$w,$h,$white);
imagecolortransparent ($im, $white);
ImageTTFText ($im, $h+ceil($h/3)+1, 0, -1, $h-1, $col1, "arialbd.ttf", "O");
ImageTTFText ($im, $h+ceil($h/3)+1, 0, $w-$h, $h-1, $col1, "arialbd.ttf", "O");
ImageTTFText ($im, $h+ceil($h/3)+1, 0, 1, $h-1, $col1, "arialbd.ttf", "O");
ImageTTFText ($im, $h+ceil($h/3)+1, 0, $w-$h-2, $h-1, $col1, "arialbd.ttf", "O");
$points=array(
   1,round($h/2),
   round($h/4),$h-round($h/4),
   round($h/2),$h,
   $w-(round($h/2)),$h,
   $w-(round($h/4)),$h-round($h/4),
   $w-2,round($h/2),
   $w-round($h/4),round($h/4),
   $w-round($h/2),0,
   round($h/2),0,
   round($h/4),round($h/4)
);
imagefilledpolygon ($im, $points, 10, $col1);

header("content-type: image/gif");
header("Content-Disposition: filename=name.gif");
ImageGif($im);
ImageDestroy($im);
foripepe at yahoo dot com
03-Sep-2001 12:56
To fill an arc (DiameterX != DiameterY):

<?
function imagefilledarc($Image, $CenterX, $CenterY, $DiameterX, $DiameterY, $Start, $End, $Color) {
  
// To draw the arc
  
imagearc($Image, $CenterX, $CenterY, $DiameterX, $DiameterY, $Start, $End, $Color);
  
// To close the arc with 2 lines between the center and the 2 limits of the arc
  
$x = $CenterX + (cos(deg2rad($Start))*($DiameterX/2));
  
$y = $CenterY + (sin(deg2rad($Start))*($DiameterY/2));
  
imageline($Image, $x, $y, $CenterX, $CenterY, $Color);
  
$x = $CenterX + (cos(deg2rad($End))*($DiameterX/2));
  
$y = $CenterY + (sin(deg2rad($End))*($DiameterY/2));
  
imageline($Image, $x, $y, $CenterX, $CenterY, $Color);
  
// To fill the arc, the starting point is a point in the middle of the closed space
  
$x = $CenterX + (cos(deg2rad(($Start+$End)/2))*($DiameterX/4));
  
$y = $CenterY + (sin(deg2rad(($Start+$End)/2))*($DiameterY/4));
  
imagefilltoborder($Image, $x, $y, $Color, $Color);
}
?>

To close the arc with 2 lines (DiameterX != DiameterY):

<?
function imagenofilledarc($Image, $CenterX, $CenterY, $DiameterX, $DiameterY, $Start, $End, $Color) {
  
// To draw the arc
  
imagearc($Image, $CenterX, $CenterY, $DiameterX, $DiameterY, $Start, $End, $Color);
  
// To close the arc with 2 lines between the center and the 2 limits of the arc
  
$x = $CenterX + (cos(deg2rad($Start))*($DiameterX/2));
  
$y = $CenterY + (sin(deg2rad($Start))*($DiameterY/2));
  
imageline($Image, $x, $y, $CenterX, $CenterY, $Color);
  
$x = $CenterX + (cos(deg2rad($End))*($DiameterX/2));
  
$y = $CenterY + (sin(deg2rad($End))*($DiameterY/2));
  
imageline($Image, $x, $y, $CenterX, $CenterY, $Color);
}
?>

An example:
<?
   $destImage
= imagecreate( 216, 152 );
  
$c0 = imagecolorallocate( $destImage, 0, 255, 255 );
  
$c1 = imagecolorallocate( $destImage, 0, 0, 0 );
  
$c2 = imagecolorallocate( $destImage, 255, 0, 0 );
  
ImageFilledRectangle ( $destImage, 0, 0, 216, 152, $c0 );
  
imagefilledarc( $destImage, 108, 76, 180, 80, 0, 130, $c1 );
  
imagenofilledarc( $destImage, 108, 76, 180, 80, 0, 130, $c2 );
  
header("content-type: image/PNG");
  
ImagePNG( $destImage );
  
ImageDestroy( $destImage );
?>
09-Apr-2001 01:37
The following site contains heaps of different functions to draw graphs with easy to follow code for newbies and heaps of examples with OVER 60 different predefined graphs
http://www.aditus.nu/jpgraph/index.php
nojer2 at yahoo dot com
02-Apr-2001 05:18
Here's a dashed circle function:

function dashedcircle($im, $cx, $cy, $radius, $colour, $dashsize=5) {

   $dash=false;
   for ($angle=0; $angle<=(180+$dashsize); $angle+=$dashsize) {
     $x = ($radius * cos(deg2rad($angle)));
     $y = ($radius * sin(deg2rad($angle)));

     if ($dash) {
         imageline($im, $cx+$px, $cy+$py, $cx+$x, $cy+$y, $colour);
         imageline($im, $cx-$px, $cx-$py, $cx-$x, $cy-$y, $colour);
     }
     $dash=!$dash;
     $px=$x;
     $py=$y;
   }
}
nojer2 at yahoo dot com
02-Apr-2001 05:06
Here's the function to draw rotated ellipses again. This time I've optimised it a bit, fixed the no-fill bug, and used a 'squishratio' rather than a 'radiusmodifier', to make the curves perfect, so ignore my previous version.

function rotatedellipse($im, $cx, $cy, $width, $height, $rotateangle, $colour, $filled=true) {
   $step=2;
   $cosangle=cos(deg2rad($rotateangle));
   $sinangle=sin(deg2rad($rotateangle));

   $squishratio = $height/$width;
   $nopreviouspoint = true;
   for ($angle=0; $angle<=(180+$step); $angle+=$step) {
      
     $ox = ($width * cos(deg2rad($angle)));
     $oy = ($width * sin(deg2rad($angle))) * $squishratio;

     $x =  + (($ox * $cosangle) - ($oy * $sinangle));
     $y = $centrey + (($ox * $sinangle) + ($oy * $cosangle));
 
     if ($nopreviouspoint) {
       $px=$x;
       $py=$y;
       $nopreviouspoint=false;
     }

     if ($filled) {
         triangle($im, $cx, $cy, $cx+$px, $cy+$py, $cx+$x, $cy+$y, $colour);
         triangle($im, $cx, $cy, $cx-$px, $cx-$py, $cx-$x, $cy-$y, $colour);
     } else {
         imageline($im, $cx+$px, $cy+$py, $cx+$x, $cy+$y, $colour);
         imageline($im, $cx-$px, $cx-$py, $cx-$x, $cy-$y, $colour);
     }
     $px=$x;
     $py=$y;
   }
}

function triangle($im, $x1,$y1, $x2,$y2, $x3,$y3, $colour) {
   $coords = array($x1,$y1, $x2,$y2, $x3,$y3);
   imagefilledpolygon($im, $coords, 3, $colour);
}
ericquil at yahoo dot com
29-Sep-2000 07:30
If circles overlap, a temporary border is needed when filling:
ImageArc ($im,$x,$y,$w,$h,0,360,$temp_color);
ImageFillToBorder($im,$x,$y,$temp_color,$fill_color);
ImageArc ($im,$x,$y,$w,$h,0,360,$fill_color);
cbriou at orange-art dot fr
18-Sep-2000 10:03
There is another way to fill an arc :

// To draw the arc
$Color = imagecolorallocate($Image, $Red, $Green, $Blue);
imagearc($Image, $CenterX, $CenterY, $Diameter, $Diameter, $Start, $End, $Color);
// To close the arc with 2 lines between the center and the 2 limits of the arc
$x = $CenterX + (cos(deg2rad($Start))*($Diameter/2));
$y = $CenterY + (sin(deg2rad($Start))*($Diameter/2));
imageline($Image, $x, $y, $CenterX, $CenterY, $Color);
$x = $CenterX + (cos(deg2rad($End))*($Diameter/2));
$y = $CenterY + (sin(deg2rad($End))*($Diameter/2));
imageline($Image, $x, $y, $CenterX, $CenterY, $Color);
// To fill the arc, the starting point is a point in the middle of the closed space
$x = $CenterX + (cos(deg2rad(($Start+$End)/2))*($Diameter/4));
$y = $CenterY + (sin(deg2rad(($Start+$End)/2))*($Diameter/4));
imagefilltoborder($Image, $x, $y, $Color, $Color);
timothyhouck at yahoo dot com
17-Aug-2000 06:58
To do filled arcs, try something like this:

$diameter = 50;
imagearc($image, 25, 25, $diameter, $diameter, $start, $end, $color);
while($diameter > 0)
{
  imagearc($image, 25, 25, $diameter, $diameter, $start, $start + 1, $color);
  imagearc($image, 25, 25, $diameter, $diameter, $end - 1, $end, $color);
  $diameter--;
}

...well you get the point.  It's a kludge, and *very* slow, but it's free.
travis at duluth dot com
23-Dec-1999 10:36
The wierd thing is that the first two integers tell where to place the "circle".
So for example I first create the "pallet" to place the circle on.
$image = imagecreate(500, 500); 
(this makes a huge 500x500 gif :) )
$colorBody = imagecolorallocate($image, 0, 0, 0);
(make the default color of the "pallet" black
$circleColor = imagecolorallocate($image, 255, 0, 255);
(going to make the circle an ugly pink color)
imagearc($image, 250, 250, 300, 300, 0, 360, $circleColor);
Places the image in the center (250,250) and the circle is 300 pixels in diameter.

Hope this helps.
 
Travis Kent Beste