vecti
Version:
A tiny TypeScript library for 2D vector math.
233 lines (157 loc) • 5.52 kB
Markdown
<p align="center">
<img src="https://github.com/DerYeger/yeger/raw/main/docs/vecti-docs/public/logo.svg" alt="Logo" width="164px" height="164px">
</p>
<h1 align="center">Vecti</h1>
<p align="center">
A tiny TypeScript library for 2D vector math.
</p>
<p align="center">
<a href="https://vecti.yeger.eu">
Documentation
</a>
</p>
<p align="center">
<a href="https://github.com/DerYeger/yeger/actions/workflows/ci.yml">
<img alt="CI" src="https://img.shields.io/github/actions/workflow/status/DerYeger/yeger/ci.yml?branch=main&label=ci&logo=github&color=#4DC71F">
</a>
<a href="https://www.npmjs.com/package/vecti">
<img alt="NPM" src="https://img.shields.io/npm/v/vecti?logo=npm">
</a>
<a href="https://app.codecov.io/gh/DerYeger/yeger/tree/main/packages/vecti">
<img alt="Coverage" src="https://codecov.io/gh/DerYeger/yeger/branch/main/graph/badge.svg?token=DjcvNlg4hd&flag=vecti">
</a>
<a href="https://opensource.org/licenses/MIT">
<img alt="MIT" src="https://img.shields.io/npm/l/vecti?color=%234DC71F">
</a>
<a href="https://bundlephobia.com/package/vecti">
<img alt="npm bundle size" src="https://img.shields.io/bundlephobia/minzip/vecti">
</a>
</p>
## Features
- 🧮 Addition, subtraction, multiplication and division
- ✨ Dot, cross and Hadamard product
- 📏 Length and normalization
- 📐 Rotation by radians and degrees
- 🪨 Immutable data structure encourages chaining
- 💾 Tiny and typed
## Projects using Vecti
- [d3-graph-controller](https://github.com/DerYeger/yeger/tree/main/packages/d3-graph-controller) - Calculation of graph [edge paths](https://github.com/DerYeger/yeger/blob/main/packages/d3-graph-controller/src/lib/paths.ts)
## Installation
```bash
# yarn
$ yarn add vecti
# npm
$ npm install vecti
```
## Usage
Vectors have two properties, `x` and `y`, representing their components.
Since vectors are entirely immutable, they are read-only.
To use Vecti, add the following import to your TypeScript file.
Instances of the `Vector` class can be created either by using its constructor or the static method of the class.
The latter accepts a `number` array of length 2, with the first element being the x-axis component and the second element being the y-axis component.
```ts
import { Vector } from 'vecti'
// eslint-disable-next-line no-new
new Vector(42, 7) // == Vector { x: 42, y: 7 }
Vector.of([42, 7]) // == Vector { x: 42, y: 7 }
```
### Addition
Two vectors can be added using the `add` method.
```ts
const a = new Vector(0, 1)
const b = new Vector(1, 0)
a.add(b) // == Vector { x: 1, y: 1 }
```
### Subtraction
Two vectors can be subtracted using the `subtract` method.
The **parameter** is the **subtrahend** and the **instance** is the **minuend**.
```ts
const a = new Vector(2, 1)
const b = new Vector(1, 0)
a.subtract(b) // == Vector { x: 1, y: 0 }
```
### Multiplication
Vectors can be multiplied by scalars using the `multiply` method.
```ts
const a = new Vector(1, 0)
a.multiply(2) // == Vector { x: 2, y: 0 }
```
### Division
Vectors can be divided by scalars using the `divide` method.
The **parameter** is the **divisor** and the **instance** is the **dividend**.
```ts
const a = new Vector(4, 2)
a.divide(2) // == Vector { x: 2, y: 1 }
```
### Dot product
The dot product of two vectors can be calculated using the `dot` method.
```ts
const a = new Vector(2, 3)
const b = new Vector(1, 3)
a.dot(b) // == 11
```
### Cross product
The cross product of two vectors can be calculated using the `cross` method.
The cross product of two vectors `a` and `b` is defined as `a.x * b.y - a.y * b.x`.
```ts
const a = new Vector(2, 1)
const b = new Vector(1, 3)
a.cross(b) // == 5
```
### Hadamard product
The Hadamard product of two vectors can be calculated using the `hadamard` method.
```ts
const a = new Vector(2, 1)
const b = new Vector(1, 3)
a.hadamard(b) // == Vector { x: 2, y: 3 }
```
### Length
The length of a vector can be calculated using the `length` method.
Length is defined as the **L2 norm**.
```ts
const a = new Vector(1, 0)
a.length() // == 1
const b = new Vector(-3, 4)
b.length() // == 5
```
### Normalization
A normalized version of a vector can be calculated using the `normalize` method.
The resulting vector will have a length of **1**.
```ts
const a = new Vector(2, 0)
a.length() // == 2
const b = a.normalize() // == Vector { x: 1, y: 0 }
b.length() // == 1
```
### Rotation
Vectors can be rotated by radians or degrees using the methods `rotateByRadians` and `rotateByDegrees` respectively.
Due to the rotation using `Math.sin` and `Math.cos`, rounding errors can occur.
Notice that in the example below, the resulting x-component is **6.123233995736766e-17** and not **0** as expected.
```ts
const a = new Vector(1, 0)
a.rotateByDegrees(90) // == Vector { x: 6.123233995736766e-17, y: 1 }
a.rotateByRadians(Math.PI / 2) // == Vector { x: 6.123233995736766e-17, y: 1 }
```
### Chaining
Vecti encourages chaining methods to achieve readable and concise calculations.
```ts
import { Vector } from 'vecti'
new Vector(-5, 0)
.normalize()
.rotateByDegrees(180)
.add(Vector.of([0, 1]))
.multiply(42) // == Vector { x: 42, y: 41.99999999999999 }
```
## Development
```bash
# install dependencies
$ pnpm install
# build for production
$ pnpm build
# lint project files
$ pnpm lint
# run tests
$ pnpm test
```
## License
[MIT](https://github.com/DerYeger/yeger/blob/main/packages/vecti/LICENSE) - Copyright © Jan Müller