Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411283 Posts in 69325 Topics- by 58380 Members - Latest Member: bob1029

March 29, 2024, 07:50:52 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)tangent to a circle from a given point
Pages: [1] 2
Print
Author Topic: tangent to a circle from a given point  (Read 2458 times)
gimymblert
Level 10
*****


The archivest master, leader of all documents


View Profile
« on: November 18, 2016, 04:54:21 PM »



I have been working on this problem for a while and I'm having bogus result for reason I don't know Huh?

Right I'm only trying to get magnitude right, I don't compute the coordinate yet, so the circle is on the origin and the point is on the x axis to simplify. Capital letters define known quantity, lower case denote unknown and derive quantity.

Given a circle C or radius R and a point P at distance D, how to find the p0 where the tangent from P to the circle go through?
Let's define: l the distance between P and p0


It seems like a simple problem, given than the the tangent point have a perpendicular that goes through the center of C it became a simple Pythagora things where:

R² + l² = D²

We know R and D but not l so we can turn it into

D² - R² = l²

We can further:
let's break the triangle C,P,P0 into two right angle triangle such as there is point T where the perpendicular to D through P0 intersect D, let's call the segment between T and P0, h. Let's call segment P,T and T,C respectively b and a. such as a+b = d.

Since we are axis align on x and centered on origin, the line D is on the axis such as y=0 (therefore a and b are, and h is parallel to y). Given that finding the tangent coordinate is given by (a,h).

h, a and b are unknown by can be express through pythagora:

h² + b² = l²
h² + a² = R²

we know l relative to R and D

h²+b² = D² - R²

we can express D² in term of a and b

D = a + b
D² = (a+b)²
D² = a² + 2ab + b²

which lead to:

h² + b² = a² + 2ab + b² -R²

let's express h²

h² = a² + 2ab + b² -R² -b² //b² get cancel
h² = a² + 2ab -R²

we can express b in term of b = D-a

h² = a² + 2a(D-a) -R²
h² = a² + 2aD -2a² -R² //a² get cancel
h² = 2aD - a² -R²

we already know h² + a² = R² we can express R:

h² + a² = 2aD -R²
R² = 2aD -R²
2R² = 2aD
R² = aD

we can now express a in term of known term

a = R²/D

Now we can come back to express h² in term of

h² = 2aD - a² -R²
h² = 2(R²/D)D - (R²/D)² - R² //R² and D get cancel
h² = R² - (R^4/D²)

Now we can have express the target coordinate (a,h)  in term of know quantity

(a,h) = (R²/D , sqr (R² - (R^4/D²) ) )

Result



 Lips Sealed

Is there a problem with my reasoning somewhere?
« Last Edit: November 18, 2016, 05:08:48 PM by gimymblert » Logged

valambrian
Level 0
**


View Profile
« Reply #1 on: November 18, 2016, 07:59:35 PM »

The math looks right. What are the numbers (a, h, D, R) related to the last graph?
Logged
gimymblert
Level 10
*****


The archivest master, leader of all documents


View Profile
« Reply #2 on: November 18, 2016, 09:21:42 PM »

The yellow circle is the target circle C of radius R
the red circle is the point P from which I want the tangent
The grey circle is supposed to be the tangent point p0 on C with x = a, and y = h
The line between both circle center is D

For the algorithm defense, it make sure the fake tangent never cross the circle  Lips Sealed does not help though
Logged

Dacke
Level 10
*****



View Profile
« Reply #3 on: November 19, 2016, 01:51:33 AM »

I'm too tired to read through your math.

But here is how I would think about it:

1. Check that D ≥ R
Otherwise P is inside the circle and there won't be a tangent

2. Find L (which I saw you did)
L = sqrt(D² - R²)

3. Imagine you have two circles:
C with radius R
P with radius L

Use standard formula to find the points where the two circles intersect.
https://en.wikipedia.org/wiki/Intersection_(Euclidean_geometry)#Two_circles
http://mathworld.wolfram.com/Circle-CircleIntersection.html
http://math.stackexchange.com/questions/256100/how-can-i-find-the-points-at-which-two-circles-intersect
« Last Edit: November 19, 2016, 01:58:37 AM by Dacke » Logged

programming • free software
animal liberation • veganism
anarcho-communism • intersectionality • feminism
gimymblert
Level 10
*****


The archivest master, leader of all documents


View Profile
« Reply #4 on: November 19, 2016, 07:51:10 AM »

I looked at it but I can't remeber what x and y are and why they are similar in the 2 circle equation.
I'm thinking (x1,y1) are the center coordinate, therefore (x,y) must the be origin right? which game us the segment [x,x1] and [x,x2] being the right angled side of the triangle and r the hypothenuse, hence why the equation of a circle is x²+y² = r², but that does not translate if x = y = 0, ,i'm clearly missing something here Sad
Logged

Glyph
Level 10
*****


Relax! It's all a dream! It HAS to be!


View Profile
« Reply #5 on: November 19, 2016, 08:49:58 AM »

x and y should not be substituted with your center coordinates, they are the variables that you plot the circle with in the usual way by finding all solutions to the equation. The full equation for a circle is (x-h)^2 + (y-k)^2 = r^2, where (h,k) denotes the center of your circle.
Logged


gimymblert
Level 10
*****


The archivest master, leader of all documents


View Profile
« Reply #6 on: November 21, 2016, 01:06:23 PM »

So I tried everything, apparently the equation thingy just gave me something I had already tried formerly but with magnitude replace instead of coordinate, or else I get stuck in equation wolfram alpha don't help either ...

I cave in and looked at programming code to copy:
http://csharphelper.com/blog/2014/09/determine-where-two-circles-intersect-in-c/

STILL DON'T WORK  Screamy Tired

Though bug are different now ...
Logged

Dacke
Level 10
*****



View Profile
« Reply #7 on: November 21, 2016, 01:15:09 PM »

If the math is correct, then maybe there is some coding error you're missing? Have you done standard debugging? Maybe step/trace through the code using a simple example that someone else has done by hand. That way you can see where it goes wrong.
Logged

programming • free software
animal liberation • veganism
anarcho-communism • intersectionality • feminism
gimymblert
Level 10
*****


The archivest master, leader of all documents


View Profile
« Reply #8 on: November 21, 2016, 01:22:40 PM »

Have been doing that for one week, but the bug I fixed didn't significantly fixed the problem
I had mostly a problem of doubling data for no reason, which was due to how circle are computed (they are generated inside a rect in the form of x,y width,height, radius was diameter (height and width) but apparently I didn't have to divide by 2 for some reason Huh? )


Code:
Graphics3D 1000,600,0,2
SetBuffer BackBuffer()

Const offsetx = -350

Origin offsetx+GraphicsWidth()/2, GraphicsHeight()/2

;planet visibility
;- surface limit (min height or Radius)
;- max height (+radius)
;- max atmosphere (+radius)


radius# = 90
maxheight# = 20
atmosphere# = 40

planetx# = 0
planety# = 0; 100

;distance = 0 ;radius + distance to surface
shipx# = 200
shipy# =0; -50

;-------------------------------------------
cam = CreateCamera ()
PositionEntity cam, 0,0,-25

l1 = CreateLight (1)
RotateEntity l1, 45,45,0

;center = CreateSphere (3)
;PositionEntity center, 0,0,0
;ScaleEntity center, 5,5,5
;EntityColor center, 255,0,0
;-------------------------------------------

While Not KeyDown(1)

;refresh
UpdateWorld 1
RenderWorld 1

shipx = -offsetx+ MouseX()-GraphicsWidth()/2

;axis
Color 255,0,0:Line 0,-GraphicsHeight(),0, GraphicsHeight()
Color 0,255,0:Line -GraphicsWidth(),0,GraphicsWidth(),0

;cursor guide
;Color 255,255,255:Line 125,-GraphicsHeight(),125, GraphicsHeight()
;Color 255,255,255:Line -GraphicsWidth(),0,GraphicsWidth(),0

;ship position
Color 255,0,0: circle (shipx,shipy, 10)

;planet position
Color 255,255,0: circle(planetx, planety, radius*2)

;planet/ship distance
Color 128,128,128: Line shipx, shipy,  planetx, planety

;data
psx = planetx - shipx
psy = planety - shipy

dist# = magnitude(psx, psy)

r2# = radius^2
d2# = dist^2

a =  (r2)/dist
h =  Sqr(r2 - ((r2*r2)/(dist^2)) )

ix2 = shipx + a * psx /dist
iy2 = shipy + a * psy /dist

circle (ix2 ,iy2 ,20)

itx2 = (ix2 - h * psy) /dist
ity2 = (iy2 + h * psx) /dist

itx1 = ix2 + h * psy /dist
ity1 = iy2 - h * psx /dist




;tangent vis
circle (itx2, ity2,20)
circle (itx1, ity1,20)

Line shipx, shipy, a,h
Line shipx, shipy, a,-h
Line planetx, planety, a, -h
Line planetx, planety, a, h


;distance circle
circle (shipx, shipy, dist*2)

;mid distance circle (tangent intersect?)
Color 0,255,255: circle( (planetx+shipx)*.5, (planety+shipy)*.5,magnitude((shipx-planetx), (shipy-planety)))

Text 0,0, a;hg;(planety+shipy)*0.5;ht;magnitude(shipx-planetx, shipy-planety)


VWait:Flip False
Wend
ClearWorld


;-------------------------------------------
Function magnitude#(x#,y#)
Return Sqr ((x^2) + (y^2))
End Function

Function normalizeX#(x#,y#)
Return x/magnitude(x,y)
End Function

Function normalizeY#(x#,y#)
Return y/magnitude(x,y)
End Function

Function Circle(x#,y#, radius#)
Oval x-radius*0.5, y-radius*0.5,  radius,radius,0
Plot x,y
End Function

Function powerof2step(x)
;which step you are on : int 1 =
Return Floor (Log (x)/Log(2) )
;height of that step, float h = pow(2,i)
End Function
Logged

Dacke
Level 10
*****



View Profile
« Reply #9 on: November 21, 2016, 01:27:13 PM »

what... what's that language? :S
Blitz something?
Logged

programming • free software
animal liberation • veganism
anarcho-communism • intersectionality • feminism
oahda
Level 10
*****



View Profile
« Reply #10 on: November 21, 2016, 01:54:33 PM »

good ol blitzbasic
Logged

Dacke
Level 10
*****



View Profile
« Reply #11 on: November 21, 2016, 02:56:41 PM »

so.. uh.. blitzbasic code. Do you have debug tools? Can you write tests? Do you generally know how to debug code that does math?

Logged

programming • free software
animal liberation • veganism
anarcho-communism • intersectionality • feminism
gimymblert
Level 10
*****


The archivest master, leader of all documents


View Profile
« Reply #12 on: November 21, 2016, 03:13:09 PM »

I know nothing about writing test though.

We have debug tools we can step line by line and look at all the variables, but I'm using visual confirmation instead, my current theory is the variable "a" is fuck somewhere, it work on axis align, it's also curved so it might be tied to positioning, so I'm back at looking at coordinate computaion (in case if it's x1-x2 instead of x2-x1), that's my current hypothesis (after a nap break)
Logged

gimymblert
Level 10
*****


The archivest master, leader of all documents


View Profile
« Reply #13 on: November 21, 2016, 03:43:47 PM »

I solved the problem by blinding shifting stuff along the intuition above ... now I need to make it worked with, maximum height (the tangent find the intersecting outgoing point), atmosphere, then in 3D >.< (note 3d would work the same for the radius shenanigan, I need to figure out the 3D position, I think it can be inferred from teh 2D model anyway)
« Last Edit: November 21, 2016, 03:51:19 PM by gimymblert » Logged

J-Snake
Level 10
*****


A fool with a tool is still a fool.


View Profile WWW
« Reply #14 on: November 23, 2016, 04:45:32 PM »

Let me put an end to your misery:

Since (D, R, L) is a right triangle, P_0 is exactly on a circle which is uniquely defined
having D as a diagonal. Therefore P_0 is the point of intersection of the two circles:

One-liner in C#:

var P0 = Util.Math.IntersectCircleCircle(new Circle(center of D, D/2), new Circle(C, R));
Logged

Independent game developer with an elaborate focus on interesting gameplay, rewarding depth of play and technical quality.<br /><br />Trap Them: http://store.steampowered.com/app/375930
gimymblert
Level 10
*****


The archivest master, leader of all documents


View Profile
« Reply #15 on: November 23, 2016, 10:59:53 PM »

It's not c#
But thanks I will port it to c# later! blitz is for dirty quick prototype without polluting production code

EDIT: I can't find the reference on c#'s doc, do you have a link?

edit2: that's not c# that's JAVA!
https://joml-ci.github.io/JOML/apidocs/org/joml/Intersectionf.html
« Last Edit: November 23, 2016, 11:05:33 PM by gimymblert » Logged

J-Snake
Level 10
*****


A fool with a tool is still a fool.


View Profile WWW
« Reply #16 on: November 24, 2016, 03:34:16 PM »

It's in-house C#-code to give you an idea how it can look like. I assume you know how to determine the collision point/s of two circles (if not, get familiar with math concepts first). If you program your library intelligently, you will store the radius as a vector.
Logged

Independent game developer with an elaborate focus on interesting gameplay, rewarding depth of play and technical quality.<br /><br />Trap Them: http://store.steampowered.com/app/375930
gimymblert
Level 10
*****


The archivest master, leader of all documents


View Profile
« Reply #17 on: November 24, 2016, 05:32:43 PM »

That's not clever at all Huh?

because the whole point of this thread is to debug this very problem (which I did, it's equivalent) Also vector is just a representation, it's a pair of coordinate, you still have to operate on the coordinate, that does not change anything how I store them. Anyway the radius is a scalar, it's not a vector, you are supposed to derive the vector from the two radius.

ANYWAY Yes it's turned into a function now.

That was disappointing I thought you were onto something ...It's like you read nothing Huh?
Logged

Dacke
Level 10
*****



View Profile
« Reply #18 on: November 25, 2016, 05:35:21 AM »

We have debug tools we can step line by line and look at all the variables, but I'm using visual confirmation instead

I think this may be your main problem. Visual confirmation is great if you quickly want to check is something is obviously wrong. But once you know it's wrong, it's close to useless to keep using visual confirmation, because it doesn't tell you what's wrong.

One thing you can do to debug:
1. Create an easy test example
2. Solve it by hand and verify the solution with wolframalpha or something similar
3. Step through the code and check where your hand-calculation differs from your program's calculation

One thing you can do to make it easier to debug:
1. Put the algorithm in a function
2. Break out parts of the algorithm to subfuctions (for example intersect(cirlceA, circleB), distance(pointA, pointB), etc.)
3. Test all the functions independently. If you can verify that distance(pointA, pointB) always works correctly, then you know the problem isn't in that piece of code

To formalize it you can write tests:
1. Take a function you want to test (intersect, distance, findtangent, etc.)
2. Create example problems and solve them (for example by hand, or wolframalpha, or examples you find online)
3. Write a test program that feeds the function with the problem and checks that it returns correct value

Let's say you want to test you function add(a, b), you could to this:

Code:
if (add(1, 2) != 3) {
   print("error: add(1, 2), expected 3, got " + add(1, 2))
}

if (add(-1, 2) != 1) {
   print("error: add(-1, 2), expected 1, got " + add(-1, 2)))
}

if (add(-1, -1) != -2) {
   print("error: add(-1, -1), expected -2, got " + add(-1, -1)))
}

So you write a question and an answer by hand and the program then checks if it works. Many languages have libraries that help you do this more automatically, but you can write it by hand like that or write your own helper functions. Then whenever you change something, you can run the program and check if it works now or if something else has stopped working.

This isn't always useful, but it can save you lots of effort if you find yourself trying to verify things visually (which takes some time and only works with one thing at a time).



haha, wow, J-Snake never ceases to amaze WTF
Logged

programming • free software
animal liberation • veganism
anarcho-communism • intersectionality • feminism
J-Snake
Level 10
*****


A fool with a tool is still a fool.


View Profile WWW
« Reply #19 on: November 25, 2016, 03:46:02 PM »

because the whole point of this thread is to debug this very problem
I assumed the point is to compute P0.

Just ignore the part about storing radius as a vector, as it is most likely going to confuse you. It is just a side note related to performance considerations.
Logged

Independent game developer with an elaborate focus on interesting gameplay, rewarding depth of play and technical quality.<br /><br />Trap Them: http://store.steampowered.com/app/375930
Pages: [1] 2
Print
Jump to:  

Theme orange-lt created by panic