github.com/15mga/kiwi@v0.0.2-0.20240324021231-b95d5c3ac751/util/vec.go (about) 1 package util 2 3 import ( 4 "math" 5 "math/rand" 6 ) 7 8 func Vec2One() Vec2 { 9 return Vec2{1, 1} 10 } 11 12 type Vec2 struct { 13 X float32 14 Y float32 15 } 16 17 func Vec2Equal(a, b Vec2) bool { 18 return Cmp(a.X, b.X) == 0 && Cmp(a.Y, b.Y) == 0 19 } 20 21 func Vec2Normalize(v Vec2) Vec2 { 22 return Vec2Div(v, Vec2Magnitude(v)) 23 } 24 25 func Vec2Radian(a, b Vec2) float32 { 26 return float32(math.Acos(float64(Vec2Dot(a, b) / (Vec2Magnitude(a) * Vec2Magnitude(b))))) 27 } 28 29 func Vec2ToRadian(a Vec2) float32 { 30 return float32(math.Atan2(float64(a.Y), float64(a.X))) 31 } 32 33 // Vec2Cross 叉积 34 func Vec2Cross(a, b Vec2) float32 { 35 return a.X*b.Y - b.X*a.Y 36 } 37 38 // Vec2Dot 点积 39 func Vec2Dot(a, b Vec2) float32 { 40 return a.X*b.X + a.Y*b.Y 41 } 42 43 func Vec2Add(a, b Vec2) Vec2 { 44 return Vec2{X: a.X + b.X, Y: a.Y + b.Y} 45 } 46 47 func Vec2Sub(a, b Vec2) Vec2 { 48 return Vec2{X: a.X - b.X, Y: a.Y - b.Y} 49 } 50 51 func Vec2Div(a Vec2, v float32) Vec2 { 52 return Vec2{X: a.X / v, Y: a.Y / v} 53 } 54 55 func Vec2Mul(a Vec2, v float32) Vec2 { 56 return Vec2{X: a.X * v, Y: a.Y * v} 57 } 58 59 func Vec2Magnitude(a Vec2) float32 { 60 return float32(math.Sqrt(float64(Vec2Dot(a, a)))) 61 } 62 63 func Vec2Dist(a, b Vec2) float32 { 64 return Vec2Magnitude(Vec2Sub(a, b)) 65 } 66 67 func Vec2DistSquare(a, b Vec2) float32 { 68 v := Vec2Sub(a, b) 69 return Vec2Dot(v, v) 70 } 71 72 func Vec2Clamp(v, min, max Vec2) Vec2 { 73 return Vec2{ 74 X: ClampFloat(v.X, min.X, max.X), 75 Y: ClampFloat(v.Y, min.Y, max.Y), 76 } 77 } 78 79 func Vec2Rotate90(a Vec2) Vec2 { 80 return Vec2{ 81 X: -a.Y, 82 Y: a.X, 83 } 84 } 85 86 func Vec2Rotate180(v Vec2) Vec2 { 87 return Vec2{ 88 X: -v.X, 89 Y: -v.Y, 90 } 91 } 92 93 func Vec2Rotate270(a Vec2) Vec2 { 94 return Vec2{ 95 X: a.Y, 96 Y: -a.X, 97 } 98 } 99 100 func Vec2Rotate(a Vec2, radian float32) Vec2 { 101 r := float64(radian) 102 s := math.Sin(r) 103 c := math.Cos(r) 104 return Vec2{ 105 X: float32(float64(a.X)*c - float64(a.Y)*s), 106 Y: float32(float64(a.X)*s + float64(a.Y)*c), 107 } 108 } 109 110 func Vec2Lerp(a, b Vec2, v float32) Vec2 { 111 return Vec2{ 112 X: a.X + (b.X-a.X)*v, 113 Y: a.Y + (b.Y-a.Y)*v, 114 } 115 } 116 117 func Vec2XRebound(a, b Vec2, bound float32) (Vec2, bool) { 118 if (a.X < bound && b.X > bound) || 119 (a.X > bound && b.X < bound) { 120 return Vec2{}, false 121 } 122 a1X := bound - a.X + bound 123 u := (bound - b.X) / (a1X - b.X) 124 w := b.Y + (a.Y-b.Y)*u 125 return Vec2{X: bound, Y: w}, true 126 } 127 128 func Vec2YRebound(a, b Vec2, bound float32) (Vec2, bool) { 129 if (a.Y < bound && b.Y > bound) || 130 (a.Y > bound && b.Y < bound) { 131 return Vec2{}, false 132 } 133 a1Y := bound - a.Y + bound 134 u := (bound - b.Y) / (a1Y - b.Y) 135 w := b.X + (a.X-b.X)*u 136 return Vec2{X: w, Y: bound}, true 137 } 138 139 func PointToVecNearPoint(p, a, b Vec2) Vec2 { 140 dot := (b.X-a.X)*(p.X-a.X) + (b.Y-a.Y)*(p.Y-a.Y) 141 dotP := (a.X-b.X)*(a.X-b.X) + (a.Y-b.Y)*(a.Y-b.Y) 142 u := dot / dotP 143 x := a.X + (b.X-a.X)*u 144 y := a.Y + (b.Y-a.Y)*u 145 return Vec2{ 146 X: x, 147 Y: y, 148 } 149 } 150 151 func PointToVecDistSquare(p, a, b Vec2) float32 { 152 dot := (b.X-a.X)*(p.X-a.X) + (b.Y-a.Y)*(p.Y-a.Y) 153 dotP := (a.X-b.X)*(a.X-b.X) + (a.Y-b.Y)*(a.Y-b.Y) 154 u := dot / dotP 155 x := a.X + (b.X-a.X)*u 156 y := a.Y + (b.Y-a.Y)*u 157 x2 := p.X - x 158 y2 := p.Y - y 159 return x2*x2 + y2*y2 160 } 161 162 func PointToVecDist(p, a, b Vec2) float32 { 163 return float32(math.Sqrt(float64(PointToVecDistSquare(p, a, b)))) 164 } 165 166 func PointToSegNearPoint(p, a, b Vec2) Vec2 { 167 dot := (b.X-a.X)*(p.X-a.X) + (b.Y-a.Y)*(p.Y-a.Y) 168 if CmpZero(dot) < 1 { 169 return a 170 } 171 dotP := (a.X-b.X)*(a.X-b.X) + (a.Y-b.Y)*(a.Y-b.Y) 172 if Cmp(dot, dotP) > -1 { 173 return b 174 } 175 u := dot / dotP 176 x := a.X + (b.X-a.X)*u 177 y := a.Y + (b.Y-a.Y)*u 178 return Vec2{ 179 X: x, 180 Y: y, 181 } 182 } 183 184 func PointToSegDistSquare(p, a, b Vec2) float32 { 185 dot := (b.X-a.X)*(p.X-a.X) + (b.Y-a.Y)*(p.Y-a.Y) 186 if dot <= 0 { 187 return (a.X-p.X)*(a.X-p.X) + (a.Y-p.Y)*(a.Y-p.Y) 188 } 189 dotP := (a.X-b.X)*(a.X-b.X) + (a.Y-b.Y)*(a.Y-b.Y) 190 if dot >= dotP { 191 return (b.X-p.X)*(b.X-p.X) + (b.Y-p.Y)*(b.Y-p.Y) 192 } 193 u := dot / dotP 194 x := a.X + (b.X-a.X)*u 195 y := a.Y + (b.Y-a.Y)*u 196 x2 := p.X - x 197 y2 := p.Y - y 198 return x2*x2 + y2*y2 199 } 200 201 // PointToSegDist 点到线段的距离 202 func PointToSegDist(p, a, b Vec2) float32 { 203 return float32(math.Sqrt(float64(PointToSegDistSquare(p, a, b)))) 204 } 205 206 // TriangleArea 三点构成的三角形面积 207 func TriangleArea(a, b, c Vec2) float32 { 208 return Vec2Cross(Vec2Sub(b, a), Vec2Sub(c, a)) 209 } 210 211 // PointOnSeg 点是否在线段上 212 func PointOnSeg(p, a, b Vec2) bool { 213 v1 := Vec2Sub(a, p) 214 v2 := Vec2Sub(b, p) 215 return CmpZero(Vec2Cross(v1, v2)) == 0 && CmpZero(Vec2Dot(v1, v2)) == -1 216 } 217 218 func PointInTriangle(p, a, b, c Vec2) bool { 219 pa := Vec2Sub(a, p) 220 pb := Vec2Sub(b, p) 221 pc := Vec2Sub(c, p) 222 c0 := Vec2Cross(pa, pb) 223 c1 := Vec2Cross(pb, pc) 224 c2 := Vec2Cross(pc, pa) 225 return (c0 < 0 && c1 < 0 && c2 < 0) || 226 (c0 > 0 && c1 > 0 && c2 > 0) 227 } 228 229 func Vec3One() Vec3 { 230 return Vec3{1, 1, 1} 231 } 232 233 type Vec3 struct { 234 X float32 235 Y float32 236 Z float32 237 } 238 239 type Vec2Int struct { 240 X int 241 Y int 242 } 243 244 func (v Vec2Int) Equal(v1 Vec2Int) bool { 245 return v.X == v1.X && v.Y == v1.Y 246 } 247 248 func RandDir() Vec2 { 249 x := rand.Float32()*2 - 1 250 y := rand.Float32()*2 - 1 251 return Vec2Normalize(Vec2{ 252 X: x, 253 Y: y, 254 }) 255 } 256 257 func RandRange(center Vec2, radius float32) Vec2 { 258 return Vec2Add(center, Vec2Mul(RandDir(), radius)) 259 }