* @implements ArrayAccess */ class Bezier implements IteratorAggregate, Countable, ArrayAccess, DrawableInterface { use HasBorder; use HasBackgroundColor; /** * Create new bezier instance * * @param array $points * @param PointInterface $pivot * @return void */ public function __construct( protected array $points = [], protected PointInterface $pivot = new Point() ) { } /** * {@inheritdoc} * * @see DrawableInterface::position() */ public function position(): PointInterface { return $this->pivot; } /** * {@inheritdoc} * * @see DrawableInterface::setPosition() */ public function setPosition(PointInterface $position): DrawableInterface { $this->pivot = $position; return $this; } /** * Implement iteration through all points of bezier * * @return Traversable */ public function getIterator(): Traversable { return new ArrayIterator($this->points); } /** * Return current pivot point * * @return PointInterface */ public function pivot(): PointInterface { return $this->pivot; } /** * Change pivot point to given point * * @param PointInterface $pivot * @return Bezier */ public function setPivot(PointInterface $pivot): self { $this->pivot = $pivot; return $this; } /** * Return first control point of bezier * * @return ?PointInterface */ public function first(): ?PointInterface { if ($point = reset($this->points)) { return $point; } return null; } /** * Return second control point of bezier * * @return ?PointInterface */ public function second(): ?PointInterface { if (array_key_exists(1, $this->points)) { return $this->points[1]; } return null; } /** * Return third control point of bezier * * @return ?PointInterface */ public function third(): ?PointInterface { if (array_key_exists(2, $this->points)) { return $this->points[2]; } return null; } /** * Return last control point of bezier * * @return ?PointInterface */ public function last(): ?PointInterface { if ($point = end($this->points)) { return $point; } return null; } /** * Return bezier's point count * * @return int */ public function count(): int { return count($this->points); } /** * Determine if point exists at given offset * * @param mixed $offset * @return bool */ public function offsetExists($offset): bool { return array_key_exists($offset, $this->points); } /** * Return point at given offset * * @param mixed $offset * @return PointInterface */ public function offsetGet($offset): mixed { return $this->points[$offset]; } /** * Set point at given offset * * @param mixed $offset * @param PointInterface $value * @return void */ public function offsetSet($offset, $value): void { $this->points[$offset] = $value; } /** * Unset offset at given offset * * @param mixed $offset * @return void */ public function offsetUnset($offset): void { unset($this->points[$offset]); } /** * Add given point to bezier * * @param PointInterface $point * @return Bezier */ public function addPoint(PointInterface $point): self { $this->points[] = $point; return $this; } /** * Return array of all x/y values of all points of bezier * * @return array */ public function toArray(): array { $coordinates = []; foreach ($this->points as $point) { $coordinates[] = $point->x(); $coordinates[] = $point->y(); } return $coordinates; } }