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  }