Smallest enclosing circle problem: Difference between revisions
Content added Content deleted
(Added Go) |
|||
Line 339: | Line 339: | ||
Center is at: [0.0405866077655439, 0.5556683897981481, -0.2313678300507679, 0.6074066023194586, -0.2003463948612026] |
Center is at: [0.0405866077655439, 0.5556683897981481, -0.2313678300507679, 0.6074066023194586, -0.2003463948612026] |
||
Radius is: 2.7946020036995454 |
Radius is: 2.7946020036995454 |
||
</pre> |
|||
=={{header|Phix}}== |
|||
Based on the same code as Wren, and likewise limited to 2D circles - I believe (but cannot prove) the main barrier to coping with more than two dimensions lies wholly within the circle_from3() routine. |
|||
<lang Phix>type point(sequence) return true end type |
|||
enum CENTRE, RADIUS |
|||
type circle(sequence) return true end type |
|||
function distance(point a, b) |
|||
return sqrt(sum(sq_power(sq_sub(a,b),2))) |
|||
end function |
|||
function in_circle(point p, circle c) |
|||
return distance(p,c[CENTRE]) <= c[RADIUS] |
|||
end function |
|||
function circle_from2(point a, b) |
|||
-- return the smallest circle that intersects 2 points: |
|||
point centre = sq_div(sq_add(a,b),2) -- (ie midpoint) |
|||
atom radius = distance(a,b)/2 |
|||
circle res = { centre, radius } |
|||
return res |
|||
end function |
|||
function circle_from3(point a, b, c) |
|||
-- return a unique circle that intersects three points |
|||
atom {{aX,aY},{bX,bY},{cX,cY}} = {a,sq_sub(b,a),sq_sub(c,a)}, |
|||
B = bX * bX + bY * bY, |
|||
C = cX * cX + cY * cY, |
|||
D = bX * cY - bY * cX |
|||
point centre = { (cY * B - bY * C) / (2 * D) + aX, |
|||
(bX * C - cX * B) / (2 * D) + aY } |
|||
circle res = { centre, distance(centre, a) } |
|||
return res |
|||
end function |
|||
function trivial(sequence r) |
|||
integer l = length(r) |
|||
switch l do |
|||
case 0: return {{0,0},0} |
|||
case 1: return {r[1],0} |
|||
case 2: return circle_from2(r[1],r[2]) |
|||
case 3: return circle_from3(r[1],r[2],r[3]) |
|||
end switch |
|||
end function |
|||
function welzlr(sequence p, r) |
|||
if p={} or length(r)=3 then return trivial(r) end if |
|||
point p1 = p[1] |
|||
p = p[2..$] |
|||
circle d = welzlr(p, r) |
|||
if in_circle(p1,d) then return d end if |
|||
return welzlr(p, append(r,p1)) |
|||
end function |
|||
procedure welzl(sequence p) |
|||
printf(1,"Points %v ==> centre %v radius %.14g\n",prepend(welzlr(shuffle(p),{}),p)) |
|||
end procedure |
|||
constant tests = {{ { 0, 0 }, { 0, 1 }, { 1, 0 } }, |
|||
{ { 5, -2 }, { -3, -2 }, { -2, 5 }, { 1, 6 }, { 0, 2 } }} |
|||
papply(tests,welzl)</lang> |
|||
{{out}} |
|||
<pre> |
|||
Points {{0,0},{0,1},{1,0}} ==> centre {0.5,0.5} radius 0.70710678118655 |
|||
Points {{5,-2},{-3,-2},{-2,5},{1,6},{0,2}} ==> centre {1,1} radius 5 |
|||
</pre> |
</pre> |
||