Reputation: 3080
I have a program that generates an image.
It places x
images around a circle with x
circumference.
See below output of the current implementation.
I need all of the rectangles to be inside of the circle and to be evenly placed.
Note that on the image above, the current implementation, some of the rectangles are on the inside and some are on the outside.
I'm unsure what is wrong with my calculation, please see below code for placing the rectangles.
/**
* Draw the points around a circle
* @param $count
* @param $circumference
*/
public function drawWheel($count, $circumference)
{
/**
* The starting angle
*/
$angle = 0;
/**
* The starting step between rectangles
*/
$step = (2 * pi()) / $count;
/**
* The center X of the canvas
*/
$startX = ($this->canvas['width'] / 2);
/**
* The center Y of the canvas
*/
$startY = ($this->canvas['height'] / 2);
for ($i = 0; $i < $count; $i++) {
/**
* Width of rectangle
*/
$width = 85;
/**
* Height of rectangle
*/
$height = 41;
/**
* Rectangle X position
*/
$x = ($startX + ($circumference / 2) * cos($angle)) - $width / 2;
/**
* Rectangle Y position
*/
$y = ($startY + ($circumference / 2) * sin($angle)) - $height / 2;
/**
* Degrees to rotate the rectangle around the circle
*/
$rotateAngle = atan2((($startX - ($width / 2)) - $x), (($startY - ($height)) - $y)) * 180 / pi();
/**
* The rectangle image
*/
$watermark = Image::make(base_path('test.png'));
$watermark->opacity(75);
$watermark->resize($width, $height);
$watermark->rotate($rotateAngle);
$this->image->insert($watermark, 'top-left', ceil($x), ceil($y));
/**
* Increment the angle
*/
$angle += $step;
}
}
The part of the function that makes the calculations is below.
$x = ($startX + ($circumference / 2) * cos($angle)) - $width / 2;
$y = ($startY + ($circumference / 2) * sin($angle)) - $height / 2;
$rotateAngle = atan2((($startX - ($width / 2)) - $x), (($startY - ($height)) - $y)) * 180 / pi();
The rotation point is the center of the rectangle.
Image is rotated using: http://php.net/manual/en/function.imagerotate.php
Circle is drawn using: http://php.net/manual/en/function.imagefilledarc.php
Upvotes: 1
Views: 375
Reputation: 3080
The width/height will be flipped once the rectangle is rotated, this is something I did not factor in.
MBo's answer helped with the main x,y and rotation coordinates.
See amended code below.
for ($i = 0; $i < $count; $i++) {
$width = 85;
$height = 41;
$x = ($startX + (($circumference - $height) / 2) * cos($angle));
$y = ($startY + (($circumference - $height) / 2) * sin($angle));
$rotateAngle = 90 - $angle * 180 / pi();
$watermark = Image::make(base_path('test.png'));
$watermark->opacity(75);
$watermark->resize($width, $height);
$watermark->rotate($rotateAngle);
$this->image->insert($watermark, 'top-left', ceil($x - ($watermark->width() / 2)), ceil($y - ($watermark->height() / 2)));
$this->drawCircle($x, $y, 10);
$this->drawCircle($x, $y, 10);
$angle += $step;
}
Upvotes: 0
Reputation: 80197
These lines are suspicious:
$x = ($startX + ($circumference / 2) * cos($angle)) - $width / 2;
$y = ($startY + ($circumference / 2) * sin($angle)) - $height / 2;
To place rectangle center inside the circle at inner radius, you have to use something like this:
$x = ($startX + (($circumference - $height) / 2) * cos($angle));
$y = ($startY + (($circumference - $height) / 2) * sin($angle));
And rotation angle is simply
$rotateAngle = $angle * 180 / Pi - 90; // probably $angle+90 depending on coordinate system
Rotated watermark has bounding rectangle with dimensions
Fi = rotateAngle * Pi / 80
New_Height = $width * Abs(Sin(Fi)) + $height * Abs(Cos(Fi))
New_Width = $width * Abs(Cos(Fi)) + $height * Abs(Sin(Fi))
Correct $x and $y for right output:
$x = $x - New_Width/2
$y = $y - New_Height/2
Upvotes: 1