diff --git a/utils/geometry/shape.go b/utils/geometry/shape.go index b885911..ae39bcb 100644 --- a/utils/geometry/shape.go +++ b/utils/geometry/shape.go @@ -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 在一组二维坐标中从大到小搜索不重复的填充满的矩形 //// - 不重复指一个位置被使用后将不会被其他矩形使用 diff --git a/utils/geometry/shape_search_options.go b/utils/geometry/shape_search_options.go index 71911a2..f04b52b 100644 --- a/utils/geometry/shape_search_options.go +++ b/utils/geometry/shape_search_options.go @@ -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) {