imagefilledpolygon

(PHP 4, PHP 5, PHP 7)

imagefilledpolygon画一多边形并填充

说明

imagefilledpolygon ( resource $image , array $points , int $num_points , int $color ) : bool

imagefilledpolygon()image 图像中画一个填充了的多边形。

points 参数是一个按顺序包含有多边形各顶点的 xy 坐标的数组。

num_points 参数是顶点的总数,必须大于 3。

Example #1 imagefilledpolygon() 例子

<?php
// 建立多边形各顶点坐标的数组
$values = array(
            
40,  50,  // Point 1 (x, y)
            
20,  240// Point 2 (x, y)
            
60,  60,  // Point 3 (x, y)
            
24020,  // Point 4 (x, y)
            
50,  40,  // Point 5 (x, y)
            
10,  10   // Point 6 (x, y)
            
);

// 创建图像
$image imagecreatetruecolor(250250);

// 设定颜色
$bg   imagecolorallocate($image200200200);
$blue imagecolorallocate($image00255);

// 画一个多边形
imagefilledpolygon($image$values6$blue);

// 输出图像
header('Content-type: image/png');
imagepng($image);
imagedestroy($image);
?>

User Contributed Notes

martin at eksperimentrum dot dk 26-Apr-2018 03:06
How to draw a simple 6-sided star img where x,y is center of the star and s is the size:

function drawStar($img, $x, $y, $s, $color) {
    $x=$x-$s/2;
    $y=$y-$s/4;
    $points=array($x,$y, $x+$s/2,$y+$s, $x+$s,$y);
    imagefilledpolygon($img, $points, 3, $color);
    $points=array($x,2/3*$s+$y, $x+$s/2,$y-$s/3, $x+$s,2/3*$s+$y);
    imagefilledpolygon($img, $points, 3, $color);
}
Steween 29-Jul-2017 09:51
My version of drawStar (with examples)

<?php
header
("Content-type: image/png");

/* drawStar or regular polygon
    $x, $y  -> Position in the image
    $radius -> Radius of the star
    $spikes -> Number of spikes (min 2)
    $ratio  -> Ratio between outer and inner points
    $dir    -> Rotation 270° for having an up spike( with ratio<1)
*/
function drawStar($x, $y, $radius, $spikes=5, $ratio=0.5, $dir=270) {
   
$coordinates = array();
   
$angle = 360 / $spikes ;
    for(
$i=0; $i<$spikes; $i++){
       
$coordinates[] = $x + (       $radius * cos(deg2rad($dir+$angle*$i)));
       
$coordinates[] = $y + (       $radius * sin(deg2rad($dir+$angle*$i)));
       
$coordinates[] = $x + ($ratio*$radius * cos(deg2rad($dir+$angle*$i + $angle/2)));
       
$coordinates[] = $y + ($ratio*$radius * sin(deg2rad($dir+$angle*$i + $angle/2)));
    }
    return
$coordinates ;
}

// 14*20+24*2 = 328 Examples
$im = imagecreate(800,600);
    
imagecolorallocate($im,   0,   0,   0);
$w = imagecolorallocate($im, 255, 255, 255);
$r = imagecolorallocate($im, 255,   0,   0);
for (
$spikes=2; $spikes<16; $spikes++) { //[2-15]
   
for ($ratio=1; $ratio<21; $ratio++) { //[0.1-2.0]
       
$values = drawStar(40*$ratio-20, $spikes*40-60, 10, $spikes, $ratio/10);
       
imagefilledpolygon($im, $values, count($values)/2, ($ratio % 5 == 0) ? $r : $w);
    }
}
for (
$dir=0; $dir<24; $dir++) {
   
$values = drawStar(30*$dir+20, 580, 10, 2, 1.5, $dir*15);
   
imagefilledpolygon($im, $values, count($values)/2, $w);
   
$values = drawStar(30*$dir+20, 580, 10, 2, 0.2, $dir*15);
   
imagefilledpolygon($im, $values, count($values)/2, $r);
}
imagepng($im);
imagedestroy($im);
?>
rbenheidorn at gmail dot com 01-Feb-2015 09:20
Discovered while working on printing geographical boundaries to an image: if you provide floating point vertices, then the decimal value is automatically truncated. This can cause images drawn with floating point vertices to shift slightly towards the top-left corner. My personal resolution is to round all of the vertices to their nearest whole values, which eliminates this shift.
austinoblouk at yahoo dot com 05-Sep-2009 08:28
Actually the minimum it allows is 3. It says "Total number of vertices, which must be bigger than 3." but it allows 3...
Arnapou 29-Oct-2007 06:49
I discovered that the GD imagefilledpolygon function is incorrect for some drawing with transparent color (for example red 50% : RGBA = 255, 0, 0, 64).

I tried to draw a complex form with lots of points really near (1 pixel of distance) and a transparent red.

The problem was : some border pixels were not drawn by the imagefilledpolygon but were drawn with imagepolygon !?!?

So I wrote my own imagefilledpolygon function which work very well in all case I tested.

<?php
// $points should be an array of coordinates like that :
$points = array(
    array(
0, 0),
    array(
100, 50),
    array(
90, 100),
    array(
50, 50),
    array(
70, 30),
    array(
10, 10),
);
?>

<?php
function myimagefilledpolygon(& $img, $points, $color) {
   
$scanline = 99999;
   
// compute edges
   
$all_edges = array();
   
$n = count($points);
    for(
$i=0; $i<$n; $i++) {
       
$p1 = $points[$i];
        if (
$i == $n-1) { $p2 = $points[0]; } else { $p2 = $points[$i+1]; }
       
$x1 = $p1[0]; $y1 = $p1[1];
       
$x2 = $p2[0]; $y2 = $p2[1];
        if (
$y1 != $y2) {
           
$invslope = ($x2 - $x1)/($y2 - $y1);
            if (
$y1 < $y2 ) {
               
$ymin = $y1;
               
$xval = $x1;
               
$ymax = $y2;
            } else {
               
$ymin = $y2;
               
$xval = $x2;
               
$ymax = $y1;
            }
           
$all_edges[] = array($ymin, $ymax, $xval, $invslope);
            if (
$ymin < $scanline) { $scanline = $ymin; }
        } else {
            if (
$y1 < $scanline) { $scanline = $y1; }
            if (
$y2 < $scanline) { $scanline = $y2; }
        }
    }
   
// draw
   
$active = array();
    do {
       
// add edges to active array
       
$tmp = array();
       
$n = count($all_edges);
        for(
$i=0; $i<$n; $i++) {
            if (
$all_edges[$i][0] == $scanline) {
               
$active[] = $all_edges[$i];
            } else {
               
$tmp[] = $all_edges[$i];
            }
        }
       
$all_edges = $tmp;
       
// remove previous edges from active array
       
$tmp = array();
       
$n = count($active);
        for(
$i=0; $i<$n; $i++) {
            if (
$active[$i][1] > $scanline) {
               
$tmp[] = $active[$i];
            }
        }
       
$active = $tmp;
       
// sort active tab
       
$n = count($active);
        for(
$i=0; $i<$n-1; $i++) {
           
$min = $i;
            for(
$k=$i+1; $k<$n; $k++) {
                if (
$active[$k][2] < $active[$min][2]) { $min = $k; }
            }
            if (
$i != $min) {
               
$tmp = $active[$i];
               
$active[$i] = $active[$min];
               
$active[$min] = $tmp;
            }
        }
       
// draw
       
$n = count($active);
        for(
$i=0; $i<$n; $i+=2) {
            if (
$i+1 < $n) {
                if (
$tmp[$i][2] == $active[$i+1][2]) {
                   
imagesetpixel($img, round($active[$i][2]), $scanline, $color);
                } else {
                   
imageline($img, round($active[$i][2]), $scanline, round($active[$i+1][2]), $scanline, $color);
                }
            }
        }
       
// increment x values
       
$n = count($active);
        for(
$i=0; $i<$n; $i++) { $active[$i][2] += $active[$i][3]; }
       
$scanline++;
    } while (
count($all_edges) + count($active) > 0);
}
?>
webmaster at mywebsolution dot de 22-Oct-2007 02:24
Just thought that 'tatlar at yahoo dot com's function has some redundant code in it, so I tried to "improve" it. Now you can choose a variable number of spikes.

<?php
error_reporting
(E_ALL);
function
drawStar($x, $y, $radius, $spikes=5) {
   
// $x, $y -> Position in the image
    // $radius -> Radius of the star
    // $spikes -> Number of spikes

   
$coordinates = array();
   
$angel = 360 / $spikes ;

   
// Get the coordinates of the outer shape of the star
   
$outer_shape = array();
    for(
$i=0; $i<$spikes; $i++){
       
$outer_shape[$i]['x'] = $x + ($radius * cos(deg2rad(270 - $angel*$i)));
       
$outer_shape[$i]['y'] = $y + ($radius * sin(deg2rad(270 - $angel*$i)));
    }

   
// Get the coordinates of the inner shape of the star
   
$inner_shape = array();
    for(
$i=0; $i<$spikes; $i++){
       
$inner_shape[$i]['x'] = $x + (0.5*$radius * cos(deg2rad(270-180 - $angel*$i)));
       
$inner_shape[$i]['y'] = $y + (0.5*$radius * sin(deg2rad(270-180 - $angel*$i)));
    }

   
// Bring the coordinates in the right order
   
foreach($inner_shape as $key => $value){
        if(
$key == (floor($spikes/2)+1))
             break;
       
$inner_shape[] = $value;
        unset(
$inner_shape[$key]);
    }

   
// Reset the keys
   
$i=0;
    foreach(
$inner_shape as $value){
       
$inner_shape[$i] = $value;
       
$i++;
    }

   
// "Merge" outer and inner shape
   
foreach($outer_shape as $key => $value){
        
$coordinates[] = $outer_shape[$key]['x'];
        
$coordinates[] = $outer_shape[$key]['y'];
        
$coordinates[] = $inner_shape[$key]['x'];
        
$coordinates[] = $inner_shape[$key]['y'];
    }

   
// Return the coordinates
   
return $coordinates ;
}

// Example
$spikes = 5;

$values = drawStar(250, 250, 200, $spikes);
$im = imagecreate(500,500);
imagecolorallocate($im,0,0,0);
$w = imagecolorallocate($im, 255, 255, 255);
imagefilledpolygon($im, $values, $spikes*2, $w);
imageGIF($im);
imagedestroy($im);
?>
jylyn at hotmail dot com 16-Oct-2006 05:11
In spite of what it says about requiring more than 3 vertices, it is possible to draw a triangle with this function!
tatlar at yahoo dot com 11-Sep-2006 05:08
<?php function _makeFiveSidedStar( $x, $y, $radius, $shape='polygon', $spiky=NULL ) {
   
// $x, $y co-ords of origin (in pixels), $radius (in pixels), $shape - 'polygon' or 'star', $spikiness - ratio between 0 and 1
   
$point = array() ;                                                                                                                   
   
$angle = 360 / 5 ;                                                                                                                   
   
$point[0]['x'] = $x ;                                                                                                                
   
$point[0]['y'] = $y - $radius ;                                                                                                      
   
$point[2]['x'] = $x + ( $radius * cos( deg2rad( 90 - $angle ) ) ) ;
   
$point[2]['y'] = $y - ( $radius * sin( deg2rad( 90 - $angle ) ) ) ;
   
$point[4]['x'] = $x + ( $radius * sin( deg2rad( 180 - ( $angle*2 ) ) ) ) ;
   
$point[4]['y'] = $y + ( $radius * cos( deg2rad( 180 - ( $angle*2 ) ) ) ) ;
   
$point[6]['x'] = $x - ( $radius * sin( deg2rad( 180 - ( $angle*2 ) ) ) ) ;                                                           
   
$point[6]['y'] = $y + ( $radius * cos( deg2rad( 180 - ( $angle*2 ) ) ) ) ;
   
$point[8]['x'] = $x - ( $radius * cos( deg2rad( 90 - $angle ) ) ) ;                                                                  
   
$point[8]['y'] = $y - ( $radius * sin( deg2rad( 90 - $angle ) ) ) ;
    if(
$shape == 'star' ) {
        if(
$spiky == NULL ) $spiky = 0.5 // default to 0.5
       
$indent = $radius * $spiky ;
       
$point[1]['x'] = $x + ( $indent * cos( deg2rad( 90 - $angle/2 ) ) ) ;                                                            
       
$point[1]['y'] = $y - ( $indent * sin( deg2rad( 90 - $angle/2 ) ) ) ;                                                    
       
$point[3]['x'] = $x + ( $indent * sin( deg2rad( 180 - $angle ) ) ) ;                                                             
       
$point[3]['y'] = $y - ( $indent * cos( deg2rad( 180 - $angle ) ) ) ;
       
$point[5]['x'] = $x ;                                                                                                            
       
$point[5]['y'] = $y + ( $indent * sin( deg2rad( 180 - $angle ) ) ) ;
       
$point[7]['x'] = $x - ( $indent * sin( deg2rad( 180 - $angle ) ) ) ;                                                             
       
$point[7]['y'] = $y - ( $indent * cos( deg2rad( 180 - $angle ) ) ) ;                                                             
       
$point[9]['x'] = $x - ( $indent * cos( deg2rad( 90 - $angle/2 ) ) ) ;                                                            
       
$point[9]['y'] = $y - ( $indent * sin( deg2rad( 90 - $angle/2 ) ) ) ;
    }
   
ksort( $point ) ;
   
$coords = array() ;  // new array                                                                                                                
   
foreach( $point as $pKey=>$pVal ) {                                                                                                  
        if(
is_array( $pVal ) ) {                                                                                                        
            foreach(
$pVal as $pSubKey=>$pSubVal ) {                                                                                     
                if( !empty(
$pSubVal ) ) array_push( $coords, $pSubVal ) ;                                                               
            }                                                                                                                            
        }                                                                                                                                
    }
    return
$coords ;
}
$values = _makeFiveSidedStar( 100, 100, 50, 'star' ) ;
// Put values into imagepolygon function. You need to define the $image and $color, and flush it out to an image type.?>
etnekor at tar dot hu 22-Jan-2006 01:18
There is a simple function to draw a filled point with a chosen radius and color.

<?php
function drawPoint($img, $radius, $origo_x, $origo_y, $pointColor)
{
  for (
$i=0;$i<=360;$i++)
  {
   
$pont[] = $origo_x + ($radius * sin(deg2rad($i)));
   
$pont[] = $origo_y - ($radius * cos(deg2rad($i)));
  }
 
reset($pont);
 
ImageFilledPolygon ($img, $pont, (sizeof($pont)/2), $pointColor);
}
?>