Helpful Information
 
 
Category: Post a PHP snippet
Geometry.

I was playing around and made this... but it can be usefull... if you'll ever need to do such things. ;)

Ah yes descritption.
It'll draw pretty much anything as long as you give coordinates.
It'll give you the length of the line and return the point at it's middle.
For polygons it'll return the area (with the exception that the polygion intersects with itself) and perimeter.
An example is given below.


<?php
class point
{
public $x = 0,
$y = 0;

function __construct($x = 0, $y = 0)
{
$this->set($x, $y);
}

function set($x, $y)
{
if(!is_nan($x) && !is_nan($y))
{
$this->x = $x;
$this->y = $y;
return true;
}
return false;
}

function pos()
{
return array($this->x, $this->y);
}

function move_by($vector)
{
if(!$vector instanceof vector)
{
return false;
}
return $this->set($this->x + $vector->x, $this->y + $vector->y);
}
}

class line
{
public $points = array();
public $length = 0;

function __construct($a = false, $b = false)
{
return $this->set($a, $b);
}

function set($a, $b)
{
if($a instanceof point && $b instanceof point)
{
$this->points[] = $a;
$this->points[] = $b;
$this->length();
return true;
}
return false;
}

private function length()
{
$this->length = sqrt((pow($this->points[1]->x - $this->points[0]->x, 2)) + (pow($this->points[1]->y - $this->points[0]->y, 2)));
}

function middle()
{
return new point(($this->points[0]->x - $this->points[1]->x) / 2, ($this->points[0]->y - $this->points[1]->y) / 2);
}
}

class vector
{
public $x,
$y;

function __construct($x, $y)
{
$this->set($x, $y);
}

function set($x, $y)
{
$this->x = (int) $x;
$this->y = (int) $y;
}
}

class polygon
{
public $points = array();
public $area = 0;
public $perimeter = 0;

function __construct()
{
$n = func_num_args();
if($n < 3)
{
return false;
}
for($i = 0; $i < $n; $i++)
{
if(func_get_arg($i) instanceof point)
{
$this->points[] = func_get_arg($i);
}
}
$this->area();
$this->perimeter();
}

private function area()
{
$area = 0;
for($i = 0, $n = count($this->points) - 1; $i < $n; $i++)
{
$area += $this->points[$i]->x * $this->points[$i + 1]->y - $this->points[$i + 1]->x * $this->points[$i]->y;
}
$area += $this->points[$n]->x * $this->points[0]->y - $this->points[0]->x * $this->points[$n]->y;
$area /= 2;
$area = abs($area);
$this->area = $area;
}

private function perimeter()
{
$perimeter = 0;
for($i = 0, $n = count($this->points) - 1; $i < $n; $i++)
{
$side = new line($this->points[$i], $this->points[$i + 1]);
$perimeter += $side->length;
// var_dump($perimeter);
}
$side = new line($this->points[$n], $this->points[0]);
$perimeter += $side->length;
$this->perimeter = $perimeter;
}

function move_by($vector)
{
if(!$vector instanceof vector)
{
return false;
}
for($i = 0, $n = count($this->points); $i < $n; $i++)
{
$this->points[$i]->set($this->points[$i]->x + $vector->x, $this->points[$i]->y + $vector->y);
}
return true;
}
}

class grid
{
private $size = array(),
$data = array(),
$im = null;


function __construct($min_x, $max_x, $min_y, $max_y, $scale_x, $scale_y)
{
$this->size['min'] = array($min_x, $max_y);
$this->size['max'] = array($max_x, $min_y);
$this->size['scale'] = array($scale_x, $scale_y);
$this->size[0] = array($scale_x * $min_x, $scale_y * $max_y);

return $this->create_image();
}

private function create_image()
{
$this->im = imagecreate(1 + ($this->size['min'][0] + $this->size['max'][0]) * $this->size['scale'][0], 1 + ($this->size['min'][1] + $this->size['max'][1]) * $this->size['scale'][1]);
$back = imagecolorallocatealpha($this->im, 255, 255, 255, 127); // transparent.
return true;
}

function plot($obj, $color = false)
{
if(!$color)
{
$color = imagecolorallocate($this->im, 0, 0, 0);
}
switch(get_class($obj))
{
case 'point':
imagefilledellipse($this->im, $this->size[0][0] + ($obj->x * $this->size['scale'][0]), $this->size[0][1] - ($obj->y * $this->size['scale'][1]), 3, 3, $color);
break;
case 'line':
imageline($this->im, $this->size[0][0] + ($obj->points[0]->x * $this->size['scale'][0]), $this->size[0][1] - ($obj->points[0]->y * $this->size['scale'][1]), $this->size[0][0] + ($obj->points[1]->x * $this->size['scale'][0]), $this->size[0][1] - ($obj->points[1]->y * $this->size['scale'][1]), $color);
break;
case 'polygon':
$data = array();
for($i = 0, $n = count($obj->points); $i < $n; $i++)
{
$data[] = $this->size[0][0] + ($obj->points[$i]->x * $this->size['scale'][0]);
$data[] = $this->size[0][1] - ($obj->points[$i]->y * $this->size['scale'][1]);
}
imagefilledpolygon($this->im, $data, $n, $color);
break;
}
}

function plot_axis()
{
$black = imagecolorallocate($this->im, 0, 0, 0);
imageline($this->im, $this->size['min'][0] * $this->size['scale'][0], 0, $this->size['min'][0] * $this->size['scale'][0], ($this->size['min'][1] + $this->size['max'][1]) * $this->size['scale'][1], $black);
imageline($this->im, 0, $this->size['min'][1] * $this->size['scale'][1], ($this->size['min'][0] + $this->size['max'][0]) * $this->size['scale'][0], $this->size['min'][1] * $this->size['scale'][1], $black);
}

function func($eval = '$x', $percision = 10, $color = false)
{
if(!$color)
{
$color = imagecolorallocate($this->im, 0, 0, 0);
}
if(substr($eval, -1) != ';')
{
$eval .= ';';
}
for($x = -1 * ($this->size['min'][0] + $this->size['max'][0]), $n = ($this->size['min'][0] + $this->size['max'][0]) * $percision; $x < $n; $x += 1 / $percision)
{
$points[] = array($this->size[0][0] + ($x * $this->size['scale'][0]), $this->size[0][1] - (eval('return ' . $eval) * $this->size['scale'][1]));
}
for($i = 0, $n = count($points) - 1; $i < $n; $i++)
{
imageline($this->im, $points[$i][0], $points[$i][1], $points[$i + 1][0], $points[$i + 1][1], $color);
}
}

function make_image($dest = false)
{
if(!$dest)
{
header('Content-Type: image/png');
return imagepng($this->im);
}
return imagepng($this->im, $dest);
}

function color($r, $g, $b, $alpha)
{
return imagecolorallocatealpha($this->im, $r, $g, $b, $alpha);
}
}
?>

Example:


<?php
$poly = new polygon(
new point(0, 0),
new point(0, 1),
new point(1, 2),
new point(2, 2),
new point(2, 3),
new point(3, 4),
new point(4, 4),
new point(5, 3),
new point(5, 0),
new point(4, 0),
new point(4, 3),
new point(3, 3),
new point(3, 2),
new point(2, 1),
new point(1, 1)
);
$point = new point(4, 4);
$line = new line(new point(-2, 2), new point(4, 5));
$poly2 = new polygon(
new point(0, 0),
new point(0, 4),
$point,
new point(4, 0),
new point(3, 0),
new point(3, 3),
new point(1, 3),
new point(1, 0)
);

$vector = new vector(-5, 3);


$grid = new grid(10, 10, 10, 10, 20, 20);
$grid->plot_axis();
$grid->plot($point);
$grid->plot($poly, $grid->color(100, 200, 100, 0));

$poly->move_by($vector);

$grid->func('pow($x, 2) + $x', 10);
$grid->make_image(/*'C:/test.png'*/);

It can produce an image like the one attached (PNG not GIF but png isn't allowed here for some reason).

Be usefull for a extremely random captcha image. ;) Or, if you really into it you could spend the time to make image generators, as in,if you have ever used that doll maker that makes dolls that look similar to the 'homies' in the quarter machines. It uses PHP to draw the characters (all designs are unditable) allowing you to customize colors and add a shirt logo. Pretty neat stuff.

Well I didn't think about any of these while writing that.

Well then it lets you know its usefull. ;)

Cool!

I spent 15 mins or so making it slightly more useful: type in a function and it graphs instantly...

graph.php



<?php
include('class.php');

$grid = new grid(10, 10, 10, 10, 20, 20);
$grid->plot_axis();

$y = split("=", $_SERVER['QUERY_STRING']);
$x = rawurldecode($y[1]);

$grid->func($x, 10);
$md5 = md5(microtime(true));
$grid->make_image($md5.".png");

header("location: {$md5}.png");
?>


class.php
...See first box of code in marek's first post -- basically contains all the math

index.php



<html>
<head>
<title>Function Grapher</title>

<script type="text/javascript">
function img_switch (that) {
im = document.getElementsByTagName('img')[0];
im.src = "graph.php?func="+escape(that.value);
}

</script>

</head>

<body>
<h1>Function Grapher</h1>

<img src="graph.php?func=$x+2" height="401" width="401" />

<input type="text" value="$x+2" onkeyup="img_switch(this)" size="100" />

</body>

</html>


I'm not going to give you a preview because of the security risks...eval($_GET) eek!

Evaling input is not secure (I know that - don't copy that). If you want to secure it you could use this class (http://www.phpclasses.org/browse/package/2695.html) that evaluates math securely.
grid::func() was the last method I've added (all I wanted was to draw polygons) so if you want to use it in public it would be wise to secure it.

hi,

i get an error with this one, no image displays.. error..


[26-Apr-2006 09:55:27] PHP Parse error: parse error, unexpected T_STRING, expecting T_OLD_FUNCTION or T_FUNCTION or T_VAR or '}' in c:\phpdev5\www\public\new folder\class.php on line 4
[26-Apr-2006 09:55:27] PHP Fatal error: Cannot instantiate non-existent class: grid in c:\phpdev5\www\public\new folder\graph.php on line 4


tried this on two servers running different php versions .. still no luck,
any thoughts? Im using the second code and M's class.php

cheers
p

You need at least PHP5 to run the code.
PHP4 does not recognise the public/private/protected properties (it uses var only) and that's why you get the parse error.

ah ok. thanks =]










privacy (GDPR)