Question About a Simple Graph

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
eBob
Forum Newbie
Posts: 1
Joined: Wed Feb 06, 2013 10:35 am

Question About a Simple Graph

Post by eBob »

I am new to PHP and even newer to graphics in PHP, and I don't know if what I am seeing I can fix or if I just have to live with it. In the simple graph, attached, 4 straight lines (radii) should be perfectly horizontal or vertical (2 of each). But line 4 is not. Is there anything I can do about that?

There are also four diagonal lines, in red. On my monitor two of those, 1 and 4, look very good, i.e. perfectly smooth. But 2 and 3 both have a one pixle dog leg at what appears to be the midpoint. Normally I wouldn't expect a diagonal line to be perfectly smooth. But since lines 1 and 3 should be parallel and since line 3 appears perfectly smooth why doesn't 1? And the same question of course regarding lines 2 and 4.

Code below. Any help will be appreciated. Thanks, Bob

Code: Select all

<?php

function imgmsg($im,$msg)
{
   static $msgoff = 0;
   $black = imagecolorallocate($im,0,0,0);
    $msgoff += 10;
//    imagestring($im,3,10,$msgoff,$msg,$black);
} 

//set up image
$height = 600;
$width = 600;
$im = imagecreatetruecolor($width, $height);
$white = imagecolorallocate($im,255,255,255);
$black = imagecolorallocate($im,0,0,0);
$red = imagecolorallocate($im,255,0,0);

// create the image

imagefill($im,0,0,$white);

// draw the circle
$center_x = $width/2;
$center_y = $height/2;
imagearc($im,$center_x,$center_y,$width-4,$height-4,0,360,$black );

// draw the radii
$radius = ($width-4)/2;
imgmsg($im,'$radius is ' . $radius);
$degree_interval = 90;
//imagestring($im,3,10,10,'before loop',$black);
//for ($angle = $degree_interval; $angle <= 360; $angle += $degree_interval )
for ($angle = 0; $angle <= 359; $angle += $degree_interval )
{    imgmsg($im,'in loop');
    $x = sin(deg2rad($angle)) * $radius;
    imgmsg($im,'$angle is '.$angle.' / $x is '.$x . ' / sin is ' . sin(deg2rad($angle)) );
    $y = sin(deg2rad(90-$angle)) * $radius;
    imgmsg($im,'$angle is ' . (90-$angle) .' / $y is '.$y. ' / sin is ' . sin(deg2rad(90-$angle)));
    imageline($im,$center_x,$center_y,$x+$center_x, $y+$center_y,$black);

    $points_x[] = $x;
    $points_Y[] = $y;
    
    if (isset($last_x))
      { imageline($im,$last_x+$center_x,$last_y+$center_y,$x+$center_x,$y+$center_y,$red);
       }
       else {$first_x = $x; $first_y = $y;}
    $last_x = $x; $last_y = $y;
}

imageline($im,$last_x+$center_x,$last_y+$center_y,$first_x+$center_x,$first_y+$center_y,$red);

//imagestring($im,3,10,10,'loop done',$black);
// output image
Header('Content-type: image/png');
imagepng($im);

// clean up
imagedestroy($im);

?>
Attachments
SimplePhpGraph.png
User avatar
Weirdan
Moderator
Posts: 5978
Joined: Mon Nov 03, 2003 6:13 pm
Location: Odessa, Ukraine

Re: Question About a Simple Graph

Post by Weirdan »

What you see is likely a rounding error when you explicitly (or implicitly) convert floating point numbers to integers, but might be inherent floating point operation impreciseness as well.

The cheap and dirty trick is to render your graphic into a high-resolution surface (like 4 times the original resolution) and then resample it down to the resolution you need. This will give you nicely antialiased lines as well.

https://www.google.com/search?q=php+antialias+gd will give you plenty of options to do it.
User avatar
requinix
Spammer :|
Posts: 6617
Joined: Wed Oct 15, 2008 2:35 am
Location: WA, USA

Re: Question About a Simple Graph

Post by requinix »

You can deal with the rounding error specifically by manually round()ing the numbers yourself. In all odds you're facing numbers like 99.9997 which gets truncated to 99 instead of rounded to the 100 it is "supposed" to be.
Post Reply