✨ 增加圆形相关处理函数
This commit is contained in:
parent
d10c05dfe1
commit
c0570392bf
|
@ -123,7 +123,7 @@ func (slf *Moving2D) handle() {
|
||||||
if interval == 0 {
|
if interval == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
distance := geometry.CalcDistance(x, y, entity.x, entity.y)
|
distance := geometry.CalcDistanceWithCoordinate(x, y, entity.x, entity.y)
|
||||||
moveDistance := interval * (entity.GetSpeed() / (slf.timeUnit / 1000 / 1000))
|
moveDistance := interval * (entity.GetSpeed() / (slf.timeUnit / 1000 / 1000))
|
||||||
if moveDistance >= distance || (x == entity.x && y == entity.y) {
|
if moveDistance >= distance || (x == entity.x && y == entity.y) {
|
||||||
entity.SetPosition(entity.x, entity.y)
|
entity.SetPosition(entity.x, entity.y)
|
||||||
|
|
|
@ -177,7 +177,7 @@ func (slf *AOI2D) refresh(entity game.AOIEntity2D) {
|
||||||
focus := slf.focus[guid]
|
focus := slf.focus[guid]
|
||||||
for eg, e := range focus {
|
for eg, e := range focus {
|
||||||
ex, ey := e.GetPosition()
|
ex, ey := e.GetPosition()
|
||||||
if geometry.CalcDistance(x, y, ex, ey) > vision {
|
if geometry.CalcDistanceWithCoordinate(x, y, ex, ey) > vision {
|
||||||
delete(focus, eg)
|
delete(focus, eg)
|
||||||
delete(slf.focus[eg], guid)
|
delete(slf.focus[eg], guid)
|
||||||
}
|
}
|
||||||
|
@ -243,13 +243,13 @@ func (slf *AOI2D) rangeVisionAreaEntities(entity game.AOIEntity2D, handle func(g
|
||||||
} else {
|
} else {
|
||||||
areaY = y
|
areaY = y
|
||||||
}
|
}
|
||||||
areaDistance := geometry.CalcDistance(x, y, areaX, areaY)
|
areaDistance := geometry.CalcDistanceWithCoordinate(x, y, areaX, areaY)
|
||||||
if areaDistance <= vision {
|
if areaDistance <= vision {
|
||||||
for eg, e := range slf.areas[w][h] {
|
for eg, e := range slf.areas[w][h] {
|
||||||
if eg == guid {
|
if eg == guid {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if ex, ey := e.GetPosition(); geometry.CalcDistance(x, y, ex, ey) > vision {
|
if ex, ey := e.GetPosition(); geometry.CalcDistanceWithCoordinate(x, y, ex, ey) > vision {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
handle(eg, e)
|
handle(eg, e)
|
||||||
|
|
|
@ -37,9 +37,9 @@ func ExampleFind() {
|
||||||
}
|
}
|
||||||
|
|
||||||
paths := astar.Find[geometry.Point[int], int](graph, geometry.NewPoint(1, 1), geometry.NewPoint(8, 6), func(a, b geometry.Point[int]) int {
|
paths := astar.Find[geometry.Point[int], int](graph, geometry.NewPoint(1, 1), geometry.NewPoint(8, 6), func(a, b geometry.Point[int]) int {
|
||||||
return geometry.CalcDistance(geometry.DoublePointToCoordinate(a, b))
|
return geometry.CalcDistanceWithCoordinate(geometry.DoublePointToCoordinate(a, b))
|
||||||
}, func(a, b geometry.Point[int]) int {
|
}, func(a, b geometry.Point[int]) int {
|
||||||
return geometry.CalcDistance(geometry.DoublePointToCoordinate(a, b))
|
return geometry.CalcDistanceWithCoordinate(geometry.DoublePointToCoordinate(a, b))
|
||||||
})
|
})
|
||||||
|
|
||||||
for _, path := range paths {
|
for _, path := range paths {
|
||||||
|
|
|
@ -5,8 +5,53 @@ import (
|
||||||
"math"
|
"math"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Circle 圆形
|
||||||
|
type Circle[V generic.SignedNumber] struct {
|
||||||
|
Shape[V]
|
||||||
|
radius V
|
||||||
|
centroid Point[V]
|
||||||
|
initCentroid bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Radius 获取圆形半径
|
||||||
|
func (slf Circle[V]) Radius() V {
|
||||||
|
if slf.radius > V(-0) {
|
||||||
|
return slf.radius
|
||||||
|
}
|
||||||
|
for _, point := range slf.Points() {
|
||||||
|
slf.radius = CalcDistanceWithPoint(slf.Centroid(), point)
|
||||||
|
return slf.radius
|
||||||
|
}
|
||||||
|
panic("circle without any points")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Centroid 获取圆形质心位置
|
||||||
|
func (slf Circle[V]) Centroid() Point[V] {
|
||||||
|
if slf.initCentroid {
|
||||||
|
return slf.centroid
|
||||||
|
}
|
||||||
|
slf.centroid = CalcRectangleCentroid(slf.Shape)
|
||||||
|
slf.initCentroid = true
|
||||||
|
return slf.centroid
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overlap 与另一个圆是否发生重叠
|
||||||
|
func (slf Circle[V]) Overlap(circle Circle[V]) bool {
|
||||||
|
return CalcDistanceWithPoint(slf.Centroid(), circle.Centroid())/2 > slf.radius
|
||||||
|
}
|
||||||
|
|
||||||
|
// Area 获取圆形面积
|
||||||
|
func (slf Circle[V]) Area() V {
|
||||||
|
return V(math.Pi * math.Pow(float64(slf.Radius()), 2))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Length 获取圆的周长
|
||||||
|
func (slf Circle[V]) Length() V {
|
||||||
|
return V(2 * math.Pi * float64(slf.Radius()))
|
||||||
|
}
|
||||||
|
|
||||||
// GenerateCircle 通过传入圆的半径和需要的点数量,生成一个圆
|
// GenerateCircle 通过传入圆的半径和需要的点数量,生成一个圆
|
||||||
func GenerateCircle[V generic.SignedNumber](radius V, points int) Shape[V] {
|
func GenerateCircle[V generic.SignedNumber](radius V, points int) Circle[V] {
|
||||||
angle := 2.0 * math.Pi / float64(points)
|
angle := 2.0 * math.Pi / float64(points)
|
||||||
var shape = make(Shape[V], points)
|
var shape = make(Shape[V], points)
|
||||||
for i := 0; i < points; i++ {
|
for i := 0; i < points; i++ {
|
||||||
|
@ -15,5 +60,5 @@ func GenerateCircle[V generic.SignedNumber](radius V, points int) Shape[V] {
|
||||||
y := radius * V(math.Sin(curAngle))
|
y := radius * V(math.Sin(curAngle))
|
||||||
shape = append(shape, NewPoint(x, y))
|
shape = append(shape, NewPoint(x, y))
|
||||||
}
|
}
|
||||||
return shape
|
return shape.ToCircle()
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,11 +109,16 @@ func CalcDirection[V generic.SignedNumber](x1, y1, x2, y2 V) Direction {
|
||||||
return DirectionUnknown
|
return DirectionUnknown
|
||||||
}
|
}
|
||||||
|
|
||||||
// CalcDistance 计算两点之间的距离
|
// CalcDistanceWithCoordinate 计算两点之间的距离
|
||||||
func CalcDistance[V generic.SignedNumber](x1, y1, x2, y2 V) V {
|
func CalcDistanceWithCoordinate[V generic.SignedNumber](x1, y1, x2, y2 V) V {
|
||||||
return V(math.Sqrt(math.Pow(float64(x2-x1), 2) + math.Pow(float64(y2-y1), 2)))
|
return V(math.Sqrt(math.Pow(float64(x2-x1), 2) + math.Pow(float64(y2-y1), 2)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CalcDistanceWithPoint 计算两点之间的距离
|
||||||
|
func CalcDistanceWithPoint[V generic.SignedNumber](point1, point2 Point[V]) V {
|
||||||
|
return CalcDistanceWithCoordinate(DoublePointToCoordinate(point1, point2))
|
||||||
|
}
|
||||||
|
|
||||||
// CalcDistanceSquared 计算两点之间的平方距离
|
// CalcDistanceSquared 计算两点之间的平方距离
|
||||||
// - 这个函数的主要用途是在需要计算两点之间距离的情况下,但不需要得到实际的距离值,而只需要比较距离大小。因为平方根运算相对较为耗时,所以在只需要比较大小的情况下,通常会使用平方距离。
|
// - 这个函数的主要用途是在需要计算两点之间距离的情况下,但不需要得到实际的距离值,而只需要比较距离大小。因为平方根运算相对较为耗时,所以在只需要比较大小的情况下,通常会使用平方距离。
|
||||||
func CalcDistanceSquared[V generic.SignedNumber](x1, y1, x2, y2 V) V {
|
func CalcDistanceSquared[V generic.SignedNumber](x1, y1, x2, y2 V) V {
|
||||||
|
|
|
@ -54,7 +54,7 @@ func (slf LineSegment[V]) GetEnd() Point[V] {
|
||||||
|
|
||||||
// GetLength 获取该线段的长度
|
// GetLength 获取该线段的长度
|
||||||
func (slf LineSegment[V]) GetLength() V {
|
func (slf LineSegment[V]) GetLength() V {
|
||||||
return CalcDistance(DoublePointToCoordinate(slf.GetStart(), slf.GetEnd()))
|
return CalcDistanceWithCoordinate(DoublePointToCoordinate(slf.GetStart(), slf.GetEnd()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// PointOnLineSegmentWithCoordinate 通过一个线段两个点的位置和一个点的坐标,判断这个点是否在一条线段上
|
// PointOnLineSegmentWithCoordinate 通过一个线段两个点的位置和一个点的坐标,判断这个点是否在一条线段上
|
||||||
|
|
|
@ -74,7 +74,7 @@ func (slf *NavMesh[V]) Find(point geometry.Point[V], maxDistance V) (distance V,
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
br := geometry.CalcBoundingRadius(meshShape.Shape)
|
br := geometry.CalcBoundingRadius(meshShape.Shape)
|
||||||
distance := geometry.CalcDistance(geometry.DoublePointToCoordinate(
|
distance := geometry.CalcDistanceWithCoordinate(geometry.DoublePointToCoordinate(
|
||||||
geometry.CalcRectangleCentroid(meshShape.Shape),
|
geometry.CalcRectangleCentroid(meshShape.Shape),
|
||||||
point,
|
point,
|
||||||
))
|
))
|
||||||
|
@ -111,13 +111,13 @@ func (slf *NavMesh[V]) FindPath(start, end geometry.Point[V]) (result []geometry
|
||||||
for _, meshShape := range slf.meshShapes {
|
for _, meshShape := range slf.meshShapes {
|
||||||
br := meshShape.BoundingRadius()
|
br := meshShape.BoundingRadius()
|
||||||
|
|
||||||
distance := geometry.CalcDistance(geometry.DoublePointToCoordinate(meshShape.Centroid(), start))
|
distance := geometry.CalcDistanceWithCoordinate(geometry.DoublePointToCoordinate(meshShape.Centroid(), start))
|
||||||
if (distance <= startDistance || startDistance == V(-1)) && distance <= br && meshShape.Contains(start) {
|
if (distance <= startDistance || startDistance == V(-1)) && distance <= br && meshShape.Contains(start) {
|
||||||
startShape = meshShape
|
startShape = meshShape
|
||||||
startDistance = distance
|
startDistance = distance
|
||||||
}
|
}
|
||||||
|
|
||||||
distance = geometry.CalcDistance(geometry.DoublePointToCoordinate(meshShape.Centroid(), end))
|
distance = geometry.CalcDistanceWithCoordinate(geometry.DoublePointToCoordinate(meshShape.Centroid(), end))
|
||||||
if (distance <= endDistance || endDistance == V(-1)) && distance <= br && meshShape.Contains(end) {
|
if (distance <= endDistance || endDistance == V(-1)) && distance <= br && meshShape.Contains(end) {
|
||||||
endShape = meshShape
|
endShape = meshShape
|
||||||
endDistance = distance
|
endDistance = distance
|
||||||
|
@ -127,7 +127,7 @@ func (slf *NavMesh[V]) FindPath(start, end geometry.Point[V]) (result []geometry
|
||||||
if endShape == nil && slf.meshShrinkAmount > V(0) {
|
if endShape == nil && slf.meshShrinkAmount > V(0) {
|
||||||
for _, meshShape := range slf.meshShapes {
|
for _, meshShape := range slf.meshShapes {
|
||||||
br := meshShape.BoundingRadius() + slf.meshShrinkAmount
|
br := meshShape.BoundingRadius() + slf.meshShrinkAmount
|
||||||
distance := geometry.CalcDistance(geometry.DoublePointToCoordinate(meshShape.Centroid(), end))
|
distance := geometry.CalcDistanceWithCoordinate(geometry.DoublePointToCoordinate(meshShape.Centroid(), end))
|
||||||
if distance <= br {
|
if distance <= br {
|
||||||
_, projectionDistance := geometry.ProjectionPointToShape(end, meshShape.Shape)
|
_, projectionDistance := geometry.ProjectionPointToShape(end, meshShape.Shape)
|
||||||
if projectionDistance <= slf.meshShrinkAmount && projectionDistance < endDistance {
|
if projectionDistance <= slf.meshShrinkAmount && projectionDistance < endDistance {
|
||||||
|
@ -145,7 +145,7 @@ func (slf *NavMesh[V]) FindPath(start, end geometry.Point[V]) (result []geometry
|
||||||
if startShape == nil && slf.meshShrinkAmount > 0 {
|
if startShape == nil && slf.meshShrinkAmount > 0 {
|
||||||
for _, meshShape := range slf.meshShapes {
|
for _, meshShape := range slf.meshShapes {
|
||||||
br := meshShape.BoundingRadius() + slf.meshShrinkAmount
|
br := meshShape.BoundingRadius() + slf.meshShrinkAmount
|
||||||
distance := geometry.CalcDistance(geometry.DoublePointToCoordinate(meshShape.Centroid(), start))
|
distance := geometry.CalcDistanceWithCoordinate(geometry.DoublePointToCoordinate(meshShape.Centroid(), start))
|
||||||
if distance <= br {
|
if distance <= br {
|
||||||
_, projectionDistance := geometry.ProjectionPointToShape(start, meshShape.Shape)
|
_, projectionDistance := geometry.ProjectionPointToShape(start, meshShape.Shape)
|
||||||
if projectionDistance <= slf.meshShrinkAmount && projectionDistance < startDistance {
|
if projectionDistance <= slf.meshShrinkAmount && projectionDistance < startDistance {
|
||||||
|
@ -165,9 +165,9 @@ func (slf *NavMesh[V]) FindPath(start, end geometry.Point[V]) (result []geometry
|
||||||
}
|
}
|
||||||
|
|
||||||
path := astar.Find[*shape[V], V](slf, startShape, endShape, func(a, b *shape[V]) V {
|
path := astar.Find[*shape[V], V](slf, startShape, endShape, func(a, b *shape[V]) V {
|
||||||
return geometry.CalcDistance(geometry.DoublePointToCoordinate(a.centroid, b.centroid))
|
return geometry.CalcDistanceWithCoordinate(geometry.DoublePointToCoordinate(a.centroid, b.centroid))
|
||||||
}, func(a, b *shape[V]) V {
|
}, func(a, b *shape[V]) V {
|
||||||
return geometry.CalcDistance(geometry.DoublePointToCoordinate(a.centroid, b.centroid))
|
return geometry.CalcDistanceWithCoordinate(geometry.DoublePointToCoordinate(a.centroid, b.centroid))
|
||||||
})
|
})
|
||||||
|
|
||||||
if len(path) == 0 {
|
if len(path) == 0 {
|
||||||
|
@ -223,7 +223,7 @@ func (slf *NavMesh[V]) generateLink() {
|
||||||
targetShapePkg := slf.meshShapes[t]
|
targetShapePkg := slf.meshShapes[t]
|
||||||
targetShapeCentroid := targetShapePkg.Centroid()
|
targetShapeCentroid := targetShapePkg.Centroid()
|
||||||
targetShapeBoundingRadius := targetShapePkg.BoundingRadius()
|
targetShapeBoundingRadius := targetShapePkg.BoundingRadius()
|
||||||
centroidDistance := geometry.CalcDistance(geometry.DoublePointToCoordinate(shapeCentroid, targetShapeCentroid))
|
centroidDistance := geometry.CalcDistanceWithCoordinate(geometry.DoublePointToCoordinate(shapeCentroid, targetShapeCentroid))
|
||||||
if centroidDistance > shapeBoundingRadius+targetShapeBoundingRadius {
|
if centroidDistance > shapeBoundingRadius+targetShapeBoundingRadius {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,5 +45,5 @@ func (slf *shape[V]) IsWall() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (slf *shape[V]) GetCost(point geometry.Point[V]) V {
|
func (slf *shape[V]) GetCost(point geometry.Point[V]) V {
|
||||||
return geometry.CalcDistance(geometry.DoublePointToCoordinate(slf.Centroid(), point))
|
return geometry.CalcDistanceWithCoordinate(geometry.DoublePointToCoordinate(slf.Centroid(), point))
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,26 @@ func (slf Point[V]) Copy() Point[V] {
|
||||||
return PointCopy(slf)
|
return PointCopy(slf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add 得到加上 point 后的点
|
||||||
|
func (slf Point[V]) Add(point Point[V]) Point[V] {
|
||||||
|
return slf.GetOffset(point.GetXY())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sub 得到减去 point 后的点
|
||||||
|
func (slf Point[V]) Sub(point Point[V]) Point[V] {
|
||||||
|
return NewPoint(slf.GetX()-point.GetX(), slf.GetY()-point.GetY())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mul 得到乘以 point 后的点
|
||||||
|
func (slf Point[V]) Mul(point Point[V]) Point[V] {
|
||||||
|
return NewPoint(slf.GetX()*point.GetX(), slf.GetY()*point.GetY())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Div 得到除以 point 后的点
|
||||||
|
func (slf Point[V]) Div(point Point[V]) Point[V] {
|
||||||
|
return NewPoint(slf.GetX()/point.GetX(), slf.GetY()/point.GetY())
|
||||||
|
}
|
||||||
|
|
||||||
// NewPointCap 创建一个由 x、y 坐标组成的点,这个点具有一个数据容量
|
// NewPointCap 创建一个由 x、y 坐标组成的点,这个点具有一个数据容量
|
||||||
func NewPointCap[V generic.SignedNumber, D any](x, y V) PointCap[V, D] {
|
func NewPointCap[V generic.SignedNumber, D any](x, y V) PointCap[V, D] {
|
||||||
return PointCap[V, D]{
|
return PointCap[V, D]{
|
||||||
|
|
|
@ -84,6 +84,12 @@ func (slf Shape[V]) Contains(point Point[V]) bool {
|
||||||
return inside
|
return inside
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToCircle 将形状转换为圆形进行处理
|
||||||
|
// - 当形状非圆形时将会产生意外情况
|
||||||
|
func (slf Shape[V]) ToCircle() Circle[V] {
|
||||||
|
return Circle[V]{slf}
|
||||||
|
}
|
||||||
|
|
||||||
// String 将该形状转换为可视化的字符串进行返回
|
// String 将该形状转换为可视化的字符串进行返回
|
||||||
func (slf Shape[V]) String() string {
|
func (slf Shape[V]) String() string {
|
||||||
var result string
|
var result string
|
||||||
|
@ -412,7 +418,7 @@ func CalcBoundingRadius[V generic.SignedNumber](shape Shape[V]) V {
|
||||||
var boundingRadius V
|
var boundingRadius V
|
||||||
var centroid = CalcRectangleCentroid(shape)
|
var centroid = CalcRectangleCentroid(shape)
|
||||||
for _, point := range shape.Points() {
|
for _, point := range shape.Points() {
|
||||||
distance := CalcDistance(DoublePointToCoordinate(centroid, point))
|
distance := CalcDistanceWithCoordinate(DoublePointToCoordinate(centroid, point))
|
||||||
if distance > boundingRadius {
|
if distance > boundingRadius {
|
||||||
boundingRadius = distance
|
boundingRadius = distance
|
||||||
}
|
}
|
||||||
|
@ -424,7 +430,7 @@ func CalcBoundingRadius[V generic.SignedNumber](shape Shape[V]) V {
|
||||||
func CalcBoundingRadiusWithCentroid[V generic.SignedNumber](shape Shape[V], centroid Point[V]) V {
|
func CalcBoundingRadiusWithCentroid[V generic.SignedNumber](shape Shape[V], centroid Point[V]) V {
|
||||||
var boundingRadius V
|
var boundingRadius V
|
||||||
for _, point := range shape.Points() {
|
for _, point := range shape.Points() {
|
||||||
distance := CalcDistance(DoublePointToCoordinate(centroid, point))
|
distance := CalcDistanceWithCoordinate(DoublePointToCoordinate(centroid, point))
|
||||||
if distance > boundingRadius {
|
if distance > boundingRadius {
|
||||||
boundingRadius = distance
|
boundingRadius = distance
|
||||||
}
|
}
|
||||||
|
@ -459,7 +465,7 @@ func ProjectionPointToShape[V generic.SignedNumber](point Point[V], shape Shape[
|
||||||
|
|
||||||
for _, edge := range shape.Edges() {
|
for _, edge := range shape.Edges() {
|
||||||
projectedPoint := CalcProjectionPoint(edge, point)
|
projectedPoint := CalcProjectionPoint(edge, point)
|
||||||
distance := CalcDistance(DoublePointToCoordinate(point, projectedPoint))
|
distance := CalcDistanceWithCoordinate(DoublePointToCoordinate(point, projectedPoint))
|
||||||
if !hasClosestProjection || distance < closestDistance {
|
if !hasClosestProjection || distance < closestDistance {
|
||||||
closestDistance = distance
|
closestDistance = distance
|
||||||
closestProjection = projectedPoint
|
closestProjection = projectedPoint
|
||||||
|
|
Loading…
Reference in New Issue