Centre and radius of a circle passing through 3 points in a plane: Difference between revisions

(14 intermediate revisions by 9 users not shown)
Line 1:
{{draft task}}
Write a function which returns the centre and radius of a circle passing through three point in a plane. Demonstrate the function using the points (22.83,2.07) (14.39,30.24) and (33.65,17.31)
 
 
 
 
 
 
 
=={{header|ALGOL 68}}==
Follows the lines of the C++ code [https://www.geeksforgeeks.org/equation-of-circle-when-three-points-on-the-circle-are-given/ at geeksforgeeks.org].
<syntaxhighlight lang="algol68">
BEGIN # find the centre and radius of a circle through 3 points #
# follows the lines of the C++ code at #
# https://www.geeksforgeeks.org/equation-of-circle-when-three-points-on-the-circle-are-given/ #
 
MODE POINT = STRUCT( REAL x, y );
MODE CIRCLE = STRUCT( POINT centre, REAL radius );
 
# returns the circle that passes through p1, p2 and p3 #
PROC find circle = ( POINT p1, p2, p3 )CIRCLE:
BEGIN
REAL x1 = x OF p1, y1 = y OF p1, x2 = x OF p2, y2 = y OF p2, x3 = x OF p3, y3 = y OF p3;
REAL x12 = x1 - x2
, x13 = x1 - x3
, y12 = y1 - y2
, y13 = y1 - y3
, y31 = y3 - y1
, y21 = y2 - y1
, x31 = x3 - x1
, x21 = x2 - x1
;
REAL sx13 = x1^2 - x3^2
, sy13 = y1^2 - y3^2
, sx21 = x2^2 - x1^2
, sy21 = y2^2 - y1^2
;
REAL f = ( ( ( sx13 + sy13 ) * x12 )
+ ( ( sx21 + sy21 ) * x13 )
)
/ ( 2 * ( ( y31 * x12 ) - ( y21 * x13 ) ) )
, g = ( ( ( sx13 + sy13 ) * y12 )
+ ( ( sx21 + sy21 ) * y13 )
)
/ ( 2 * ( ( x31 * y12 ) - ( x21 * y13 ) ) )
;
REAL c = - (x1^2) - (y1^2) - ( 2 * g * x1 ) - ( 2 * f * y1 );
( ( -g, -f ), sqrt( g^2 + f^2 - c ) )
END # find circle # ;
 
CIRCLE c = find circle( ( 22.83, 2.07 ), ( 14.39, 30.24 ), ( 33.65, 17.31 ) );
 
print( ( "Centre = ( ", fixed( x OF centre OF c, -10, 6 ) ) );
print( ( ", ", fixed( y OF centre OF c, -10, 6 ) ) );
print( ( " ), Radius = ", fixed( radius OF c, -10, 6 ), newline ) )
 
END
</syntaxhighlight>
{{out}}
<pre>
Centre = ( 18.978516, 16.265411 ), Radius = 14.708624
</pre>
 
=={{header|BASIC}}==
Line 166 ⟶ 227:
 
==={{header|Yabasic}}===
{{incorrect|Ybasic|Radius appears to be wildly inaccurate}}
{{trans|FreeBASIC}}
<syntaxhighlight lang="qbasic">findCircle(22.83, 2.07, 14.39, 30.24, 33.65, 17.31)
Line 192 ⟶ 252:
h = -g
k = -f
r = SQRSQRT(h * h + k * k - c)
 
PRINT "Centre is at (", h, ", ", k, ")"
Line 198 ⟶ 258:
PRINT
PRINT "Check radius as the distance between the centre and the first point:"
PRINT SQRSQRT((22.83 - h) ^ 2 + (2.07 - k) ^ 2)
END SUB</syntaxhighlight>
{{out}}
<pre>Centre is at (18.9785, 16.2654)
Radius is 4680414.67086
 
Check radius as the distance between the centre and the first point:
4680414.67086</pre>
 
=={{header|C++}}==
Line 286 ⟶ 346:
}</syntaxhighlight>
{{out}}
<pre>Centre is at (18.978515660148815, 16.265410797715866)</pre>
 
Check radius as the distance between the centre and the first point: 14.70862397833418</pre>
 
=={{header|EasyLang}}==
{{trans|Wren}}
<syntaxhighlight>
proc circ x1 y1 x2 y2 x3 y3 . cx cy cr .
x12 = x1 - x2
x13 = x1 - x3
y12 = y1 - y2
y13 = y1 - y3
y31 = y3 - y1
y21 = y2 - y1
x31 = x3 - x1
x21 = x2 - x1
sx13 = x1 * x1 - x3 * x3
sy13 = y1 * y1 - y3 * y3
sx21 = x2 * x2 - x1 * x1
sy21 = y2 * y2 - y1 * y1
f = (sx13 * x12 + sy13 * x12 + sx21 * x13 + sy21 * x13) / (y31 * x12 - y21 * x13) / 2
g = (sx13 * y12 + sy13 * y12 + sx21 * y13 + sy21 * y13) / (x31 * y12 - x21 * y13) / 2
c = -x1 * x1 - y1 * y1 - 2 * g * x1 - 2 * f * y1
cx = -g
cy = -f
cr = sqrt (cx * cx + cy * cy - c)
.
circ 22.83 2.07 14.39 30.24 33.65 17.31 cx cy cr
print "Centre: (" & cx & ", " & cy & ") Radius: " & cr
</syntaxhighlight>
 
{{out}}
<pre>
Centre: (18.98, 16.27) Radius: 14.71
</pre>
 
=={{header|F_Sharp|F#}}==
{{incorrect|F_Sharp|Radius is off by a factor of 1/2}}
<syntaxhighlight lang="fsharp">
// Centre and radius of a circle passing through 3 points in a plane. Nigel Galloway: February 20th., 2024
let c (a,b) (c,d) (e,f)=(0.5*((a*a+b*b)*(f-d)+(c*c+d*d)*(b-f)+(e*e+f*f)*(d-b))/(a*(f-d)+c*(b-f)+e*(d-b)),
0.5*((a*a+b*b)*(e-c)+(c*c+d*d)*(a-e)+(e*e+f*f)*(c-a))/(b*(e-c)+d*(a-e)+f*(c-a)))
let d n g = let n,g=fst n-fst g,snd n-snd g in sqrt(n*n+g*g)/2.0
let circ P1 P2 P3 = let c=c P1 P2 P3 in (c,d c P1)
 
Line 302 ⟶ 395:
{{out}}
<pre>
Centre = (18.97851566, 16.2654108), radius = 714.354312708624
</pre>
 
Line 346 ⟶ 439:
Check radius as the distance between the centre and the first point:
14.70862397833418</pre>
 
=={{header|jq}}==
'''Adapted from [[#Julia|Julia]]'''
 
'''Works with jq, the C implementation of jq'''
 
'''Works with gojq, the Go implementation of jq'''
<syntaxhighlight lang="jq">
# Emit {x,y,r} corresponding to the circle through the three points
# specified as [x,y] pairs.
def findcircle($p1; $p2; $p3):
 
def assertEq($p; $q): if ($p - $q)|length < 1e-12 then . else "assertion failed: \($p) != \($q)" | error end;
 
def ss($a; $b) : ($a|.*.) + ($b|.*.);
$p1 as [$a,$b]
| $p2 as [$c,$d]
| $p3 as [$e,$f]
 
| ($a - $e) as $ae
| ($d - $b) as $db
| ($b - $f) as $bf
| ($e - $c) as $ec
| ($c - $a) as $ca
| ($f - $d) as $fd
 
| ss($a; $b) as $a2b2
| ss($c; $d) as $c2d2
| ss($e; $f) as $e2f2
 
| {x: (0.5 * ($a2b2 * $fd + $c2d2 * $bf + $e2f2 * $db) / ($a * $fd + $c * $bf + $e * $db)),
y: (0.5 * ($a2b2 * $ec + $c2d2 * $ae + $e2f2 * $ca) / ($b * $ec + $d * $ae + $f * $ca)) }
# any one of these should do / be nearly identical:
| [ss(.x-$a; .y-$b), ss(.x-$c; .y-$d), ss(.x-$e; .y-$f)] as $r123
| assertEq( $r123|max; $r123|min )
| .r = (($r123 | add) / 3 | sqrt) ;
 
findcircle( [22.83, 2.07]; [14.39, 30.24]; [33.65, 17.31])
| "Centre = \([.x, .y]), radius = \(.r)"
</syntaxhighlight>
{{output}}
<pre>
Centre = [18.978515660148815,16.26541079771587], radius = 14.708623978334177
</pre>
 
=={{header|Julia}}==
Line 375 ⟶ 513:
</syntaxhighlight>{{out}}
<pre>Centre = (18.978515660148815, 16.26541079771587), radius = 14.708623978334177</pre>
 
=={{header|Kotlin}}==
<syntaxhighlight lang="kotlin">
import kotlin.math.sqrt
 
data class Point(val x: Double, val y: Double)
 
fun findCircle(p1: Point, p2: Point, p3: Point): Pair<Point, Double> {
fun sq(x: Double) = x * x
val centreX =
0.5 * (
(sq(p1.x) + sq(p1.y)) * (p3.y - p2.y) +
(sq(p2.x) + sq(p2.y)) * (p1.y - p3.y) +
(sq(p3.x) + sq(p3.y)) * (p2.y - p1.y)
) / (
p1.x * (p3.y - p2.y) +
p2.x * (p1.y - p3.y) +
p3.x * (p2.y - p1.y)
)
val centreY =
0.5 * (
(sq(p1.x) + sq(p1.y)) * (p3.x - p2.x) +
(sq(p2.x) + sq(p2.y)) * (p1.x - p3.x) +
(sq(p3.x) + sq(p3.y)) * (p2.x - p1.x)
) / (
p1.y * (p3.x - p2.x) +
p2.y * (p1.x - p3.x) +
p3.y * (p2.x - p1.x)
)
val centre = Point(centreX, centreY)
val radius = sqrt(sq(centreX - p1.x) + sq(centreY - p1.y))
return Pair(centre, radius)
}
 
fun main() {
findCircle(Point(22.83,2.07), Point(14.39,30.24), Point(33.65,17.31))
.let { (c, r) ->
println("Centre = $c")
println("Radius = $r")
}
}
</syntaxhighlight>
 
{{out}}
<pre>
Centre = Point(x=18.978515660148815, y=16.26541079771587)
Radius = 14.70862397833418
</pre>
 
=={{header|Phix}}==
Line 407 ⟶ 593:
=={{header|Raku}}==
Don't bother defining all the intermediate variables.
<syntaxhighlight lang="raku" line>sub circle( (\x𝒳ᵢ, \y𝒴ᵢ), (\X𝒳ⱼ, \Y𝒴ⱼ), (\Х𝒳ₖ, \У𝒴ₖ) ) {
:center(
my $cx𝒞ₓ = ((x𝒳ᵢ² + y𝒴ᵢ²) × (У𝒴ₖ - Y𝒴ⱼ) + (X𝒳ⱼ² + Y𝒴ⱼ²) × (y𝒴ᵢ - У𝒴ₖ) + (Х𝒳ₖ² + У𝒴ₖ²) × (Y𝒴ⱼ - y𝒴ᵢ)) /
(x𝒳ᵢ × (У𝒴ₖ - Y𝒴ⱼ) + X𝒳ⱼ × (y𝒴ᵢ - У𝒴ₖ) + Х𝒳ₖ × (Y𝒴ⱼ - y𝒴ᵢ)) / 2,
my $cy𝒞ᵧ = ((x𝒳ᵢ² + y𝒴ᵢ²) × (Х𝒳ₖ - X𝒳ⱼ) + (X𝒳ⱼ² + Y𝒴ⱼ²) × (x𝒳ᵢ - Х𝒳ₖ) + (Х𝒳ₖ² + У𝒴ₖ²) × (X𝒳ⱼ - x𝒳ᵢ)) /
(y𝒴ᵢ × (Х𝒳ₖ - X𝒳ⱼ) + Y𝒴ⱼ × (x𝒳ᵢ - Х𝒳ₖ) + У𝒴ₖ × (X𝒳ⱼ - x𝒳ᵢ)) / 2
),
radius => (($cx𝒞ₓ - x𝒳ᵢ)² + ($cy𝒞ᵧ - y𝒴ᵢ)²).sqrt
}
 
Line 421 ⟶ 607:
{{out}}
<pre>(center => (18.97851566 16.2654108) radius => 14.70862397833418)</pre>
 
You may [https://ato.pxeger.com/run?1=jZO9TsMwFIUHtjzFHRhs4ZrGLrSAypOwhBCkih8JJxkqxJJHACkMCFQhEHPrdutU3oKtfQIeATv1T6UqKJ6ur3x8vntkv3yI6CofjT7z7LLV-9khaX4O8UDE1wkCdPb7-iiXs3cCupqqChPTXY3npqsq3y1K2y1KDBjuA1DrOE5us0SgaqPXzRB21am3VfEEfUDI-CwmsAfGaTHB8P0MyFwGLbBm6gwyCE5Q1V6g9FagOaygKL1A1xsO47kR6CEx7DtUvyxlPZahqscwFPW2wMhWSMvZV4OQpKORzUKSjk42C0k6Wvl_SNONkLax7Ny1GDbaWltglTFeRyWii0GeQv9UReQelT9fDYNckD5tNRlN70QWPARBGg3NqwfEGO1xwmi7q5912KH8iPA2ZR295ZweHpCwS3mIT9afxvwd-4f-AA Attempt This Online!]
=={{header|Swift}}==
<syntaxhighlight lang="swift">
import Foundation
import Matrix
 
extension Matrix where Element: SignedNumeric {
func minor(row: Int, column: Int) -> Element {
var submatrix = self
_ = submatrix.remove(rowAt: row - 1)
_ = submatrix.remove(columnAt: column - 1)
return submatrix.determinant as Element
}
}
 
enum MatrixErrors: Error {
case notEnoughPoints, tooManyPoints, pointsOnALine, miscError
}
 
func circleFrom3Points(points: (Double,Double)... ) throws -> (Double,Double,Double){
var pointArray: [[Double]] = [[0,0,0,0]]
for p in points {
pointArray.append([pow(p.0, 2) + pow(p.1, 2), p.0, p.1, 1])
}
guard pointArray.count > 3 else { throw MatrixErrors.notEnoughPoints }
guard pointArray.count < 5 else { throw MatrixErrors.tooManyPoints }
var matrix = Matrix(elements:pointArray)
var m11 = matrix.minor(row: 1, column: 1)
guard m11 != 0 else { throw MatrixErrors.pointsOnALine }
var m12 = matrix.minor(row: 1, column: 2)
var m13 = matrix.minor(row: 1, column: 3)
 
let x = 0.5 * m12 / m11
let y = -0.5 * m13 / m11
let r = (pow(x - pointArray[1][1],2) + pow(y - pointArray[1][2],2)).squareRoot()
return (x,y,r)
}
 
do {
let (x,y,r) = try circleFrom3Points(points: (22.83,2.07), (14.39,30.24), (33.65,17.31))
print("x:\(x), y:\(y), r: \(r)")
} catch {
debugPrint(error)
exit(1)
}
</syntaxhighlight>
<pre>
x:18.978515660148812, y:16.265410797715873, r: 14.708623978334185
</pre>
 
=={{header|Wren}}==
2,442

edits