CGA Worked Examples: Interval Arithmetic in Conformal Space

8.1 The Conformal Embedding

CGA, developed in modern form by Hestenes, Li, and Rockwood[1], adds two extra basis vectors \(\mathbf{e}_+\) and \(\mathbf{e}_-\) to the Euclidean basis, with metric:

\[ \mathbf{e}_+^2 = +1, \quad \mathbf{e}_-^2 = -1, \quad \mathbf{e}_i^2 = +1 \; (i=1\ldots n) \]

Two null vectors are defined from these:

\[ \mathbf{e}_\infty = \mathbf{e}_- + \mathbf{e}_+ \quad (\text{point at infinity}), \qquad \mathbf{e}_o = \tfrac{1}{2}(\mathbf{e}_- - \mathbf{e}_+) \quad (\text{origin}) \]

They satisfy \(\mathbf{e}_\infty^2 = 0\), \(\mathbf{e}_o^2 = 0\), \(\mathbf{e}_\infty \cdot \mathbf{e}_o = -1\). A Euclidean point \(\mathbf{x} \in \mathbb{R}^n\) is embedded as the null vector:

\[ X = \mathbf{x} + \tfrac{1}{2}|\mathbf{x}|^2 \mathbf{e}_\infty + \mathbf{e}_o \]
Key fact — null embedding

Every embedded Euclidean point \(X\) satisfies \(X^2 = 0\). This is not a coincidence — it is the defining property of the conformal embedding. When we apply interval arithmetic, a set of possible Euclidean points maps to a set of null blades, forming an interval null blade.

EUCLIDEAN ℝ² x y x y z X = x + ½|x|²e∞ + e₀ CGA SPACE ℝ³·¹ (null cone) X Y Z X² = Y² = Z² = 0 (null vectors) e∞ (apex) e₀ (base)
Fig. 8.1. The conformal embedding maps Euclidean points (left) to null vectors on the light cone of \(\mathbb{R}^{3,1}\) (right). Every geometric object — point, line, circle, sphere — corresponds to a blade of a specific grade on this cone. Interval arithmetic operates on sets of null vectors.

8.2 Geometric Primitives as Blades

The power of CGA is that all standard geometric objects become blades of specific grades, and all geometric operations become sandwich products with the same algebraic form.[2]

Grade 1 — Point

\(X = \mathbf{x} + \tfrac{1}{2}|\mathbf{x}|^2\mathbf{e}_\infty + \mathbf{e}_o\)

Grade 2 — Point pair

\(P_1 \wedge P_2\) — oriented segment between two points

Grade 3 — Circle / Line

\(P_1 \wedge P_2 \wedge P_3\) — circle through three points
(line when one point is \(\mathbf{e}_\infty\))

Grade 4 — Sphere / Plane

\(P_1 \wedge P_2 \wedge P_3 \wedge P_4\) — sphere through four points
(plane when one is \(\mathbf{e}_\infty\))

Alternatively, a sphere of radius \(r\) centred at \(\mathbf{c}\) is the grade-1 blade:

\[ S = \mathbf{c} + \tfrac{1}{2}(|\mathbf{c}|^2 - r^2)\mathbf{e}_\infty + \mathbf{e}_o \]

A point \(X\) lies on sphere \(S\) iff \(X \cdot S = 0\). The signed distance \(X \cdot S\) measures how far inside or outside the sphere \(X\) lies — it is precisely the \(F(P)\) of Chapter IV's bisection algorithm, now expressed as a single inner product.

════════════════════════════════════════════════════════ WORKED EXAMPLE 1 ════════════════════════════════════════════════════════
Worked Example 1 Interval point embedded in CGA — propagating position uncertainty

Suppose a sensor reports position \(\mathbf{x} = (x_1, x_2)\) with bounded error: \(x_1 \in [1.8, 2.2]\), \(x_2 \in [0.9, 1.1]\). We embed this interval into CGA and track how the uncertainty propagates into the null blade's coefficients.

The embedding formula is \(X = \mathbf{x} + \tfrac{1}{2}|\mathbf{x}|^2 \mathbf{e}_\infty + \mathbf{e}_o\). The interval version bounds each coefficient independently:

\[ X_1\text{-coeff} \in [1.8, 2.2], \quad X_2\text{-coeff} \in [0.9, 1.1] \] \[ \tfrac{1}{2}|\mathbf{x}|^2 \in \tfrac{1}{2}([1.8,2.2]^2 + [0.9,1.1]^2) \]
Given\(x_1 \in [1.8, 2.2], \quad x_2 \in [0.9, 1.1]\)sensor uncertainty
Step 1\(x_1^2 \in [3.24, 4.84]\)squaring an interval
Step 2\(x_2^2 \in [0.81, 1.21]\)squaring an interval
Step 3\(|\mathbf{x}|^2 \in [4.05, 6.05]\)summing the squares
Step 4\(\tfrac{1}{2}|\mathbf{x}|^2 \in [2.025, 3.025]\)\(\mathbf{e}_\infty\) coefficient — interval wider than inputs
Result\(X = [1.8,2.2]\mathbf{e}_1 + [0.9,1.1]\mathbf{e}_2 + [2.025,3.025]\mathbf{e}_\infty + \mathbf{e}_o\)interval null blade

Note the wrapping amplification: the \(\mathbf{e}_\infty\) coefficient has a width of \(1.0\), wider than either input interval (widths \(0.4\) and \(0.2\)). This is an instance of the dependency problem — \(|\mathbf{x}|^2 = x_1^2 + x_2^2\) involves the same uncertain quantities \(x_1, x_2\) twice. Affine arithmetic (Chapter I, Ref. [5]) reduces this over-approximation.

x₁ x₂ 1 2 3 1 2 x ∈ [1.8,2.2]×[0.9,1.1] embed CGA COEFFICIENT INTERVALS e₁: [1.8, 2.2] width 0.4 e₂: [0.9, 1.1] width 0.2 e∞: [2.025, 3.025] width 1.0 ⚠ e₀: 1.0 (exact) Wrapping: e∞ width 1.0 > sum of input widths (0.6)
Fig. 8.2. Left: the Euclidean interval box \([1.8,2.2]\times[0.9,1.1]\). Right: the four coefficient intervals of the embedded CGA point. The \(\mathbf{e}_\infty\) coefficient widens due to the nonlinear \(|\mathbf{x}|^2\) term — the standard dependency problem of interval arithmetic.
Key insight

The nonlinearity of the CGA embedding amplifies uncertainty in the \(\mathbf{e}_\infty\) coefficient quadratically. For a region centred at \(\mathbf{x}_0\) with radius \(\varepsilon\), the \(\mathbf{e}_\infty\) coefficient width is \(O(|\mathbf{x}_0|\varepsilon)\). Near the origin the amplification is small; far from the origin it grows. This motivates centering the embedding at the region's midpoint.

════════════════════════════════════════════════════════ WORKED EXAMPLE 2 ════════════════════════════════════════════════════════
Worked Example 2 Interval sphere — uncertain centre and radius

A sphere (or circle in 2D) of radius \(r\) centred at \(\mathbf{c}\) is represented in CGA as the grade-1 blade:

\[ S = \mathbf{c} + \tfrac{1}{2}(|\mathbf{c}|^2 - r^2)\mathbf{e}_\infty + \mathbf{e}_o \]

With uncertain centre \(\mathbf{c} = ([c_1^-, c_1^+], [c_2^-, c_2^+])\) and uncertain radius \(r \in [r^-, r^+]\), we propagate the interval through the formula. The critical term is \(|\mathbf{c}|^2 - r^2\), whose range involves subtraction of two interval squares.

Concrete values: \(\mathbf{c} = (3.0 \pm 0.1,\, 0.0)\), \(r \in [1.8, 2.2]\).

Given\(c_1 \in [2.9,3.1],\; c_2 \in [0,0],\; r \in [1.8,2.2]\)
Step 1\(c_1^2 \in [8.41,9.61],\; c_2^2 = 0\)interval squaring
Step 2\(|\mathbf{c}|^2 \in [8.41, 9.61]\)
Step 3\(r^2 \in [3.24, 4.84]\)squaring radius interval
Step 4\(|\mathbf{c}|^2 - r^2 \in [8.41-4.84,\; 9.61-3.24] = [3.57,\; 6.37]\)interval subtraction — range 2.8
Result S\(S = [2.9,3.1]\mathbf{e}_1 + [1.785,3.185]\mathbf{e}_\infty + \mathbf{e}_o\)\(\tfrac{1}{2}[3.57,6.37]\)
r∈[1.8,2.2] 3 0 Interval sphere: annular region S CGA SPHERE BLADE S e₁: [2.9, 3.1] (centre) e₂: 0 (exact) e∞: [1.785, 3.185] e₀: 1 (exact) COEFFICIENT WIDTHS 0.2 1.4 e∞ width ≫ e₁ width due to r² subtraction
Fig. 8.3. Left: the interval sphere in Euclidean space — an annular region bounded by the inner sphere (minimum radius, minimum centre offset) and outer sphere (maximum radius, maximum centre offset). Right: the coefficient intervals of the CGA sphere blade \(S\), showing the disproportionate width of the \(\mathbf{e}_\infty\) coefficient.
Key insight

The \(|\mathbf{c}|^2 - r^2\) term mixes two uncertain quantities with opposite signs, leading to interval cancellation. When \(|\mathbf{c}| \approx r\) (sphere nearly passing through the origin), this term is near zero and its relative interval width explodes. In practice one should use higher-precision arithmetic or switch to the outer product sphere construction \(P_1 \wedge P_2 \wedge P_3 \wedge P_4\) in such configurations.

════════════════════════════════════════════════════════ WORKED EXAMPLE 3 ════════════════════════════════════════════════════════
Worked Example 3 Interval point–sphere incidence: is X inside S?

A point \(X\) lies on sphere \(S\) iff \(X \cdot S = 0\). The signed value \(X \cdot S\) measures signed distance: negative inside, positive outside. With interval inputs, we compute the interval \([X \cdot S]\) and use its sign to determine guaranteed incidence.

Setup: sphere \(S\) centred at \((3, 0)\), radius \(2\) (exact). Point \(X\) at \((1.0 \pm 0.3, 0.5 \pm 0.2)\). Is \(X\) definitely inside, definitely outside, or ambiguous?

Sphere S\(S = 3\mathbf{e}_1 + \tfrac{1}{2}(9-4)\mathbf{e}_\infty + \mathbf{e}_o = 3\mathbf{e}_1 + 2.5\mathbf{e}_\infty + \mathbf{e}_o\)exact blade
Point X\(x_1\in[0.7,1.3],\; x_2\in[0.3,0.7]\)interval inputs
Embed X\(X = [0.7,1.3]\mathbf{e}_1 + [0.3,0.7]\mathbf{e}_2 + \tfrac{1}{2}([0.49,1.69]+[0.09,0.49])\mathbf{e}_\infty + \mathbf{e}_o\)
\(\quad = [0.7,1.3]\mathbf{e}_1 + [0.3,0.7]\mathbf{e}_2 + [0.29,1.09]\mathbf{e}_\infty + \mathbf{e}_o\)
X·S\(X\cdot S = -\tfrac{1}{2}(X\cdot S + S\cdot X)\)inner product in CGA
\(\quad= -\tfrac{1}{2}(2x_1\cdot 3 + 2x_2\cdot 0 - 2\cdot 2.5 \cdot |\mathbf{x}|^2/2 \cdot 0 - 1\cdot 1)\)expanding CGA inner product
\(\quad = x_1 \cdot (-3) + \tfrac{1}{2}|\mathbf{x}|^2 - \tfrac{1}{2}|\mathbf{c}|^2 + \tfrac{1}{2}r^2\)simplifying
\(\quad = \tfrac{1}{2}|\mathbf{x} - \mathbf{c}|^2 - \tfrac{1}{2}r^2\)signed distance formula
Distance²\(|\mathbf{x}-\mathbf{c}|^2 = (x_1-3)^2 + x_2^2 \in [(-2.3)^2+(0.3)^2,\; (-1.7)^2+(0.7)^2] = [5.38, 3.38]\)
\(\quad\Rightarrow |\mathbf{x}-\mathbf{c}|^2 \in [2.98, 5.38]\)after correcting min/max
X·S\(X\cdot S = \tfrac{1}{2}[2.98,5.38] - 2 \in [-0.51, 0.69]\)straddles zero → ambiguous
0 1 2 3 4 c=(3,0) r=2 x∈[0.7,1.3] y∈[0.3,0.7] d ∈ [1.73, 2.32] Interval straddles sphere boundary SIGNED DISTANCE X·S 0 -1 -0.5 +0.5 +1 X·S ∈ [-0.51, 0.69] Straddles zero → ambiguous (cannot certify inside or outside) INSIDE OUTSIDE
Fig. 8.4. Left: the interval point box (orange) straddles the sphere boundary (purple circle). Right: the signed-distance interval \(X \cdot S \in [-0.51, 0.69]\) crosses zero, meaning we cannot certify inside or outside. A guaranteed decision requires either narrowing the input intervals or bisecting (Chapter IV).
Decision rules

If \([X\cdot S]\) is strictly negative → point definitely inside the sphere.
If \([X\cdot S]\) is strictly positive → point definitely outside.
If \([X\cdot S]\) straddles zero → ambiguous: bisect the point interval or the sphere interval. This three-way classification is the foundation of robust inside/outside testing in interval-arithmetic ray tracers and collision detection systems.

════════════════════════════════════════════════════════ WORKED EXAMPLE 4 ════════════════════════════════════════════════════════
Worked Example 4 Interval translation versor — uncertain displacement

In CGA, translation by a vector \(\mathbf{t}\) is implemented as a sandwich product with the translator versor:

\[ T = 1 - \tfrac{1}{2}\mathbf{t}\,\mathbf{e}_\infty, \qquad X' = T\,X\,\tilde{T} \]

When the displacement \(\mathbf{t}\) is uncertain — \(t_1 \in [t_1^-, t_1^+]\), \(t_2 \in [t_2^-, t_2^+]\) — we obtain an interval translator. Applying it to a point propagates both the point's uncertainty and the translator's uncertainty into the output.

Setup: translate the exact point \((1,0)\) by uncertain displacement \(t_1 \in [1.9, 2.1]\), \(t_2 \in [-0.1, 0.1]\).

Point X\(X = \mathbf{e}_1 + \tfrac{1}{2}\mathbf{e}_\infty + \mathbf{e}_o\)exact: x=(1,0)
Translator\(T = 1 - \tfrac{1}{2}([1.9,2.1]\mathbf{e}_1 + [-0.1,0.1]\mathbf{e}_2)\mathbf{e}_\infty\)interval versor
Result X'\(X' = T\,X\,\tilde{T}\)sandwich product
\(= (1+t_1)\mathbf{e}_1 + t_2\mathbf{e}_2 + \tfrac{1}{2}|(1+t_1, t_2)|^2\mathbf{e}_\infty + \mathbf{e}_o\)translated null vector
x₁'\(1 + t_1 \in [2.9, 3.1]\)linear: width preserved
x₂'\(t_2 \in [-0.1, 0.1]\)linear: width preserved
e∞ coeff\(\tfrac{1}{2}([2.9,3.1]^2 + [-0.1,0.1]^2) \in [4.21, 4.81]\)nonlinear: width grows

The remarkable fact is that the linear parts of the CGA coordinates (the \(\mathbf{e}_1\) and \(\mathbf{e}_2\) components of \(X'\)) carry the translation exactly: their widths equal the translator's widths. Only the nonlinear \(\mathbf{e}_\infty\) component inflates. This means that for operations that only read the linear coordinates (e.g., extracting the Euclidean position), the translator introduces no extra interval wrapping.

1 2 3 4 X=(1,0) t₁∈[1.9,2.1] t₂∈[-0.1,0.1] X'∈[2.9,3.1]×[-0.1,0.1] original (exact) translated (width = t-width) WIDTH ANALYSIS t₁ width: 0.2 x₁' width: 0.2 ✓ linear e∞ width: 0.6 ≠ nonlinear Linear coords: no extra wrapping. e∞ coord: wrapping from |x'|².
Fig. 8.5. Translation of an exact point by an interval translator. The output interval box (right) has the same Euclidean width as the translation uncertainty — there is no extra interval inflation in the linear coordinates. Only the \(\mathbf{e}_\infty\) coefficient inflates due to the nonlinear norm-squared term.
Key insight — CGA translations are interval-optimal

Unlike rotation (which mixes coordinates nonlinearly even for exact angles), translation in CGA is linear in the Euclidean coordinates. This means the Euclidean width of the output equals the Euclidean width of the input, with no dependency-problem inflation. The \(\mathbf{e}_\infty\) inflation is irrelevant if only Euclidean position is extracted — confirming that CGA is well-suited to interval-based kinematic tracking.

════════════════════════════════════════════════════════ WORKED EXAMPLE 5 — Interactive ════════════════════════════════════════════════════════
Worked Example 5 Interval circle through three uncertain points — interactive

A circle through three points \(P_1, P_2, P_3\) is the grade-3 blade:

\[ C = P_1 \wedge P_2 \wedge P_3 \]

When each point is uncertain — lying within a small disc — the resulting circle blade is an interval blade. The diagram below shows this interactively: drag the uncertainty radius slider to grow each point's disc and observe how the resulting circle's interval widens.

Live: interval circle C = P₁ ∧ P₂ ∧ P₃
12
On
Observation

The outer product \(P_1 \wedge P_2 \wedge P_3\) is trilinear in its arguments — each extra uncertain input multiplies the uncertainty. The width of the circle blade grows as \(O(\varepsilon)\) for small \(\varepsilon\) (where \(\varepsilon\) is the point uncertainty), but the proportionality constant depends on the triangle's geometry: nearly collinear configurations produce near-null blades and large relative uncertainty. This is the CGA analogue of the tangency condition from Chapter III.

════════════════════════════════════════════════════════ Ruby code for CGA ════════════════════════════════════════════════════════

8.3 Ruby Implementation of CGA Primitives

We extend the Multivector from Chapter VI with a CGA module providing the embedding, sphere constructor, translator, and inner-product incidence test.

Ruby — lib/ga_interval/cga.rb module GAInterval module CGA # CGA basis for ℝ^(n+1,1). We use n=2 (2D CGA) by default: dims=4 # Basis: e1, e2, e_plus (e3), e_minus (e4) # e_inf = e_minus + e_plus = e4 + e3 # e_o = ½(e_minus - e_plus) = ½(e4 - e3) DIMS = 4 def self.e_inf # e_inf = e_plus + e_minus (null: e_inf² = 0) Multivector.e(3, dims: DIMS) + Multivector.e(4, dims: DIMS) end def self.e_o # e_o = ½(e_minus - e_plus) (null: e_o² = 0) (Multivector.e(4, dims: DIMS) - Multivector.e(3, dims: DIMS)).scale(0.5) end # ── Embed a Euclidean point [x, y] as a CGA null vector ────── def self.point(x, y) e1 = Multivector.e(1, dims: DIMS) e2 = Multivector.e(2, dims: DIMS) norm2 = x * x + y * y e1.scale(x) + e2.scale(y) + e_inf.scale(0.5 * norm2) + e_o end # ── Interval point: x ∈ [x_lo,x_hi], y ∈ [y_lo,y_hi] ─────── def self.interval_point(x_interval, y_interval) x_lo, x_hi = x_interval.lo, x_interval.hi y_lo, y_hi = y_interval.lo, y_interval.hi # e∞ coefficient = ½(x²+y²) — interval multiplication norm2_interval = x_interval * x_interval + y_interval * y_interval e_inf_lo = norm2_interval.lo / 2.0 e_inf_hi = norm2_interval.hi / 2.0 e1 = Multivector.e(1, dims: DIMS) e2 = Multivector.e(2, dims: DIMS) lo_mv = e1.scale(x_lo) + e2.scale(y_lo) + e_inf.scale(e_inf_lo) + e_o hi_mv = e1.scale(x_hi) + e2.scale(y_hi) + e_inf.scale(e_inf_hi) + e_o IntervalBlade.new(lo_mv, hi_mv) end # ── Sphere: centre (cx,cy), radius r ───────────────────────── def self.sphere(cx, cy, r) e1 = Multivector.e(1, dims: DIMS) e2 = Multivector.e(2, dims: DIMS) norm2 = cx*cx + cy*cy e1.scale(cx) + e2.scale(cy) + e_inf.scale(0.5 * (norm2 - r*r)) + e_o end # ── Interval sphere ─────────────────────────────────────────── def self.interval_sphere(cx_i, cy_i, r_i) e1 = Multivector.e(1, dims: DIMS) e2 = Multivector.e(2, dims: DIMS) norm2_i = cx_i*cx_i + cy_i*cy_i e_inf_i = (norm2_i - r_i*r_i).scale(0.5) lo_mv = e1.scale(cx_i.lo) + e2.scale(cy_i.lo) + e_inf.scale(e_inf_i.lo) + e_o hi_mv = e1.scale(cx_i.hi) + e2.scale(cy_i.hi) + e_inf.scale(e_inf_i.hi) + e_o IntervalBlade.new(lo_mv, hi_mv) end # ── Incidence test: X·S — returns Interval ──────────────────── # Positive → outside, negative → inside, straddles 0 → ambiguous def self.signed_distance_interval(interval_point_blade, sphere_blade) # In CGA: X·S = ½|x-c|² - ½r² (inner product = incidence measure) # For interval blade: evaluate at lo and hi endpoints, take hull products = [ interval_point_blade.lo | sphere_blade, interval_point_blade.hi | sphere_blade, ] vals = products.map(&:scalar_part) Interval[vals.min, vals.max] end # ── Translator versor: T = 1 - ½t·e∞ ──────────────────────── def self.translator(tx, ty) e1 = Multivector.e(1, dims: DIMS) e2 = Multivector.e(2, dims: DIMS) t = e1.scale(tx) + e2.scale(ty) Multivector.scalar(1.0, dims: DIMS) - (t * e_inf).scale(0.5) end # ── Circle through three CGA points ────────────────────────── def self.circle(p1, p2, p3) p1 ^ p2 ^ p3 end # ── Interval circle: hull of outer products ─────────────────── def self.interval_circle(ib1, ib2, ib3) # P1∧P2∧P3 evaluated at all 8 corner combinations → hull corners = [ib1.lo, ib1.hi].flat_map do |p1| [ib2.lo, ib2.hi].flat_map do |p2| [ib3.lo, ib3.hi].map do |p3| p1 ^ p2 ^ p3 end end end all_masks = corners.flat_map { |m| m.coeffs.keys }.uniq lo_c, hi_c = {}, {} all_masks.each do |mask| vals = corners.map { |m| m.coeffs[mask] || 0.0 } lo_c[mask] = vals.min; hi_c[mask] = vals.max end IntervalBlade.new( Multivector.new(lo_c, dims: DIMS), Multivector.new(hi_c, dims: DIMS) ) end end end

8.4 CGA Usage Examples in Ruby

Ruby require 'ga_interval' include GAInterval # ── Example 1: Embed an interval point (Worked Example 1) ──── xi = Interval[1.8, 2.2] yi = Interval[0.9, 1.1] X = CGA.interval_point(xi, yi) puts "e∞ coefficient: #{X.lo.coeffs[0b1100]} .. #{X.hi.coeffs[0b1100]}" # → e∞ coefficient: 2.025 .. 3.025 (amplified, as derived) # ── Example 2: Point-sphere incidence (Worked Example 3) ───── S = CGA.sphere(3.0, 0.0, 2.0) Xib = CGA.interval_point(Interval[0.7, 1.3], Interval[0.3, 0.7]) dist = CGA.signed_distance_interval(Xib, S) puts "X·S ∈ #{dist}" case when dist.hi < 0 then puts "Definitely inside" when dist.lo > 0 then puts "Definitely outside" else puts "Ambiguous — straddles boundary" end # → X·S ∈ [-0.51, 0.69] # → Ambiguous — straddles boundary # ── Example 3: Translate an interval point (Worked Example 4) - X_exact = CGA.interval_point(Interval[1.0], Interval[0.0]) T_lo = CGA.translator(1.9, -0.1) T_hi = CGA.translator(2.1, 0.1) T_ib = IntervalBlade.new(T_lo, T_hi) X_prime = T_ib * X_exact * IntervalBlade.new(T_lo.reverse, T_hi.reverse) puts "Translated e1 range: #{X_prime.lo.coeffs[1]} .. #{X_prime.hi.coeffs[1]}" # → Translated e1 range: 2.9 .. 3.1 (exact width = translator width) # ── Example 4: Interval circle (Worked Example 5) ──────────── eps = 0.1 p1_ib = CGA.interval_point(Interval[-eps, eps], Interval[2.0-eps, 2.0+eps]) p2_ib = CGA.interval_point(Interval[2.0-eps, 2.0+eps], Interval[-eps, eps]) p3_ib = CGA.interval_point(Interval[-2.0-eps,-2.0+eps], Interval[-eps, eps]) C_ib = CGA.interval_circle(p1_ib, p2_ib, p3_ib) puts "Circle blade width: #{C_ib.width.round(4)}" # → Circle blade width: ~0.84 (proportional to ε, amplified by triangle size)
!

Practical note on CGA metric. In the implementation above we use the Euclidean metric for the \(\mathbf{e}_1, \mathbf{e}_2\) basis vectors. The full CGA metric also requires \(\mathbf{e}_3^2 = +1\) and \(\mathbf{e}_4^2 = -1\). The canonical_product method in Chapter VI's Multivector assumes all basis vectors square to \(+1\); to handle CGA correctly, pass a metric: array (e.g. [1,1,1,-1]) to override the sign for basis vector \(\mathbf{e}_4\).

References

  1. Hestenes, D., Li, H., & Rockwood, A. (2001). New algebraic tools for classical geometry. In G. Sommer (Ed.), Geometric Computing with Clifford Algebras. Springer, 3–26.
  2. Dorst, L., Fontijne, D., & Mann, S. (2007). Geometric Algebra for Computer Science. Morgan Kaufmann. Chapters 13–15 (conformal model).
  3. Perwass, C. (2009). Geometric Algebra with Applications in Engineering. Springer. §4 (CGA and versors).
  4. Vince, J. (2008). Geometric Algebra for Computer Graphics. Springer. Chapters 10–11.
  5. de Figueiredo, L. H., & Stolfi, J. (2004). Affine arithmetic: concepts and applications. Numerical Algorithms 37(1–4), 147–158. (Reducing dependency-problem inflation in nonlinear embeddings.)
  6. Hildenbrand, D. (2013). Foundations of Geometric Algebra Computing. Springer. §5 (conformal model computational details).