✨ 通过传入的一组坐标 xys 计算一个图形覆盖的矩形范围
This commit is contained in:
parent
41e0f404b5
commit
e14c871ff0
6
go.mod
6
go.mod
|
@ -29,7 +29,9 @@ require (
|
||||||
github.com/go-playground/validator/v10 v10.14.0 // indirect
|
github.com/go-playground/validator/v10 v10.14.0 // indirect
|
||||||
github.com/goccy/go-json v0.10.2 // indirect
|
github.com/goccy/go-json v0.10.2 // indirect
|
||||||
github.com/golang/protobuf v1.5.3 // indirect
|
github.com/golang/protobuf v1.5.3 // indirect
|
||||||
|
github.com/gopherjs/gopherjs v1.17.2 // indirect
|
||||||
github.com/jonboulle/clockwork v0.3.0 // indirect
|
github.com/jonboulle/clockwork v0.3.0 // indirect
|
||||||
|
github.com/jtolds/gls v4.20.0+incompatible // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
|
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
|
||||||
github.com/klauspost/reedsolomon v1.11.7 // indirect
|
github.com/klauspost/reedsolomon v1.11.7 // indirect
|
||||||
github.com/kr/pretty v0.3.1 // indirect
|
github.com/kr/pretty v0.3.1 // indirect
|
||||||
|
@ -43,6 +45,8 @@ require (
|
||||||
github.com/nats-io/nuid v1.0.1 // indirect
|
github.com/nats-io/nuid v1.0.1 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
|
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
github.com/smartystreets/assertions v1.13.1 // indirect
|
||||||
|
github.com/smartystreets/goconvey v1.8.0 // indirect
|
||||||
github.com/templexxx/cpu v0.0.9 // indirect
|
github.com/templexxx/cpu v0.0.9 // indirect
|
||||||
github.com/templexxx/xorsimd v0.4.1 // indirect
|
github.com/templexxx/xorsimd v0.4.1 // indirect
|
||||||
github.com/tidwall/match v1.1.1 // indirect
|
github.com/tidwall/match v1.1.1 // indirect
|
||||||
|
@ -55,9 +59,11 @@ require (
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
golang.org/x/arch v0.3.0 // indirect
|
golang.org/x/arch v0.3.0 // indirect
|
||||||
golang.org/x/crypto v0.9.0 // indirect
|
golang.org/x/crypto v0.9.0 // indirect
|
||||||
|
golang.org/x/mod v0.9.0 // indirect
|
||||||
golang.org/x/net v0.10.0 // indirect
|
golang.org/x/net v0.10.0 // indirect
|
||||||
golang.org/x/sys v0.8.0 // indirect
|
golang.org/x/sys v0.8.0 // indirect
|
||||||
golang.org/x/text v0.9.0 // indirect
|
golang.org/x/text v0.9.0 // indirect
|
||||||
|
golang.org/x/tools v0.7.0 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
|
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
|
||||||
google.golang.org/protobuf v1.30.0 // indirect
|
google.golang.org/protobuf v1.30.0 // indirect
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
||||||
|
|
12
go.sum
12
go.sum
|
@ -60,12 +60,16 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
|
github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g=
|
||||||
|
github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k=
|
||||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
github.com/jonboulle/clockwork v0.3.0 h1:9BSCMi8C+0qdApAp4auwX0RkLGUjs956h0EkuQymUhg=
|
github.com/jonboulle/clockwork v0.3.0 h1:9BSCMi8C+0qdApAp4auwX0RkLGUjs956h0EkuQymUhg=
|
||||||
github.com/jonboulle/clockwork v0.3.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
|
github.com/jonboulle/clockwork v0.3.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
|
||||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
|
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||||
|
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
github.com/klauspost/compress v1.16.4 h1:91KN02FnsOYhuunwU4ssRe8lc2JosWmizWa91B5v1PU=
|
github.com/klauspost/compress v1.16.4 h1:91KN02FnsOYhuunwU4ssRe8lc2JosWmizWa91B5v1PU=
|
||||||
github.com/klauspost/cpuid v1.2.4/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
github.com/klauspost/cpuid v1.2.4/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||||
github.com/klauspost/cpuid v1.3.1 h1:5JNjFYYQrZeKRJ0734q51WCEEn2huer72Dc7K+R/b6s=
|
github.com/klauspost/cpuid v1.3.1 h1:5JNjFYYQrZeKRJ0734q51WCEEn2huer72Dc7K+R/b6s=
|
||||||
|
@ -124,6 +128,10 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||||
|
github.com/smartystreets/assertions v1.13.1 h1:Ef7KhSmjZcK6AVf9YbJdvPYG9avaF0ZxudX+ThRdWfU=
|
||||||
|
github.com/smartystreets/assertions v1.13.1/go.mod h1:cXr/IwVfSo/RbCSPhoAPv73p3hlSdrBH/b3SdnW/LMY=
|
||||||
|
github.com/smartystreets/goconvey v1.8.0 h1:Oi49ha/2MURE0WexF052Z0m+BNSGirfjg5RL+JXWq3w=
|
||||||
|
github.com/smartystreets/goconvey v1.8.0/go.mod h1:EdX8jtrTIj26jmjCOVNMVSIYAtgexqXKHOXW2Dx9JLg=
|
||||||
github.com/sony/sonyflake v1.1.0 h1:wnrEcL3aOkWmPlhScLEGAXKkLAIslnBteNUq4Bw6MM4=
|
github.com/sony/sonyflake v1.1.0 h1:wnrEcL3aOkWmPlhScLEGAXKkLAIslnBteNUq4Bw6MM4=
|
||||||
github.com/sony/sonyflake v1.1.0/go.mod h1:LORtCywH/cq10ZbyfhKrHYgAUGH7mOBa76enV9txy/Y=
|
github.com/sony/sonyflake v1.1.0/go.mod h1:LORtCywH/cq10ZbyfhKrHYgAUGH7mOBa76enV9txy/Y=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
@ -202,6 +210,8 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
|
||||||
|
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
@ -254,6 +264,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
|
||||||
golang.org/x/tools v0.0.0-20200425043458-8463f397d07c/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200425043458-8463f397d07c/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20200808161706-5bf02b21f123/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
golang.org/x/tools v0.0.0-20200808161706-5bf02b21f123/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
|
golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
|
||||||
|
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
|
|
@ -1,140 +1,10 @@
|
||||||
package g2d
|
package g2d
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/kercylan98/minotaur/utils/g2d/shape"
|
|
||||||
"github.com/kercylan98/minotaur/utils/geometry"
|
"github.com/kercylan98/minotaur/utils/geometry"
|
||||||
"sort"
|
"sort"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MatrixShapeSearchResult[Mark any] struct {
|
|
||||||
Shape *shape.Shape[Mark]
|
|
||||||
Points []shape.Point
|
|
||||||
}
|
|
||||||
|
|
||||||
// MatrixShapeSearchWithYX 二维矩阵形状搜索
|
|
||||||
func MatrixShapeSearchWithYX[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[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[Mark]
|
|
||||||
|
|
||||||
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[Mark]{
|
|
||||||
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, Mark any](matrix [][]T, shapes []*shape.Shape[Mark], checkMatchHandle func(val T) bool) []MatrixShapeSearchResult[Mark] {
|
|
||||||
width := len(matrix)
|
|
||||||
height := len(matrix[0])
|
|
||||||
record := map[int]map[int]bool{}
|
|
||||||
for x := 0; x < width; x++ {
|
|
||||||
for y := 0; y < height; y++ {
|
|
||||||
record[x] = map[int]bool{y: true}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var result []MatrixShapeSearchResult[Mark]
|
|
||||||
|
|
||||||
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[Mark]{
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
// SearchNotRepeatCross 在一组二维坐标中从大到小搜索不重复交叉(十字)线
|
// SearchNotRepeatCross 在一组二维坐标中从大到小搜索不重复交叉(十字)线
|
||||||
// - 不重复指一个位置被使用后将不会被其他交叉线(十字)使用
|
// - 不重复指一个位置被使用后将不会被其他交叉线(十字)使用
|
||||||
func SearchNotRepeatCross(xys ...[2]int) (result [][][2]int) {
|
func SearchNotRepeatCross(xys ...[2]int) (result [][][2]int) {
|
||||||
|
@ -949,24 +819,3 @@ func CoverageAreaBoundless(l, r, t, b int) (left, right, top, bottom int) {
|
||||||
bottom = b + differentY
|
bottom = b + differentY
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetShapeCoverageArea 获取一个图形覆盖的范围
|
|
||||||
func GetShapeCoverageArea(xys ...[2]int) (left, right, top, bottom int) {
|
|
||||||
left, top = -1, -1
|
|
||||||
for _, xy := range xys {
|
|
||||||
x, y := geometry.CoordinateArrayToCoordinate(xy)
|
|
||||||
if x < left || left == -1 {
|
|
||||||
left = x
|
|
||||||
}
|
|
||||||
if x > right {
|
|
||||||
right = x
|
|
||||||
}
|
|
||||||
if y < top || top == -1 {
|
|
||||||
top = y
|
|
||||||
}
|
|
||||||
if y > bottom {
|
|
||||||
bottom = y
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
|
@ -143,3 +143,49 @@ func CoordinateMatrixToPosMatrix[V any](matrix [][]V) (width int, posMatrix []V)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetShapeCoverageAreaWithCoordinateArray 通过传入的一组坐标 xys 计算一个图形覆盖的矩形范围
|
||||||
|
func GetShapeCoverageAreaWithCoordinateArray[V generic.Number](xys ...Point[V]) (left, right, top, bottom V) {
|
||||||
|
hasLeft, hasTop := false, false
|
||||||
|
for _, xy := range xys {
|
||||||
|
x, y := CoordinateArrayToCoordinate(xy)
|
||||||
|
if x < left || !hasLeft {
|
||||||
|
hasLeft = true
|
||||||
|
left = x
|
||||||
|
}
|
||||||
|
if x > right {
|
||||||
|
right = x
|
||||||
|
}
|
||||||
|
if y < top || !hasTop {
|
||||||
|
hasTop = true
|
||||||
|
top = y
|
||||||
|
}
|
||||||
|
if y > bottom {
|
||||||
|
bottom = y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetShapeCoverageAreaWithPos 通过传入的一组坐标 xys 计算一个图形覆盖的矩形范围
|
||||||
|
func GetShapeCoverageAreaWithPos[V generic.Number](width V, positions ...V) (left, right, top, bottom V) {
|
||||||
|
hasLeft, hasTop := false, false
|
||||||
|
for _, pos := range positions {
|
||||||
|
x, y := PosToCoordinate(width, pos)
|
||||||
|
if x < left || !hasLeft {
|
||||||
|
hasLeft = true
|
||||||
|
left = x
|
||||||
|
}
|
||||||
|
if x > right {
|
||||||
|
right = x
|
||||||
|
}
|
||||||
|
if y < top || !hasTop {
|
||||||
|
hasTop = true
|
||||||
|
top = y
|
||||||
|
}
|
||||||
|
if y > bottom {
|
||||||
|
bottom = y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
package geometry_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/kercylan98/minotaur/utils/geometry"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ExampleGetShapeCoverageAreaWithCoordinateArray() {
|
||||||
|
// # # #
|
||||||
|
// # X #
|
||||||
|
// # X X
|
||||||
|
|
||||||
|
var points []geometry.Point[int]
|
||||||
|
points = append(points, geometry.NewPoint(1, 1))
|
||||||
|
points = append(points, geometry.NewPoint(2, 1))
|
||||||
|
points = append(points, geometry.NewPoint(2, 2))
|
||||||
|
|
||||||
|
left, right, top, bottom := geometry.GetShapeCoverageAreaWithCoordinateArray(points...)
|
||||||
|
fmt.Println(fmt.Sprintf("left: %v, right: %v, top: %v, bottom: %v", left, right, top, bottom))
|
||||||
|
|
||||||
|
// left: 1, right: 2, top: 1, bottom: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleGetShapeCoverageAreaWithPos() {
|
||||||
|
// # # # 0 1 2
|
||||||
|
// # X # 3 4 5
|
||||||
|
// # X X 6 7 8
|
||||||
|
|
||||||
|
left, right, top, bottom := geometry.GetShapeCoverageAreaWithPos(3, 4, 7, 8)
|
||||||
|
fmt.Println(fmt.Sprintf("left: %v, right: %v, top: %v, bottom: %v", left, right, top, bottom))
|
||||||
|
|
||||||
|
// left: 1, right: 2, top: 1, bottom: 2
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package geometry_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/kercylan98/minotaur/utils/geometry"
|
||||||
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetShapeCoverageAreaWithCoordinateArray(t *testing.T) {
|
||||||
|
Convey("TestGetShapeCoverageAreaWithCoordinateArray", t, func() {
|
||||||
|
var points []geometry.Point[int]
|
||||||
|
points = append(points, geometry.NewPoint(1, 1))
|
||||||
|
points = append(points, geometry.NewPoint(2, 1))
|
||||||
|
points = append(points, geometry.NewPoint(2, 2))
|
||||||
|
|
||||||
|
left, right, top, bottom := geometry.GetShapeCoverageAreaWithCoordinateArray(points...)
|
||||||
|
|
||||||
|
So(left, ShouldEqual, 1)
|
||||||
|
So(right, ShouldEqual, 2)
|
||||||
|
So(top, ShouldEqual, 1)
|
||||||
|
So(bottom, ShouldEqual, 2)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetShapeCoverageAreaWithPos(t *testing.T) {
|
||||||
|
Convey("TestGetShapeCoverageAreaWithPos", t, func() {
|
||||||
|
left, right, top, bottom := geometry.GetShapeCoverageAreaWithPos(3, 4, 7, 8)
|
||||||
|
|
||||||
|
So(left, ShouldEqual, 1)
|
||||||
|
So(right, ShouldEqual, 2)
|
||||||
|
So(top, ShouldEqual, 1)
|
||||||
|
So(bottom, ShouldEqual, 2)
|
||||||
|
})
|
||||||
|
}
|
Loading…
Reference in New Issue