# Circle from two points and projected point

Hi Everyone, I’ve been learning GA using enkimute’s Ganja coffeeshop. I have a 2D CGA problem where the wedge of three points does not line up with the points and I wonder what is different.

With three explicit points, this works as expected. However, when one of the points is the projection of a point on a circle, then the resulting circle does not coincide with the projected point.

I wonder if this is because the projection is a point pair? I have used split() to get the correct point.

Instructions: Drag `p1` and observe that circle `edge` does not line up with `s1`.

``````// Create a Clifford Algebra with 3,1 metric for 2D CGA.
Algebra(3,1,()=>{

// The conformal model adds in more element types. (circles, point-pairs)
// We no longer work in a dual space. (so ^ = join and & = meet)
// Vectors are points, Bivectors are point pairs, Trivectors are lines/circles

// We don't work directly in the e3/e4 basis, but instead rotate it so we have
// two null vectors to work with (called origin and infinite)
var ni = 1e4+1e3,           // n-infinite
no = .5e4-.5e3;         // n-origin

// Define points, lines, circles using the null basis.
var point  = (x,y)=>no + x*1e1 + y*1e2 + 0.5*(x*x+y*y)*ni,
line   = (a,b,c)=>!(a*1e1 + b*1e2 + c*ni),
circle = (x,y,r)=>!(point(x,y) - r**2/2*ni);

// Distances and Angles.
var dist=(x,y)=>(2*(x<<y).Length)**0.5,
angle=(x,y)=>Math.acos(!x.Normalized<<!y.Normalized);

// Rotator, Translator
var translate = (v)=>(1-.5*v^ni),
rotate    = (P,a)=>Math.cos(a/2) - Math.sin(a/2)*(1e12-P<<1e12^ni);

// Some identities
var line_through_P_parallel_with_X = (P,X)=>(P^ni)<<X*(P^ni),
project_point_on_circle        = (P,C)=>(P^ni)<<C*C,
project_point_on_line          = (P,L)=>P<<L.Normalized*L.Normalized,
position                       = (X)=>{ X=X/(X^ni); return X/(X<<-ni); },
attitude                       = (X)=>(ni^no<<(X^ni)).Normalized,

// FIXME?
var split_point_pair = (pp) => {
return split(pp)
}

var p1 = point(0, 1.2, 0)
var p2 = () => rotate(0, 2*Math.PI/3)>>>p1
var p3 = () => rotate(0, 2*Math.PI/3)>>>p2

var p4 = () => rotate(0, 2*Math.PI/6)>>>p1
var p5 = () => rotate(0, 2*Math.PI/3)>>>p4
var p6 = () => rotate(0, 2*Math.PI/3)>>>p5

var R = () => p1^p2^p3

var petal = (p) => !(p - 0.4**2/2*ni);

var P1 = () => petal(p1)
var P2 = () => petal(p2)
var P3 = () => petal(p3)
var P4 = () => petal(p4)
var P5 = () => petal(p5)
var P6 = () => petal(p6)

var origin = point(0, 0, 0)

var X14 = () => split_point_pair(P1 & P4);
var s1 = () => split_point_pair(project_point_on_circle(origin, P4)) // X14 + (X14 ^ ni).Normalized * 0.1

console.log("p2", p2())
console.log("s1", s1())

// FIXME: circle doesn't like s1
var e1 = () => p1 ^ p2 ^ (position(s1));

// Graph these items.
document.body.appendChild(this.graph([
"2D CGA - drag p1","",                  // title                   // circles
0x44AA44,                // lines
0x4444FF,  p2, "p2", p3, "p3",    // points
0x6633FF, p4, "p4", p5, "p5", p6, "p6",

0xFF8888, R, "R", P1, "P1", P2, "P2", P3, "P3",
0xBB88BB, P4, "P4", P5, "P5", P6, "P6",

0x44AA44, // X14, "X14",
0x4444FF, s1, "s1",
e1, "edge", origin, "O",

0x33FF55, p1, "p1",
],{conformal:true,grid:true}));                 // conformal flag!
});
``````

the new split function is:

``````  var split = (P) => {
const denominator = Math.sqrt(-(P * ~P)[0])
const A = (-1 + P/denominator) * (P | ni)
return A
}
``````