Equation of circle when three points are given

Game development specific discussions.
Post Reply
Gunslinger
Posts: 115
Joined: Mar 08, 2016 19:10
Location: The Netherlands

Equation of circle when three points are given

Post by Gunslinger »

I was in need of a circle through 3 point in 2d space.
Nothing new so i just got source translated from here.
https://www.geeksforgeeks.org/equation- ... are-given/

Now i was playing with segmented circle and tested workings.
Soon found out the precision is bad when all points are almost inline.
So i used a chat GPT helped me with adding extra checks, not helping..
With the mouse you can move points points 1,2,3 (with buttons 1,2 and 3.)
When all are aligned i can make the program hang/crash.

Any idea why this happens?
How can it hang on calculations? or is it the fb circle function itself?

Any help would be great.

Code: Select all

#Define Pi 3.1415926535897932

type v2dr_double
	as double x, y
	as double r
end type

function calculate_3p_circle(p1 as v2dr_double, p2 as v2dr_double, p3 as v2dr_double) as v2dr_double
	dim as double x12 = p1.x - p2.x
	dim as double x13 = p1.x - p3.x
	dim as double y12 = p1.y - p2.y
	dim as double y13 = p1.y - p3.y
	dim as double y31 = p3.y - p1.y
	dim as double y21 = p2.y - p1.y
	dim as double x31 = p3.x - p1.x
	dim as double x21 = p2.x - p1.x
	
	dim as double sx13 = (p1.x * p1.x) - (p3.x * p3.x)
	dim as double sy13 = (p1.y * p1.y) - (p3.y * p3.y)
	dim as double sx21 = (p2.x * p2.x) - (p1.x * p1.x)
	dim as double sy21 = (p2.y * p2.y) - (p1.y * p1.y)
	
	dim as double denominator_f = 2 * ((y31) * (x12) - (y21) * (x13))
	dim as double denominator_g = 2 * ((x31) * (y12) - (x21) * (y13))
	
	' Check for collinear points (division by zero)
	if abs(denominator_f) < 1e-10 or abs(denominator_g) < 1e-10 then ' Using a small tolerance
		' Handle collinear case (e.g., return an error value)
		return type(0.0, 0.0, -1.0) ' Indicate an error with a negative radius
	end if
	
	dim as double f = ((sx13) * (x12) _
			 + (sy13) * (x12) _
			 + (sx21) * (x13) _
			 + (sy21) * (x13)) _
			/ denominator_f
	
	dim as double g = ((sx13) * (y12) _
			 + (sy13) * (y12) _
			 + (sx21) * (y13) _
			 + (sy21) * (y13)) _
			/ denominator_g
	
	dim as double c = -(p1.x * p1.x) - (p1.y * p1.y) - 2 * g * p1.x - 2 * f * p1.y
	dim as double r = sqr(g * g + f * f - c)
	
	' Handle invalid radius (e.g., return an error value)
	if r < 0 then return type(0.0, 0.0, -1.0)
	
	return type<v2dr_double>(-g, -f, r)
end function

screenres 800, 600, 32
dim as long x, y, b, res 

dim as v2dr_double p1 = type(2, 1.5)
dim as v2dr_double p2 = type(2.5, 4)
dim as v2dr_double p3 = type(5, 3)


window screen(0, 0)-(8, 6) ' Use this resolution
sleep 500
do
	res = GetMouse (x, y, , b)
	if res = 0 then
		if b and 1 then p1.x = PMap(x, 2): p1.y = PMap(y, 3)
		if b and 2 then p3.x = PMap(x, 2): p3.y = PMap(y, 3)
		if b and 4 then p2.x = PMap(x, 2): p2.y = PMap(y, 3)
	end if
	
	var p4 = calculate_3p_circle(p1, p2, p3)
	
	screenlock()
		cls
		locate 1,1
		print p4.x, p4.y, p4.r
		circle (p1.x, p1.y), .2, &hFF0000
		circle (p2.x, p2.y), .2, &h00FF00
		circle (p3.x, p3.y), .2, &h0000FF
		
		if p4.r > 0 then
			dim as double x41 = p4.x-p1.x
			dim as double y41 = p4.y-p1.y
			dim as double x43 = p4.x-p3.x
			dim as double y43 = p4.y-p3.y
			print 
			
			var _start = (atan2(x41, y41)+Pi*2.5): if _start > Pi*2 then _start -= Pi*2
			var _end = (atan2(x43, y43)+Pi*2.5): if _end > Pi*2 then _end -= Pi*2
			print _start, _end
			line (p1.x, p1.y)-(p3.x, p3.y), &h888888,  , &b0000000011110000
			
			circle (p4.x, p4.y), p4.r, &hFFFF00, _start, _end
		end if
	screenunlock()
	
	sleep 10
loop until multikey(&h01) 'escape

sleep
end
Edit: GPT suggest increase the input resolution bij 100 or more, then it is still possible to get hanging.
dafhi
Posts: 1741
Joined: Jun 04, 2005 9:51

Re: Equation of circle when three points are given

Post by dafhi »

i am unable to produce the issue but guess would be the circle .. comment it out, print the radius so u get an idea
Gunslinger
Posts: 115
Joined: Mar 08, 2016 19:10
Location: The Netherlands

Re: Equation of circle when three points are given

Post by Gunslinger »

dafhi wrote: Apr 29, 2025 21:27 i am unable to produce the issue but guess would be the circle .. comment it out, print the radius so u get an idea
good idea, also write my one circle function to be more accurate maybe.
also will test on a other pc tomorrow.
btw i use windows 11 64bit
angros47
Posts: 2415
Joined: Jun 21, 2005 19:04

Re: Equation of circle when three points are given

Post by angros47 »

Gunslinger wrote: Apr 29, 2025 11:08 When all are aligned i can make the program hang/crash.

Any idea why this happens?
Yes: it happens because it's not possible to draw a circle in these conditions.
First of all, let's see how to solve the problem on paper, using just ruler and compass:

https://www.youtube.com/watch?v=P0xEOGNxok8
(sorry if I am showing you something you already know, but it may be useful to others as well)

As you can see, the center of the circle is the point where bisectors cross. And bisectors are perpendicular to segments joining the points (the trick works because every point of the bisector has the same distance from both the points, so the point where both bisectors cross have the same distance from all the three points, and this makes possible to draw the circle)

What happens if the three points are aligned? The two bisectors will be parallels: and parallels never cross, so it's impossible to find the crossing point (and thus it's impossible to construct the circle). Hence, the program won't work (probably it will fail due to a division by zero).

Likely, instead of returning an error, it hangs because it tries to draw a circle with infinite radius or such.
D.J.Peters
Posts: 8642
Joined: May 28, 2005 3:28
Contact:

Re: Equation of circle when three points are given

Post by D.J.Peters »

here are my solution from 1997 :-)
give it a try

Joshy
dodicat
Posts: 8271
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Equation of circle when three points are given

Post by dodicat »

Taken from my post https://www.freebasic.net/forum/viewtop ... ry#p144329
(which amazingly still runs with the latest version of fb 14 + years on)

Code: Select all

Type line2d
    As Double x1,y1,x2,y2 'start and end of lines(x1,y1)-(x2,y2)
End Type

type point2d
    As Double x,y
End Type

type circle
    as double cx
    as double cy
    as double rad
end type

function rotatepoint2d(pivot As point2d,_point as point2d,angle as double) as point2d
      const pi As Double=4*Atn(1) 
    #define rad *pi/180
dim as point2d np
np.x=(Cos(angle rad)*(_point.x-pivot.x)-Sin(angle rad)*(_point.y-pivot.y)) +pivot.x
np.y=(Sin(angle rad)*(_point.x-pivot.x)+Cos(angle rad)*(_point.y-pivot.y)) +pivot.y
return np
End function

'perpendicular bisector of a line
function bisect(L2 as line2d) as line2d
    dim as point2d p1,p2,piv,temp
    dim as line2d L
    piv.x=(L2.x1+L2.x2)/2
    piv.y=(L2.y1+L2.y2)/2
    p1.x=L2.x1:p1.y=L2.y1
    p2.x=L2.x2:p2.y=L2.y2
   temp =rotatepoint2d(piv,p1,90)
   L.x1=temp.x:L.y1=temp.y
   temp =rotatepoint2d(piv,p2,90)
   L.x2=temp.x:L.y2=temp.y
    Return L
end function

'point of intersection of two lines
 function intersect(L1 As line2d,L2 As line2d) As point2d
    Dim As Double M1,M2,C1,C2
    Dim As point2d pt
    M1=(L1.y2-L1.y1)/(L1.x2-L1.x1)
    M2=(L2.y2-L2.y1)/(L2.x2-L2.x1)
    C1=(L1.y1*L1.x2-L1.x1*L1.y2)/(L1.x2-L1.x1)
    C2=(L2.y1*L2.x2-L2.x1*L2.y2)/(L2.x2-L2.x1)
    pt.x=(C2-C1)/(M1-M2)
    pt.y=(M1*C2-M2*C1)/(M1-M2)
    Return pt
End Function

function getcircle(p1 as point2d,p2 as point2d,p3 as point2d) as circle
dim as line2d L1=type(p1.x,p1.y,p2.x,p2.y)
dim as line2d L2=type(p2.x,p2.y,p3.x,p3.y)
dim as line2d b1=bisect(L1)
dim as line2d b2=bisect(L2)
dim as point2d centre=intersect(b1,b2)
dim as double radius=sqr((centre.x-p1.x)^2+(centre.y-p1.y)^2)
return type(centre.x,centre.y,radius)
end function

screen 20
do
dim as point2d a,b,c
a=type(rnd*1025,rnd*768)
b=type(rnd*1025,rnd*768)
c=type(rnd*1025,rnd*768)
circle(a.x,a.y),5
circle(b.x,b.y),5
circle(c.x,c.y),5
dim as circle d=getcircle(a,b,c)
circle (d.cx,d.cy),d.rad
circle (d.cx,d.cy),5,4,,,,f
locate 2
print "press space to refresh, escape to end"
print "centre = ";d.cx,d.cy
print "radius = ";d.rad
sleep
cls
loop until inkey=chr(27)
Gunslinger
Posts: 115
Joined: Mar 08, 2016 19:10
Location: The Netherlands

Re: Equation of circle when three points are given

Post by Gunslinger »

Thank you all for other code examples.

I spend more time to find out what the hang/crash is and it the circle render that freebasic is using that makes it crash.
Sure has to do with the combination of this code

Code: Select all

screenres 800, 600, 32
window screen(0, 0)-(8, 6)
And also use segmented circle, when i draw a full circle outside the screen space i can no make it crash again.

Any way my stolen 3point circle calculation seem fine :)
Just the draw circle function crash is a surprise for me.
Gunslinger
Posts: 115
Joined: Mar 08, 2016 19:10
Location: The Netherlands

Re: Equation of circle when three points are given

Post by Gunslinger »

screenres 1280, 720, 32
window screen(0, 0)-(12.8, 7.2)
circle (0,0),109766.269893732, &HFFFFFF, 1.912081970313402, 1.912003984356504

This make my compiled code crash under 64bit windows 11

I can not test 32bit, then i get
The system cannot execute the specified program.
Must be a problem with 32bit floating point, not compile errors
Post Reply