Rev 60 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
<?php/** This work is hereby released into the Public Domain.* To view a copy of the public domain dedication,* visit http://creativecommons.org/licenses/publicdomain/ or send a letter to* Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.**/require_once dirname(__FILE__)."/../Graph.class.php";abstract class awShape {/*** Is the shape hidden ?** @var bool*/protected $hide = FALSE;/*** Shape style** @var int*/public $style;/*** Shape thickness** @var int*/public $thickness;/*** Solid shape** @var int*/const SOLID = 1;/*** Dotted shape** @var int*/const DOTTED = 2;/*** Dashed shape** @var int*/const DASHED = 3;/*** Change shape style** @param int $style Line style*/public function setStyle($style) {$this->style = (int)$style;}/*** Return shape style** @return int*/public function getStyle() {return $this->style;}/*** Change shape thickness** @param int $thickness Shape thickness in pixels*/public function setThickness($thickness) {$this->thickness = (int)$thickness;}/*** Return shape thickness** @return int*/public function getThickness() {return $this->thickness;}/*** Hide the shape** @param bool $hide*/public function hide($hide) {$this->hide = (bool)$hide;}/*** Show the shape** @param bool $shape*/public function show($shape) {$this->hide = (bool)!$shape;}/*** Is the line hidden ?** @return bool*/public function isHidden() {return $this->hide;}}registerClass('Shape', TRUE);/*** Describe a point** @package Artichow*/class awPoint extends awShape {/*** X coord** @var float*/public $x;/*** Y coord** @var float*/public $y;/*** Build a new awpoint** @param float $x* @param float $y*/public function __construct($x, $y) {$this->setLocation($x, $y);}/*** Change X value** @param float $x*/public function setX($x) {$this->x = (float)$x;}/*** Change Y value** @param float $y*/public function setY($y) {$this->y = (float)$y;}/*** Change point location** @param float $x* @param float $y*/public function setLocation($x, $y) {$this->setX($x);$this->setY($y);}/*** Get point location** @param array Point location*/public function getLocation() {return array($this->x, $this->y);}/*** Get distance to another point** @param awPoint $p A point* @return float*/public function getDistance(awPoint $p) {return sqrt(pow($p->x - $this->x, 2) + pow($p->y - $this->y, 2));}/*** Move the point to another location** @param Point A Point with the new awlocation*/public function move($x, $y) {return new awPoint($this->x + $x,$this->y + $y);}}registerClass('Point');/*** Describe a line** @package Artichow*/class awLine extends awShape {/*** Line first point** @param Point*/public $p1;/*** Line second point** @param Point*/public $p2;/*** The line slope (the m in y = mx + p)** @param float*/private $slope;/*** The y-intercept value of the line (the p in y = mx + p)** @param float*/private $origin;/*** Build a new awline** @param awPoint $p1 First point* @param awPoint $p2 Second point* @param int $type Style of line (default to solid)* @param int $thickness Line thickness (default to 1)*/public function __construct($p1 = NULL, $p2 = NULL, $type = awLine::SOLID, $thickness = 1) {$this->setLocation($p1, $p2);$this->setStyle($type);$this->setThickness($thickness);}/*** Build a line from 4 coords** @param int $x1 Left position* @param int $y1 Top position* @param int $x2 Right position* @param int $y2 Bottom position*/public static function build($x1, $y1, $x2, $y2) {return new awLine(new awPoint($x1, $y1),new awPoint($x2, $y2));}/*** Change X values of the line** @param int $x1 Begin value* @param int $x2 End value*/public function setX($x1, $x2) {$this->p1->setX($x1);$this->p2->setX($x2);// Resets slope and origin values so they are// recalculated when and if needed.$this->slope = NULL;$this->origin = NULL;}/*** Change Y values of the line** @param int $y1 Begin value* @param int $y2 End value*/public function setY($y1, $y2) {$this->p1->setY($y1);$this->p2->setY($y2);// Resets slope and origin values so they are// recalculated when and if needed.$this->slope = NULL;$this->origin = NULL;}/*** Change line location** @param awPoint $p1 First point* @param awPoint $p2 Second point*/public function setLocation($p1, $p2) {if(is_null($p1) or $p1 instanceof awPoint) {$this->p1 = $p1;}if(is_null($p2) or $p2 instanceof awPoint) {$this->p2 = $p2;}// Resets slope and origin values so they are// recalculated when and if needed.$this->slope = NULL;$this->origin = NULL;}/*** Get line location** @param array Line location*/public function getLocation() {return array($this->p1, $this->p2);}/*** Get the line size** @return float*/public function getSize() {$square = pow($this->p2->x - $this->p1->x, 2) + pow($this->p2->y - $this->p1->y, 2);return sqrt($square);}/*** Calculate the line slope**/private function calculateSlope() {if($this->isHorizontal()) {$this->slope = 0;} else {$slope = ($this->p1->y - $this->p2->y) / ($this->p1->x - $this->p2->x);$this->slope = $slope;}}/*** Calculate the y-intercept value of the line**/private function calculateOrigin() {if($this->isHorizontal()) {$this->origin = $this->p1->y; // Or p2->y} else {$y1 = $this->p1->y;$y2 = $this->p2->y;$x1 = $this->p1->x;$x2 = $this->p2->x;$origin = ($y2 * $x1 - $y1 * $x2) / ($x1 - $x2);$this->origin = $origin;}}/*** Calculate the slope and y-intercept value of the line**/private function calculateEquation() {$this->calculateSlope();$this->calculateOrigin();}/*** Get the line slope value** @return float*/public function getSlope() {if($this->isVertical()) {return NULL;} elseif($this->slope !== NULL) {return $this->slope;} else {$this->calculateSlope();return $this->slope;}}/*** Get the line y-intercept value** @return float*/public function getOrigin() {if($this->isVertical()) {return NULL;} elseif($this->origin !== NULL) {return $this->origin;} else {$this->calculateOrigin();return $this->origin;}}/*** Get the line equation** @return array An array containing the slope and y-intercept value of the line*/public function getEquation() {$slope = $this->getSlope();$origin = $this->getOrigin();return array($slope, $origin);}/*** Return the x coordinate of a point on the line* given its y coordinate.** @param float $y The y coordinate of the Point* @return float $x The corresponding x coordinate*/public function getXFrom($y) {$x = NULL;if($this->isVertical()) {list($p, ) = $this->getLocation();$x = $p->x;} else {list($slope, $origin) = $this->getEquation();if($slope !== 0) {$y = (float)$y;$x = ($y - $origin) / $slope;}}return $x;}/*** Return the y coordinate of a point on the line* given its x coordinate.** @param float $x The x coordinate of the Point* @return float $y The corresponding y coordinate*/public function getYFrom($x) {$y = NULL;if($this->isHorizontal()) {list($p, ) = $this->getLocation();$y = $p->y;} else {list($slope, $origin) = $this->getEquation();if($slope !== NULL) {$x = (float)$x;$y = $slope * $x + $origin;}}return $y;}/*** Test if the line can be considered as a point** @return bool*/public function isPoint() {return ($this->p1->x === $this->p2->x and $this->p1->y === $this->p2->y);}/*** Test if the line is a vertical line** @return bool*/public function isVertical() {return ($this->p1->x === $this->p2->x);}/*** Test if the line is an horizontal line** @return bool*/public function isHorizontal() {return ($this->p1->y === $this->p2->y);}/*** Returns TRUE if the line is going all the way from the top* to the bottom of the polygon surrounding box.** @param $polygon Polygon A Polygon object* @return bool*/public function isTopToBottom(awPolygon $polygon) {list($xMin, $xMax) = $polygon->getBoxXRange();list($yMin, $yMax) = $polygon->getBoxYRange();if($this->isHorizontal()) {return FALSE;} else {if($this->p1->y < $this->p2->y) {$top = $this->p1;$bottom = $this->p2;} else {$top = $this->p2;$bottom = $this->p1;}return ($this->isOnBoxTopSide($top, $xMin, $xMax, $yMin)and$this->isOnBoxBottomSide($bottom, $xMin, $xMax, $yMax));}}/*** Returns TRUE if the line is going all the way from the left side* to the right side of the polygon surrounding box.** @param $polygon Polygon A Polygon object* @return bool*/public function isLeftToRight(awPolygon $polygon) {list($xMin, $xMax) = $polygon->getBoxXRange();list($yMin, $yMax) = $polygon->getBoxYRange();if($this->isVertical()) {return FALSE;} else {if($this->p1->x < $this->p2->x) {$left = $this->p1;$right = $this->p2;} else {$left = $this->p2;$right = $this->p1;}}return ($this->isOnBoxLeftSide($left, $yMin, $yMax, $xMin)and$this->isOnBoxRightSide($right, $yMin, $yMax, $xMax));}private function isOnBoxTopSide(awPoint $point, $xMin, $xMax, $yMin) {if($point->y === $yMinand$point->x >= $xMinand$point->x <= $xMax) {return TRUE;} else {return FALSE;}}private function isOnBoxBottomSide(awPoint $point, $xMin, $xMax, $yMax) {if($point->y === $yMaxand$point->x >= $xMinand$point->x <= $xMax) {return TRUE;} else {return FALSE;}}private function isOnBoxLeftSide(awPoint $point, $yMin, $yMax, $xMin) {if($point->x === $xMinand$point->y >= $yMinand$point->y <= $yMax) {return TRUE;} else {return FALSE;}}private function isOnBoxRightSide(awPoint $point, $yMin, $yMax, $xMax) {if($point->x === $xMaxand$point->y >= $yMinand$point->y <= $yMax) {return TRUE;} else {return FALSE;}}}registerClass('Line');/*** A vector is a type of line* The sense of the vector goes from $p1 to $p2.** @package Artichow*/class awVector extends awLine {/*** Get vector angle in radians** @return float*/public function getAngle() {if($this->isPoint()) {return 0.0;}$size = $this->getSize();$width = ($this->p2->x - $this->p1->x);$height = ($this->p2->y - $this->p1->y) * -1;if($width >= 0 and $height >= 0) {return acos($width / $size);} else if($width <= 0 and $height >= 0) {return acos($width / $size);} else {$height *= -1;if($width >= 0 and $height >= 0) {return 2 * M_PI - acos($width / $size);} else if($width <= 0 and $height >= 0) {return 2 * M_PI - acos($width / $size);}}}}registerClass('Vector');/*** Describe a polygon** @package Artichow*/class awPolygon extends awShape {/*** Polygon points** @var array*/protected $points = array();/*** Set a point in the polygon** @param int $pos Point position* @param awPoint $point*/public function set($pos, $point) {if(is_null($point) or $point instanceof awPoint) {$this->points[$pos] = $point;}}/*** Add a point at the end of the polygon** @param awPoint $point*/public function append($point) {if(is_null($point) or $point instanceof awPoint) {$this->points[] = $point;}}/*** Get a point at a position in the polygon** @param int $pos Point position* @return Point*/public function get($pos) {return $this->points[$pos];}/*** Count number of points in the polygon** @return int*/public function count() {return count($this->points);}/*** Returns all points in the polygon** @return array*/public function all() {return $this->points;}/*** Returns the different lines formed by the polygon vertices** @return array*/public function getLines() {$lines = array();$count = $this->count();for($i = 0; $i < $count - 1; $i++) {$lines[] = new Line($this->get($i), $this->get($i + 1));}// "Close" the polygon$lines[] = new Line($this->get($count - 1), $this->get(0));return $lines;}/*** Get the upper-left and lower-right points* of the bounding box around the polygon** @return array An array of two Point objects*/public function getBoxPoints() {$count = $this->count();$x = $y = array();for($i = 0; $i < $count; $i++) {$point = $this->get($i);list($x[], $y[]) = $point->getLocation();}$upperLeft = new Point(min($x), min($y));$lowerRight = new Point(max($x), max($y));return array($upperLeft, $lowerRight);}/*** Return the range of the polygon on the y axis,* i.e. the minimum and maximum y value of any point in the polygon** @return array*/public function getBoxYRange() {list($p1, $p2) = $this->getBoxPoints();list(, $yMin) = $p1->getLocation();list(, $yMax) = $p2->getLocation();return array($yMin, $yMax);}/*** Return the range of the polygon on the x axis,* i.e. the minimum and maximum x value of any point in the polygon** @return array*/public function getBoxXRange() {list($p1, $p2) = $this->getBoxPoints();list($xMin, ) = $p1->getLocation();list($xMax, ) = $p2->getLocation();return array($xMin, $xMax);}}registerClass('Polygon');?>