图形搜索增加可选项 WithShapeSearchOppositionDirection 支持通过限制对立方向的方式搜索

This commit is contained in:
kercylan 2023-06-18 00:47:48 +08:00
parent 3a999a6eb3
commit 78ab5ac7fe
2 changed files with 20 additions and 701 deletions

View File

@ -168,6 +168,10 @@ func (slf Shape[V]) getAllGraphicComposition(opt *shapeSearchOptions) (result []
match = false
}
if match && (directionCount[DirectionUp] > 0 && directionCount[DirectionDown] > 0) || (directionCount[DirectionLeft] > 0 && directionCount[DirectionRight] > 0) {
match = false
}
if match {
result = append(result, links)
}
@ -198,697 +202,6 @@ func (slf Shape[V]) getAllGraphicCompositionWithDesc(opt *shapeSearchOptions) (r
return
}
//
//// SearchNotRepeatCross 在一组二维坐标中从大到小搜索不重复交叉(十字)线
//// - 不重复指一个位置被使用后将不会被其他交叉线(十字)使用
//func SearchNotRepeatCross[V generic.Number](findHandle func(findCount map[Direction]int, nextDirection func(direction Direction), stop func()), points []Point[V]) (result [][]Point[V]) {
// left, right, top, bottom := GetShapeCoverageAreaWithCoordinateArray(points...)
// width := right - left + 1
// height := bottom - top + 1
// size := width * height
// rectangleShape := GenerateShapeOnRectangle(points...)
// record := map[V]map[V]bool{}
// for x := V(0); x < width; x++ {
// for y := V(0); y < height; y++ {
// record[x] = map[V]bool{}
// }
// }
//
// var findCount = map[Direction]int{}
//
// for _, point := range points {
//
// var next = -1
// for {
// var direction Direction
// next, direction = slice.NextLoop(Directions, next)
// nextPoint := point
// for {
// nextPoint = GetDirectionNextWithCoordinateArray(direction, point)
// nextPos := nextPoint.GetPos(width)
// if nextPos < 0 || nextPos >= size {
// break
// }
// if rectangleShape[int(nextPos)].Data {
// findCount[direction]++
// var goToNextDirection bool
// var stop bool
// findHandle(findCount, func(direction Direction) {
// switch direction {
// case DirectionUp:
// next = -1
// case DirectionDown:
// next = 0
// case DirectionLeft:
// next = 1
// case DirectionRight:
// next = 2
// }
// goToNextDirection = true
// }, func() {
// stop = true
// })
// if stop {
// return
// }
// if goToNextDirection {
// break
// }
// } else {
// break
// }
// }
// }
//
// for _, direction := range Directions {
// for {
// nextPoint := GetDirectionNextWithCoordinateArray(direction, point)
// nextPos := nextPoint.GetPos(width)
// if nextPos < 0 || nextPos >= size {
// break
// }
// if rectangleShape[int(nextPos)].Data {
// findCount[direction]++
// } else {
// break
// }
// }
//
// // 十字至少各边需要长度1
// totalCount := hash.Sum(findCount)
// if totalCount < 4 {
// continue
// }
// }
// }
//
// for _, xy := range xys {
// var points []Point[V]
// var find = map[int]bool{}
// x, y := xy.GetXY()
// x = x + (0 - left)
// y = y + (0 - top)
// // 搜索四个方向
// for sx := x - 1; sx >= 0; sx-- {
// if !rectangleShape[int(CoordinateToPos(width, sx, y))].Data {
// break
// }
// find[1] = true
// points = append(points, NewPoint(sx+left, y+top))
// }
// if !find[1] {
// continue
// }
// for sx := x + 1; sx < V(len(rectangleShape)); sx++ {
// if !rectangleShape[int(CoordinateToPos(width, sx, y))].Data {
// break
// }
// find[2] = true
// points = append(points, NewPoint(sx+left, y+top))
// }
// if !find[2] {
// continue
// }
// for sy := y - 1; sy >= 0; sy-- {
// if !rectangleShape[int(CoordinateToPos(width, x, sy))].Data {
// break
// }
// find[3] = true
// points = append(points, NewPoint(x+left, sy+top))
// }
// if !find[3] {
// continue
// }
// for sy := y + 1; sy < V(len(rectangleShape)); sy++ {
// if !rectangleShape[int(CoordinateToPos(width, x, sy))].Data {
// break
// }
// find[4] = true
// points = append(points, NewPoint(x+left, sy+top))
// }
// if !find[4] {
// continue
// }
// result = append(result, append(points, NewPoint(x+left, y+top)))
// }
//
// sort.Slice(result, func(i, j int) bool {
// return len(result[i]) > len(result[j])
// })
//
// var notRepeat [][]Point[V]
// for _, points := range result {
// var match = true
// for _, point := range points {
// x, y := CoordinateArrayToCoordinate(point)
// x = x + (0 - left)
// y = y + (0 - top)
// if record[x][y] {
// match = false
// break
// }
// record[x][y] = true
// }
// if match {
// notRepeat = append(notRepeat, points)
// }
// }
//
// return notRepeat
//}
//
//// SearchContainCross 在一组二维坐标中查找是否存在交叉(十字)线
//func SearchContainCross(xys ...[2]int) bool {
// 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{}
// }
// }
//
// for _, xy := range xys {
// var points [][2]int
// var find = map[int]bool{}
// x, y := CoordinateArrayToCoordinate(xy)
// x = x + (0 - left)
// y = y + (0 - top)
// // 搜索四个方向
// for sx := x - 1; sx >= 0; sx-- {
// if !rectangleShape[sx][y] {
// break
// }
// find[1] = true
// points = append(points, [2]int{sx + left, y + top})
// }
// if !find[1] {
// continue
// }
// for sx := x + 1; sx < len(rectangleShape); sx++ {
// if !rectangleShape[sx][y] {
// break
// }
// find[2] = true
// points = append(points, [2]int{sx + left, y + top})
// }
// if !find[2] {
// continue
// }
// for sy := y - 1; sy >= 0; sy-- {
// if !rectangleShape[x][sy] {
// break
// }
// find[3] = true
// points = append(points, [2]int{x + left, sy + top})
// }
// if !find[3] {
// continue
// }
// for sy := y + 1; sy < len(rectangleShape[0]); sy++ {
// if !rectangleShape[x][sy] {
// break
// }
// find[4] = true
// points = append(points, [2]int{x + left, sy + top})
// }
// if !find[4] {
// continue
// }
// return true
// }
//
// return false
//}
//
//// SearchNotRepeatStraightLine 在一组二维坐标中从大到小搜索不重复的直线
//// - 最低需要长度为3
//func SearchNotRepeatStraightLine(minLength int, xys ...[2]int) (result [][][2]int) {
// if minLength < 3 {
// return nil
// }
// 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{}
// }
// }
//
// for _, xy := range xys {
// var points [][2]int
// var find = map[int]bool{}
// x, y := CoordinateArrayToCoordinate(xy)
// x = x + (0 - left)
// y = y + (0 - top)
// // 搜索四个方向
// for sx := x - 1; sx >= 0; sx-- {
// if !rectangleShape[sx][y] {
// break
// }
// find[1] = true
// points = append(points, [2]int{sx + left, y + top})
// }
// for sx := x + 1; sx < len(rectangleShape); sx++ {
// if !rectangleShape[sx][y] {
// break
// }
// find[2] = true
// points = append(points, [2]int{sx + left, y + top})
// }
// if len(find) == 0 {
// points = nil
// } else if len(points) >= minLength-1 {
// goto end
// } else {
// points = nil
// }
// for sy := y - 1; sy >= 0; sy-- {
// if !rectangleShape[x][sy] {
// break
// }
// find[3] = true
// points = append(points, [2]int{x + left, sy + top})
// }
// for sy := y + 1; sy < len(rectangleShape[0]); sy++ {
// if !rectangleShape[x][sy] {
// break
// }
// find[4] = true
// points = append(points, [2]int{x + left, sy + top})
// }
// if !find[3] && !find[4] {
// continue
// }
// end:
// {
// if len(points) < minLength-1 {
// continue
// }
// result = append(result, append(points, [2]int{x + left, y + top}))
// }
// }
//
// sort.Slice(result, func(i, j int) bool {
// return len(result[i]) > len(result[j])
// })
//
// var notRepeat [][][2]int
// for _, points := range result {
// var match = true
// for _, point := range points {
// x, y := CoordinateArrayToCoordinate(point)
// x = x + (0 - left)
// y = y + (0 - top)
// if record[x][y] {
// match = false
// break
// }
// record[x][y] = true
// }
// if match {
// notRepeat = append(notRepeat, points)
// }
// }
//
// return notRepeat
//}
//
//// SearchContainStraightLine 在一组二维坐标中查找是否存在直线
//func SearchContainStraightLine(minLength int, xys ...[2]int) bool {
// if minLength < 3 {
// return false
// }
// 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{}
// }
// }
//
// for _, xy := range xys {
// var points [][2]int
// var find = map[int]bool{}
// x, y := CoordinateArrayToCoordinate(xy)
// x = x + (0 - left)
// y = y + (0 - top)
// // 搜索四个方向
// for sx := x - 1; sx >= 0; sx-- {
// if !rectangleShape[sx][y] {
// break
// }
// find[1] = true
// points = append(points, [2]int{sx + left, y + top})
// }
// for sx := x + 1; sx < len(rectangleShape); sx++ {
// if !rectangleShape[sx][y] {
// break
// }
// find[2] = true
// points = append(points, [2]int{sx + left, y + top})
// }
// if len(find) == 0 {
// points = nil
// } else if len(points) >= minLength-1 {
// goto end
// } else {
// points = nil
// }
// for sy := y - 1; sy >= 0; sy-- {
// if !rectangleShape[x][sy] {
// break
// }
// find[3] = true
// points = append(points, [2]int{x + left, sy + top})
// }
// for sy := y + 1; sy < len(rectangleShape[0]); sy++ {
// if !rectangleShape[x][sy] {
// break
// }
// find[4] = true
// points = append(points, [2]int{x + left, sy + top})
// }
// if !find[3] && !find[4] {
// continue
// }
// end:
// {
// if len(points) < minLength-1 {
// continue
// }
// return true
// }
// }
//
// return false
//}
//
//// SearchNotRepeatT 在一组二维坐标中从大到小搜索不重复T型T线
//func SearchNotRepeatT(minLength int, xys ...[2]int) (result [][][2]int) {
// if minLength < 4 {
// return nil
// }
// 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{}
// }
// }
//
// for _, xy := range xys {
// var points [][2]int
// var find = map[int]bool{}
// x, y := CoordinateArrayToCoordinate(xy)
// x = x + (0 - left)
// y = y + (0 - top)
// // 搜索四个方向
// for sx := x - 1; sx >= 0; sx-- {
// if !rectangleShape[sx][y] {
// break
// }
// find[1] = true
// points = append(points, [2]int{sx + left, y + top})
// }
// for sx := x + 1; sx < len(rectangleShape); sx++ {
// if !rectangleShape[sx][y] {
// break
// }
// find[2] = true
// points = append(points, [2]int{sx + left, y + top})
// }
// for sy := y - 1; sy >= 0; sy-- {
// if !rectangleShape[x][sy] {
// break
// }
// find[3] = true
// points = append(points, [2]int{x + left, sy + top})
// }
// for sy := y + 1; sy < len(rectangleShape[0]); sy++ {
// if !rectangleShape[x][sy] {
// break
// }
// find[4] = true
// points = append(points, [2]int{x + left, sy + top})
// }
// if len(find) != 3 || len(points) < minLength {
// continue
// }
// result = append(result, append(points, [2]int{x + left, y + top}))
// }
//
// sort.Slice(result, func(i, j int) bool {
// return len(result[i]) > len(result[j])
// })
//
// var notRepeat [][][2]int
// for _, points := range result {
// var match = true
// for _, point := range points {
// x, y := CoordinateArrayToCoordinate(point)
// x = x + (0 - left)
// y = y + (0 - top)
// if record[x][y] {
// match = false
// break
// }
// record[x][y] = true
// }
// if match {
// notRepeat = append(notRepeat, points)
// }
// }
//
// return notRepeat
//}
//
//// SearchContainT 在一组二维坐标中查找是否存在T型T线
//func SearchContainT(minLength int, xys ...[2]int) bool {
// if minLength < 4 {
// return false
// }
// 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{}
// }
// }
//
// for _, xy := range xys {
// var points [][2]int
// var find = map[int]bool{}
// x, y := CoordinateArrayToCoordinate(xy)
// x = x + (0 - left)
// y = y + (0 - top)
// // 搜索四个方向
// for sx := x - 1; sx >= 0; sx-- {
// if !rectangleShape[sx][y] {
// break
// }
// find[1] = true
// points = append(points, [2]int{sx + left, y + top})
// }
// for sx := x + 1; sx < len(rectangleShape); sx++ {
// if !rectangleShape[sx][y] {
// break
// }
// find[2] = true
// points = append(points, [2]int{sx + left, y + top})
// }
// for sy := y - 1; sy >= 0; sy-- {
// if !rectangleShape[x][sy] {
// break
// }
// find[3] = true
// points = append(points, [2]int{x + left, sy + top})
// }
// for sy := y + 1; sy < len(rectangleShape[0]); sy++ {
// if !rectangleShape[x][sy] {
// break
// }
// find[4] = true
// points = append(points, [2]int{x + left, sy + top})
// }
// if len(find) != 3 || len(points) < minLength-1 {
// continue
// }
// return true
// }
//
// return false
//}
//
//// SearchNotRepeatRightAngle 在一组二维坐标中从大到小搜索不重复的直角L线
//func SearchNotRepeatRightAngle(minLength int, xys ...[2]int) (result [][][2]int) {
// if minLength < 3 {
// return nil
// }
// 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{}
// }
// }
//
// for _, xy := range xys {
// var points [][2]int
// var find = map[int]bool{}
// x, y := CoordinateArrayToCoordinate(xy)
// x = x + (0 - left)
// y = y + (0 - top)
// // 搜索四个方向
// for sx := x - 1; sx >= 0; sx-- {
// if !rectangleShape[sx][y] {
// break
// }
// find[1] = true
// points = append(points, [2]int{sx + left, y + top})
// }
// if find[1] {
// goto up
// }
// for sx := x + 1; sx < len(rectangleShape); sx++ {
// if !rectangleShape[sx][y] {
// break
// }
// find[2] = true
// points = append(points, [2]int{sx + left, y + top})
// }
// up:
// for sy := y - 1; sy >= 0; sy-- {
// if !rectangleShape[x][sy] {
// break
// }
// find[3] = true
// points = append(points, [2]int{x + left, sy + top})
// }
// if find[3] {
// goto end
// }
// // down
// for sy := y + 1; sy < len(rectangleShape[0]); sy++ {
// if !rectangleShape[x][sy] {
// break
// }
// find[4] = true
// points = append(points, [2]int{x + left, sy + top})
// }
// if !find[4] {
// continue
// }
// end:
// {
// if len(find) != 2 || len(points) < minLength-1 {
// continue
// }
// result = append(result, append(points, [2]int{x + left, y + top}))
// }
// }
//
// sort.Slice(result, func(i, j int) bool {
// return len(result[i]) > len(result[j])
// })
//
// var notRepeat [][][2]int
// for _, points := range result {
// var match = true
// for _, point := range points {
// x, y := CoordinateArrayToCoordinate(point)
// x = x + (0 - left)
// y = y + (0 - top)
// if record[x][y] {
// match = false
// break
// }
// record[x][y] = true
// }
// if match {
// notRepeat = append(notRepeat, points)
// }
// }
//
// return notRepeat
//}
//
//// SearchContainRightAngle 在一组二维坐标中查找是否存在直角L线
//func SearchContainRightAngle(minLength int, xys ...[2]int) bool {
// if minLength < 3 {
// return false
// }
// 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{}
// }
// }
//
// for _, xy := range xys {
// var points [][2]int
// var find = map[int]bool{}
// x, y := CoordinateArrayToCoordinate(xy)
// x = x + (0 - left)
// y = y + (0 - top)
// // 搜索四个方向
// for sx := x - 1; sx >= 0; sx-- {
// if !rectangleShape[sx][y] {
// break
// }
// find[1] = true
// points = append(points, [2]int{sx + left, y + top})
// }
// if find[1] {
// goto up
// }
// for sx := x + 1; sx < len(rectangleShape); sx++ {
// if !rectangleShape[sx][y] {
// break
// }
// find[2] = true
// points = append(points, [2]int{sx + left, y + top})
// }
// up:
// for sy := y - 1; sy >= 0; sy-- {
// if !rectangleShape[x][sy] {
// break
// }
// find[3] = true
// points = append(points, [2]int{x + left, sy + top})
// }
// if find[3] {
// goto end
// }
// // down
// for sy := y + 1; sy < len(rectangleShape[0]); sy++ {
// if !rectangleShape[x][sy] {
// break
// }
// find[4] = true
// points = append(points, [2]int{x + left, sy + top})
// }
// if !find[4] {
// continue
// }
// end:
// {
// if len(find) != 2 || len(points) < minLength-1 {
// continue
// }
// return true
// }
// }
//
// return false
//}
//
//// SearchNotRepeatFullRectangle 在一组二维坐标中从大到小搜索不重复的填充满的矩形
//// - 不重复指一个位置被使用后将不会被其他矩形使用

View File

@ -8,11 +8,27 @@ type shapeSearchOptions struct {
directionCountLower map[Direction]int
directionCountUpper map[Direction]int
directionCount int
oppositionDirection Direction
}
// ShapeSearchOption 图形搜索可选项,用于 Shape.ShapeSearch 搜索支持
type ShapeSearchOption func(options *shapeSearchOptions)
// WithShapeSearchOppositionDirection 通过限制对立方向的方式搜索
// - 对立方向例如上不能与下共存
func WithShapeSearchOppositionDirection(direction Direction) ShapeSearchOption {
return func(options *shapeSearchOptions) {
options.oppositionDirection = direction
}
}
// WithShapeSearchDirectionCount 通过限制方向数量的方式搜索
func WithShapeSearchDirectionCount(count int) ShapeSearchOption {
return func(options *shapeSearchOptions) {
options.directionCount = count
}
}
// WithShapeSearchDirectionCountLowerLimit 通过限制特定方向数量下限的方式搜索
func WithShapeSearchDirectionCountLowerLimit(direction Direction, count int) ShapeSearchOption {
return func(options *shapeSearchOptions) {
@ -23,16 +39,6 @@ func WithShapeSearchDirectionCountLowerLimit(direction Direction, count int) Sha
}
}
// WithShapeSearchDirectionCount 通过限制方向数量的方式搜索
func WithShapeSearchDirectionCount(count int) ShapeSearchOption {
return func(options *shapeSearchOptions) {
if options.directionCountLower == nil {
options.directionCountLower = map[Direction]int{}
}
options.directionCount = count
}
}
// WithShapeSearchDirectionCountUpperLimit 通过限制特定方向数量上限的方式搜索
func WithShapeSearchDirectionCountUpperLimit(direction Direction, count int) ShapeSearchOption {
return func(options *shapeSearchOptions) {