tags:

views:

195

answers:

3

Hi guys,

I have run into some trouble with the gd library's imagefilledpolygon().

For some reason some of my lines were ending up 1px out of place so I decided to debug it using imagepixelset to set the colour of my shapes points to red.

alt text if you look at the picture you can see some of the points are inside the shape ... some are outside....its very illogical.

(the picture has been scaled up to make it more visible)

Does anyone have a solution?

Update:

My points for the shape above were: 0,0 40,0 40,20 20,20 20,40 0,40

I require that the height and width of the shape produced should be a multiple of 20.... but for some reason some of the shape ends up 21 px high or wide.

I have made a script to work out what the points would be to get the shape I wanted but I can not work out why and so I can't work out a script to correct all my shapes.

<?php

// set up array of points for polygon
$values = array(0,0, 39,0, 39,20, 19,20, 19,39, 0,39);

//My original values were 0,0 40,0 40,20 20,20 20,40 0,40
//I do not understand why some values require minus 1 and others can remain as they were (a multiple of 20)

// create image
$image = imagecreatetruecolor(40, 40);

// allocate colors
$bg   = imagecolorallocate($image, 200, 200, 200);
$blue = imagecolorallocate($image, 0, 0, 255);

// fill the background
imagefilledrectangle($image, 0, 0, 39, 39, $bg);

// draw a polygon
imagefilledpolygon($image, $values, 6, $blue);

// flush image
header('Content-type: image/png');
imagepng($image);
imagedestroy($image);


?>
+2  A: 

My guess is that you're mixing up width with position.

For example a line from 0px to 9px is 10px long... if you used length as the second parameter instead of position, it would end up 11px long.

If I could see some code I could confirm this.

Greg
I wondered that too... but the squares that make up the shape are all 20px by 20px and I have checked the points they are all dividable by 20...
Mark
For a polygon there shouldn't be any widths, though. Only positions of the outline points.
Joey
you seem to be partly right... but some of the points should not be "-1" ... its very odd
Mark
Imagine your polygon is only 1 pixel wide. What would the x-coordinates be? 0, 1 sounds right, but that's 2 pixels. 0, 0 is the right answer - that's 1 pixel
Greg
+1  A: 

Normal polygon rendering ensures that each pixel can only be in one polygon, if the 2 polygons share an edge. If you imagine drawing 2 squares, next to each other, so they share a common edge, you don't want to render the pixels along that edge twice.

There is an explanation of determining which pixels on the edge of a polygon should be considered inside the polygon here: http://www.gameprogrammer.com/5-poly.html

A common solution is to say that "pixels on the left and top edges of a polygon belong to the polygon and pixels on the right and bottom edges don't". I am not 100% sure what solution GD uses, as I could not find any documentation on it, but I expect it is something similar to this.

rikh
I think I understand what you mean... in a square: the pixel in the top left is in the shape completely,the pixel in the top right is touching on the left side,the pixel in the bottom right is diagonally touching,the pixel in the bottom left is touching on the top sidebut if you look its not like that... only one pixel is outside
Mark
indeed, your example does not seem to follow any sane pixel selection rule that I can determine, so I am not sure how to explain the result you are seeing. What we need is some clear documentation that explains how the GD library decides if a pixel is inside or outside the polygon.
rikh
I spoke with the creator of the GD library, he says it is based around the winding ruleWhich is explained here http://en.wikipedia.org/wiki/Point_in_polygon under the title "Winding number algorithm"Winding numbers are explained here http://en.wikipedia.org/wiki/Winding_numberBut I can't for the life of me work out how I would adjust my coordinates to suit.
Mark
Hmm, the winding number system is used for rendering polygons with potential holes in them, or that have edges cross each other, rather than addressing the specific issue of determining which pixels along an edges are considered to be inside and outside.Maybe it is a bug and no proper rule is enforced.Try drawing 2 squares. The first with corners at (0,0) and (10,10) and the other with corners at (10,10) and (20,20) and see what you get...
rikh
With a convex shapes it does it perfectly. I decided to scrap it in the end and I made my polygon using multiple imagefilledrectabgles which worked a treat... Thanks for the help :D
Mark
+1  A: 

I spoke to the guy who currently develops the GD library he explained that it follows the 'Winding number algorithm' - can be found here. Having looked at my example image, it does match how the 'winding number algorithm' works, however the function should take this into account and produce the shape that was input.

As far as I can see the only way to accurately (to the pixel) generate a concave polygon with this function is to write another function that also applies the winding rule to your coordinates and adjusts them accordingly and then put it into the function.

Mark