文字

imagefilledpolygon

(PHP 4, PHP 5, PHP 7)

imagefilledpolygon画一多边形并填充

说明

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

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)
            
240 20 ,   // Point 4 (x, y)
            
50 ,   40 ,   // Point 5 (x, y)
            
10 ,   10    // Point 6 (x, y)
            
);

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

// 设定颜色
$bg    imagecolorallocate ( $image 200 200 200 );
$blue  imagecolorallocate ( $image 0 0 255 );

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

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

用户评论:

[#1] rbenheidorn at gmail dot com [2015-02-01 21:20:05]

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.

[#2] austinoblouk at yahoo dot com [2009-09-05 20:28:18]

Actually the minimum it allows is 3. It says "Total number of vertices, which must be bigger than 3." but it allows 3...

[#3] Arnapou [2007-10-29 06:49:00]

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(
00),
    array(
10050),
    array(
90100),
    array(
5050),
    array(
7030),
    array(
1010),
);
?>


<?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+$n) {
                if (
$tmp[$i][2] == $active[$i+1][2]) {
                    
imagesetpixel($imground($active[$i][2]), $scanline$color);
                } else {
                    
imageline($imground($active[$i][2]), $scanlineround($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);
}
?>

[#4] webmaster at mywebsolution dot de [2007-10-22 14:24:53]

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(250250200$spikes);
$im imagecreate(500,500);
imagecolorallocate($im,0,0,0);
$w imagecolorallocate($im255255255);
imagefilledpolygon($im$values$spikes*2$w);
imageGIF($im);
imagedestroy($im);
?>

[#5] jylyn at hotmail dot com [2006-10-16 17:11:12]

In spite of what it says about requiring more than 3 vertices, it is possible to draw a triangle with this function!

[#6] tatlar at yahoo dot com [2006-09-11 17:08:22]

<?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.?>

[#7] etnekor at tar dot hu [2006-01-22 13:18:16]

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);
}
?>

上一篇: 下一篇: