Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
285 views
in Technique[技术] by (71.8m points)

processing - What is the math behind creation of a star in p5js

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 ?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

My answer is simply an additonal visual explanation over laancelot's excellent answer(+1):

Have a look at this diagram:

polar-cartesian coordinate conversion

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)
" +
                  "cos(angle) / 1 = x / radius
" + 
                  "x = cos(angle) * radius

" + 
                  "sin(angle) = BC (y) / AB (radius)
" + 
                  "sin(angle) / 1 = y / radius
" +
                  "y = sin(angle) * radius

";
                  
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
" + 
       "press 'p' to toggle polar grid

" + 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>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...