-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
other: v2 geometry 包调整、astar、navmesh 移动到 navigate 包
- Loading branch information
1 parent
438134f
commit bd21158
Showing
21 changed files
with
1,425 additions
and
73 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package geometry | ||
|
||
import "github.com/kercylan98/minotaur/toolkit/constraints" | ||
|
||
// CalcAngleDifference 计算两个极角之间的最小角度差。 | ||
// 结果在 -180 到 180 度之间,适用于极角、方位角或其他类似场景。 | ||
func CalcAngleDifference[T constraints.Number](a, b T) float64 { | ||
diff := float64(a) - float64(b) | ||
if diff > 180 { | ||
diff -= 360 | ||
} else if diff < -180 { | ||
diff += 360 | ||
} | ||
return diff | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package geometry | ||
|
||
// AssertPolygonValid 断言检查多边形是否有效 | ||
func AssertPolygonValid(polygons ...Polygon) { | ||
for _, polygon := range polygons { | ||
AssertPointValid(polygon...) | ||
if len(polygon) < 3 { | ||
panic("polygon must have at least 3 points") | ||
} | ||
} | ||
} | ||
|
||
// AssertLineSegmentValid 断言检查线段是否有效 | ||
func AssertLineSegmentValid(lineSegments ...LineSegment) { | ||
for _, lineSegment := range lineSegments { | ||
AssertPointValid(lineSegment...) | ||
if len(lineSegment) < 2 { | ||
panic("line segment must have at least 2 points") | ||
} | ||
} | ||
} | ||
|
||
// AssertPointValid 断言检查点是否有效 | ||
func AssertPointValid(points ...Point) { | ||
for _, point := range points { | ||
if len(point) != 2 { | ||
panic("point must have 2 coordinates") | ||
} | ||
} | ||
} | ||
|
||
// AssertVector2Valid 断言检查二维向量是否有效 | ||
func AssertVector2Valid(vectors ...Vector2) { | ||
for _, vector := range vectors { | ||
if len(vector) != 2 { | ||
panic("vector must have 2 coordinates") | ||
} | ||
} | ||
} | ||
|
||
// AssertVector3Valid 断言检查三维向量是否有效 | ||
func AssertVector3Valid(vectors ...Vector3) { | ||
for _, vector := range vectors { | ||
if len(vector) != 3 { | ||
panic("vector must have 3 coordinates") | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
package geometry | ||
|
||
import ( | ||
"github.com/kercylan98/minotaur/toolkit/constraints" | ||
"math" | ||
) | ||
|
||
// Direction2D 二维方向 | ||
type Direction2D = Vector2 | ||
|
||
var ( | ||
direction2DUnknown = NewVector2(0, 0) // 未知 | ||
direction2DUp = NewVector2(0, 1) // 上 | ||
direction2DDown = NewVector2(0, -1) // 下 | ||
direction2DLeft = NewVector2(-1, 0) // 左 | ||
direction2DRight = NewVector2(1, 0) // 右 | ||
direction2DLeftUp = NewVector2(-1, 1) // 左上 | ||
direction2DRightUp = NewVector2(1, 1) // 右上 | ||
direction2DLeftDown = NewVector2(-1, -1) // 左下 | ||
direction2DRightDown = NewVector2(1, -1) // 右下 | ||
|
||
direction2D4 = []Direction2D{direction2DUp, direction2DDown, direction2DLeft, direction2DRight} // 上下左右四个方向的数组 // 上下左右四个方向的数组 | ||
direction2D8 = []Direction2D{ // 上下左右、左上、右上、左下、右下八个方向的数组 | ||
direction2DUp, direction2DDown, direction2DLeft, direction2DRight, | ||
direction2DLeftUp, direction2DRightUp, direction2DLeftDown, direction2DRightDown, | ||
} | ||
) | ||
|
||
// Direction2D4 上下左右四个方向 | ||
func Direction2D4() []Direction2D { | ||
return direction2D4 | ||
} | ||
|
||
// Direction2D8 上下左右、左上、右上、左下、右下八个方向 | ||
func Direction2D8() []Direction2D { | ||
return direction2D8 | ||
} | ||
|
||
// Direction2DUnknown 获取未知方向 | ||
func Direction2DUnknown() Direction2D { | ||
return direction2DUnknown | ||
} | ||
|
||
// Direction2DUp 获取上方向 | ||
func Direction2DUp() Direction2D { | ||
return direction2DUp | ||
} | ||
|
||
// Direction2DDown 获取下方向 | ||
func Direction2DDown() Direction2D { | ||
return direction2DDown | ||
} | ||
|
||
// Direction2DLeft 获取左方向 | ||
func Direction2DLeft() Direction2D { | ||
return direction2DLeft | ||
} | ||
|
||
// Direction2DRight 获取右方向 | ||
func Direction2DRight() Direction2D { | ||
return direction2DRight | ||
} | ||
|
||
// Direction2DLeftUp 获取左上方向 | ||
func Direction2DLeftUp() Direction2D { | ||
return direction2DLeftUp | ||
} | ||
|
||
// Direction2DRightUp 获取右上方向 | ||
func Direction2DRightUp() Direction2D { | ||
return direction2DRightUp | ||
} | ||
|
||
// Direction2DLeftDown 获取左下方向 | ||
func Direction2DLeftDown() Direction2D { | ||
return direction2DLeftDown | ||
} | ||
|
||
// Direction2DRightDown 获取右下方向 | ||
func Direction2DRightDown() Direction2D { | ||
return direction2DRightDown | ||
} | ||
|
||
// CalcOppositionDirection2D 计算二维方向的反方向 | ||
func CalcOppositionDirection2D(direction Direction2D) Direction2D { | ||
switch { | ||
case direction.Equal(direction2DUp): | ||
return direction2DDown | ||
case direction.Equal(direction2DDown): | ||
return direction2DUp | ||
case direction.Equal(direction2DLeft): | ||
return direction2DRight | ||
case direction.Equal(direction2DRight): | ||
return direction2DLeft | ||
case direction.Equal(direction2DLeftUp): | ||
return direction2DRightDown | ||
case direction.Equal(direction2DRightUp): | ||
return direction2DLeftDown | ||
case direction.Equal(direction2DLeftDown): | ||
return direction2DRightUp | ||
case direction.Equal(direction2DRightDown): | ||
return direction2DLeftUp | ||
default: | ||
return direction2DUnknown | ||
} | ||
} | ||
|
||
// CalcOffsetInDirection2D 计算特定方向上按照指定距离偏移后的坐标 | ||
func CalcOffsetInDirection2D[T constraints.Number](vector Vector2, direction Direction2D, offset T) Vector2 { | ||
return vector.Add(direction.Mul(float64(offset))) | ||
} | ||
|
||
// CalcDirection2DWithAngle 通过角度计算二维方向 | ||
func CalcDirection2DWithAngle[T constraints.Number](angle T) Direction2D { | ||
angleFloat := float64(angle) | ||
return NewVector2(math.Cos(angleFloat), math.Sin(angleFloat)) | ||
} | ||
|
||
// CalcAngleWithDirection2D 计算二维方向的角度 | ||
func CalcAngleWithDirection2D(direction Direction2D) float64 { | ||
return math.Atan2(direction.GetY(), direction.GetX()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package geometry | ||
|
||
import ( | ||
"strings" | ||
) | ||
|
||
// FloorPlan 平面图 | ||
type FloorPlan []string | ||
|
||
// IsFree 检查位置是否为空格 | ||
func (fp FloorPlan) IsFree(position Vector2) bool { | ||
return fp.IsInBounds(position) && fp[int(position.GetY())][int(position.GetX())] == ' ' | ||
} | ||
|
||
// IsInBounds 检查位置是否在边界内 | ||
func (fp FloorPlan) IsInBounds(position Vector2) bool { | ||
x, y := int(position.GetX()), int(position.GetY()) | ||
return (0 <= x && x < len(fp[y])) && (0 <= y && y < len(fp)) | ||
} | ||
|
||
// Put 设置平面图特定位置的字符 | ||
func (fp FloorPlan) Put(position Vector2, c rune) { | ||
x, y := int(position.GetX()), int(position.GetY()) | ||
fp[y] = fp[y][:x] + string(c) + fp[y][x+1:] | ||
} | ||
|
||
// String 获取平面图结果 | ||
func (fp FloorPlan) String() string { | ||
var builder strings.Builder | ||
var last = len(fp) - 1 | ||
for i, row := range fp { | ||
builder.WriteString(row) | ||
if i != last { | ||
builder.WriteByte('\n') | ||
} | ||
} | ||
return builder.String() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,82 +1,55 @@ | ||
package geometry | ||
|
||
import "math" | ||
|
||
type Line [2]Vector2 | ||
|
||
// NewLine 创建一条直线 | ||
func NewLine(start, end Vector2) Line { | ||
if len(start) != 2 || len(end) != 2 { | ||
panic("vector size mismatch") | ||
} | ||
return Line{start, end} | ||
func NewLine(point Point, slope float64) Line { | ||
AssertPointValid(point) | ||
return Line{point, slope} | ||
} | ||
|
||
// GetStart 获取起点 | ||
func (l Line) GetStart() Vector2 { | ||
return l[0] | ||
// Line 直线是由一个点和斜率定义的 | ||
type Line struct { | ||
point Point // 直线上的一个点 | ||
slope float64 // 斜率 | ||
} | ||
|
||
// GetEnd 获取终点 | ||
func (l Line) GetEnd() Vector2 { | ||
return l[1] | ||
// IsPointOn 判断点是否在直线上 | ||
func (l Line) IsPointOn(point Point) bool { | ||
AssertPointValid(l.point, point) | ||
return l.slope*(point[0]-l.point[0]) == point[1]-l.point[1] | ||
} | ||
|
||
// GetLength 获取长度 | ||
func (l Line) GetLength() float64 { | ||
return l.GetStart().Sub(l.GetEnd()).Length() | ||
// IsPointOnOrAbove 判断点是否在直线上或者在直线上方 | ||
func (l Line) IsPointOnOrAbove(point Point) bool { | ||
AssertPointValid(l.point, point) | ||
return l.slope*(point[0]-l.point[0]) >= point[1]-l.point[1] | ||
} | ||
|
||
// Contains 判断点是否在直线上 | ||
func (l Line) Contains(point Vector2) bool { | ||
if len(point) != 2 { | ||
panic("vector size mismatch") | ||
} | ||
|
||
v1 := l.GetEnd().Sub(l.GetStart()) // 直线的向量 | ||
v2 := point.Sub(l.GetStart()) // 直线起点到给定点的向量 | ||
|
||
// 计算交叉积 | ||
crossProduct := v1[0]*v2[1] - v1[1]*v2[0] | ||
|
||
// 数值误差 | ||
epsilon := 1e-9 | ||
return math.Abs(crossProduct) < epsilon | ||
// IsPointOnOrBelow 判断点是否在直线上或者在直线下方 | ||
func (l Line) IsPointOnOrBelow(point Point) bool { | ||
AssertPointValid(l.point, point) | ||
return l.slope*(point[0]-l.point[0]) <= point[1]-l.point[1] | ||
} | ||
|
||
// Intersect 判断两条直线是否相交 | ||
func (l Line) Intersect(l2 Line) bool { | ||
// 两条直线的向量 | ||
v1 := l.GetEnd().Sub(l.GetStart()) | ||
v2 := l2.GetEnd().Sub(l2.GetStart()) | ||
|
||
// 计算交叉积 | ||
crossProduct1 := v1[0]*v2[1] - v1[1]*v2[0] | ||
|
||
// 两条直线的起点到另一条直线起点的向量 | ||
v3 := l2.GetStart().Sub(l.GetStart()) | ||
v4 := l2.GetEnd().Sub(l.GetStart()) | ||
|
||
// 计算交叉积 | ||
crossProduct2 := v1[0]*v3[1] - v1[1]*v3[0] | ||
crossProduct3 := v1[0]*v4[1] - v1[1]*v4[0] | ||
|
||
return crossProduct1 != 0 && crossProduct2*crossProduct3 < 0 | ||
// IsPointAbove 判断点是否在直线上方 | ||
func (l Line) IsPointAbove(point Point) bool { | ||
AssertPointValid(l.point, point) | ||
return l.slope*(point[0]-l.point[0]) > point[1]-l.point[1] | ||
} | ||
|
||
// IntersectCircle 判断直线是否与圆相交 | ||
func (l Line) IntersectCircle(c Circle) bool { | ||
// 直线的向量 | ||
v1 := l.GetEnd().Sub(l.GetStart()) | ||
|
||
// 直线起点到圆心的向量 | ||
v2 := c.GetCenter().Sub(l.GetStart()) | ||
|
||
// 计算直线到圆心的投影长度 | ||
projection := v1.Dot(v2) / v1.Length() | ||
// IsPointBelow 判断点是否在直线下方 | ||
func (l Line) IsPointBelow(point Point) bool { | ||
AssertPointValid(l.point, point) | ||
return l.slope*(point[0]-l.point[0]) < point[1]-l.point[1] | ||
} | ||
|
||
// 计算直线到圆心的距离 | ||
distance := v2.Length() | ||
// IsPointLeft 判断点是否在直线左侧 | ||
func (l Line) IsPointLeft(point Point) bool { | ||
AssertPointValid(l.point, point) | ||
return l.slope*(point[0]-l.point[0]) < point[1]-l.point[1] | ||
} | ||
|
||
return distance <= c.GetRadius() && projection >= 0 && projection <= v1.Length() | ||
// IsPointRight 判断点是否在直线右侧 | ||
func (l Line) IsPointRight(point Point) bool { | ||
AssertPointValid(l.point, point) | ||
return l.slope*(point[0]-l.point[0]) > point[1]-l.point[1] | ||
} |
Oops, something went wrong.