二维矩阵图形搜索
This commit is contained in:
parent
b312639dc6
commit
d2a6c5d8c7
|
@ -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
|
||||||
|
}
|
|
@ -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]
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -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))
|
||||||
|
}
|
Loading…
Reference in New Issue