Files
vRp.CD2g_test/utils/geometry/position.go
T
kercylan98 18b8729a94 💥 几何库优化
2023-06-17 19:33:59 +08:00

150 lines
4.6 KiB
Go

package geometry
import (
"github.com/kercylan98/minotaur/utils/generic"
"math"
)
// Point 表示了一个由 x、y 坐标组成的点
type Point[V generic.Number] [2]V
// NewPoint 创建一个由 x、y 坐标组成的点
func NewPoint[V generic.Number](x, y V) Point[V] {
return Point[V]{x, y}
}
// GetX 返回该点的 x 坐标
func (slf Point[V]) GetX() V {
return slf[0]
}
// GetY 返回该点的 y 坐标
func (slf Point[V]) GetY() V {
return slf[1]
}
// GetXY 返回该点的 x、y 坐标
func (slf Point[V]) GetXY() (x, y V) {
return slf[0], slf[1]
}
// GetPos 返回该点位于特定宽度的二维数组的顺序位置
func (slf Point[V]) GetPos(width V) V {
return CoordinateArrayToPos(width, slf)
}
// GetOffset 获取偏移后的新坐标
func (slf Point[V]) GetOffset(x, y V) Point[V] {
return NewPoint(slf.GetX()+x, slf.GetY()+y)
}
// Equal 返回两个点是否相等
func (slf Point[V]) Equal(point Point[V]) bool {
return slf.GetX() == point.GetX() && slf.GetY() == point.GetY()
}
// Copy 复制一个点位置
func (slf Point[V]) Copy() Point[V] {
return CoordinateArrayCopy(slf)
}
// NewPointCap 创建一个由 x、y 坐标组成的点,这个点具有一个数据容量
func NewPointCap[V generic.Number, D any](x, y V) PointCap[V, D] {
return PointCap[V, D]{
Point: NewPoint(x, y),
}
}
// NewPointCapWithData 通过设置数据的方式创建一个由 x、y 坐标组成的点,这个点具有一个数据容量
func NewPointCapWithData[V generic.Number, D any](x, y V, data D) PointCap[V, D] {
return PointCap[V, D]{
Point: NewPoint(x, y),
Data: data,
}
}
// PointCap 表示了一个由 x、y 坐标组成的点,这个点具有一个数据容量
type PointCap[V generic.Number, D any] struct {
Point[V]
Data D
}
// GetData 获取数据
func (slf PointCap[V, D]) GetData() D {
return slf.Data
}
// CoordinateToCoordinateArray 将坐标转换为x、y的坐标数组
func CoordinateToCoordinateArray[V generic.Number](x, y V) Point[V] {
return [2]V{x, y}
}
// CoordinateToPos 将坐标转换为二维数组的顺序位置坐标
// - 需要确保x的取值范围必须小于width,或者将会得到不正确的值
func CoordinateToPos[V generic.Number](width, x, y V) V {
return y*width + x
}
// CoordinateArrayToCoordinate 将坐标数组转换为x和y坐标
func CoordinateArrayToCoordinate[V generic.Number](position Point[V]) (x, y V) {
return position[0], position[1]
}
// CoordinateArrayToPos 将坐标转换为二维数组的顺序位置
// - 需要确保x的取值范围必须小于width,或者将会得到不正确的值
func CoordinateArrayToPos[V generic.Number](width V, xy Point[V]) V {
return CoordinateToPos(width, xy[0], xy[1])
}
// PosToCoordinate 通过宽度将一个二维数组的顺序位置转换为xy坐标
func PosToCoordinate[V generic.Number](width, pos V) (x, y V) {
x = V(math.Mod(float64(pos), float64(width)))
y = pos / width
return x, y
}
// PosToCoordinateArray 通过宽度将一个二维数组的顺序位置转换为x、y的坐标数组
func PosToCoordinateArray[V generic.Number](width, pos V) Point[V] {
return [2]V{V(math.Mod(float64(pos), float64(width))), pos / width}
}
// PosToCoordinateX 通过宽度将一个二维数组的顺序位置转换为X坐标
func PosToCoordinateX[V generic.Number](width, pos V) V {
return V(math.Mod(float64(pos), float64(width)))
}
// PosToCoordinateY 通过宽度将一个二维数组的顺序位置转换为Y坐标
func PosToCoordinateY[V generic.Number](width, pos V) V {
return pos / width
}
// CoordinateArrayCopy 复制一个坐标数组
func CoordinateArrayCopy[V generic.Number](position Point[V]) Point[V] {
return NewPoint(position[0], position[1])
}
// CoordinateArrayToPosWithMulti 将一组坐标转换为二维数组的顺序位置
// - 需要确保x的取值范围必须小于width,或者将会得到不正确的值
func CoordinateArrayToPosWithMulti[V generic.Number](width V, xys ...Point[V]) []V {
var result = make([]V, len(xys), len(xys))
for i := 0; i < len(xys); i++ {
result[i] = CoordinateArrayToPos(width, xys[i])
}
return result
}
// PosToCoordinateArrayWithMulti 将一组二维数组的顺序位置转换为一组数组坐标
func PosToCoordinateArrayWithMulti[V generic.Number](width V, positions ...V) []Point[V] {
var result = make([]Point[V], len(positions))
for i := 0; i < len(positions); i++ {
result[i] = PosToCoordinateArray(width, positions[i])
}
return result
}
// PosSameRow 返回两个顺序位置在同一宽度是否位于同一行
func PosSameRow[V generic.Number](width, pos1, pos2 V) bool {
return (pos1 / width) == (pos2 / width)
}