[Translated] the JavaScript Linear Algebra: Vector

This article is the " JavaScript linear algebra part of the" tutorial.

Vector is a method for accurate representation space direction. Vectors of a range of values, each dimension value is a vector component . In the following figure, you can see a composed of two components of a two-dimensional vector space. In the three-dimensional space, the vector will consist of three components.

We can create a 2-dimensional vector space Vector2D class, and then create a vector space of dimension 3 Vector3D class. But we do have a problem: not only for the direction of the vector and the physical space of representation. For example, we may need to color (RGBA) represented as a vector, then it will have four components: red, green, blue, and alpha channels. Alternatively, we use vectors to represent the different proportion of n choices (such as horse racing represents 5 per horse to win the vector probability game). Therefore, we will not create a class specified dimension, and use it like this:

class Vector {
  constructor(...components) {
    this.components = components
  }
}

const direction2d = new Vector(1, 2)
const direction3d = new Vector(1, 2, 3)
const color = new Vector(0.5, 0.4, 0.7, 0.15)
const probabilities = new Vector(0.1, 0.3, 0.15, 0.25, 0.2)
复制代码

Vector operations

Consider the case of two vectors, they can define the following calculation:

Wherein, [alpha] R & lt ∈ is an arbitrary constant.

In addition to the cross product of our operations are visualized, you can here find examples. This GitHub repository , there used to create these visual examples of React project and associated libraries. If you want to know how to React and SVG to create a two-dimensional visualization of these examples, please refer to this article .

Addition and subtraction

Similar numerical calculation, you can of vector addition and subtraction. When the vector arithmetic operations, the respective components of the vector may be direct numerical calculation results obtained:

Another vector adder function receives as a parameter, and the corresponding vector components are added, and returns the new vector obtained. Similarly subtraction function, but will be replaced by the addition subtraction:

class Vector {
  constructor(...components) {
    this.components = components
  }

  add({ components }) {
    return new Vector(
      ...components.map((component, index) => this.components[index] + component)
    )
  }
  subtract({ components }) {
    return new Vector(
      ...components.map((component, index) => this.components[index] - component)
    )
  }
}

const one = new Vector(2, 3)
const other = new Vector(2, 1)
console.log(one.add(other))
// Vector { components: [ 4, 4 ] }
console.log(one.subtract(other))
// Vector { components: [ 0, 2 ] }
复制代码

Scaling

We may scale a vector, scaling can be any value [alpha] R & lt ∈ . Zoom, all the vector components are multiplied by a scaling factor [alpha] . When α> 1 , the vector becomes longer; if 0 ≤ α <1 , the vector becomes shorter. If α is negative, the vector will be scaled original vector pointing in the opposite direction.

In scaleBy method, we have to take all of the components of the vector values for incoming parameters, and return to get the new vector:

class Vector {
  constructor(...components) {
    this.components = components
  }
  // ...

  scaleBy(number) {
    return new Vector(
      ...this.components.map(component => component * number)
    )
  }
}

const vector = new Vector(1, 2)
console.log(vector.scaleBy(2))
// Vector { components: [ 2, 4 ] }
console.log(vector.scaleBy(0.5))
// Vector { components: [ 0.5, 1 ] }
console.log(vector.scaleBy(-1))
// Vector { components: [ -1, -2 ] }
复制代码

length

Vector length derived by the Pythagorean theorem:

Because existing JavaScript function built-in Math object, so the method is very simple calculation of the length:

class Vector {
  constructor(...components) {
    this.components = components
  }
  // ...
  
  length() {
    return Math.hypot(...this.components)
  }
}

const vector = new Vector(2, 3)
console.log(vector.length())
// 3.6055512754639896
复制代码

Dot product

Dot product can calculate the degree of similarity of the two vectors. The dot product of two vectors received as input method, and outputs a value. Dot product of two vectors is equal to the corresponding sum of the products of their respective components and.

In dotProduct method, another vector received as a parameter, calculated by a sum of products of the corresponding components and the reduce method:

class Vector {
  constructor(...components) {
    this.components = components
  }
  // ...
  
  dotProduct({ components }) {
    return components.reduce((acc, component, index) => acc + component * this.components[index], 0)
  }
}

const one = new Vector(1, 4)
const other = new Vector(2, 2)
console.log(one.dotProduct(other))
// 10
复制代码

Before we look at the relationship between the direction of several vectors, we need to implement a length of the vector into a normalized method. This vector after normalization will be used in many scenarios. For example, when we need to specify a direction in space, we need to use a vector after a Naturalization be represented in this direction.

class Vector {
  constructor(...components) {
    this.components = components
  }
  // ...
  
  normalize() {
    return this.scaleBy(1 / this.length())
  }
}

const vector = new Vector(2, 4)
const normalized = vector.normalize()
console.log(normalized)
// Vector { components: [ 0.4472135954999579, 0.8944271909999159 ] }
console.log(normalized.length())
// 1
复制代码

If the two normalized vectors of a dot product is equal to 1, it means that the directions of these two vectors are the same. We created areEqual function is used to compare two floating-point numbers:

const EPSILON = 0.00000001

const areEqual = (one, other, epsilon = EPSILON) =>
  Math.abs(one - other) < epsilon

class Vector {
  constructor(...components) {
    this.components = components
  }
  // ...
  
  haveSameDirectionWith(other) {
    const dotProduct = this.normalize().dotProduct(other.normalize())
    return areEqual(dotProduct, 1)
  }
}

const one = new Vector(2, 4)
const other = new Vector(4, 8)
console.log(one.haveSameDirectionWith(other))
// true
复制代码

If the dot product of two vectors normalizing the result of a equal to -1, it indicates the opposite direction thereof:

class Vector {
  constructor(...components) {
    this.components = components
  }
  // ...
  haveOppositeDirectionTo(other) {
    const dotProduct = this.normalize().dotProduct(other.normalize())
    return areEqual(dotProduct, -1)
  }
}

const one = new Vector(2, 4)
const other = new Vector(-4, -8)
console.log(one.haveOppositeDirectionTo(other))
// true
复制代码

If the two normalized vectors of a dot product is 0, it means that two vectors are orthogonal to each other:

class Vector {
  constructor(...components) {
    this.components = components
  }
  // ...
  
  isPerpendicularTo(other) {
    const dotProduct = this.normalize().dotProduct(other.normalize())
    return areEqual(dotProduct, 0)
  }
}

const one = new Vector(-2, 2)
const other = new Vector(2, 2)
console.log(one.isPerpendicularTo(other))
// true
复制代码

Cross product

Applies only to three-dimensional vector cross product, it will produce a vector normal to the two input vectors:

When we realize cross product, assuming that it is only within the vector calculation for the three-dimensional space.

class Vector {
  constructor(...components) {
    this.components = components
  }
  // ...
  
  // 只适用于 3 维向量
  crossProduct({ components }) {
    return new Vector(
      this.components[1] * components[2] - this.components[2] * components[1],
      this.components[2] * components[0] - this.components[0] * components[2],
      this.components[0] * components[1] - this.components[1] * components[0]
    )
  }
}

const one = new Vector(2, 1, 1)
const other = new Vector(1, 2, 2)
console.log(one.crossProduct(other))
// Vector { components: [ 0, -3, 3 ] }
console.log(other.crossProduct(one))
// Vector { components: [ 0, 3, -3 ] }
复制代码

Other common methods

In real life application, the above method is not enough. For example, we may need to find the angle between two vectors, one vector reverse, or calculate a projected vector on another vector, and the like.

Before you start writing method said above, we need to write the following two functions for conversion between the angle in radians:

const toDegrees = radians => (radians * 180) / Math.PI
const toRadians = degrees => (degrees * Math.PI) / 180
复制代码

Angle

class Vector {
  constructor(...components) {
    this.components = components
  }
  // ...
  
  angleBetween(other) {
    return toDegrees(
      Math.acos(
        this.dotProduct(other) /
        (this.length() * other.length())
      )
    )
  }
}

const one = new Vector(0, 4)
const other = new Vector(4, 4)
console.log(one.angleBetween(other))
// 45.00000000000001
复制代码

Reverse

When you need to reverse the direction of a vector point, we can be scaled to -1 this vector:

class Vector {
  constructor(...components) {
    this.components = components
  }
  // ...
  
  negate() {
    return this.scaleBy(-1)
  }
}

const vector = new Vector(2, 2)
console.log(vector.negate())
// Vector { components: [ -2, -2 ] }
复制代码

projection

class Vector {
  constructor(...components) {
    this.components = components
  }
  // ...
  
  projectOn(other) {
    const normalized = other.normalize()
    return normalized.scaleBy(this.dotProduct(normalized))
  }
}

const one = new Vector(8, 4)
const other = new Vector(4, 7)
console.log(other.projectOn(one))
// Vector { components: [ 6, 3 ] }
复制代码

Set length

When required to specify the length of a vector, a method may be used:

class Vector {
  constructor(...components) {
    this.components = components
  }
  // ...
  withLength(newLength) {
    return this.normalize().scaleBy(newLength)
  }
}

const one = new Vector(2, 3)
console.log(one.length())
// 3.6055512754639896
const modified = one.withLength(10)
// 10
console.log(modified.length())
复制代码

For equality

To determine whether the two vectors are equal, they may be used for components corresponding areEqual function:

class Vector {
  constructor(...components) {
    this.components = components
  }
  // ...
  
  equalTo({ components }) {
    return components.every((component, index) => areEqual(component, this.components[index]))
  }
}

const one = new Vector(1, 2)
const other = new Vector(1, 2)
console.log(one.equalTo(other))
// true
const another = new Vector(2, 1)
console.log(one.equalTo(another))
// false
复制代码

The base unit vector

We can be seen as a vector "x-axis walking v_xdistance, the y-axis walking v_ydistance, the z-axis walking v_zdistance." We can use has \ {\} imath, \hat { \jmath }and \hat { k }are multiplied by a value more clearly expressed above. FIG case are x, Y, withaxis unit vector :

has \ {\ imath} = (1,0,0) \ quad \ hat {\ jMath} = (0,1,0) \ quad \ hat {k} = (0,0,1)

Any numerical value is multiplied by has \ {\} imathvectors, can obtain a value of the vector component is equal to the first dimension. E.g:

\ 2 has {\ imath} = (2,0,0) \ quad 3 \ hat {\ jMath} = (0,3,0) \ quad has 5 \ {k} = (0,0,5)

Vector is the most important concept is the base . There is a 3-dimensional vector \mathbb{R}^3, which is a set of base vectors: \ {\ Hat {e} has _1, \ {e} has _2, \ {e} _3 \}This may be a set of vectors \mathbb{R}^3of the coordinate system. If \ {\ Hat {e} has _1, \ {e} has _2, \ {e} _3 \}a group of the substrate, any vector can be \vec{v} \in \mathbb{R}^3represented for the coefficient of the substrate (V_1, v_2, v_3):

\ Vec {v} = v_1 \ hat {e} _1 + v_2 \ hat {e} _2 + v_3 \ hat {e} _3

Vector \ Begin {at}is obtained by in \hat{e}_1the direction of the measuring v_2distance in \hat{e}_2the measurement direction v_1a distance, in \hat{e}_3measuring the direction of v_3distances obtained.

Before the base do not know of a vector, the vector of coefficients triples and does not make sense. Only you know the vector base, similar to the (a,b,c)mathematical object triples into concepts (such as color, probability, location, etc.) in the real world.

If you find there is a translation error or other areas for improvement, welcome to Denver translation program to be modified and translations PR, also obtained the corresponding bonus points. The beginning of the article Permalink article is the MarkDown the links in this article on GitHub.


Nuggets Translation Project is a high-quality translation of technical articles Internet community, Source for the Nuggets English Share article on. Content covering Android , iOS , front-end , back-end , block chain , product , design , artificial intelligence field, etc., you want to see more high-quality translations, please continue to focus Nuggets translation program , the official micro-blog , we know almost columns .

Reproduced in: https: //juejin.im/post/5cf61bf8e51d45775653674e

Guess you like

Origin blog.csdn.net/weixin_34377919/article/details/91473775