增加圆形相关处理函数

This commit is contained in:
kercylan98 2023-06-20 17:39:35 +08:00
parent d10c05dfe1
commit c0570392bf
10 changed files with 99 additions and 23 deletions

View File

@ -123,7 +123,7 @@ func (slf *Moving2D) handle() {
if interval == 0 {
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))
if moveDistance >= distance || (x == entity.x && y == entity.y) {
entity.SetPosition(entity.x, entity.y)

View File

@ -177,7 +177,7 @@ func (slf *AOI2D) refresh(entity game.AOIEntity2D) {
focus := slf.focus[guid]
for eg, e := range focus {
ex, ey := e.GetPosition()
if geometry.CalcDistance(x, y, ex, ey) > vision {
if geometry.CalcDistanceWithCoordinate(x, y, ex, ey) > vision {
delete(focus, eg)
delete(slf.focus[eg], guid)
}
@ -243,13 +243,13 @@ func (slf *AOI2D) rangeVisionAreaEntities(entity game.AOIEntity2D, handle func(g
} else {
areaY = y
}
areaDistance := geometry.CalcDistance(x, y, areaX, areaY)
areaDistance := geometry.CalcDistanceWithCoordinate(x, y, areaX, areaY)
if areaDistance <= vision {
for eg, e := range slf.areas[w][h] {
if eg == guid {
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
}
handle(eg, e)

View File

@ -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 {
return geometry.CalcDistance(geometry.DoublePointToCoordinate(a, b))
return geometry.CalcDistanceWithCoordinate(geometry.DoublePointToCoordinate(a, b))
}, 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 {

View File

@ -5,8 +5,53 @@ import (
"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 通过传入圆的半径和需要的点数量,生成一个圆
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)
var shape = make(Shape[V], points)
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))
shape = append(shape, NewPoint(x, y))
}
return shape
return shape.ToCircle()
}

View File

@ -109,11 +109,16 @@ func CalcDirection[V generic.SignedNumber](x1, y1, x2, y2 V) Direction {
return DirectionUnknown
}
// CalcDistance 计算两点之间的距离
func CalcDistance[V generic.SignedNumber](x1, y1, x2, y2 V) V {
// CalcDistanceWithCoordinate 计算两点之间的距离
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)))
}
// CalcDistanceWithPoint 计算两点之间的距离
func CalcDistanceWithPoint[V generic.SignedNumber](point1, point2 Point[V]) V {
return CalcDistanceWithCoordinate(DoublePointToCoordinate(point1, point2))
}
// CalcDistanceSquared 计算两点之间的平方距离
// - 这个函数的主要用途是在需要计算两点之间距离的情况下,但不需要得到实际的距离值,而只需要比较距离大小。因为平方根运算相对较为耗时,所以在只需要比较大小的情况下,通常会使用平方距离。
func CalcDistanceSquared[V generic.SignedNumber](x1, y1, x2, y2 V) V {

View File

@ -54,7 +54,7 @@ func (slf LineSegment[V]) GetEnd() Point[V] {
// GetLength 获取该线段的长度
func (slf LineSegment[V]) GetLength() V {
return CalcDistance(DoublePointToCoordinate(slf.GetStart(), slf.GetEnd()))
return CalcDistanceWithCoordinate(DoublePointToCoordinate(slf.GetStart(), slf.GetEnd()))
}
// PointOnLineSegmentWithCoordinate 通过一个线段两个点的位置和一个点的坐标,判断这个点是否在一条线段上

View File

@ -74,7 +74,7 @@ func (slf *NavMesh[V]) Find(point geometry.Point[V], maxDistance V) (distance V,
break
}
br := geometry.CalcBoundingRadius(meshShape.Shape)
distance := geometry.CalcDistance(geometry.DoublePointToCoordinate(
distance := geometry.CalcDistanceWithCoordinate(geometry.DoublePointToCoordinate(
geometry.CalcRectangleCentroid(meshShape.Shape),
point,
))
@ -111,13 +111,13 @@ func (slf *NavMesh[V]) FindPath(start, end geometry.Point[V]) (result []geometry
for _, meshShape := range slf.meshShapes {
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) {
startShape = meshShape
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) {
endShape = meshShape
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) {
for _, meshShape := range slf.meshShapes {
br := meshShape.BoundingRadius() + slf.meshShrinkAmount
distance := geometry.CalcDistance(geometry.DoublePointToCoordinate(meshShape.Centroid(), end))
distance := geometry.CalcDistanceWithCoordinate(geometry.DoublePointToCoordinate(meshShape.Centroid(), end))
if distance <= br {
_, projectionDistance := geometry.ProjectionPointToShape(end, meshShape.Shape)
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 {
for _, meshShape := range slf.meshShapes {
br := meshShape.BoundingRadius() + slf.meshShrinkAmount
distance := geometry.CalcDistance(geometry.DoublePointToCoordinate(meshShape.Centroid(), start))
distance := geometry.CalcDistanceWithCoordinate(geometry.DoublePointToCoordinate(meshShape.Centroid(), start))
if distance <= br {
_, projectionDistance := geometry.ProjectionPointToShape(start, meshShape.Shape)
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 {
return geometry.CalcDistance(geometry.DoublePointToCoordinate(a.centroid, b.centroid))
return geometry.CalcDistanceWithCoordinate(geometry.DoublePointToCoordinate(a.centroid, b.centroid))
}, 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 {
@ -223,7 +223,7 @@ func (slf *NavMesh[V]) generateLink() {
targetShapePkg := slf.meshShapes[t]
targetShapeCentroid := targetShapePkg.Centroid()
targetShapeBoundingRadius := targetShapePkg.BoundingRadius()
centroidDistance := geometry.CalcDistance(geometry.DoublePointToCoordinate(shapeCentroid, targetShapeCentroid))
centroidDistance := geometry.CalcDistanceWithCoordinate(geometry.DoublePointToCoordinate(shapeCentroid, targetShapeCentroid))
if centroidDistance > shapeBoundingRadius+targetShapeBoundingRadius {
continue
}

View File

@ -45,5 +45,5 @@ func (slf *shape[V]) IsWall() bool {
}
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))
}

View File

@ -59,6 +59,26 @@ func (slf Point[V]) Copy() Point[V] {
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 坐标组成的点,这个点具有一个数据容量
func NewPointCap[V generic.SignedNumber, D any](x, y V) PointCap[V, D] {
return PointCap[V, D]{

View File

@ -84,6 +84,12 @@ func (slf Shape[V]) Contains(point Point[V]) bool {
return inside
}
// ToCircle 将形状转换为圆形进行处理
// - 当形状非圆形时将会产生意外情况
func (slf Shape[V]) ToCircle() Circle[V] {
return Circle[V]{slf}
}
// String 将该形状转换为可视化的字符串进行返回
func (slf Shape[V]) String() string {
var result string
@ -412,7 +418,7 @@ func CalcBoundingRadius[V generic.SignedNumber](shape Shape[V]) V {
var boundingRadius V
var centroid = CalcRectangleCentroid(shape)
for _, point := range shape.Points() {
distance := CalcDistance(DoublePointToCoordinate(centroid, point))
distance := CalcDistanceWithCoordinate(DoublePointToCoordinate(centroid, point))
if distance > boundingRadius {
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 {
var boundingRadius V
for _, point := range shape.Points() {
distance := CalcDistance(DoublePointToCoordinate(centroid, point))
distance := CalcDistanceWithCoordinate(DoublePointToCoordinate(centroid, point))
if distance > boundingRadius {
boundingRadius = distance
}
@ -459,7 +465,7 @@ func ProjectionPointToShape[V generic.SignedNumber](point Point[V], shape Shape[
for _, edge := range shape.Edges() {
projectedPoint := CalcProjectionPoint(edge, point)
distance := CalcDistance(DoublePointToCoordinate(point, projectedPoint))
distance := CalcDistanceWithCoordinate(DoublePointToCoordinate(point, projectedPoint))
if !hasClosestProjection || distance < closestDistance {
closestDistance = distance
closestProjection = projectedPoint