Darts (Draft)
Steps
- Construct a set of geometries representing a dartboard with individual sector scores
- Develop a model of the dart trajectory with probability density distribution
- Use integration over each geometry to determine the probabilities of particular outcomes
- Calculate expected value for the throw, repeat for other distributions to compare strategies
using CairoMakie
using Colors
using Distributions
using GeometryBasics
using Meshes
using MeshIntegrals
using Unitful
using Unitful.DefaultSymbols: mm, m
red = colorant"red"
black = colorant"black"
white = colorant"white"
green = colorant"green"
# For containing any scored landing region on the dart board
struct ScoredRegion{G, C}
geometry::G
points::Int64
color::C
end
# For defining an annular region
struct Sector{L, A}
r_inner::L
r_outer::L
phi_a::A
phi_b::A
end
Sector(rs, phis) = Sector(rs..., phis...)
# Sector -> Ngon
function _Ngon(sector::Sector; N=8)
ϕs = range(sector.phi_a, sector.phi_b, length=N)
arc_o = [point(sector.r_outer, ϕ) for ϕ in ϕs]
arc_i = [point(sector.r_inner, ϕ) for ϕ in reverse(ϕs)]
return Meshes.Ngon(arc_o..., arc_i...)
end
function _Point2f(p::Meshes.Point)
x, y, z = ustrip.(m, [p.coords.x, p.coords.y, p.coords.z])
return Point2f(y, z)
end
function _Point3f(p::Meshes.Point)
x, y, z = ustrip.(m, [p.coords.x, p.coords.y, p.coords.z])
return Point3f(x, y, z)
end
_poly(circle::Meshes.Circle; N=32) = [(_Point3f(circle(t)) for t in range(0, 1, length=N))...]
_poly(ngon::Meshes.Ngon) = [(_Point3f(pt) for pt in ngon.vertices)...]
_poly2d(circle::Meshes.Circle; N=32) = [(_Point2f(circle(t)) for t in range(0, 1, length=N))...]
_poly2d(ngon::Meshes.Ngon) = [(_Point2f(pt) for pt in ngon.vertices)...]
_poly2d (generic function with 2 methods)
Modeling the Dartboard
Model the dartboard
dartboard_center = Meshes.Point(0m, 0m, 1.5m)
dartboard_plane = Plane(dartboard_center, Meshes.Vec(1, 0, 0))
function point(r::Unitful.Length, ϕ)
t = ustrip(m, r)
dartboard_plane(t * sin(ϕ), t * cos(ϕ))
end
# Scores on the Board
ring1 = [20, 1, 18, 4, 13, 6, 10, 15, 2, 17, 3, 19, 7, 16, 8, 11, 14, 9, 12, 5]
ring2 = 3 .* ring1
ring3 = ring1
ring4 = 2 .* ring1
board_points = hcat(ring1, ring2, ring3, ring4)
# Colors on the board
ring1 = repeat([black, white], 10)
ring2 = repeat([red, green], 10)
ring3 = ring1
ring4 = ring2
board_colors = hcat(ring1, ring2, ring3, ring4)
# Sector geometries
sector_width = 2π/20
sector_centers = [n * sector_width for n in 0:19]
phis_a = sector_centers .- sector_width/2
phis_b = sector_centers .+ sector_width/2
phis = Iterators.zip(phis_a, phis_b)
rs = [ (16mm, 99mm), (99mm, 107mm), (107mm, 162mm), (162mm, 170mm) ]
board_coords = Iterators.product(phis, rs)
board_sectors = map(((phis, rs),) -> Sector(rs, phis), board_coords)
board_ngons = _Ngon.(board_sectors)
# Consolidate the Sectors
sector_data = Iterators.zip(board_ngons, board_points, board_colors)
board_regions = map(args -> ScoredRegion(args...), sector_data)
# Center region
bullseye_inner = ScoredRegion(Meshes.Circle(dartboard_plane, 6.35mm), 50, red)
bullseye_outer = ScoredRegion(_Ngon(Sector((6.35mm, 16.0mm), (0.0, 2π)); N=32), 25, green)
# Get set of all regions
all_regions = vcat(vec(board_regions), bullseye_inner, bullseye_outer)
fig = Figure()
ax = Axis(fig[1, 1], xlabel="y [m]", ylabel="z [m]")
ax.aspect = DataAspect()
for region in board_regions
pts = _poly2d(region.geometry)
poly!(ax, pts, color=region.color)
centerPt = centroid(region.geometry)
center = ustrip.(u"m", [centerPt.coords.y, centerPt.coords.z])
text!(ax, string(region.points), position=Point2f(center...), align=(:center,:center), color=:blue, fontsize=10)
end
fig

Modeling the Dart Trajectory
Define a probability distribution for where the dart will land
# TODO
dist = MvNormal(μs, σs)
Integrand function is the distribution's PDF value at any particular point
# TODO
function integrand(p::Point)
v_error = dist_center - p
pdf(dist, v_error)
end
Example image of trajectory probability distribution on board
Strategy Evaluation
Use these tools to evaluate different aiming/throwing parameters and their impact on expected scores.