init commit

This commit is contained in:
= 2024-07-05 22:54:49 +03:00
commit 43b2a34fe7
14 changed files with 4024 additions and 0 deletions

29
.eslintrc.cjs Normal file
View File

@ -0,0 +1,29 @@
module.exports = {
env: {
es2021: true,
node: true,
},
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"prettier",
],
overrides: [
{
env: {
node: true,
},
files: [".eslintrc.{js,cjs}"],
parserOptions: {
sourceType: "script",
},
},
],
parser: "@typescript-eslint/parser",
parserOptions: {
ecmaVersion: "latest",
sourceType: "module",
},
plugins: ["@typescript-eslint"],
rules: {},
};

24
.gitignore vendored Normal file
View File

@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist-ssr
*.local
# Editor directories and files
.vscode/*
.vs
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

3
.prettierignore Normal file
View File

@ -0,0 +1,3 @@
# Ignore artifacts:
dist
example

1
.prettierrc.json Normal file
View File

@ -0,0 +1 @@
{}

74
README.md Normal file
View File

@ -0,0 +1,74 @@
# Vector2D Library for TypeScript
A comprehensive TypeScript library for 2D vector operations, including addition, subtraction, multiplication, division, normalization, and more. Ideal for game development, physics simulations, and graphical applications.
## Features
- Create and manipulate 2D vectors
- Perform vector arithmetic (addition, subtraction, multiplication, division)
- Calculate dot and cross products
- Normalize vectors
- Calculate magnitude and distance between vectors
- Rotate vectors
- Linear interpolation between vectors
## Installation
You can install the library using npm:
```bash
npm install vector2d
```
## Usage
Here's a quick example of how to use the `Vector2D` class:
```typescript
import { Vector2D } from 'vector2d';
const vector1 = new Vector2D(3, 4);
const vector2 = new Vector2D(1, 2);
// Vector addition
const result = vector1.add(vector2);
console.log(`Result of addition: (${result.getX()}, ${result.getY()})`);
// Vector normalization
const normalized = vector1.normalize();
console.log(`Normalized vector: (${normalized.getX()}, ${normalized.getY()})`);
```
## API Reference
### `Vector2D`
#### Constructor
```typescript
constructor(x: number, y: number)
x - The x-coordinate.
y - The y-coordinate.
Methods
- `getX(): number` - Gets the x-coordinate.
- `getY(): number` - Gets the y-coordinate.
- `setX(x: number): void` - Sets the x-coordinate.
- `setY(y: number): void` - Sets the y-coordinate.
- `set(x: number, y: number): void` - Sets both the x and y coordinates.
- `add(vector: Vector2D): Vector2D` - Adds another vector to this vector.
- `subtract(vector: Vector2D): Vector2D` - Subtracts another vector from this vector.
- `multiply(scalar: number): Vector2D` - Multiplies this vector by a scalar.
- `divide(scalar: number): Vector2D` - Divides this vector by a scalar.
- `dot(vector: Vector2D): number` - Calculates the dot product of this vector and another vector.
- `cross(vector: Vector2D): number` - Calculates the cross product of this vector and another vector.
- `magnitude(): number` - Calculates the magnitude (length) of this vector.
- `normalize(): Vector2D` - Normalizes this vector (makes it have a magnitude of 1).
- `clone(): Vector2D` - Creates a copy of this vector.
- `equals(vector: Vector2D): boolean` - Checks if this vector is equal to another vector.
- `toString(): string` - Returns a string representation of this vector.
- `distance(vector: Vector2D): number` - Calculates the distance to another vector.
- `angle(): number` - Calculates the angle of this vector relative to the positive X-axis.
- `rotate(angle: number): Vector2D` - Rotates this vector by a given angle.
- `lerp(vector: Vector2D, t: number): Vector2D` - Performs linear interpolation between this vector and another vector.
```

5
jest.config.js Normal file
View File

@ -0,0 +1,5 @@
/** @type {import('ts-jest').JestConfigWithTsJest} */
export default {
preset: 'ts-jest',
testEnvironment: 'node',
};

44
package.json Normal file
View File

@ -0,0 +1,44 @@
{
"name": "@yazmeyaa/vector2d",
"private": false,
"version": "0.0.1",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/yazmeyaa/vector2d"
},
"main": "./dist/index.umd.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"type": "module",
"scripts": {
"build": "tsc && vite build",
"preview": "vite preview",
"predeploy": "npm run dist",
"lint": "eslint src --ext .ts",
"lint:fix": "eslint src --ext .ts --fix",
"format": "prettier --write ./src/**/*.ts"
},
"devDependencies": {
"@jest/globals": "^29.7.0",
"@rollup/plugin-typescript": "^11.1.6",
"@types/jest": "^29.5.12",
"@types/node": "^20.14.10",
"@typescript-eslint/eslint-plugin": "^7.15.0",
"@typescript-eslint/parser": "^7.15.0",
"eslint": "8.57.0",
"eslint-config-prettier": "^9.1.0",
"jest": "^29.7.0",
"prettier": "^3.3.2",
"rollup-plugin-typescript-paths": "^1.5.0",
"ts-jest": "^29.1.5",
"tslib": "^2.6.3",
"typescript": "^5.5.3",
"vite": "^5.3.1",
"vite-plugin-dts": "^3.9.1",
"vite-tsconfig-paths": "^4.3.2"
}
}

21
src/types.ts Normal file
View File

@ -0,0 +1,21 @@
export interface IVector2D {
getX(): number;
getY(): number;
setX(x: number): void;
setY(y: number): void;
set(x: number, y: number): void;
add(vector: IVector2D): IVector2D;
subtract(vector: IVector2D): IVector2D;
multiply(scalar: number): IVector2D;
divide(scalar: number): IVector2D;
dot(vector: IVector2D): number;
cross(vector: IVector2D): number;
magnitude(): number;
normalize(): IVector2D;
clone(): IVector2D;
equals(vector: IVector2D): boolean;
toString(): string;
distance(vector: IVector2D): number;
angle(): number;
rotate(angle: number): IVector2D;
}

130
src/vector2d.test.ts Normal file
View File

@ -0,0 +1,130 @@
import { Vector2D } from "./vector2d";
describe("Vector2D", () => {
test("constructor initializes correctly", () => {
const vector = new Vector2D(3, 4);
expect(vector.getX()).toBe(3);
expect(vector.getY()).toBe(4);
});
test("setX and setY update coordinates", () => {
const vector = new Vector2D(0, 0);
vector.setX(5);
vector.setY(-3);
expect(vector.getX()).toBe(5);
expect(vector.getY()).toBe(-3);
});
test("set updates both coordinates", () => {
const vector = new Vector2D(0, 0);
vector.set(2, 3);
expect(vector.getX()).toBe(2);
expect(vector.getY()).toBe(3);
});
test("add returns correct vector", () => {
const vector1 = new Vector2D(1, 2);
const vector2 = new Vector2D(3, 4);
const result = vector1.add(vector2);
expect(result.getX()).toBe(4);
expect(result.getY()).toBe(6);
});
test("subtract returns correct vector", () => {
const vector1 = new Vector2D(5, 7);
const vector2 = new Vector2D(2, 3);
const result = vector1.subtract(vector2);
expect(result.getX()).toBe(3);
expect(result.getY()).toBe(4);
});
test("multiply scales vector correctly", () => {
const vector = new Vector2D(2, 3);
const result = vector.multiply(2);
expect(result.getX()).toBe(4);
expect(result.getY()).toBe(6);
});
test("divide scales vector correctly", () => {
const vector = new Vector2D(4, 8);
const result = vector.divide(2);
expect(result.getX()).toBe(2);
expect(result.getY()).toBe(4);
});
test("dot product is correct", () => {
const vector1 = new Vector2D(1, 2);
const vector2 = new Vector2D(3, 4);
expect(vector1.dot(vector2)).toBe(11);
});
test("cross product is correct", () => {
const vector1 = new Vector2D(1, 2);
const vector2 = new Vector2D(3, 4);
expect(vector1.cross(vector2)).toBe(-2);
});
test("magnitude is correct", () => {
const vector = new Vector2D(3, 4);
expect(vector.magnitude()).toBe(5);
});
test("normalize returns unit vector", () => {
const vector = new Vector2D(3, 4);
const result = vector.normalize();
expect(result.magnitude()).toBeCloseTo(1);
expect(result.getX()).toBeCloseTo(0.6);
expect(result.getY()).toBeCloseTo(0.8);
});
test("clone creates a copy of the vector", () => {
const vector = new Vector2D(1, 2);
const clone = vector.clone();
expect(clone.getX()).toBe(1);
expect(clone.getY()).toBe(2);
expect(clone).not.toBe(vector);
});
test("equals returns true for identical vectors", () => {
const vector1 = new Vector2D(1, 2);
const vector2 = new Vector2D(1, 2);
expect(vector1.equals(vector2)).toBe(true);
});
test("equals returns false for different vectors", () => {
const vector1 = new Vector2D(1, 2);
const vector2 = new Vector2D(2, 3);
expect(vector1.equals(vector2)).toBe(false);
});
test("toString returns correct string representation", () => {
const vector = new Vector2D(1, 2);
expect(vector.toString()).toBe("(1, 2)");
});
test("distance calculates correctly", () => {
const vector1 = new Vector2D(1, 2);
const vector2 = new Vector2D(4, 6);
expect(vector1.distance(vector2)).toBe(5);
});
test("angle calculates correctly", () => {
const vector = new Vector2D(1, 1);
expect(vector.angle()).toBeCloseTo(Math.PI / 4);
});
test("rotate rotates vector correctly", () => {
const vector = new Vector2D(1, 0);
const result = vector.rotate(Math.PI / 2);
expect(result.getX()).toBeCloseTo(0);
expect(result.getY()).toBeCloseTo(1);
});
test('lerp interpolates correctly', () => {
const vector1 = new Vector2D(0, 0);
const vector2 = new Vector2D(10, 10);
const result = vector1.lerp(vector2, 0.5);
expect(result.getX()).toBe(5);
expect(result.getY()).toBe(5);
});
});

198
src/vector2d.ts Normal file
View File

@ -0,0 +1,198 @@
export class Vector2D {
private x: number;
private y: number;
/**
* Creates a new vector with coordinates (x, y).
* @param {number} x - The x-coordinate.
* @param {number} y - The y-coordinate.
*/
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
/**
* Gets the x-coordinate.
* @returns {number} The x-coordinate.
*/
getX(): number {
return this.x;
}
/**
* Gets the y-coordinate.
* @returns {number} The y-coordinate.
*/
getY(): number {
return this.y;
}
/**
* Sets the x-coordinate.
* @param {number} x - The new x-coordinate.
*/
setX(x: number): void {
this.x = x;
}
/**
* Sets the y-coordinate.
* @param {number} y - The new y-coordinate.
*/
setY(y: number): void {
this.y = y;
}
/**
* Sets both the x and y coordinates.
* @param {number} x - The new x-coordinate.
* @param {number} y - The new y-coordinate.
*/
set(x: number, y: number): void {
this.x = x;
this.y = y;
}
/**
* Adds another vector to this vector.
* @param {Vector2D} vector - The vector to add.
* @returns {Vector2D} The resulting vector.
*/
add(vector: Vector2D): Vector2D {
return new Vector2D(this.x + vector.getX(), this.y + vector.getY());
}
/**
* Subtracts another vector from this vector.
* @param {Vector2D} vector - The vector to subtract.
* @returns {Vector2D} The resulting vector.
*/
subtract(vector: Vector2D): Vector2D {
return new Vector2D(this.x - vector.getX(), this.y - vector.getY());
}
/**
* Multiplies this vector by a scalar.
* @param {number} scalar - The scalar to multiply by.
* @returns {Vector2D} The resulting vector.
*/
multiply(scalar: number): Vector2D {
return new Vector2D(this.x * scalar, this.y * scalar);
}
/**
* Divides this vector by a scalar.
* @param {number} scalar - The scalar to divide by.
* @returns {Vector2D} The resulting vector.
*/
divide(scalar: number): Vector2D {
return new Vector2D(this.x / scalar, this.y / scalar);
}
/**
* Calculates the dot product of this vector and another vector.
* @param {Vector2D} vector - The other vector.
* @returns {number} The dot product.
*/
dot(vector: Vector2D): number {
return this.x * vector.getX() + this.y * vector.getY();
}
/**
* Calculates the cross product of this vector and another vector.
* @param {Vector2D} vector - The other vector.
* @returns {number} The cross product.
*/
cross(vector: Vector2D): number {
return this.x * vector.getY() - this.y * vector.getX();
}
/**
* Calculates the magnitude (length) of this vector.
* @returns {number} The magnitude of the vector.
*/
magnitude(): number {
return Math.sqrt(this.x * this.x + this.y * this.y);
}
/**
* Normalizes this vector (makes it have a magnitude of 1).
* @returns {Vector2D} The normalized vector.
*/
normalize(): Vector2D {
const mag = this.magnitude();
return new Vector2D(this.x / mag, this.y / mag);
}
/**
* Creates a copy of this vector.
* @returns {Vector2D} The cloned vector.
*/
clone(): Vector2D {
return new Vector2D(this.x, this.y);
}
/**
* Checks if this vector is equal to another vector.
* @param {Vector2D} vector - The other vector.
* @returns {boolean} True if the vectors are equal, false otherwise.
*/
equals(vector: Vector2D): boolean {
return this.x === vector.getX() && this.y === vector.getY();
}
/**
* Returns a string representation of this vector.
* @returns {string} The string representation of the vector.
*/
toString(): string {
return `(${this.x}, ${this.y})`;
}
/**
* Calculates the distance to another vector.
* @param {Vector2D} vector - The other vector.
* @returns {number} The distance to the other vector.
*/
distance(vector: Vector2D): number {
const dx = this.x - vector.getX();
const dy = this.y - vector.getY();
return Math.sqrt(dx * dx + dy * dy);
}
/**
* Calculates the angle of this vector relative to the positive X-axis.
* @returns {number} The angle in radians.
*/
angle(): number {
return Math.atan2(this.y, this.x);
}
/**
* Rotates this vector by a given angle.
* @param {number} angle - The angle to rotate by in radians.
* @returns {Vector2D} The rotated vector.
*/
rotate(angle: number): Vector2D {
const cos = Math.cos(angle);
const sin = Math.sin(angle);
return new Vector2D(
this.x * cos - this.y * sin,
this.x * sin + this.y * cos,
);
}
/**
* Performs linear interpolation between this vector and another vector.
* @param {Vector2D} vector - The other vector.
* @param {number} t - The interpolation factor (between 0 and 1).
* @returns {Vector2D} The interpolated vector.
*/
lerp(vector: Vector2D, t: number): Vector2D {
return new Vector2D(
this.x + t * (vector.getX() - this.x),
this.y + t * (vector.getY() - this.y),
);
}
}

1
src/vite-env.d.ts vendored Normal file
View File

@ -0,0 +1 @@
/// <reference types="vite/client" />

24
tsconfig.json Normal file
View File

@ -0,0 +1,24 @@
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src"]
}

16
vite.config.ts Normal file
View File

@ -0,0 +1,16 @@
import { defineConfig } from "vite";
import path from "path";
import dts from 'vite-plugin-dts';
const libConfig = defineConfig({
build: {
lib: {
entry: path.resolve(__dirname, "src/index.ts"),
fileName: "index",
name: 'vector2d'
},
},
plugins: [dts({exclude: "**/*.test.ts"})],
});
export default libConfig

3454
yarn.lock Normal file

File diff suppressed because it is too large Load Diff