©
本文档使用
php.cn手册 发布
(PHP 4, PHP 5, PHP 7)
imagefilledpolygon — 画一多边形并填充
$image
, array $points
, int $num_points
, int $color
) imagefilledpolygon() 在 image
图像中画一个填充了的多边形。
points
参数是一个按顺序包含有多边形各顶点的
x 和 y
坐标的数组。
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(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);
}
?>
[#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(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);
?>
[#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);
}
?>