Programmation, maths, géométrie comme, par exemple, pour dessiner des cercles d'Apollonius en utilisant le théorème de Descartes avec des nombres complexes.

On peut noter la concision du code avec F#
module ApollonianGasket
open System.Numerics
let solve a b c =
a + b + c + 2. * sqrt (a * b + b * c + a * c)
let scale a (c: Complex) = Complex(a * c.Real, a * c.Imaginary)
let solveComplex (a: Complex) (b: Complex) (c: Complex) =
a + b + c + scale 2. (Complex.Sqrt(a * b + b * c + a * c))
let apollonianCircle (x1, y1, k1) (x2, y2, k2) (x3, y3, k3) =
let kz1 = scale k1 (Complex(x1,y1))
let kz2 = scale k2 (Complex(x2,y2))
let kz3 = scale k3 (Complex(x3,y3))
let k4 = solve k1 k2 k3
let p4 = solveComplex kz1 kz2 kz3 |> scale (1.0 / k4)
p4.Real, p4.Imaginary, k4
let rec apollonianGasket c1 c2 c3 i =
match i with
| 0 -> []
| _ ->
let c4 = apollonianCircle c1 c2 c3
[(c4, i)] @
apollonianGasket c1 c2 c4 (i - 1) @
apollonianGasket c2 c3 c4 (i - 1) @
apollonianGasket c3 c1 c4 (i - 1)
let circlePacking x y r i =
let rt3 = sqrt 3.
let innerRad = r / (1. + 2. / rt3)
let innerCur = 1. / innerRad
let h = innerRad * (rt3 + 1.)
let c0 = x, y, -1.0 / r
let c1 = x, y + r - innerRad, innerCur
let c2 = x + innerRad, y + r - h, innerCur
let c3 = x - innerRad, y + r - h, innerCur
[(c1, i); (c2, i); (c3, i)] @
apollonianGasket c1 c2 c3 (i - 1) @
apollonianGasket c1 c2 c0 (i - 1) @
apollonianGasket c2 c3 c0 (i - 1) @
apollonianGasket c3 c1 c0 (i - 1)
// Commande AutoCAD
open Autodesk.AutoCAD.ApplicationServices
open Autodesk.AutoCAD.DatabaseServices
open Autodesk.AutoCAD.EditorInput
open Autodesk.AutoCAD.Geometry
open Autodesk.AutoCAD.Runtime
let mutable numSteps = 8
[<CommandMethod("APOLLONIUS")>]
let apolloniusCmd () =
let doc = Application.DocumentManager.MdiActiveDocument
let db = doc.Database
let ed = doc.Editor
let peo = PromptEntityOptions("\nSélectionnez un cercle: ")
peo.SetRejectMessage("\nUniquement un cercle.")
peo.AddAllowedClass(typeof<Circle>, false)
let per = ed.GetEntity(peo)
if per.Status = PromptStatus.OK then
let pio = PromptIntegerOptions("\nEntrez le nombre de niveaux: ")
pio.LowerLimit <- 1
pio.UpperLimit <- 12
pio.DefaultValue <- numSteps
pio.UseDefaultValue <- true
let pir = ed.GetInteger(pio)
if pir.Status = PromptStatus.OK then
numSteps <- pir.Value
use tr = db.TransactionManager.StartTransaction()
let cir = tr.GetObject(per.ObjectId, OpenMode.ForRead) :?> Circle
let rad = cir.Radius
let offset = 2. * rad - cir.Center.X
let cSpace = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) :?> BlockTableRecord
circlePacking (cir.Center.X + offset) cir.Center.Y rad numSteps
|> List.iter(fun ((x, y, k), step) ->
let c = new Circle(Point3d(x - offset, y, 0.), Vector3d.ZAxis, 1. / abs k)
c.ColorIndex <- numSteps - step + 1
cSpace.AppendEntity(c) |> ignore
tr.AddNewlyCreatedDBObject(c, true))
tr.Commit()