增加二维矩形相关辅助函数
This commit is contained in:
parent
40184121ce
commit
da60965471
|
@ -24,15 +24,16 @@ func CoverageAreaBoundless(l, r, t, b int) (left, right, top, bottom int) {
|
||||||
|
|
||||||
// GetShapeCoverageArea 获取一个图形覆盖的范围
|
// GetShapeCoverageArea 获取一个图形覆盖的范围
|
||||||
func GetShapeCoverageArea(xys ...[2]int) (left, right, top, bottom int) {
|
func GetShapeCoverageArea(xys ...[2]int) (left, right, top, bottom int) {
|
||||||
|
left, top = -1, -1
|
||||||
for _, xy := range xys {
|
for _, xy := range xys {
|
||||||
x, y := PositionArrayToXY(xy)
|
x, y := PositionArrayToXY(xy)
|
||||||
if x < left {
|
if x < left || left == -1 {
|
||||||
left = x
|
left = x
|
||||||
}
|
}
|
||||||
if x > right {
|
if x > right {
|
||||||
right = x
|
right = x
|
||||||
}
|
}
|
||||||
if y < top {
|
if y < top || top == -1 {
|
||||||
top = y
|
top = y
|
||||||
}
|
}
|
||||||
if y > bottom {
|
if y > bottom {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"github.com/kercylan98/minotaur/utils/g2d"
|
"github.com/kercylan98/minotaur/utils/g2d"
|
||||||
"github.com/kercylan98/minotaur/utils/random"
|
"github.com/kercylan98/minotaur/utils/random"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Item[Type comparable] struct {
|
type Item[Type comparable] struct {
|
||||||
|
@ -65,6 +66,7 @@ func TestMatch3(t *testing.T) {
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var now = time.Now()
|
||||||
var xys [][2]int
|
var xys [][2]int
|
||||||
for guid := range links {
|
for guid := range links {
|
||||||
xys = append(xys, match3.positions[guid])
|
xys = append(xys, match3.positions[guid])
|
||||||
|
@ -73,4 +75,15 @@ func TestMatch3(t *testing.T) {
|
||||||
for _, rect := range g2d.SearchNotRepeatFullRectangle(xys...) {
|
for _, rect := range g2d.SearchNotRepeatFullRectangle(xys...) {
|
||||||
fmt.Println(fmt.Sprintf("找到矩形: TopLeft: (%d, %d), BottomRight: (%d, %d)", rect[0][0], rect[0][1], rect[1][0], rect[1][1]))
|
fmt.Println(fmt.Sprintf("找到矩形: TopLeft: (%d, %d), BottomRight: (%d, %d)", rect[0][0], rect[0][1], rect[1][0], rect[1][1]))
|
||||||
}
|
}
|
||||||
|
fmt.Println("耗时", time.Since(now))
|
||||||
|
|
||||||
|
now = time.Now()
|
||||||
|
for _, rect := range g2d.SearchNotRepeatCross(xys...) {
|
||||||
|
fmt.Print("找到十字:")
|
||||||
|
for _, points := range rect {
|
||||||
|
fmt.Print(fmt.Sprintf("{%d, %d}", points[0], points[1]))
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
}
|
||||||
|
fmt.Println("耗时", time.Since(now))
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,9 +73,9 @@ func MatrixShapeSearchWithYX[T any, Mark any](matrix [][]T, shapes []*shape.Shap
|
||||||
|
|
||||||
// MatrixShapeSearchWithXY 二维矩阵形状搜索
|
// MatrixShapeSearchWithXY 二维矩阵形状搜索
|
||||||
func MatrixShapeSearchWithXY[T any, Mark any](matrix [][]T, shapes []*shape.Shape[Mark], checkMatchHandle func(val T) bool) []MatrixShapeSearchResult[Mark] {
|
func MatrixShapeSearchWithXY[T any, Mark any](matrix [][]T, shapes []*shape.Shape[Mark], checkMatchHandle func(val T) bool) []MatrixShapeSearchResult[Mark] {
|
||||||
record := map[int]map[int]bool{}
|
|
||||||
width := len(matrix)
|
width := len(matrix)
|
||||||
height := len(matrix[0])
|
height := len(matrix[0])
|
||||||
|
record := map[int]map[int]bool{}
|
||||||
for x := 0; x < width; x++ {
|
for x := 0; x < width; x++ {
|
||||||
for y := 0; y < height; y++ {
|
for y := 0; y < height; y++ {
|
||||||
record[x] = map[int]bool{y: true}
|
record[x] = map[int]bool{y: true}
|
||||||
|
@ -133,6 +133,79 @@ func MatrixShapeSearchWithXY[T any, Mark any](matrix [][]T, shapes []*shape.Shap
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SearchNotRepeatCross 在一组二维坐标中从大到小搜索不重复交叉(十字)线
|
||||||
|
// - 不重复指一个位置被使用后将不会被其他交叉线(十字)使用
|
||||||
|
func SearchNotRepeatCross(xys ...[2]int) (result [][][2]int) {
|
||||||
|
left, _, top, _ := GetShapeCoverageArea(xys...)
|
||||||
|
rectangleShape := GenerateShape(xys...)
|
||||||
|
record := map[int]map[int]bool{}
|
||||||
|
for x := 0; x < len(rectangleShape); x++ {
|
||||||
|
for y := 0; y < len(rectangleShape[0]); y++ {
|
||||||
|
record[x] = map[int]bool{y: true}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, xy := range xys {
|
||||||
|
var points [][2]int
|
||||||
|
var records [][2]int
|
||||||
|
var find = map[int]bool{}
|
||||||
|
x, y := PositionArrayToXY(xy)
|
||||||
|
x = x + (0 - left)
|
||||||
|
y = y + (0 - top)
|
||||||
|
// 搜索四个方向
|
||||||
|
for sx := x - 1; sx >= 0; sx-- {
|
||||||
|
if record[sx][y] || !rectangleShape[sx][y] {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
find[1] = true
|
||||||
|
points = append(points, [2]int{sx + left, y + top})
|
||||||
|
records = append(records, [2]int{sx, y})
|
||||||
|
}
|
||||||
|
if !find[1] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for sx := x + 1; sx < len(rectangleShape); sx++ {
|
||||||
|
if record[sx][y] || !rectangleShape[sx][y] {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
find[2] = true
|
||||||
|
points = append(points, [2]int{sx + left, y + top})
|
||||||
|
records = append(records, [2]int{sx, y})
|
||||||
|
}
|
||||||
|
if !find[2] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for sy := y - 1; sy >= 0; sy-- {
|
||||||
|
if record[x][sy] || !rectangleShape[x][sy] {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
find[3] = true
|
||||||
|
points = append(points, [2]int{x + left, sy + top})
|
||||||
|
records = append(records, [2]int{x, sy})
|
||||||
|
}
|
||||||
|
if !find[3] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for sy := y + 1; sy <= len(rectangleShape[0]); sy++ {
|
||||||
|
if record[x][sy] || !rectangleShape[x][sy] {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
find[4] = true
|
||||||
|
points = append(points, [2]int{x + left, sy + top})
|
||||||
|
records = append(records, [2]int{x, sy})
|
||||||
|
}
|
||||||
|
if !find[4] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, point := range records {
|
||||||
|
record[point[0]][point[1]] = true
|
||||||
|
}
|
||||||
|
result = append(result, append(points, [2]int{x + left, y + top}))
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// SearchNotRepeatFullRectangle 在一组二维坐标中从大到小搜索不重复的填充满的矩形
|
// SearchNotRepeatFullRectangle 在一组二维坐标中从大到小搜索不重复的填充满的矩形
|
||||||
// - 不重复指一个位置被使用后将不会被其他矩形使用
|
// - 不重复指一个位置被使用后将不会被其他矩形使用
|
||||||
// - 返回值表示了匹配的形状的左上角和右下角的点坐标
|
// - 返回值表示了匹配的形状的左上角和右下角的点坐标
|
||||||
|
@ -234,7 +307,8 @@ func GetExpressibleRectangleBySize(width, height, minWidth, minHeight int) (resu
|
||||||
// - 这个形状将被在一个刚好能容纳形状的矩形中表示
|
// - 这个形状将被在一个刚好能容纳形状的矩形中表示
|
||||||
// - 为true的位置表示了形状的每一个点
|
// - 为true的位置表示了形状的每一个点
|
||||||
func GenerateShape(xys ...[2]int) [][]bool {
|
func GenerateShape(xys ...[2]int) [][]bool {
|
||||||
_, right, _, bottom := CoverageAreaBoundless(GetShapeCoverageArea(xys...))
|
left, r, top, b := GetShapeCoverageArea(xys...)
|
||||||
|
_, right, _, bottom := CoverageAreaBoundless(left, r, top, b)
|
||||||
w, h := right+1, bottom+1
|
w, h := right+1, bottom+1
|
||||||
m := make([][]bool, w)
|
m := make([][]bool, w)
|
||||||
for x := 0; x < w; x++ {
|
for x := 0; x < w; x++ {
|
||||||
|
@ -242,7 +316,7 @@ func GenerateShape(xys ...[2]int) [][]bool {
|
||||||
}
|
}
|
||||||
for _, xy := range xys {
|
for _, xy := range xys {
|
||||||
x, y := PositionArrayToXY(xy)
|
x, y := PositionArrayToXY(xy)
|
||||||
m[x][y] = true
|
m[x-(r-right)][y-(b-bottom)] = true
|
||||||
}
|
}
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue