src/image/RotImage.php
<?php
/**
* JPGraph v4.0.3
*/
namespace Amenadiel\JpGraph\Image;
/**
* @class RotImage
* // Description: Exactly as Image but draws the image at
* // a specified angle around a specified rotation point.
*/
class RotImage extends Image
{
public $a = 0;
public $dx = 0;
public $dy = 0;
public $transx = 0;
public $transy = 0;
private $m = [];
public function __construct($aWidth, $aHeight, $a = 0, $aFormat = DEFAULT_GFORMAT, $aSetAutoMargin = true)
{
parent::__construct($aWidth, $aHeight, $aFormat, $aSetAutoMargin);
$this->dx = $this->left_margin + $this->plotwidth / 2;
$this->dy = $this->top_margin + $this->plotheight / 2;
$this->SetAngle($a);
}
public function SetCenter($dx, $dy)
{
$old_dx = $this->dx;
$old_dy = $this->dy;
$this->dx = $dx;
$this->dy = $dy;
$this->SetAngle($this->a);
return [$old_dx, $old_dy];
}
public function SetTranslation($dx, $dy)
{
$old = [$this->transx, $this->transy];
$this->transx = $dx;
$this->transy = $dy;
return $old;
}
public function UpdateRotMatrice()
{
$a = $this->a;
$a *= M_PI / 180;
$sa = sin($a);
$ca = cos($a);
// Create the rotation matrix
$this->m[0][0] = $ca;
$this->m[0][1] = -$sa;
$this->m[0][2] = $this->dx * (1 - $ca) + $sa * $this->dy;
$this->m[1][0] = $sa;
$this->m[1][1] = $ca;
$this->m[1][2] = $this->dy * (1 - $ca) - $sa * $this->dx;
}
public function SetAngle($a)
{
$tmp = $this->a;
$this->a = $a;
$this->UpdateRotMatrice();
return $tmp;
}
public function Circle($xc, $yc, $r)
{
list($xc, $yc) = $this->Rotate($xc, $yc);
parent::Circle($xc, $yc, $r);
}
public function FilledCircle($xc, $yc, $r)
{
list($xc, $yc) = $this->Rotate($xc, $yc);
parent::FilledCircle($xc, $yc, $r);
}
public function Arc($xc, $yc, $w, $h, $s, $e)
{
list($xc, $yc) = $this->Rotate($xc, $yc);
$s += $this->a;
$e += $this->a;
parent::Arc($xc, $yc, $w, $h, $s, $e);
}
public function FilledArc($xc, $yc, $w, $h, $s, $e, $style = '')
{
list($xc, $yc) = $this->Rotate($xc, $yc);
$s += $this->a;
$e += $this->a;
parent::FilledArc($xc, $yc, $w, $h, $s, $e);
}
public function SetMargin($lm, $rm, $tm, $bm)
{
parent::SetMargin($lm, $rm, $tm, $bm);
$this->dx = $this->left_margin + $this->plotwidth / 2;
$this->dy = $this->top_margin + $this->plotheight / 2;
$this->UpdateRotMatrice();
}
public function Rotate($x, $y)
{
// Optimization. Ignore rotation if Angle==0 || Angle==360
if ($this->a == 0 || $this->a == 360) {
return [$x + $this->transx, $y + $this->transy];
}
$x1 = round($this->m[0][0] * $x + $this->m[0][1] * $y, 1) + $this->m[0][2] + $this->transx;
$y1 = round($this->m[1][0] * $x + $this->m[1][1] * $y, 1) + $this->m[1][2] + $this->transy;
return [$x1, $y1];
}
public function CopyMerge($fromImg, $toX, $toY, $fromX, $fromY, $toWidth, $toHeight, $fromWidth = -1, $fromHeight = -1, $aMix = 100)
{
list($toX, $toY) = $this->Rotate($toX, $toY);
parent::CopyMerge($fromImg, $toX, $toY, $fromX, $fromY, $toWidth, $toHeight, $fromWidth, $fromHeight, $aMix);
}
public function ArrRotate($pnts)
{
$n = safe_count($pnts) - 1;
for ($i = 0; $i < $n; $i += 2) {
list($x, $y) = $this->Rotate($pnts[$i], $pnts[$i + 1]);
$pnts[$i] = $x;
$pnts[$i + 1] = $y;
}
return $pnts;
}
public function DashedLine($x1, $y1, $x2, $y2, $dash_length = 1, $dash_space = 4)
{
list($x1, $y1) = $this->Rotate($x1, $y1);
list($x2, $y2) = $this->Rotate($x2, $y2);
parent::DashedLine($x1, $y1, $x2, $y2, $dash_length, $dash_space);
}
public function Line($x1, $y1, $x2, $y2)
{
list($x1, $y1) = $this->Rotate($x1, $y1);
list($x2, $y2) = $this->Rotate($x2, $y2);
parent::Line($x1, $y1, $x2, $y2);
}
public function Rectangle($x1, $y1, $x2, $y2)
{
// Rectangle uses Line() so it will be rotated through that call
parent::Rectangle($x1, $y1, $x2, $y2);
}
public function FilledRectangle($x1, $y1, $x2, $y2)
{
if ($y1 == $y2 || $x1 == $x2) {
$this->Line($x1, $y1, $x2, $y2);
} else {
$this->FilledPolygon([$x1, $y1, $x2, $y1, $x2, $y2, $x1, $y2]);
}
}
public function Polygon($pnts, $closed = false, $fast = false)
{
// Polygon uses Line() so it will be rotated through that call unless
// fast drawing routines are used in which case a rotate is needed
if ($fast) {
parent::Polygon($this->ArrRotate($pnts));
} else {
parent::Polygon($pnts, $closed, $fast);
}
}
public function FilledPolygon($pnts)
{
parent::FilledPolygon($this->ArrRotate($pnts));
}
public function Point($x, $y)
{
list($xp, $yp) = $this->Rotate($x, $y);
parent::Point($xp, $yp);
}
public function StrokeText($x, $y, $txt, $dir = 0, $paragraph_align = 'left', $debug = false)
{
list($xp, $yp) = $this->Rotate($x, $y);
return parent::StrokeText($xp, $yp, $txt, $dir, $paragraph_align, $debug);
}
}