From d2a6c5d8c73611b4d015da0dd13f6de4d76696d9 Mon Sep 17 00:00:00 2001 From: kercylan98 Date: Wed, 31 May 2023 10:47:41 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BA=8C=E7=BB=B4=E7=9F=A9=E9=98=B5=E5=9B=BE?= =?UTF-8?q?=E5=BD=A2=E6=90=9C=E7=B4=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- utils/g2d/shape.go | 134 +++++++++++++++++++++++++++++++++++++++ utils/g2d/shape/point.go | 31 +++++++++ utils/g2d/shape/shape.go | 79 +++++++++++++++++++++++ utils/g2d/shape_test.go | 28 ++++++++ 4 files changed, 272 insertions(+) create mode 100644 utils/g2d/shape.go create mode 100644 utils/g2d/shape/point.go create mode 100644 utils/g2d/shape/shape.go create mode 100644 utils/g2d/shape_test.go diff --git a/utils/g2d/shape.go b/utils/g2d/shape.go new file mode 100644 index 0000000..78a7bc6 --- /dev/null +++ b/utils/g2d/shape.go @@ -0,0 +1,134 @@ +package g2d + +import ( + "github.com/kercylan98/minotaur/utils/g2d/shape" +) + +type MatrixShapeSearchResult struct { + Shape *shape.Shape + Points []shape.Point +} + +// MatrixShapeSearchWithYX 二维矩阵形状搜索 +func MatrixShapeSearchWithYX[T any](matrix [][]T, shapes []*shape.Shape, checkMatchHandle func(val T) bool) []MatrixShapeSearchResult { + record := map[int]map[int]bool{} + width := len(matrix[0]) + height := len(matrix) + for x := 0; x < width; x++ { + for y := 0; y < height; y++ { + record[x] = map[int]bool{y: true} + } + } + + var result []MatrixShapeSearchResult + + for _, s := range shapes { + points := s.GetPoints() + x, y := 0, 0 + mx, my := s.GetMaxXY() + for { + if x+mx >= width { + x = 0 + y++ + } + if y+my >= height { + break + } + var count int + for _, point := range points { + px, py := point.GetXY() + px, py = px+x, py+y + if record[px][py] { + break + } + if checkMatchHandle(matrix[py][px]) { + count++ + } else { + break + } + } + if count == len(points) { + target := MatrixShapeSearchResult{ + Shape: s, + } + for _, point := range points { + px, py := point.GetXY() + px, py = px+x, py+y + ys, exist := record[px] + if !exist { + ys = map[int]bool{} + record[px] = ys + } + ys[py] = true + target.Points = append(target.Points, shape.NewPoint(px, py)) + } + result = append(result, target) + } + x++ + } + } + + return result +} + +// MatrixShapeSearchWithXY 二维矩阵形状搜索 +func MatrixShapeSearchWithXY[T any](matrix [][]T, shapes []*shape.Shape, checkMatchHandle func(val T) bool) []MatrixShapeSearchResult { + record := map[int]map[int]bool{} + width := len(matrix) + height := len(matrix[0]) + for x := 0; x < width; x++ { + for y := 0; y < height; y++ { + record[x] = map[int]bool{y: true} + } + } + + var result []MatrixShapeSearchResult + + for _, s := range shapes { + points := s.GetPoints() + x, y := 0, 0 + mx, my := s.GetMaxXY() + for { + if x+mx >= width { + x = 0 + y++ + } + if y+my >= height { + break + } + var count int + for _, point := range points { + px, py := point.GetXY() + px, py = px+x, py+y + if record[px][py] { + break + } + if checkMatchHandle(matrix[px][py]) { + count++ + } else { + break + } + } + if count == len(points) { + target := MatrixShapeSearchResult{ + Shape: s, + } + for _, point := range points { + px, py := point.GetXY() + px, py = px+x, py+y + ys, exist := record[px] + if !exist { + ys = map[int]bool{} + record[px] = ys + } + ys[py] = true + target.Points = append(target.Points, shape.NewPoint(px, py)) + } + result = append(result, target) + } + x++ + } + } + + return result +} diff --git a/utils/g2d/shape/point.go b/utils/g2d/shape/point.go new file mode 100644 index 0000000..0604789 --- /dev/null +++ b/utils/g2d/shape/point.go @@ -0,0 +1,31 @@ +package shape + +func NewPoint(x, y int) Point { + return Point{x, y} +} + +func NewPointWithArray(arr [2]int) Point { + return Point{arr[0], arr[1]} +} + +func NewPointWithArrays(arrays ...[2]int) []Point { + var points = make([]Point, len(arrays), len(arrays)) + for i, arr := range arrays { + points[i] = NewPointWithArray(arr) + } + return points +} + +type Point [2]int + +func (slf Point) GetX() int { + return slf[0] +} + +func (slf Point) GetY() int { + return slf[1] +} + +func (slf Point) GetXY() (int, int) { + return slf[0], slf[1] +} diff --git a/utils/g2d/shape/shape.go b/utils/g2d/shape/shape.go new file mode 100644 index 0000000..095d891 --- /dev/null +++ b/utils/g2d/shape/shape.go @@ -0,0 +1,79 @@ +package shape + +func NewShape() *Shape { + shape := &Shape{ + maxX: -1, + maxY: -1, + points: map[int]map[int]Point{}, + } + return shape +} + +// Shape 2D形状定义 +type Shape struct { + maxX int + maxY int + points map[int]map[int]Point +} + +func (slf *Shape) AddPoints(points ...Point) { + for _, point := range points { + slf.AddPoint(point) + } +} + +func (slf *Shape) AddPoint(point Point) { + x, y := point.GetXY() + if x < 0 || y < 0 { + panic("only positive integers are allowed for shape point positions") + } + if x > slf.maxX { + slf.maxX = x + } + if y > slf.maxY { + slf.maxY = y + } + ys, exist := slf.points[x] + if !exist { + ys = map[int]Point{} + slf.points[x] = ys + } + ys[y] = point +} + +func (slf *Shape) GetPoints() []Point { + var points []Point + for _, m := range slf.points { + for _, point := range m { + points = append(points, point) + } + } + return points +} + +func (slf *Shape) GetMaxX() int { + return slf.maxX +} + +func (slf *Shape) GetMaxY() int { + return slf.maxY +} + +func (slf *Shape) GetMaxXY() (int, int) { + return slf.maxX, slf.maxY +} + +func (slf *Shape) String() string { + var str string + for y := 0; y <= slf.maxY; y++ { + for x := 0; x <= slf.maxX; x++ { + if _, exist := slf.points[x][y]; exist { + str += "1" + } else { + str += "0" + } + } + str += "\r\n" + } + return str +} diff --git a/utils/g2d/shape_test.go b/utils/g2d/shape_test.go new file mode 100644 index 0000000..f6f3e10 --- /dev/null +++ b/utils/g2d/shape_test.go @@ -0,0 +1,28 @@ +package g2d + +import ( + "fmt" + "github.com/kercylan98/minotaur/utils/g2d/shape" + "testing" +) + +func TestMatrixShape(t *testing.T) { + var m = [][]int{ + {1, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 1, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 1, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}, + } + s := shape.NewShape() + s.AddPoints(shape.NewPointWithArrays([][2]int{{0, 0}, {0, 1}, {1, 1}, {2, 1}}...)...) + fmt.Println(s) + result := MatrixShapeSearchWithYX(m, []*shape.Shape{s}, func(val int) bool { + return val == 1 + }) + fmt.Println(len(result)) +}