Файл: toolkit/geometry/Rectangle.php
Строк: 250
<?php
/**
* @package geometry
* @author Антон Кургузенков <kurguzenkov@list.ru>
*/
require_once 'exceptions.php';
require_once 'Point.php';
require_once 'Size.php';
/**
* Класс, описывающий прямоугольник
*/
class Rectangle {
/**
* Позиция прямоугольника
*
* @var Point
*/
private $location;
/**
* Размер прямоугольника
*
* @var Size
*/
private $size;
/**
* Принимает либо позицию прямоугольника (Point) и его размер (Size),
* либо координаты позиции, высоту и ширину.
*
* @throws IllegalArgumentException;
*/
public function __construct() {
$args = func_get_args();
if (count($args) == 4) {
$this->setLocation($args[0], $args[1]);
$this->setSize($args[2], $args[3]);
} else if (count($args) == 2
&& $args[0] instanceof Point
&& $args[1] instanceof Size) {
$this->setLocation($args[0]);
$this->setSize($args[1]);
}
}
/**
* Меняет местами высоту и ширину прямогольника
* и возвращает изменённый прямоугольник
* @see Size::flip()
*
* @return Rectangle
*/
public function flip() {
$t = $this->getWidth();
$this->setWidth($this->getHeight());
$this->setHeight($t);
return $this;
}
/**
* Увеличивает размеры прямоугольника.
*
* Принимает либо значения, на которые нужно
* увеличить прямоугольник, либо размер.
*
* @return Rectangle
* @throws IllegalArgumentException
*/
public function inflate() {
$args = func_get_args();
if (count($args) == 2) {
$this->setWidth($this->getWidth() + $args[0]);
$this->setHeight($this->getHeight() + $args[1]);
} else if (count($args) == 1) {
$this->setSize(Size::add($this->getSize(), $args[0]));
} else {
throw new IllegalArgumentException();
}
return $this;
}
/**
* Определяет, пересикается ли текущий прямоугольник
* с заданным по оси X
*
* @param Rectangle $rect
* @return boolean
*/
public function isIntersectsWithX(Rectangle $rect) {
if ($rect->isNull() || $this->isNull()) {
return false;
}
$left1 = $this->getLeft();
$left2 = $rect->getLeft();
if ($left1 < $left2) {
return $left2 - $left1 < $this->getWidth();
} else if ($left1 >= $left2) {
return $left1 - $left2 < $rect->getWidth();
}
}
/**
* Определяет, пересикается ли текущий прямоугольник
* с заданным по оси Y
*
* @param Rectangle $rect
* @return boolean
*/
public function isIntersectsWithY(Rectangle $rect) {
if ($rect->isNull() || $this->isNull()) {
return false;
}
$top1 = $this->getTop();
$top2 = $rect->getTop();
if ($top1 < $top2) {
return $top2 - $top1 < $this->getHeight();
} else if ($top1 >= $top2) {
return $top1 - $top2 < $rect->getHeight();
}
}
/**
* Определяет, пересекаются ли текущий прямоугольник с заданным.
*
* @param Rectangle $rect
* @return type
*/
public function isIntersectsWith(Rectangle $rect) {
return $this->isIntersectsWithX($rect) && $this->isIntersectsWithY($rect);
}
/**
* Возвращает пересечение текущего прямоугольника с заданным.
* В случае, если они не пересекаются, возвращает false.
*
* @param Rectangle $rect
* @return boolean|Rectangle
*/
public function getIntersectsWith(Rectangle $rect) {
if (!$this->isIntersectsWith($rect)) {
return false;
}
$left = max($rect->getLeft(), $this->getLeft());
$top = max($rect->getTop(), $this->getTop());
$right = min($rect->getRight(), $this->getRight());
$bottom = min($rect->getBottom(), $this->getBottom());
$width = $right - $left;
$height = $bottom - $top;
return new Rectangle($left, $top, $width, $height);
}
/**
* Определяет, вложен ли текущий прямоугольник в заданный.
*
* @param Rectangle $rect
* @return type
*/
public function isInner(Rectangle $rect) {
return $this->getTop() >= 0 && $this->getLeft() >= 0 &&
$this->getBottom() <= $rect->getHeight() && $this->getRight() <= $rect->getWidth();
}
/**
* Определяет, равны ли высота и ширина прямоугольника нулю.
*
* @return type
*/
public function isNull() {
return $this->getWidth() == 0 && $this->getHeight() == 0;
}
/**
*
* Центрирует текущий прямоугольник относительно заданного.
*
* Принимает либо прямоугольник, относительно которого производится центрирование,
* либо координаты позиции прямоугольника, его высоту и ширину.
*
* @return Rectangle
* @throws IllegalArgumentException
*/
public function center() {
$args = func_get_args();
if (count($args) == 4) {
return $this->center(new Rectangle($args[0], $args[1], $args[2], $args[3]));
} else if (count($args) == 1 && $args[0] instanceof Rectangle) {
$rect = $args[0];
$left = (int)(($rect->getWidth() - $this->getWidth()) / 2) + $rect->getLeft();
$top = (int)(($rect->getHeight() - $this->getHeight()) / 2) + $rect->getTop();
$this->setLeft($left);
$this->setTop($top);
return $this;
}
throw new IllegalArgumentException();
}
/**
* Определяет, является ли текущий прямоугольник квадратом.
* @return bool
*/
public function isSquare() {
return $this->getWidth() == $this->getHeight();
}
// getters
public function getLocation() {
return clone $this->location;
}
public function getSize() {
return clone $this->size;
}
public function getX() {
return $this->location->getX();
}
public function getY() {
return $this->location->getY();
}
public function getWidth() {
return abs($this->getSize()->getWidth());
}
public function getHeight() {
return abs($this->getSize()->getHeight());
}
public function getBottom() {
if ($this->getSize()->getHeight() > 0) {
return $this->getY() + $this->getHeight();
} else {
return $this->getY();
}
}
public function getRight() {
if ($this->getSize()->getWidth() < 0) {
return $this->getX();
} else {
return $this->getX() + $this->getWidth();
}
}
public function getTop() {
if ($this->getSize()->getHeight() > 0) {
return $this->getY();
} else {
return $this->getY() - $this->getHeight();
}
}
public function getLeft() {
if ($this->getSize()->getWidth() > 0) {
return $this->getX();
} else {
return $this->getX() - $this->getWidth();
}
}
public function getTopLeft() {
return new Point($this->getLeft(), $this->getTop());
}
// setters
/**
* @throws IllegalArgumentException
*/
public function setLocation() {
$args = func_get_args();
if (count($args) == 2) {
$this->location = new Point($args[0], $args[1]);
} else if(count($args) == 1 && $args[0] instanceof Point) {
$this->location = $args[0];
} else {
throw new IllegalArgumentException();
}
}
/**
* @throws IllegalArgumentException
*/
public function setSize() {
$args = func_get_args();
if (count($args) == 2) {
$this->size= new Size($args[0], $args[1]);
} else if(count($args) == 1 && $args[0] instanceof Size) {
$this->size = $args[0];
} else {
throw new IllegalArgumentException();
}
}
/**
* @param int
* @throws IllegalArgumentException
*/
public function setX($x) {
$this->location->setX($x);
}
/**
* @param int
* @throws IllegalArgumentException
*/
public function setY($y) {
$this->location->setY($y);
}
/**
* @param int
* @throws IllegalArgumentException
*/
public function setWidth($width) {
$this->size->setWidth($width);
}
/**
* @param int
* @throws IllegalArgumentException
*/
public function setHeight($height) {
$this->size->setHeight($height);
}
/**
* Изменяет y-координату верхнего левого угла.
*
* @param int
* @throws IllegalArgumentException
*/
public function setTop($top) {
if (!is_int($top)) {
throw new IllegalArgumentException();
}
if ($this->size->getHeight() > 0) {
$this->setY($top);
} else {
$y = $top + $this->getHeight();
$this->setY($y);
}
}
/**
* Изменяет, x-координату ыерхнего левого угла
*
* @param int
* @throws IllegalArgumentException
*/
public function setLeft($left) {
if (!is_int($left)) {
throw new IllegalArgumentException();
}
if ($this->size->getWidth() > 0) {
$this->setX($left);
} else {
$x = $left + $this->getWidth();
$this->setX($x);
}
}
public function __toString() {
return "{location: {$this->location}, size: {$this->size}, left: {$this->getLeft()}, top: {$this->getTop()}}";
}
}
?>