Another update from ingydotnet^djgoku

This commit is contained in:
Ingy döt Net 2015-11-18 06:14:39 +00:00
parent 91df62d461
commit 948b86eafa
7604 changed files with 108452 additions and 22726 deletions

View file

@ -0,0 +1,33 @@
defmodule Circle do
def apollonius(c1, c2, c3, s1, s2, s3) do
{x1, y1, r1} = c1
{w12, w13, w14} = calc(c1, c2, s1, s2)
{u22, u23, u24} = calc(c2, c3, s2, s3)
{w22, w23, w24} = {u22 - w12, u23 - w13, u24 - w14}
p = -w23 / w22
q = w24 / w22
m = -w12 * p - w13
n = w14 - w12 * q
a = n*n + q*q - 1
b = 2*m*n - 2*n*x1 + 2*p*q - 2*q*y1 + 2*s1*r1
c = x1*x1 + m*m - 2*m*x1 + p*p + y1*y1 - 2*p*y1 - r1*r1
d = b*b - 4*a*c
rs = (-b - :math.sqrt(d)) / (2*a)
{m + n*rs, p + q*rs, rs}
end
defp calc({x1, y1, r1}, {x2, y2, r2}, s1, s2) do
v1 = x2 - x1
{(y2 - y1) / v1, (x1*x1 - x2*x2 + y1*y1 - y2*y2 - r1*r1 + r2*r2) / (2*v1), (s2*r2 - s1*r1) / v1}
end
end
c1 = {0, 0, 1}
c2 = {2, 4, 2}
c3 = {4, 0, 1}
IO.inspect Circle.apollonius(c1, c2, c3, 1, 1, 1)
IO.inspect Circle.apollonius(c1, c2, c3, -1, -1, -1)

View file

@ -0,0 +1,55 @@
using Polynomials
immutable Point{T<:Real}
x::T
y::T
end
immutable Circle{T<:Real}
c::Point{T}
r::T
end
Circle{T<:Real}(x::T, y::T, r::T) = Circle(Point(x,y), r)
function apollonius{T<:Real}(ap::Array{Circle{T},1},
enc::Array{Int,1}=Int[])
length(ap) == 3 || error("This Apollonius problem needs 3 circles.")
x = map(u->u.c.x, ap)
y = map(u->u.c.y, ap)
r = map(u->u in enc ? -1 : 1, 1:3) .* map(u->u.r, ap)
a = 2x[1] - 2x[2:3]
b = 2y[1] - 2y[2:3]
c = 2r[1] - 2r[2:3]
d = (x[1]^2 + y[1]^2 - r[1]^2)
d -= (map(u->u^2, x) + map(u->u^2, y) - map(u->u^2, r))[2:3]
u = Poly([-det(hcat(b,d)), det(hcat(b,c))]/det(hcat(a,b)))
v = Poly([det(hcat(a,d)), -det(hcat(a,c))]/det(hcat(a,b)))
w = Poly([r[1], 1.0])^2
s = (u - x[1])^2 + (v - y[1])^2 - w
r = filter(x->imag(x)==0 && 0<x, roots(s))
length(r) < 2 || error("The solution is not unique.")
length(r) == 1 || error("There is no solution.")
r = r[1]
Circle(polyval(u,r), polyval(v,r), r)
end
function detail(c::Circle)
x = @sprintf "%.4f" c.c.x
y = @sprintf "%.4f" c.c.y
r = @sprintf "%.4f" c.r
@sprintf "centered at (%s, %s) with radius %s" x y r
end
test = [Circle(0.,0.,1.),
Circle(4.,0.,1.),
Circle(2.,4.,2.)]
println("The defining circles are:")
for c in test
println(" ", detail(c))
end
println("The internal circle is:")
println(" ", detail(apollonius(test)))
println("The external circle is:")
println(" ", detail(apollonius(test, [1:3])))

View file

@ -1,41 +1,37 @@
/*REXX program to solve the problem of Apollonius, named after the Greek*/
/*────────── Apollonius of Perga [Pergæus] (circa 262 BC ──► 190 BC).*/
w=20; numeric digits w-5 /*width used to display numbers. */
c1.x=0; c1.y=0; c1.r=1
c2.x=4; c2.y=0; c2.r=1
c3.x=2; c3.y=4; c3.r=2
call tell 'external tangent:', solveApollonius( 1, 1, 1)
call tell 'internal tangent:', solveApollonius(-1, -1, -1)
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────SOLVEAPOLLONIUS subroutine──────────*/
/*───────────────────this code should be covered with a very thick tarp.*/
solveApollonius: parse arg s1,s2,s3 /*internal or external tangent ? */
numeric digits digits()*3 /*reduce rounding: use triple dig*/
x1=c1.x; x2=c2.x; x3=c3.x
y1=c1.y; y2=c2.y; y3=c3.y
r1=c1.r; r2=c2.r; r3=c3.r
va=2*x2-2*x1; vb=2*y2-2*y1; vc=x1*x1-x2*x2+y1*y1-y2*y2-r1*r1+r2*r2
vd=2*s2*r2-2*s1*r1; ve=2*x3-2*x2; vf=2*y3-2*y2
vg=x2*x2-x3*x3+y2*y2-y3*y3-r2*r2+r3*r3; vh=2*s3*r3-2*s2*r2
vj=vb/va; vk=vc/va; vm=vd/va
vn=vf/ve-vj; vp=vg/ve-vk; vr=vh/ve-vm
p=-vp/vn
q= vr/vn
m=-vj*p-vk
n=vm-vj*q
a=n*n+q*q-1
b=2*m*n-2*n*x1+2*p*q-2*q*y1+2*s1*r1
c=x1*x1+m*m-2*m*x1+p*p+y1*y1-2*p*y1-r1*r1
_=b*b-4*a*c; $.r=(-b-sqrt(_))/(a+a); $.x=m+n*$.r; $.y=p+q*$.r
numeric digits digits()%3 /*reset DIGITS to the original.*/
return $.x+0 $.y+0 $.r+0 /*return with 3 args, normalized.*/
/*──────────────────────────────────SQRT subroutine─────────────────────*/
sqrt: procedure; parse arg x; if x=0 then return 0; m.=9; p=digits(); i=
numeric digits 9; if x<0 then do; x=-x; i='i'; end; numeric form; m.0=p
parse value format(x,2,1,,0) 'E0' with g 'E' _ .; g=g*.5'E'_%2; m.1=p
do j=2 while p>9; m.j=p; p=p%2+1; end /*j*/
do k=j+5 to 0 by -1; numeric digits m.k; g=.5*(g+x/g); end /*k*/
numeric digits m.0; return (g/1)i
/*──────────────────────────────────TELL subroutine─────────────────────*/
tell: parse arg _,a b c; say _ left(a/1,w) left(b/1,w) left(c/1,w); return
/*dividing by 1 reformats #s to W*/
/*REXX program solves the problem of Apollonius, named after the Greek */
/*──────────────── Apollonius of Perga [Pergæus] (circa 262 BC ──► 190 BC).*/
w=20; numeric digits w-5 /*the width used to display the numbers*/
c1.x=0; c1.y=0; c1.r=1
c2.x=4; c2.y=0; c2.r=1
c3.x=2; c3.y=4; c3.r=2
call tell 'external tangent:', Apollonius( 1, 1, 1)
call tell 'internal tangent:', Apollonius(-1, -1, -1)
exit /*stick a fork in it, we're all done. */
/*────────────────────────────────────────────────────────────────────────────*/
Apollonius: parse arg s1,s2,s3 /*could be an internal/external tangent*/
numeric digits digits()*3 /*reduce rounding by using 3 times digs*/
x1=c1.x; x2=c2.x; x3=c3.x
y1=c1.y; y2=c2.y; y3=c3.y
r1=c1.r; r2=c2.r; r3=c3.r
va=2*x2-2*x1; vb=2*y2-2*y1
vc=x1*x1-x2*x2+y1*y1-y2*y2-r1*r1+r2*r2
vd=2*s2*r2-2*s1*r1; ve=2*x3-2*x2; vf=2*y3-2*y2
vg=x2*x2-x3*x3+y2*y2-y3*y3-r2*r2+r3*r3; vh=2*s3*r3-2*s2*r2
vj=vb/va; vk=vc/va; vm=vd/va; vn=vf/ve-vj
vp=vg/ve-vk; vr=vh/ve-vm; p=-vp/vn; q =vr/vn
m=-vj*p-vk; n=vm-vj*q; a=n*n+q*q-1
b=2*m*n-2*n*x1+2*p*q-2*q*y1+2*s1*r1
c=x1*x1+m*m-2*m*x1+p*p+y1*y1-2*p*y1-r1*r1
_=b*b-4*a*c; $.r=(-b-sqrt(_))/(a+a); $.x=m+n*$.r; $.y=p+q*$.r
numeric digits digits()%3 /*reset DIGITS to the original.*/
return $.x $.y $.r /*return with 3 args, normalized.*/
/*────────────────────────────────────────────────────────────────────────────*/
sqrt: procedure; parse arg x; if x=0 then return 0; d=digits(); i=; m.=9
numeric digits 9; numeric form; h=d+6; if x<0 then do; x=-x; i='i'; end
parse value format(x,2,1,,0) 'E0' with g 'E' _ .; g=g*.5'e'_%2
do j=0 while h>9; m.j=h; h=h%2+1; end /*j*/
do k=j+5 to 0 by -1; numeric digits m.k; g=(g+x/g)*.5; end /*k*/
numeric digits d; return (g/1)i /*make complex if X < 0.*/
/*────────────────────────────────────────────────────────────────────────────*/
tell: parse arg _,a b c; say _ left(a/1,w) left(b/1,w) left(c/1,w); return
/*dividing by 1 normalizes the numbers.*/

View file

@ -5,9 +5,9 @@ class Circle
attr_reader :x, :y, :r
def self.apollonius(c1, c2, c3, s1=1, s2=1, s3=1)
x1, y1, r1 = [c1.x, c1.y, c1.r]
x2, y2, r2 = [c2.x, c2.y, c2.r]
x3, y3, r3 = [c3.x, c3.y, c3.r]
x1, y1, r1 = c1.x, c1.y, c1.r
x2, y2, r2 = c2.x, c2.y, c2.r
x3, y3, r3 = c3.x, c3.y, c3.r
v11 = 2*x2 - 2*x1
v12 = 2*y2 - 2*y1
@ -41,14 +41,17 @@ class Circle
xs = m + n*rs
ys = p + q*rs
return self.new(xs, ys, rs)
self.new(xs, ys, rs)
end
def to_s
"Circle: x=#{@x}, y=#{@y}, r=#{@r}"
end
end
puts c1 = Circle.new(0, 0, 1)
puts c2 = Circle.new(2, 4, 2)
puts c3 = Circle.new(4, 0, 1)
p c1 = Circle.new(0, 0, 1)
p c2 = Circle.new(2, 4, 2)
p c3 = Circle.new(4, 0, 1)
p Circle.apollonius(c1, c2, c3)
p Circle.apollonius(c1, c2, c3, -1, -1, -1)
puts Circle.apollonius(c1, c2, c3)
puts Circle.apollonius(c1, c2, c3, -1, -1, -1)

View file

@ -0,0 +1,196 @@
Option Explicit
Option Base 0
Private Const intBase As Integer = 0
Private Type tPoint
X As Double
Y As Double
End Type
Private Type tCircle
Centre As tPoint
Radius As Double
End Type
Private Sub sApollonius()
Dim Circle1 As tCircle
Dim Circle2 As tCircle
Dim Circle3 As tCircle
Dim CTanTanTan(intBase + 0 to intBase + 7) As tCircle
With Circle1
With .Centre
.X = 0
.Y = 0
End With
.Radius = 1
End With
With Circle2
With .Centre
.X = 4
.Y = 0
End With
.Radius = 1
End With
With Circle3
With .Centre
.X = 2
.Y = 4
End With
.Radius = 2
End With
Call fApollonius(Circle1,Circle2,Circle3,CTanTanTan()))
End Sub
Public Function fApollonius(ByRef C1 As tCircle, _
ByRef C2 As tCircle, _
ByRef C3 As tCircle, _
ByRef CTanTanTan() As tCircle) As Boolean
' Solves the Problem of Apollonius (finding a circle tangent to three other circles in the plane)
' (x_s - x_1)^2 + (y_s - y_1)^2 = (r_s - Tan_1 * r_1)^2
' (x_s - x_2)^2 + (y_s - y_2)^2 = (r_s - Tan_2 * r_2)^2
' (x_s - x_3)^2 + (y_s - y_3)^2 = (r_s - Tan_3 * r_3)^2
' x_s = M + N * r_s
' y_s = P + Q * r_s
' Parameters:
' C1, C2, C3 (circles in the problem)
' Tan1 := An indication if the solution should be externally or internally tangent (+1/-1) to Circle1 (C1)
' Tan2 := An indication if the solution should be externally or internally tangent (+1/-1) to Circle2 (C2)
' Tan3 := An indication if the solution should be externally or internally tangent (+1/-1) to Circle3 (C3)
Dim Tangent(intBase + 0 To intBase + 7, intBase + 0 To intBase + 2) As Integer
Dim lgTangent As Long
Dim Tan1 As Integer
Dim Tan2 As Integer
Dim Tan3 As Integer
Dim v11 As Double
Dim v12 As Double
Dim v13 As Double
Dim v14 As Double
Dim v21 As Double
Dim v22 As Double
Dim v23 As Double
Dim v24 As Double
Dim w12 As Double
Dim w13 As Double
Dim w14 As Double
Dim w22 As Double
Dim w23 As Double
Dim w24 As Double
Dim p As Double
Dim Q As Double
Dim M As Double
Dim N As Double
Dim A As Double
Dim b As Double
Dim c As Double
Dim D As Double
'Check if circle centers are colinear
If fColinearPoints(C1.Centre, C2.Centre, C3.Centre) Then
fApollonius = False
Exit Function
End If
Tangent(intBase + 0, intBase + 0) = -1
Tangent(intBase + 0, intBase + 1) = -1
Tangent(intBase + 0, intBase + 2) = -1
Tangent(intBase + 1, intBase + 0) = -1
Tangent(intBase + 1, intBase + 1) = -1
Tangent(intBase + 1, intBase + 2) = 1
Tangent(intBase + 2, intBase + 0) = -1
Tangent(intBase + 2, intBase + 1) = 1
Tangent(intBase + 2, intBase + 2) = -1
Tangent(intBase + 3, intBase + 0) = -1
Tangent(intBase + 3, intBase + 1) = 1
Tangent(intBase + 3, intBase + 2) = 1
Tangent(intBase + 4, intBase + 0) = 1
Tangent(intBase + 4, intBase + 1) = -1
Tangent(intBase + 4, intBase + 2) = -1
Tangent(intBase + 5, intBase + 0) = 1
Tangent(intBase + 5, intBase + 1) = -1
Tangent(intBase + 5, intBase + 2) = 1
Tangent(intBase + 6, intBase + 0) = 1
Tangent(intBase + 6, intBase + 1) = 1
Tangent(intBase + 6, intBase + 2) = -1
Tangent(intBase + 7, intBase + 0) = 1
Tangent(intBase + 7, intBase + 1) = 1
Tangent(intBase + 7, intBase + 2) = 1
For lgTangent = LBound(Tangent) To UBound(Tangent)
Tan1 = Tangent(lgTangent, intBase + 0)
Tan2 = Tangent(lgTangent, intBase + 1)
Tan3 = Tangent(lgTangent, intBase + 2)
v11 = 2 * (C2.Centre.X - C1.Centre.X)
v12 = 2 * (C2.Centre.Y - C1.Centre.Y)
v13 = (C1.Centre.X * C1.Centre.X) _
- (C2.Centre.X * C2.Centre.X) _
+ (C1.Centre.Y * C1.Centre.Y) _
- (C2.Centre.Y * C2.Centre.Y) _
- (C1.Radius * C1.Radius) _
+ (C2.Radius * C2.Radius)
v14 = 2 * (Tan2 * C2.Radius - Tan1 * C1.Radius)
v21 = 2 * (C3.Centre.X - C2.Centre.X)
v22 = 2 * (C3.Centre.Y - C2.Centre.Y)
v23 = (C2.Centre.X * C2.Centre.X) _
- (C3.Centre.X * C3.Centre.X) _
+ (C2.Centre.Y * C2.Centre.Y) _
- (C3.Centre.Y * C3.Centre.Y) _
- (C2.Radius * C2.Radius) _
+ (C3.Radius * C3.Radius)
v24 = 2 * ((Tan3 * C3.Radius) - (Tan2 * C2.Radius))
w12 = v12 / v11
w13 = v13 / v11
w14 = v14 / v11
w22 = (v22 / v21) - w12
w23 = (v23 / v21) - w13
w24 = (v24 / v21) - w14
p = -w23 / w22
Q = w24 / w22
M = -(w12 * p) - w13
N = w14 - (w12 * Q)
A = (N * N) + (Q * Q) - 1
b = 2 * ((M * N) - (N * C1.Centre.X) + (p * Q) - (Q * C1.Centre.Y) + (Tan1 * C1.Radius))
c = (C1.Centre.X * C1.Centre.X) _
+ (M * M) _
- (2 * M * C1.Centre.X) _
+ (p * p) _
+ (C1.Centre.Y * C1.Centre.Y) _
- (2 * p * C1.Centre.Y) _
- (C1.Radius * C1.Radius)
'Find a root of a quadratic equation (requires the circle centers not to be e.g. colinear)
D = (b * b) - (4 * A * c)
With CTanTanTan(lgTangent)
.Radius = (-b - VBA.Sqr(D)) / (2 * A)
.Centre.X = M + (N * .Radius)
.Centre.Y = p + (Q * .Radius)
End With
Next lgTangent
fApollonius = True
End Function