> show canvas only <


/* built with Studio Sketchpad: 
 *   https://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   https://studio.sketchpad.cc/sp/pad/view/ro.iol3AoQzf9Y/rev.5
 * 
 * authors: 
 *   GoToLoop

 * license (unless otherwise specified): 
 *   creative commons attribution-share alike 3.0 license.
 *   https://creativecommons.org/licenses/by-sa/3.0/ 
 */ 



/**
 Line vs Circle Intersection
 by KarlHungus (2013/Apr)
 
 http://forum.processing.org/topic/if-touched-send-once
 
 */

int circleX, circleY, circleR;
int lineX, lineY;

boolean isIntersecting;

final static String GFX = P2D; // Use JAVA2D for Processing 2+

void setup() {
  size(600, 400, GFX);
  noLoop();  // turn off draw()!;
  smooth();
  ellipseMode(RADIUS);
  strokeWeight(2);

  circleX = width  >> 1;
  circleY = height >> 1;
  circleR = height >> 2;

  lineX = width  - width/8;
  lineY = height - height/8;

  mouseX = mouseY = lineX;
}

void mouseMoved() {
  redraw();  // 1 round of draw()!
}

void draw() {
  background(0300);

  if ( checkIntersection(lineX, lineY, mouseX, mouseY, 
  circleX, circleY, circleR) ) {
    if (!isIntersecting)   println("Sending OSC...");
    isIntersecting = true;
  } 
  else {
    if (isIntersecting)    println("Stopped intersecting!");
    isIntersecting = false;
  }

  noStroke();
  fill(isIntersecting? 0 : -1);
  ellipse(circleX, circleY, circleR, circleR);

  stroke(#00FF00);
  line(lineX, lineY, mouseX, mouseY);
}

// Code adapted from Paul Bourke:
// http://local.wasp.uwa.edu.au/~pbourke/geometry/sphereline/raysphere.c

boolean checkIntersection(float x1, float y1, float x2, float y2, 
float cx, float cy, float cr ) {
  float dx = x2 - x1;
  float dy = y2 - y1;

  float a = dx*dx + dy*dy;
  float b = (dx*(x1 - cx) + (y1 - cy)*dy) * 2;
  float c = cx*cx + cy*cy;

  c += x1*x1 + y1*y1;
  c -= (cx*x1 + cy*y1) * 2;
  c -= cr*cr;

  float delta = b*b - 4*a*c;

  if (delta < 0)   return false; // Not intersecting

  delta = sqrt(delta);

  float mu = (-b + delta) / (2*a);
  float ix1 = x1 + mu*dx;
  float iy1 = y1 + mu*dy;

  mu = (b + delta) / (-2*a);
  float ix2 = x1 + mu*dx;
  float iy2 = y1 + mu*dy;

  // Intersection points
  fill(#FF0000);
  ellipse(ix1, iy1, 5, 5);
  ellipse(ix2, iy2, 5, 5);

  // Figure out which point is closer to the circle
  boolean test = dist(x1, y1, cx, cy) < dist(x2, y2, cx, cy);

  float closerX = test? x2:x1;
  float closerY = test? y2:y1;

  return dist(closerX, closerY, ix1, iy1) < dist(x1, y1, x2, y2) || 
    dist(closerX, closerY, ix2, iy2) < dist(x1, y1, x2, y2);
}