Reputation: 361
I was doing one of the examples code from the website p5js.org - https://p5js.org/examples/form-star.html. I understood all the code except the below lines.
function star(x, y, radius1, radius2, npoints) {
let angle = TWO_PI / npoints;
let halfAngle = angle / 2.0;
beginShape();
for (let a = 0; a < TWO_PI; a += angle) {
let sx = x + cos(a) * radius2;
let sy = y + sin(a) * radius2;
vertex(sx, sy);
sx = x + cos(a + halfAngle) * radius1;
sy = y + sin(a + halfAngle) * radius1;
vertex(sx, sy);
}
endShape(CLOSE);
}
What is the concept of taking two angles . I understand that this is using polar coordinates to cartesian coordinates mapping. But I am not able to visualize this in head that how this computation works. How the author come up with this logic in the code ?
Upvotes: 3
Views: 1415
Reputation: 3207
The author is drawing lines. To do so, they need 2 points.
To get the coordinates of these points, they "imagine" a circle because if the star is regular, every point should be at the same distance from the middle (hence drawing an imaginary circle around the middle point of the star). Like this:
Now, a circle is 360 degrees, or, in radians, 2 * PI. Like this:
Note that: zero radians is on the right. If you read counter clockwise, you get to 1/2 PI when you're on "top" of the circle, 1 * PI when you're on the left, 1,5 * PI on the bottom and 2 * PI once back on the right side.
By dividing the circle by the amount of points the star has, the author can now use trigonometry to get the coordinates they need to draw the star:
That's the idea. Have fun!
Upvotes: 4
Reputation: 51857
My answer is simply an additonal visual explanation over laancelot's excellent answer(+1):
Have a look at this diagram:
You're probably used to the cartesian coordinates system, where the X axis is the horizontal axis and Y is the vertial axis perpendicular on it, both centering at 0,0.
There's another way to look at the same x,y cartesian location from another point of view.
Imagine line from the centre to a point x,y without the square grid.
If the point was on a clock you could describe that point using the time where let's say the hour points to x,y (is angle towards it) and the clock handle is the distance to x,y.
That's an illustration of viewing the same coordinates in the polar coordinate system, where the coordinates are not x,y but angle and radius (distance from centre to x,y).
On the diagram you can see AB as the point from centre to the cursor. Recall the old trigonometry mnemonic: SOH-CAH-TOA (sin = opposite / hypothenuse, cos = adjacent / hypothenuse).
If we know the angle and radius of a point, we can solve for x,y.
sin(angle) = BC (y) / AB (radius)
which is the same as
sin(angle) / 1 = y / radius
from which we can extract:
y = sin(angle) * radius
and similarly
cos(angle) = AC (x) / AB (radius)
which is the same as
cos(angle) / 1 = x / radius
from which we can extract:
x = cos(angle) * radius
hence the polar(angle, radius) to cartesian(x,y) conversion formula:
x = cos(angle) * radius
y = sin(angle) * radius
Bonus points: now you visually get how the dist() function works under the hood.
It's simpy using Pythagoras theorem to solve for the hypothenuse of the right angle triangle formed by the centre and mouse location.
AC = mouseX - centerX
BC = mouseY - centerY
dist = sqrt( (AB * AB) + (BC * BC) )
You can actually play with the illustration here:
let showCartesian = true;
let showPolar = true;
let explanation = "cos(angle) = AC (x) / AB (radius)\n" +
"cos(angle) / 1 = x / radius\n" +
"x = cos(angle) * radius\n\n" +
"sin(angle) = BC (y) / AB (radius)\n" +
"sin(angle) / 1 = y / radius\n" +
"y = sin(angle) * radius\n\n";
function setup() {
createCanvas(600, 600);
}
function draw() {
background(255);
if(showCartesian) drawCartesianGrid(20,20,30);
if(showPolar) drawPolarGrid(300, 300, 30);
stroke(0);
// instructions
text("press 'c' to toggle cartesian grid\n" +
"press 'p' to toggle polar grid\n\n" + explanation, 10, 15);
stroke(0);
// center
let cx = width * 0.5;
let cy = height * 0.5;
// mouse
let x = mouseX;
let y = mouseY;
// cartesian to polar conversion (e.g. x,y to angle, radius )
let angle = atan2(y - cy, x - cx);
let radius = dist(cx, cy, x, y);
// polar to cartesian conversion
let px = cos(angle) * radius;
let py = sin(angle) * radius;
// visualise triangle
strokeWeight(3);
line(cx, cy, x, y);
strokeWeight(1);
line(cx, cy, x, cx);
line(x, cy, x, y);
text("x = " + nfc(x, 0) + ", y = " + nfc(y, 0), x, y - 12);
// visualise angle
noFill();
arc(cx, cy, radius * 0.25, radius * 0.25, angle < 0 ? angle : 0, angle < 0 ? 0 : angle);
text("angle: " + nfc(degrees(angle),2), cx + 12, cy - 12);
// visualise radius / hypothenuse / AB
push();
translate(cx, cy);
rotate(angle);
text("radius / AB / hypo.: " + nfc(radius, 2), radius * 0.25, -12);
pop();
// triangle corner labels
text("A", cx - 12, cy);
text("B", x + 12, y);
text("C", x + 12, cy);
// visualise cartesian coordinate point (offset from centre = same as x,y)
stroke(0,192,0);
ellipse(cx + px, cy + py, 30, 30);
}
function drawCartesianGrid(segsW, segsH, spacing){
stroke(198);
for(let y = 0; y < segsH; y++){
for(let x = 0; x < segsW; x++){
line(x * spacing, y * spacing,
(x+1) * spacing, y * spacing);
line(x * spacing, y * spacing,
x * spacing, (y+1) * spacing);
}
}
}
function drawPolarGrid(x,y,spacing){
let count = width / spacing;
let cx = width * 0.5;
let cy = height * 0.5;
stroke(192);
for(let i = 1 ; i <= count; i++){
ellipse(x, y, (spacing * 2) * i);
}
stroke(127);
line(cx, 0, cx, height);
line(0, cy, width, cy);
line(0, 0, width, height);
line(0, height, width, 0);
}
function keyPressed(){
if(key == 'c'){
showCartesian = !showCartesian;
}
if(key == 'p'){
showPolar = !showPolar;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.0.0/p5.min.js"></script>
(Note as opposed to math class where the cartesian system origin is at the centre with Y axis positive upwards, in p5.js 0,0 is top left with y increasing downwards. Similarly, mind the angle which is from -180 (-PI) to 180 (PI), with pointing right, as opposed to 0, 360 (0 - TWO_PI) range)
For fun you can comment out vertices being drawn in the star()
function to get a feel for which point is which, how does the angle
/halfAngle
change as well as radius1
, radius2
For the hardcore thorough examination you can use the JS Debugger to put a breakpoint at each vertex(sx, sy);
and see how the angle/halfAngle
change.
Upvotes: 4