Circles Common Invariant

Schwerdteger describes an interesting “invariant” relationship between any two circles:

\frac{\Delta_{12}}{\sqrt{\Delta_1} \sqrt{\Delta_2}}

where

\Delta_1 = | \mathfrak{C}_1 |, \Delta_2 = | \mathfrak{C}_2 |, and 2 \Delta_{12} = A_1 D_2 + A_2 D_1 - B_1 C_2 - B_2 C_1

with the circles represented as Hermitian matrices \begin{bmatrix} A & B \\ C & D \end{bmatrix}.

The point is, in the end you come up with this single number which represents whether the smaller circle is inside the first, overlapping the first, just touching the first, or outside the first. Here are the cases:

common invariant > 1 : smaller circle contained withing the greater circle

common invariant = 1 : touching from the inside

-1 > common invariant > 1 : overlapping at two points

common invariant = -1 : touching from the outside

common invariant < -1 : completely outside

Here is Racket code used for calculations and plotting:

(require math/array)
(require math/matrix)
(require plot)

(define (circle-to-matrix zC r)
  (let ([B (* -1 (conjugate zC))]
        [mzC (magnitude zC)])
    (matrix [[ 1             B                       ]
             [ (conjugate B) (- (* mzC mzC) (* r r)) ]])))

;; gothic C - 212d
;; delta - 394
(define (invariant ℭ1 ℭ2)
  (let* ([Δ1 (matrix-determinant ℭ1)]
         [Δ2 (matrix-determinant ℭ2)]
         [A1 (array-ref ℭ1 #[0 0])]
         [B1 (array-ref ℭ1 #[0 1])]
         [C1 (array-ref ℭ1 #[1 0])]
         [D1 (array-ref ℭ1 #[1 1])]
         [A2 (array-ref ℭ2 #[0 0])]
         [B2 (array-ref ℭ2 #[0 1])]
         [C2 (array-ref ℭ2 #[1 0])]
         [D2 (array-ref ℭ2 #[1 1])]
         [Δ12 (* 0.5 (+ (* A1 D2)
                        (* A2 D1)
                        (* -1 B1 C2)
                        (* -1 B2 C1)))])
    (/ Δ12 (* (sqrt Δ1) (sqrt Δ2)))))

(define (circle-isoline x y r)
  (isoline
   (lambda (x_ y_) (sqrt (+ (sqr (- x_ x)) (sqr (- y_ y))))) r))

(define (circles-invariant-plot x1 y1 r1 x2 y2 r2 min max)
  (let ([C1 (circle-to-matrix (make-rectangular x1 y1) r1)]
        [C2 (circle-to-matrix (make-rectangular x2 y2) r2)])
    (plot-file
     (list
      (circle-isoline x1 y1 r1)
      (circle-isoline x2 y2 r2)
      (point-label (vector (+ min (* (- max min) 0.1))
                           (+ min (* (- max min) 0.9)))
                   (number->string (invariant C1 C2)) #:point-size 0))
     "out.png"
     #:x-min min
     #:x-max max
     #:y-min min
     #:y-max max
     #:width 400
     #:height 400)))

Representation of Circles by Hermitian Matrices

I borrowed the book Geometry of Complex Numbers by Schwerdtfeger. The material has been fascinating so far, though admittedly it took me about 3 hours to comprehend the material in page 1 of chapter 1. The first subject is this intriguing idea that you can represent a circle as a matrix. More specifically, you you can represent a circle with (complex) center 𝛾 and radius 𝜌 as a matrix

\begin{bmatrix} A & B \\ C & D \end{bmatrix}

Where B = – A𝛾̅, C = -A𝛾, and D = A(𝛾𝛾̅-𝜌²), so that A and D are real numbers, and B and C are complex numbers. For normal circles, you will have A=1, though you can scale the matrix to have other (non-zero) values of A and still have the same circle. (If A is zero, you end up with a straight line, or some other mysterious thing that is not a circle.)

The simple case is the unit circle:

Which is \begin{bmatrix} 1 & 0 \\ 0 & -1 \end{bmatrix}

More exotic is the circle away from the origin, centered at 10+10i, i.e., (10, 10), with radius 3:

\begin{bmatrix} 1 & -10+10i \\ -10-10i & 191 \end{bmatrix}

Here is some code to generate the matrix in Racket, and to put it back:

lang racket

(require math/array)
(require math/matrix)

(define (circle-to-matrix zC r)
  (let ([B (* -1 (conjugate zC))]
        [mzC (magnitude zC)])
    (matrix [[ 1             B                       ]
             [ (conjugate B) (- (* mzC mzC) (* r r)) ]])))

(define (matrix-circle-radius M)
  (let ([A (array-ref M #[0 0])]
        [d (matrix-determinant M)])
    (sqrt (/ d (* -1 (* A A))))))

(define (matrix-circle-center M)
  (let ([C (array-ref M #[1 0])]
        [A (array-ref M #[0 0])])
    (/ C (* -1 A))))
racket@circle.rkt> (circle-to-matrix 0 1)
(array #[#[1 0] #[0 -1]])
racket@circle.rkt> (matrix-circle-radius (circle-to-matrix 0 1))
1
racket@circle.rkt> (matrix-circle-center (circle-to-matrix 0 1))
0

Why is this significant? I think Schwerdtfeger is going to cover that on page 2. :)

Emacs Calc: Matrix Mapping “Close Enough” Keyboard Macro

In Emacs Calculator, frequently I come up with results that that are algebraically supposed to be a whole number, but instead because of precision error they end up as some annoying value that is very close. For example, I’m expecting a 0 but get “3.69600000004e-11” which is an extremely small value close to zero. For matrices, I defined this shortcut which maps over the elements, rounding them if they are “close enough” to the whole number.

After defining the macro I inserted it into ~/.emacs.d/calc.el:

(fset 'calc-ce
   (lambda (&optional arg) "Keyboard macro." (interactive "p") (kmacro-exec-ring-item (quote ([86 77 39 105 102 40 97 98 115 40 114 111 117 110 100 40 120 41 45 120 41 32 60 32 48 46 48 48 48 48 48 48 49 44 114 111 117 110 100 40 120 41 44 120 41 return return] 0 "%d")) arg)))

In calc, press ‘x c e’.

So, this

becomes

This is not the same thing as simply rounding as it only rounds if the value is very close (under 0.0000001 difference). The formula mapped over the matrix is

if(abs(round(x)-x) < 0.0000001,round(x),x)

A different approach I tried was to multiply, truncate, and reverse the multiplication, but this doesn’t work for values like 0.9999999999.