ludic/packages/ludic.compass/bearing.ludic

61 lines
2.5 KiB
Text

# bearing.ludic - the frame's marks as the strip reads them: how many, each one, where it bears
# from the viewer's facing and how far it is. A heading is the world's (0 toward -z, a quarter
# turn toward -x), a bearing is the heading less the viewer's yaw, in -pi .. pi.
export function compass_count(compass_st: CompassState) -> int {
if compass_st.cmp_list == null { return 0 }
return len(compass_st.cmp_list)
}
# the i-th mark, or an empty one past the end
export function compass_at(compass_st: CompassState, i: int) -> CompassMark {
if i < 0 or i >= compass_count(compass_st) { return compass_st.cmp_none }
return compass_st.cmp_list[i]
}
export function compass_wrap(a: float) -> float {
var r = a
let turn = 2.0 * CMP_PI
while r > CMP_PI { r -= turn }
while r < -CMP_PI { r += turn }
return r
}
export function compass_heading(dx: float, dz: float) -> float { return Math.atan2(-dx, -dz) }
# a world heading as the strip sees it
export function compass_rel(heading: float) -> float { return compass_wrap(heading - CompassWorld.yaw()) }
export function compass_bearing_to(x: float, z: float) -> float { return compass_rel(compass_heading(x - CompassWorld.x(), z - CompassWorld.z())) }
export function compass_dist_to(x: float, z: float) -> float {
let dx = x - CompassWorld.x()
let dz = z - CompassWorld.z()
return Math.sqrt(dx * dx + dz * dz)
}
export function compass_bearing(compass_st: CompassState, i: int) -> float {
let m = compass_at(compass_st, i)
return compass_bearing_to(m.x, m.z)
}
export function compass_dist(compass_st: CompassState, i: int) -> float {
let m = compass_at(compass_st, i)
return compass_dist_to(m.x, m.z)
}
# where a bearing falls across a strip showing `half` radians either side: -1 .. 1, or past it
export function compass_strip_t(bearing: float, half: float) -> float { return bearing / Math.max(half, 0.001) }
# the objective: the first tracked mark of the frame, or -1
export function compass_tracked(compass_st: CompassState) -> int {
for i in 0 .. compass_count(compass_st) { if compass_st.cmp_list[i].prio >= COMPASS_TRACKED { return i } }
return -1
}
# which of eight points an offset lies toward: 0 the heading 0, then a quarter turn in two steps
# at a time toward -x (for a world where 0 is north: N, NW, W, SW, S, SE, E, NE)
export function compass_octant(dx: float, dz: float) -> int {
var deg = compass_heading(dx, dz) * 180.0 / CMP_PI
if deg < 0.0 { deg += 360.0 }
return int(Math.floor(deg / 45.0 + 0.5)) % 8
}