Circles of given radius through two points: Difference between revisions

→‎Tcl: Added implementation
(→‎{{header|Python}}: Update to handle r==0.0 special case.)
(→‎Tcl: Added implementation)
Line 106:
You can construct the following circles:
ERROR: radius of zero</pre>
 
=={{header|Tcl}}==
{{trans|Python}}
<lang tcl>proc findCircles {p1 p2 r} {
lassign $p1 x1 y1
lassign $p2 x2 y2
# Special case: coincident & zero size
if {$x1 == $x2 && $y1 == $y2 && $r == 0.0} {
return [list [list $x1 $y1 0.0]]
}
if {$r <= 0.0} {
error "radius must be positive for sane results"
}
if {$x1 == $x2 && $y1 == $y2} {
error "no sane solution: points are coincident"
}
 
# Calculate distance apart and separation vector
set dx [expr {$x2 - $x1}]
set dy [expr {$y2 - $y1}]
set q [expr {hypot($dx, $dy)}]
if {$q > 2*$r} {
error "no solution: points are further apart than required diameter"
}
 
# Calculate midpoint
set x3 [expr {($x1+$x2)/2.0}]
set y3 [expr {($y1+$y2)/2.0}]
# Fractional distance along the mirror line
set f [expr {($r**2 - ($q/2.0)**2)**0.5 / $q}]
# The two answers
set c1 [list [expr {$x3 - $f*$dy}] [expr {$y3 + $f*$dx}] $r]
set c2 [list [expr {$x3 + $f*$dy}] [expr {$y3 - $f*$dx}] $r]
return [list $c1 $c2]
}</lang>
Demonstrating:
<lang tcl>foreach {p1 p2 r} {
{0.1234 0.9876} {0.8765 0.2345} 2.0
{0.0000 2.0000} {0.0000 0.0000} 1.0
{0.1234 0.9876} {0.1234 0.9876} 2.0
{0.1234 0.9876} {0.8765 0.2345} 0.5
{0.1234 0.9876} {0.1234 0.9876} 0.0
} {
puts "p1:([join $p1 {, }]) p2:([join $p2 {, }]) r:$r =>"
if {[catch {
foreach c [findCircles $p1 $p2 $r] {
puts "\tCircle:([join $c {, }])"
}
} msg]} {
puts "\tERROR: $msg"
}
}</lang>
{{out}}
<pre>
p1:(0.1234, 0.9876) p2:(0.8765, 0.2345) r:2.0 =>
Circle:(1.863111801658189, 1.974211801658189, 2.0)
Circle:(-0.8632118016581891, -0.752111801658189, 2.0)
p1:(0.0000, 2.0000) p2:(0.0000, 0.0000) r:1.0 =>
Circle:(0.0, 1.0, 1.0)
Circle:(0.0, 1.0, 1.0)
p1:(0.1234, 0.9876) p2:(0.1234, 0.9876) r:2.0 =>
ERROR: no sane solution: points are coincident
p1:(0.1234, 0.9876) p2:(0.8765, 0.2345) r:0.5 =>
ERROR: no solution: points are further apart than required diameter
p1:(0.1234, 0.9876) p2:(0.1234, 0.9876) r:0.0 =>
Circle:(0.1234, 0.9876, 0.0)
</pre>
Anonymous user