2020-06-13 21:40:56 +08:00

417 lines
7.0 KiB
Go

// Copyright 2017-2020 The ShadowEditor Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
//
// For more information, please visit: https://github.com/tengge1/ShadowEditor
// You can also visit: https://gitee.com/tengge1/ShadowEditor
//
// This package is translated from three.js, visit `https://github.com/mrdoob/three.js`
// for more information.
package three
import (
"math"
"math/rand"
"strconv"
)
// NewVector2 :
func NewVector2(x, y float64) *Vector2 {
return &Vector2{x, y, true}
}
// Vector2 :
type Vector2 struct {
X float64
Y float64
IsVector2 bool
}
// Width :
func (v Vector2) Width() float64 {
return v.X
}
// SetWidth :
func (v Vector2) SetWidth(value float64) {
v.X = value
}
// Height :
func (v Vector2) Height() float64 {
return v.Y
}
// SetHeight :
func (v Vector2) SetHeight(value float64) {
v.Y = value
}
// Set :
func (v Vector2) Set(x, y float64) *Vector2 {
v.X = x
v.Y = y
return &v
}
// SetScalar :
func (v Vector2) SetScalar(scalar float64) *Vector2 {
v.X = scalar
v.Y = scalar
return &v
}
// SetX :
func (v Vector2) SetX(x float64) *Vector2 {
v.X = x
return &v
}
// SetY :
func (v Vector2) SetY(y float64) *Vector2 {
v.Y = y
return &v
}
// SetComponent :
func (v Vector2) SetComponent(index int, value float64) *Vector2 {
switch index {
default:
panic("index is out of range: " + strconv.Itoa(index))
case 0:
v.X = value
case 1:
v.Y = value
}
return &v
}
// GetComponent :
func (v Vector2) GetComponent(index int) float64 {
switch index {
default:
panic("index is out of range: " + strconv.Itoa(index))
case 0:
return v.X
case 1:
return v.Y
}
}
// Clone :
func (v Vector2) Clone() *Vector2 {
return NewVector2(v.X, v.Y)
}
// Copy :
func (v Vector2) Copy(w Vector2) *Vector2 {
v.X = w.X
v.Y = w.Y
return &v
}
// Add :
func (v Vector2) Add(w Vector2) *Vector2 {
v.X += w.X
v.Y += w.Y
return &v
}
// AddScalar :
func (v Vector2) AddScalar(s float64) *Vector2 {
v.X += s
v.Y += s
return &v
}
// AddVectors :
func (v Vector2) AddVectors(a, b Vector2) *Vector2 {
v.X = a.X + b.X
v.Y = a.Y + b.Y
return &v
}
// AddScaledVector :
func (v Vector2) AddScaledVector(w Vector2, s float64) *Vector2 {
v.X += w.X * s
v.Y += w.Y * s
return &v
}
// Sub :
func (v Vector2) Sub(w Vector2) *Vector2 {
v.X -= w.X
v.Y -= w.Y
return &v
}
// SubScalar :
func (v Vector2) SubScalar(s float64) *Vector2 {
v.X -= s
v.Y -= s
return &v
}
// SubVectors :
func (v Vector2) SubVectors(a, b Vector2) *Vector2 {
v.X = a.X - b.X
v.Y = a.Y - b.Y
return &v
}
// Multiply :
func (v Vector2) Multiply(w Vector2) *Vector2 {
v.X *= w.X
v.Y *= w.Y
return &v
}
// MultiplyScalar :
func (v Vector2) MultiplyScalar(scalar float64) *Vector2 {
v.X *= scalar
v.Y *= scalar
return &v
}
// Divide :
func (v Vector2) Divide(w Vector2) *Vector2 {
v.X /= w.X
v.Y /= w.Y
return &v
}
// DivideScalar :
func (v Vector2) DivideScalar(scalar float64) *Vector2 {
return v.MultiplyScalar(1 / scalar)
}
// ApplyMatrix3 :
func (v Vector2) ApplyMatrix3(m Matrix3) *Vector2 {
x, y := v.X, v.Y
e := m.Elements
v.X = e[0]*x + e[3]*y + e[6]
v.Y = e[1]*x + e[4]*y + e[7]
return &v
}
// Min :
func (v Vector2) Min(w Vector2) *Vector2 {
v.X = math.Min(v.X, w.X)
v.Y = math.Min(v.Y, w.Y)
return &v
}
// Max :
func (v Vector2) Max(w Vector2) *Vector2 {
v.X = math.Max(v.X, w.X)
v.Y = math.Max(v.Y, w.Y)
return &v
}
// Clamp :
func (v Vector2) Clamp(min, max Vector2) *Vector2 {
// assumes min < max, componentwise
v.X = math.Max(min.X, math.Min(max.X, v.X))
v.Y = math.Max(min.Y, math.Min(max.Y, v.Y))
return &v
}
// ClampScalar :
func (v Vector2) ClampScalar(minVal, maxVal float64) *Vector2 {
v.X = math.Max(minVal, math.Min(maxVal, v.X))
v.Y = math.Max(minVal, math.Min(maxVal, v.Y))
return &v
}
// ClampLength :
func (v Vector2) ClampLength(min, max float64) *Vector2 {
length := v.Length()
if length == 0 {
length = 1
}
return v.DivideScalar(length).MultiplyScalar(math.Max(min, math.Min(max, length)))
}
// Floor :
func (v Vector2) Floor() *Vector2 {
v.X = math.Floor(v.X)
v.Y = math.Floor(v.Y)
return &v
}
// Ceil :
func (v Vector2) Ceil() *Vector2 {
v.X = math.Ceil(v.X)
v.Y = math.Ceil(v.Y)
return &v
}
// Round :
func (v Vector2) Round() *Vector2 {
v.X = math.Round(v.X)
v.Y = math.Round(v.Y)
return &v
}
// RoundToZero :
func (v Vector2) RoundToZero() *Vector2 {
if v.X < 0 {
v.X = math.Ceil(v.X)
} else {
v.X = math.Floor(v.X)
}
if v.Y < 0 {
v.Y = math.Ceil(v.X)
} else {
v.Y = math.Floor(v.X)
}
return &v
}
// Negate :
func (v Vector2) Negate() *Vector2 {
v.X = -v.X
v.Y = -v.Y
return &v
}
// Dot :
func (v Vector2) Dot(w Vector2) float64 {
return v.X*w.X + v.Y*w.Y
}
// Cross :
func (v Vector2) Cross(w Vector2) float64 {
return v.X*w.Y - v.Y*w.X
}
// LengthSq :
func (v Vector2) LengthSq() float64 {
return v.X*v.X + v.Y*v.Y
}
// Length :
func (v Vector2) Length() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
// ManhattanLength :
func (v Vector2) ManhattanLength() float64 {
return math.Abs(v.X) + math.Abs(v.Y)
}
// Normalize :
func (v Vector2) Normalize() *Vector2 {
length := v.Length()
if length == 0 {
length = 1
}
return v.DivideScalar(length)
}
// Angle :
func (v Vector2) Angle() float64 {
// computes the angle in radians with respect to the positive x-axis
var angle = math.Atan2(-v.Y, -v.X) + math.Pi
return angle
}
// DistanceTo :
func (v Vector2) DistanceTo(w Vector2) float64 {
return math.Sqrt(v.DistanceToSquared(w))
}
// DistanceToSquared :
func (v Vector2) DistanceToSquared(w Vector2) float64 {
dx, dy := v.X-w.X, v.Y-w.Y
return dx*dx + dy*dy
}
// ManhattanDistanceTo :
func (v Vector2) ManhattanDistanceTo(w Vector2) float64 {
return math.Abs(v.X-w.X) + math.Abs(v.Y-w.Y)
}
// SetLength :
func (v Vector2) SetLength(length float64) *Vector2 {
return v.Normalize().MultiplyScalar(length)
}
// Lerp :
func (v Vector2) Lerp(w Vector2, alpha float64) *Vector2 {
v.X += (w.X - v.X) * alpha
v.Y += (w.Y - v.Y) * alpha
return &v
}
// LerpVectors :
func (v Vector2) LerpVectors(v1, v2 Vector2, alpha float64) *Vector2 {
v.X = v1.X + (v2.X-v1.X)*alpha
v.Y = v1.Y + (v2.Y-v1.Y)*alpha
return &v
}
// Equals :
func (v Vector2) Equals(w Vector2) bool {
return ((w.X == v.X) && (w.Y == v.Y))
}
// FromArray :
func (v Vector2) FromArray(array []float64, offset int) *Vector2 {
if len(array) < offset+2 {
panic("array length should be greater than offset+2")
}
v.X = array[offset]
v.Y = array[offset+1]
return &v
}
// ToArray :
func (v Vector2) ToArray(array []float64, offset int) []float64 {
if len(array) < offset+2 {
panic("array length should be greater than offset+2")
}
array[offset] = v.X
array[offset+1] = v.Y
return array
}
// RotateAround :
func (v Vector2) RotateAround(center Vector2, angle float64) *Vector2 {
c, s := math.Cos(angle), math.Sin(angle)
var x = v.X - center.X
var y = v.Y - center.Y
v.X = x*c - y*s + center.X
v.Y = x*s + y*c + center.Y
return &v
}
// Random :
func (v Vector2) Random() *Vector2 {
v.X = rand.Float64()
v.Y = rand.Float64()
return &v
}