1

I have a simple sketch with circle and a rotating arm, rotating clockwise from the center of the circle. In the sketch there are two smaller ellipses to the left of the center.

I am looking for a way to detect when the rotating arm has collided with the smaller ellipses, because of how it's rotating the arm is going the hit the ellipse closer to the center first. Im having a bit of trouble in fully realising this idea and I'm wondering if anyone has encountered this before?

Here some code to better illustrate my point

hope this makes sense!

let angle;

function setup() {
  createCanvas(400, 400);
  angleMode(RADIANS);
  angle = 0.00;
}

function draw() {
  background(220);
  translate(width / 2, height / 2);
  noFill();
  ellipse(0, 0, 400);

  fill(255, 0, 0, 40);
  ellipse(60, 0, 30);
  ellipse(160, 0, 30);

  stroke(0, 200);
  strokeWeight(3);
  rotate(angle);
  line(0, 0, 0, -200);
  angle += 0.015;
}

function doSomthing() {
  // when arm collides with smaller circles
  // do somthing. 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
Paul Wheeler
  • 18,988
  • 3
  • 28
  • 41
  • 1
    Related [How to calculate intersection point of a line on a circle using p5.js](https://stackoverflow.com/questions/57891494/how-to-calculate-intersection-point-of-a-line-on-a-circle-using-p5-js) – Rabbid76 Nov 05 '21 at 17:24

1 Answers1

2

This question is basically a duplicate, but I just wanted to make sure the solution worked:

const lineLength = 200;
const radius = 15;

let angle;
let lineStart;
let circleOne;
let circleTwo;

function setup() {
  createCanvas(400, 400);
  angleMode(RADIANS);
  ellipseMode(RADIUS);
  
  angle = -PI / 2;
  
  lineStart = createVector(0, 0);
  circleOne = createVector(60, 0);
  circleTwo = createVector(160, 0);
}

function draw() {
  background(220);
  translate(width / 2, height / 2);
  noFill();
  ellipse(0, 0, 400);
  
  let lineEnd = createVector(lineLength * cos(angle), lineLength * sin(angle));

  fill(255, 0, 0, 40);
  push();
  if (getLineCircleIntersections(lineStart, lineEnd, circleOne, radius).length > 0) {
    fill('red');
  }
  ellipse(circleOne.x, circleOne.y, radius);
  pop();
  push();
  if (getLineCircleIntersections(lineStart, lineEnd, circleTwo, radius).length > 0) {
    fill('red');
  }
  ellipse(circleTwo.x, circleTwo.y, radius);
  pop();


  stroke(0, 200);
  push();
  strokeWeight(2);
  rotate(angle);
  line(lineStart.x, lineStart.y, 200, 0);
  pop();
  
  push();
  strokeWeight(6);
  stroke('blue');
  point(lineEnd.x, lineEnd.y);
  pop();
  
  angle += 0.015;
}

function getLineCircleIntersections(p1, p2, cpt, r) {
  let x1 = p1.copy().sub(cpt);
  let x2 = p2.copy().sub(cpt);

  let dv = x2.copy().sub(x1)
  let dr = dv.mag();
  let D = x1.x * x2.y - x2.x * x1.y;

  // evaluate if there is an intersection
  let di = r * r * dr * dr - D * D;
  if (di < 0.0) {
    return [];
  }

  let t = sqrt(di);

  let ip = [];
  ip.push(new p5.Vector(D * dv.y + Math.sign(dv.y) * dv.x * t, -D * dv.x + abs(dv.y) * t).div(dr * dr).add(cpt));
  if (di > 0.0) {
    ip.push(new p5.Vector(D * dv.y - Math.sign(dv.y) * dv.x * t, -D * dv.x - abs(dv.y) * t).div(dr * dr).add(cpt));
  }
  
  push();
  for (let p of ip) {
    stroke('lime');
    strokeWeight(8);
    point(p.x, p.y);
  }
  pop();
  
  return ip.filter(p => p.x >= p1.x && p.x <= p2.x);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>

A few tweaks were required to work with this example, but the getLineCircleIntersections is basically a direct copy of How to calculate intersection point of a line on a circle using p5.js

Paul Wheeler
  • 18,988
  • 3
  • 28
  • 41
  • I did vote to close this. And I marked your comment as helpful. But if you meant I should upvote your original answer which I borrowed code from, you’re absolutely right. Sorry for the oversight. I’ve upvoted that answer. – Paul Wheeler Nov 09 '21 at 16:45
  • This is exactly what I was trying to articulate. Thank you very much! – Offt_madone Nov 10 '21 at 10:59