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 === $yMin and $point->x >= $xMin and $point->x <= $xMax ) { return TRUE; } else { return FALSE; } } private function isOnBoxBottomSide(awPoint $point, $xMin, $xMax, $yMax) { if ( $point->y === $yMax and $point->x >= $xMin and $point->x <= $xMax ) { return TRUE; } else { return FALSE; } } private function isOnBoxLeftSide(awPoint $point, $yMin, $yMax, $xMin) { if ( $point->x === $xMin and $point->y >= $yMin and $point->y <= $yMax ) { return TRUE; } else { return FALSE; } } private function isOnBoxRightSide(awPoint $point, $yMin, $yMax, $xMax) { if ( $point->x === $xMax and $point->y >= $yMin and $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); } elseif ($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); } elseif ($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');