module Engine export Construction, mprod import Subscripts using LinearAlgebra using AbstractAlgebra using Groebner # --- primitve elements --- mutable struct Point{T} coords::Union{Vector{MPolyRingElem{T}}, Nothing} vec::Union{Vector{MPolyRingElem{T}}, Nothing} ## [to do] constructor argument never needed? Point{T}(vec::Union{Vector{MPolyRingElem{T}}, Nothing} = nothing) where T = new(vec) end coordnames(_::Point) = [:xₚ, :yₚ, :zₚ] function buildvec(pt::Point, coordqueue) pt.coords = splice!(coordqueue, 1:3) coordring = parent(coordqueue[1]) pt.vec = [one(coordring), dot(pt.coords, pt.coords), pt.coords...] end mutable struct Sphere{T} coords::Union{Vector{MPolyRingElem{T}}, Nothing} vec::Union{Vector{MPolyRingElem{T}}, Nothing} Sphere{T}(vec::Union{Vector{MPolyRingElem{T}}, Nothing} = nothing) where T = new(vec) end coordnames(_::Sphere) = [:rₛ, :sₛ, :xₛ, :yₛ, :zₛ] function buildvec(sph::Sphere, coordqueue) sph.coords = splice!(coordqueue, 1:5) sph.vec = sph.coords end # --- primitive relations --- abstract type Relation{T} end mprod(v, w) = v[1]*w[2] + w[1]*v[2] - dot(v[3:end], w[3:end]) struct LiesOn{T} <: Relation{T} pt::Point{T} sph::Sphere{T} end struct AlignsWithBy{T} <: Relation{T} sph_v::Sphere{T} sph_w::Sphere{T} cos_angle::T end # --- constructions --- mutable struct Construction{T} points::Vector{Point{T}} spheres::Vector{Sphere{T}} Construction{T}(; points = Point{T}[], spheres = Sphere{T}[]) where T = new{T}(points, spheres) end function Base.push!(ctx::Construction{T}, elem::Point{T}) where T push!(ctx.points, elem) end function Base.push!(ctx::Construction{T}, elem::Sphere{T}) where T push!(ctx.spheres, elem) end function realize(ctx::Construction{T}) where T # collect variable names allcoordnames = Symbol[] elements = vcat(ctx.points, ctx.spheres) for (index, elem) in enumerate(elements) subscript = Subscripts.sub(string(index)) append!(allcoordnames, [Symbol(name, subscript) for name in coordnames(elem)] ) end # construct coordinate ring coordring, coordqueue = polynomial_ring(parent_type(T)(), allcoordnames) # construct coordinate vectors for elem in elements buildvec(elem, coordqueue) end end end # ~~~ sandbox setup ~~~ a = Engine.Point{Rational{Int64}}() b = Engine.Point{Rational{Int64}}() s = Engine.Sphere{Rational{Int64}}() ctx = Engine.Construction{Rational{Int64}}(points = [a]) Engine.push!(ctx, b) Engine.push!(ctx, s)