#### Howdy, Stranger!

We are about to switch to a new forum software. Until then we have removed the registration on this forum.

# Point on an outer circle intercepted by a line perpendicular to the tangent of an inner circle?

edited March 2014

Basically, I want to find this point (highlighted in blue): Given the coordinates of the centers of both circles and both circles' radii, as well as the coordinates of the point on the inner circle.

The point on the inner circle is already selected randomly as follows:

``````          float a = radians(random(0, 360));
``````

Not sure if that helps at all, but that's what I'm doing.

Tagged:

• Is this applicable? ;-) (just copied this phrase)

??

http://en.wikipedia.org/wiki/Spirograph#Mathematical_basis

• Holy crap what?

• Sorry, just took me a second to digest. It may be... I'll take a look.

• I don't think so.

• It would take me longer to digest this... ;-)

• which of the two is it not? both?

• Since the red line is a tangent to the smaller circle and the green line is perpendicular to it, then if we extend the green line it will pass through the centre of the smaller circle. So now we have two points on the line we need to find the line-circle intersection and there are several algorithms for that. The only other problem is that if we consider the green line to be of infinite length then there will 2 intersections of the outer circle and we have to decide which one to use.

Anyway the sketch below does all that for you - move the mouse round the centre of the smaller circle to see what I mean.

Although lengthy the code should be easy enough to follow and there is no need to understand how the line_circle_p code works - just accept it does what it says on the can. :\">

``````final float ACCY    = 1E-9f;

float cx0, cy0, rad0, ix0, iy0;
float cx1, cy1, rad1, ix1, iy1;
float angle;

public void setup() {
size(400, 400);
// Big circle
cx1 = width/2;
cy1 = height/2;
// Little circle
cx0 = 2.9 * width/4;
cy0 = 2.5 * height/4;
}

public void draw() {
background(255);
// Draw circles
noFill();
stroke(0, 0, 200);
strokeWeight(2);
stroke(200, 0, 200);
angle = atan2(mouseY - cy0, mouseX - cx0);
// Calculate intersection with small circle
ix0 = cx0 + rad0 * cos(angle);
iy0 = cy0 + rad0 * sin(angle);
// Get the 2 possible intersection points on the outer circle
float[] pts = line_circle_p(cx0, cy0, ix0, iy0, cx1, cy1, rad1);
// Now work out which one we want
ix1 = pts;
iy1 = pts;
if ( (ix1-cx0)*(ix0-cx0) + (iy1-cy0)*(iy0-cy0) < 0) {
ix1 = pts;
iy1 = pts;
}
// Draw the line linking the points
stroke(200, 0, 0);
strokeWeight(2);
line(cx0, cy0, ix1, iy1);
// draw intersection on outer circle
noStroke();
fill(255, 0, 0, 96);
ellipse(ix1, iy1, 16, 16);
}

/**
* Calculate the points of intersection between a line and the
* circumference of a circle.
* [x0, y0] - [x1, y1] the line end coordinates
* [cx, cy] the centre of the circle
* r the radius of the circle
*
* An array is returned that contains the intersection points in x, y order.
* If the returned array is of length:
* 0 then there is no intersection
* 2 there is just one intersection (the line is a tangent to the circle)
* 4 there are two intersections
*/
public float[] line_circle_p(float x0, float y0, float x1, float y1, float cx, float cy, float r) {
float[] result = null;
float f = (x1 - x0);
float g = (y1 - y0);
float fSQ = f*f;
float gSQ = g*g;
float fgSQ = fSQ + gSQ;

float xc0 = cx - x0;
float yc0 = cy - y0;

float fygx = f*yc0 - g*xc0;
float root = r*r*fgSQ - fygx*fygx;
if (root > -ACCY) {
float[] temp = null;
int np = 0;
float fxgy = f*xc0 + g*yc0;
if (root < ACCY) {    // tangent so just one point
float t = fxgy / fgSQ;
temp = new float[] {
x0 + f*t, y0 + g*t
};
np = 2;
}
else {  // possibly two intersections
temp = new float;
root = sqrt(root);
float t = (fxgy - root)/fgSQ;
//     if (t >= 0 && t <= 1) {
temp[np++] = x0 + f*t;
temp[np++] = y0 + g*t;
t = (fxgy + root)/fgSQ;
temp[np++] = x0 + f*t;
temp[np++] = y0 + g*t;
}
if (temp != null) {
result = new float[np];
System.arraycopy(temp, 0, result, 0, np);
}
}
return (result == null) ? new float : result;
}
``````
• Thank you! This is perfect!