mirror of https://github.com/tidwall/tile38.git
72 lines
1.9 KiB
Go
72 lines
1.9 KiB
Go
package algo
|
|
|
|
// Box performs simple box-distance algorithm on rectangles. When wrapX
|
|
// is provided, the operation does a cylinder wrapping of the X value to allow
|
|
// for antimeridian calculations. When itemDist is provided (not nil), it
|
|
// becomes the caller's responsibility to return the box-distance.
|
|
func Box(
|
|
targetMin, targetMax [2]float64, wrapX bool,
|
|
itemDist func(min, max [2]float64, data interface{}) float64,
|
|
) (
|
|
algo func(min, max [2]float64, data interface{}, item bool) (dist float64),
|
|
) {
|
|
return func(min, max [2]float64, data interface{}, item bool) (dist float64) {
|
|
if item && itemDist != nil {
|
|
return itemDist(min, max, data)
|
|
}
|
|
return BoxDistCalc(targetMin, targetMax, min, max, wrapX)
|
|
}
|
|
}
|
|
|
|
func mmin(x, y float64) float64 {
|
|
if x < y {
|
|
return x
|
|
}
|
|
return y
|
|
}
|
|
|
|
func mmax(x, y float64) float64 {
|
|
if x > y {
|
|
return x
|
|
}
|
|
return y
|
|
}
|
|
|
|
// BoxDistCalc returns the distance from rectangle A to rectangle B. When wrapX
|
|
// is provided, the operation does a cylinder wrapping of the X value to allow
|
|
// for antimeridian calculations.
|
|
func BoxDistCalc(aMin, aMax, bMin, bMax [2]float64, wrapX bool) float64 {
|
|
var dist float64
|
|
var squared float64
|
|
|
|
// X
|
|
squared = mmax(aMin[0], bMin[0]) - mmin(aMax[0], bMax[0])
|
|
if wrapX {
|
|
squaredLeft := mmax(aMin[0]-360, bMin[0]) - mmin(aMax[0]-360, bMax[0])
|
|
squaredRight := mmax(aMin[0]+360, bMin[0]) - mmin(aMax[0]+360, bMax[0])
|
|
squared = mmin(squared, mmin(squaredLeft, squaredRight))
|
|
}
|
|
if squared > 0 {
|
|
dist += squared * squared
|
|
}
|
|
|
|
// Y
|
|
squared = mmax(aMin[1], bMin[1]) - mmin(aMax[1], bMax[1])
|
|
if squared > 0 {
|
|
dist += squared * squared
|
|
}
|
|
|
|
return dist
|
|
}
|
|
|
|
// contains return struct when b is fully contained inside of n
|
|
func intersects(aMin, aMax, bMin, bMax [2]float64) bool {
|
|
if bMin[0] > aMax[0] || bMax[0] < aMin[0] {
|
|
return false
|
|
}
|
|
if bMin[1] > aMax[1] || bMax[1] < aMin[1] {
|
|
return false
|
|
}
|
|
return true
|
|
}
|