95 lines
1.7 KiB
Go
95 lines
1.7 KiB
Go
package util
|
|
|
|
import (
|
|
"galaxy/calc"
|
|
"math"
|
|
)
|
|
|
|
// WrapF maps value into the half-open interval [0, float64(size)).
|
|
// It supports negative input values and is used for torus coordinates
|
|
// when the coordinate is represented as float64.
|
|
//
|
|
// size must be greater than zero.
|
|
func WrapF(value float64, size int) float64 {
|
|
if size <= 0 {
|
|
panic("WrapF: size must be > 0")
|
|
}
|
|
|
|
s := float64(size)
|
|
|
|
r := math.Mod(value, s)
|
|
if r < 0 {
|
|
r += s
|
|
}
|
|
|
|
// Protect against a possible boundary artifact and keep result in [0, s).
|
|
// In normal cases math.Mod already gives a value with |r| < s.
|
|
if r >= s {
|
|
r -= s
|
|
}
|
|
|
|
return r
|
|
}
|
|
|
|
func NextTravelCoord(w, h uint32, x1, y1, x2, y2, delta float64) (float64, float64, bool) {
|
|
deltaX, deltaY := calc.Deltas(w, h, x1, y1, x2, y2)
|
|
distance := math.Hypot(deltaX, deltaY)
|
|
if distance <= delta {
|
|
return x2, y2, true
|
|
}
|
|
// [ ] refactor - remove extra vars
|
|
xa := 0.
|
|
ya := 0.
|
|
xb := deltaX
|
|
yb := deltaY
|
|
d := distance
|
|
d2 := delta
|
|
xc := xa - (d2*(xa-xb))/d
|
|
yc := ya - (d2*(ya-yb))/d
|
|
|
|
// ---
|
|
var tx, ty float64
|
|
|
|
if math.Abs(x2-x1) > float64(w/2) {
|
|
// moving across X boundary
|
|
if x2 < x1 {
|
|
// moving across higher border
|
|
tx = math.Mod(x1+xc, float64(w))
|
|
} else {
|
|
// moving across lower border
|
|
tx = x1 - xc
|
|
if tx < 0 {
|
|
tx = float64(w) + tx
|
|
}
|
|
}
|
|
} else {
|
|
if x2 < x1 {
|
|
tx = x1 - xc
|
|
} else {
|
|
tx = x1 + xc
|
|
}
|
|
}
|
|
|
|
if math.Abs(y2-y1) > float64(h/2) {
|
|
// moving across Y boundary
|
|
if y2 < y1 {
|
|
// moving across higher border
|
|
ty = math.Mod(y1+yc, float64(h))
|
|
} else {
|
|
// moving across lower border
|
|
ty = y1 - yc
|
|
if ty < 0 {
|
|
ty = float64(h) + ty
|
|
}
|
|
}
|
|
} else {
|
|
if y2 < y1 {
|
|
ty = y1 - yc
|
|
} else {
|
|
ty = y1 + yc
|
|
}
|
|
}
|
|
|
|
return tx, ty, false
|
|
}
|