@immugio/three-math-extensions 0.0.5 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,34 +1,39 @@
1
- # Changelog
2
-
3
- All notable changes to this project will be documented in this file.
4
-
5
- The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
6
- and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
-
8
- Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
9
-
10
- ## 0.0.4 - 2022-11-21
11
-
12
- ### Commits
13
-
14
- - Automatic publish with change log [`a70c99d`](https://github.com/Immugio/three-math-extensions/commit/a70c99d0d42e60411ce01bcdb8dd4f3f489bb949)
15
- - Switch to npm [`ed47a17`](https://github.com/Immugio/three-math-extensions/commit/ed47a1787522db3bde5a2112bfd02480fe2edc54)
16
- - Initial commit [`3d1bf9e`](https://github.com/Immugio/three-math-extensions/commit/3d1bf9ef015570830007c9be99140c8c8d760d7f)
17
- - Add Line2D [`9a1dd0f`](https://github.com/Immugio/three-math-extensions/commit/9a1dd0f58352b7b25828693c688aa4770e95c174)
18
- - Readme, npm info [`dda4a28`](https://github.com/Immugio/three-math-extensions/commit/dda4a282a71a00308dcae858ffe53d67d4185be8)
19
- - Run tests in CI on commit [`e3f77ca`](https://github.com/Immugio/three-math-extensions/commit/e3f77ca76e25f4d99eef0130e5779b5e7c5aec6b)
20
- - Remove babel.config.js [`c9a1e16`](https://github.com/Immugio/three-math-extensions/commit/c9a1e1607cffec8a3d74adcca644320a79ca4c43)
21
- - Initial changelog [`6c98aa6`](https://github.com/Immugio/three-math-extensions/commit/6c98aa6ad631cf5e73d32dd76276f99b3ba5089f)
22
- - Release 0.0.4 [`bdac840`](https://github.com/Immugio/three-math-extensions/commit/bdac840f33261a3f39ef33bc05c80772169cfe87)
23
- - Add test badge [`37c62e8`](https://github.com/Immugio/three-math-extensions/commit/37c62e809bdcdfc63f7fe135469fd131f190f950)
24
- - Edit publish script condition [`dc77d89`](https://github.com/Immugio/three-math-extensions/commit/dc77d8978d87daab8732d6429ad1b01ba0ca6f97)
25
- - CI to use node version 16 [`dc42650`](https://github.com/Immugio/three-math-extensions/commit/dc426508939de922cc0316b7652bbd09aeed4610)
26
- - Action rename [`26a1f01`](https://github.com/Immugio/three-math-extensions/commit/26a1f014827faab2c02d30ca8ed18dac8f9ff8af)
27
- - Release 0.0.4 - tag pattern 4 [`ab9ad4e`](https://github.com/Immugio/three-math-extensions/commit/ab9ad4e49477a991482ed6d4d3a3ca4687a70b44)
28
- - Release 0.0.4 - tag pattern 3 [`d7d4c8f`](https://github.com/Immugio/three-math-extensions/commit/d7d4c8f546e6550868ddd06a5213fdec6c68bcd2)
29
- - Release 0.0.4 - tag pattern 2 [`0dcf801`](https://github.com/Immugio/three-math-extensions/commit/0dcf80190bd67a3ca93d45131a403201ab39e00f)
30
- - Release 0.0.4 - tag pattern [`e7f2f76`](https://github.com/Immugio/three-math-extensions/commit/e7f2f76aa247e1c51f0522c300a7aaf07253039c)
31
- - Release 0.0.5 [`c80d6bd`](https://github.com/Immugio/three-math-extensions/commit/c80d6bd12c25ddad0f67610cdf5c804d5759f084)
32
- - Status badge update [`370843e`](https://github.com/Immugio/three-math-extensions/commit/370843ed0a28b024761555572b7d51ccbdb4b77d)
33
- - Run tests in CI on commit [`aee8c55`](https://github.com/Immugio/three-math-extensions/commit/aee8c556ae1cab9025dbe0984dd17278fe6275a1)
34
- - Add Line2D to index [`a5fb6bd`](https://github.com/Immugio/three-math-extensions/commit/a5fb6bdeee5d9f07f325bfffc31ef96f0ce167d1)
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
9
+
10
+ ## 0.0.6
11
+
12
+ ### Commits
13
+
14
+ - Automatic publish with change log [`a70c99d`](https://github.com/Immugio/three-math-extensions/commit/a70c99d0d42e60411ce01bcdb8dd4f3f489bb949)
15
+ - Switch to npm [`ed47a17`](https://github.com/Immugio/three-math-extensions/commit/ed47a1787522db3bde5a2112bfd02480fe2edc54)
16
+ - Initial commit [`3d1bf9e`](https://github.com/Immugio/three-math-extensions/commit/3d1bf9ef015570830007c9be99140c8c8d760d7f)
17
+ - Add Line2D [`9a1dd0f`](https://github.com/Immugio/three-math-extensions/commit/9a1dd0f58352b7b25828693c688aa4770e95c174)
18
+ - Improve API, minor bug fix, improve test coverage [`881a5f0`](https://github.com/Immugio/three-math-extensions/commit/881a5f096823f0d5fd90faa76cd602f076291bc5)
19
+ - Readme, npm info [`dda4a28`](https://github.com/Immugio/three-math-extensions/commit/dda4a282a71a00308dcae858ffe53d67d4185be8)
20
+ - Add .npmignore [`f58329a`](https://github.com/Immugio/three-math-extensions/commit/f58329a86b96589bb574d6ebed37d4cc4474663a)
21
+ - Run tests in CI on commit [`e3f77ca`](https://github.com/Immugio/three-math-extensions/commit/e3f77ca76e25f4d99eef0130e5779b5e7c5aec6b)
22
+ - Remove babel.config.js [`c9a1e16`](https://github.com/Immugio/three-math-extensions/commit/c9a1e1607cffec8a3d74adcca644320a79ca4c43)
23
+ - Initial changelog [`6c98aa6`](https://github.com/Immugio/three-math-extensions/commit/6c98aa6ad631cf5e73d32dd76276f99b3ba5089f)
24
+ - Release 0.0.4 [`bdac840`](https://github.com/Immugio/three-math-extensions/commit/bdac840f33261a3f39ef33bc05c80772169cfe87)
25
+ - Add test badge [`37c62e8`](https://github.com/Immugio/three-math-extensions/commit/37c62e809bdcdfc63f7fe135469fd131f190f950)
26
+ - Edit publish script condition [`dc77d89`](https://github.com/Immugio/three-math-extensions/commit/dc77d8978d87daab8732d6429ad1b01ba0ca6f97)
27
+ - CI to use node version 16 [`dc42650`](https://github.com/Immugio/three-math-extensions/commit/dc426508939de922cc0316b7652bbd09aeed4610)
28
+ - Action rename [`26a1f01`](https://github.com/Immugio/three-math-extensions/commit/26a1f014827faab2c02d30ca8ed18dac8f9ff8af)
29
+ - Correct change log version [`c6244bf`](https://github.com/Immugio/three-math-extensions/commit/c6244bf1488ad21bcc5589d1dff62c41d8182d48)
30
+ - Release 0.0.4 - tag pattern 6 [`c1c5454`](https://github.com/Immugio/three-math-extensions/commit/c1c54541ed400e1ad49bf42fe8926cd5293efefd)
31
+ - Release 0.0.4 - tag pattern 5 [`5245eed`](https://github.com/Immugio/three-math-extensions/commit/5245eed60195103e989c0fadf9bd642f39ef4589)
32
+ - Release 0.0.4 - tag pattern 4 [`ab9ad4e`](https://github.com/Immugio/three-math-extensions/commit/ab9ad4e49477a991482ed6d4d3a3ca4687a70b44)
33
+ - Release 0.0.4 - tag pattern 3 [`d7d4c8f`](https://github.com/Immugio/three-math-extensions/commit/d7d4c8f546e6550868ddd06a5213fdec6c68bcd2)
34
+ - Release 0.0.4 - tag pattern 2 [`0dcf801`](https://github.com/Immugio/three-math-extensions/commit/0dcf80190bd67a3ca93d45131a403201ab39e00f)
35
+ - Release 0.0.4 - tag pattern [`e7f2f76`](https://github.com/Immugio/three-math-extensions/commit/e7f2f76aa247e1c51f0522c300a7aaf07253039c)
36
+ - Release 0.0.5 [`c80d6bd`](https://github.com/Immugio/three-math-extensions/commit/c80d6bd12c25ddad0f67610cdf5c804d5759f084)
37
+ - Status badge update [`370843e`](https://github.com/Immugio/three-math-extensions/commit/370843ed0a28b024761555572b7d51ccbdb4b77d)
38
+ - Run tests in CI on commit [`aee8c55`](https://github.com/Immugio/three-math-extensions/commit/aee8c556ae1cab9025dbe0984dd17278fe6275a1)
39
+ - Add Line2D to index [`a5fb6bd`](https://github.com/Immugio/three-math-extensions/commit/a5fb6bdeee5d9f07f325bfffc31ef96f0ce167d1)
package/cjs/Line2D.js CHANGED
@@ -492,6 +492,28 @@ class Line2D {
492
492
  lineToExtend.end.copy(this.end);
493
493
  }
494
494
  }
495
+ /**
496
+ * If there is an intersection between this and other, this line is extended to the intersection point. Lines are assumed to be infinite.
497
+ * Modifies this line.
498
+ * @param other
499
+ * @param maxDistanceToIntersection
500
+ */
501
+ extendToOrTrimAtIntersection(other, maxDistanceToIntersection = Number.MAX_VALUE) {
502
+ const intersection = this.intersect(other);
503
+ if (intersection) {
504
+ const distanceToStart = this.start.distanceTo(intersection);
505
+ const distanceToEnd = this.end.distanceTo(intersection);
506
+ if (distanceToStart <= maxDistanceToIntersection || distanceToEnd <= maxDistanceToIntersection) {
507
+ if (distanceToStart < distanceToEnd) {
508
+ this.start.copy(intersection);
509
+ }
510
+ else {
511
+ this.end.copy(intersection);
512
+ }
513
+ }
514
+ }
515
+ return this;
516
+ }
495
517
  /**
496
518
  * Returns the intersection point of two lines. The lines are assumed to be infinite.
497
519
  */
package/cjs/Vec2.js CHANGED
@@ -19,5 +19,11 @@ class Vec2 extends three_1.Vector2 {
19
19
  in3DSpace(z = 0) {
20
20
  return new Vec3_1.Vec3(this.x, z, this.y);
21
21
  }
22
+ isNear(v, maxDistance = undefined) {
23
+ if (!maxDistance) {
24
+ return this.equals(v);
25
+ }
26
+ return this.distanceTo(v) <= maxDistance;
27
+ }
22
28
  }
23
29
  exports.Vec2 = Vec2;
package/cjs/Vec3.js CHANGED
@@ -50,6 +50,12 @@ class Vec3 extends three_1.Vector3 {
50
50
  horizontalDistanceTo(point) {
51
51
  return new three_1.Vector3(this.x, 0, this.z).distanceTo(new three_1.Vector3(point.x, 0, point.z));
52
52
  }
53
+ isNear(v, maxDistance = undefined) {
54
+ if (maxDistance === undefined) {
55
+ return this.equals(v);
56
+ }
57
+ return this.distanceTo(v) <= maxDistance;
58
+ }
53
59
  clone() {
54
60
  return super.clone();
55
61
  }
package/esm/Line2D.js CHANGED
@@ -489,6 +489,28 @@ export class Line2D {
489
489
  lineToExtend.end.copy(this.end);
490
490
  }
491
491
  }
492
+ /**
493
+ * If there is an intersection between this and other, this line is extended to the intersection point. Lines are assumed to be infinite.
494
+ * Modifies this line.
495
+ * @param other
496
+ * @param maxDistanceToIntersection
497
+ */
498
+ extendToOrTrimAtIntersection(other, maxDistanceToIntersection = Number.MAX_VALUE) {
499
+ const intersection = this.intersect(other);
500
+ if (intersection) {
501
+ const distanceToStart = this.start.distanceTo(intersection);
502
+ const distanceToEnd = this.end.distanceTo(intersection);
503
+ if (distanceToStart <= maxDistanceToIntersection || distanceToEnd <= maxDistanceToIntersection) {
504
+ if (distanceToStart < distanceToEnd) {
505
+ this.start.copy(intersection);
506
+ }
507
+ else {
508
+ this.end.copy(intersection);
509
+ }
510
+ }
511
+ }
512
+ return this;
513
+ }
492
514
  /**
493
515
  * Returns the intersection point of two lines. The lines are assumed to be infinite.
494
516
  */
package/esm/Vec2.js CHANGED
@@ -16,4 +16,10 @@ export class Vec2 extends Vector2 {
16
16
  in3DSpace(z = 0) {
17
17
  return new Vec3(this.x, z, this.y);
18
18
  }
19
+ isNear(v, maxDistance = undefined) {
20
+ if (!maxDistance) {
21
+ return this.equals(v);
22
+ }
23
+ return this.distanceTo(v) <= maxDistance;
24
+ }
19
25
  }
package/esm/Vec3.js CHANGED
@@ -47,6 +47,12 @@ export class Vec3 extends Vector3 {
47
47
  horizontalDistanceTo(point) {
48
48
  return new Vector3(this.x, 0, this.z).distanceTo(new Vector3(point.x, 0, point.z));
49
49
  }
50
+ isNear(v, maxDistance = undefined) {
51
+ if (maxDistance === undefined) {
52
+ return this.equals(v);
53
+ }
54
+ return this.distanceTo(v) <= maxDistance;
55
+ }
50
56
  clone() {
51
57
  return super.clone();
52
58
  }
package/package.json CHANGED
@@ -1,52 +1,52 @@
1
- {
2
- "name": "@immugio/three-math-extensions",
3
- "version": "0.0.5",
4
- "description": "Set of utilities for 2d and 3d line math built on top of three.js",
5
- "author": "Jan Mikeska <janmikeska@gmail.com>",
6
- "license": "ISC",
7
- "keywords": [
8
- "threejs",
9
- "three",
10
- "math"
11
- ],
12
- "bugs": {
13
- "url": "https://github.com/Immugio/three-math-extensions/issues"
14
- },
15
- "homepage": "https://github.com/Immugio/three-math-extensions#readme",
16
- "sideEffects": false,
17
- "source": "src/index.ts",
18
- "main": "cjs/index.js",
19
- "module": "esm/index.js",
20
- "types": "types/index.d.ts",
21
- "auto-changelog": {
22
- "commitLimit": false,
23
- "template": "keepachangelog"
24
- },
25
- "scripts": {
26
- "test": "npx jest",
27
- "build:esm": "tsc",
28
- "build:cjs": "tsc -p tsconfig-cjs.json",
29
- "clean": "rimraf types cjs esm",
30
- "build": "npm run clean && npm run build:esm && npm run build:cjs",
31
- "preversion": "npm run clean && npm run build && npm run test",
32
- "version": "auto-changelog -p && git add CHANGELOG.md",
33
- "postversion": "git push && git push --tags"
34
- },
35
- "devDependencies": {
36
- "@types/jest": "^29.2.1",
37
- "@types/offscreencanvas": "2019.7.0",
38
- "@types/three": "0.130.1",
39
- "auto-changelog": "^2.4.0",
40
- "jest": "^29.2.2",
41
- "rimraf": "^3.0.2",
42
- "ts-jest": "^29.0.0",
43
- "typescript": "4.7.4"
44
- },
45
- "peerDependencies": {
46
- "three": "^0.130.1"
47
- },
48
- "repository": {
49
- "type": "git",
50
- "url": "git+https://github.com/Immugio/three-math-extensions.git"
51
- }
52
- }
1
+ {
2
+ "name": "@immugio/three-math-extensions",
3
+ "version": "0.0.7",
4
+ "description": "Set of utilities for 2d and 3d line math built on top of three.js",
5
+ "author": "Jan Mikeska <janmikeska@gmail.com>",
6
+ "license": "ISC",
7
+ "keywords": [
8
+ "threejs",
9
+ "three",
10
+ "math"
11
+ ],
12
+ "bugs": {
13
+ "url": "https://github.com/Immugio/three-math-extensions/issues"
14
+ },
15
+ "homepage": "https://github.com/Immugio/three-math-extensions#readme",
16
+ "sideEffects": false,
17
+ "source": "src/index.ts",
18
+ "main": "cjs/index.js",
19
+ "module": "esm/index.js",
20
+ "types": "types/index.d.ts",
21
+ "auto-changelog": {
22
+ "commitLimit": false,
23
+ "template": "keepachangelog"
24
+ },
25
+ "scripts": {
26
+ "test": "npx jest",
27
+ "build:esm": "tsc",
28
+ "build:cjs": "tsc -p tsconfig-cjs.json",
29
+ "clean": "rimraf types cjs esm",
30
+ "build": "npm run clean && npm run build:esm && npm run build:cjs",
31
+ "preversion": "npm run clean && npm run build && npm run test",
32
+ "version": "auto-changelog -p && git add CHANGELOG.md",
33
+ "postversion": "git push && git push --tags"
34
+ },
35
+ "devDependencies": {
36
+ "@types/jest": "^29.2.1",
37
+ "@types/offscreencanvas": "2019.7.0",
38
+ "@types/three": "0.130.1",
39
+ "auto-changelog": "^2.4.0",
40
+ "jest": "^29.2.2",
41
+ "rimraf": "^3.0.2",
42
+ "ts-jest": "^29.0.0",
43
+ "typescript": "4.7.4"
44
+ },
45
+ "peerDependencies": {
46
+ "three": "^0.130.1"
47
+ },
48
+ "repository": {
49
+ "type": "git",
50
+ "url": "git+https://github.com/Immugio/three-math-extensions.git"
51
+ }
52
+ }
package/src/Line2D.ts CHANGED
@@ -572,6 +572,32 @@ export class Line2D {
572
572
  }
573
573
  }
574
574
 
575
+ /**
576
+ * If there is an intersection between this and other, this line is extended to the intersection point. Lines are assumed to be infinite.
577
+ * Modifies this line.
578
+ * @param other
579
+ * @param maxDistanceToIntersection
580
+ */
581
+ public extendToOrTrimAtIntersection(other: Line2D, maxDistanceToIntersection: number = Number.MAX_VALUE): Line2D {
582
+ const intersection = this.intersect(other);
583
+
584
+ if (intersection) {
585
+ const distanceToStart = this.start.distanceTo(intersection);
586
+ const distanceToEnd = this.end.distanceTo(intersection);
587
+
588
+ if (distanceToStart <= maxDistanceToIntersection || distanceToEnd <= maxDistanceToIntersection) {
589
+ if (distanceToStart < distanceToEnd) {
590
+ this.start.copy(intersection);
591
+
592
+ } else {
593
+ this.end.copy(intersection);
594
+ }
595
+ }
596
+ }
597
+
598
+ return this;
599
+ }
600
+
575
601
  /**
576
602
  * Returns the intersection point of two lines. The lines are assumed to be infinite.
577
603
  */
package/src/Vec2.ts CHANGED
@@ -21,4 +21,12 @@ export class Vec2 extends Vector2 {
21
21
  public in3DSpace(z: number = 0): Vec3 {
22
22
  return new Vec3(this.x, z, this.y);
23
23
  }
24
+
25
+ public isNear(v: Vector2, maxDistance: number = undefined): boolean {
26
+ if (!maxDistance) {
27
+ return this.equals(v);
28
+ }
29
+
30
+ return this.distanceTo(v) <= maxDistance;
31
+ }
24
32
  }
package/src/Vec3.ts CHANGED
@@ -64,6 +64,14 @@ export class Vec3 extends Vector3 {
64
64
  return new Vector3(this.x, 0, this.z).distanceTo(new Vector3(point.x, 0, point.z));
65
65
  }
66
66
 
67
+ public isNear(v: Vector3, maxDistance: number = undefined): boolean {
68
+ if (maxDistance === undefined) {
69
+ return this.equals(v);
70
+ }
71
+
72
+ return this.distanceTo(v) <= maxDistance;
73
+ }
74
+
67
75
  public clone(): this {
68
76
  return super.clone();
69
77
  }
package/types/Line2D.d.ts CHANGED
@@ -196,6 +196,13 @@ export declare class Line2D {
196
196
  * @param tolerance
197
197
  */
198
198
  extendToEnds(lineToExtend: Line2D, tolerance: number): void;
199
+ /**
200
+ * If there is an intersection between this and other, this line is extended to the intersection point. Lines are assumed to be infinite.
201
+ * Modifies this line.
202
+ * @param other
203
+ * @param maxDistanceToIntersection
204
+ */
205
+ extendToOrTrimAtIntersection(other: Line2D, maxDistanceToIntersection?: number): Line2D;
199
206
  /**
200
207
  * Returns the intersection point of two lines. The lines are assumed to be infinite.
201
208
  */
package/types/Vec2.d.ts CHANGED
@@ -5,4 +5,5 @@ export declare class Vec2 extends Vector2 {
5
5
  static fromPoint(point: Point2): Vec2;
6
6
  roundIfCloseToInteger(max?: number): this;
7
7
  in3DSpace(z?: number): Vec3;
8
+ isNear(v: Vector2, maxDistance?: number): boolean;
8
9
  }
package/types/Vec3.d.ts CHANGED
@@ -13,5 +13,6 @@ export declare class Vec3 extends Vector3 {
13
13
  toPointWithFlippedYZ(): Vec3;
14
14
  onPlan(): Vec2;
15
15
  horizontalDistanceTo(point: Vector3): number;
16
+ isNear(v: Vector3, maxDistance?: number): boolean;
16
17
  clone(): this;
17
18
  }
package/.eslintrc.json DELETED
@@ -1,32 +0,0 @@
1
- {
2
- "env": {
3
- "browser": true,
4
- "es2020": true
5
- },
6
- "extends": [
7
- "eslint:recommended",
8
- "plugin:@typescript-eslint/recommended"
9
- ],
10
- "parser": "@typescript-eslint/parser",
11
- "parserOptions": {
12
- "ecmaVersion": 11,
13
- "sourceType": "module"
14
- },
15
- "plugins": [
16
- "@typescript-eslint"
17
- ],
18
- "rules": {
19
- "linebreak-style": [
20
- "error",
21
- "windows"
22
- ],
23
- "quotes": [
24
- "error",
25
- "double"
26
- ],
27
- "semi": [
28
- "error",
29
- "always"
30
- ]
31
- }
32
- }
package/jest.config.js DELETED
@@ -1,6 +0,0 @@
1
- /** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
2
- // eslint-disable-next-line no-undef
3
- module.exports = {
4
- preset: "ts-jest",
5
- testEnvironment: "node",
6
- };
@@ -1,358 +0,0 @@
1
- import { Line2D } from "../Line2D";
2
- import { Vector2 } from "three";
3
- import { Vec2 } from "../Vec2";
4
- import { Point2 } from "../Point2";
5
-
6
- describe("Line2D", () => {
7
- it("should be created", () => {
8
- const start = new Vec2(1, 2);
9
- const end = new Vec2(3, 4);
10
- const line = new Line2D(start, end, 20);
11
- expect(line).toEqual(new Line2D(start, end, 20));
12
- expect(line.start).toBe(start);
13
- expect(line.end).toBe(end);
14
- });
15
-
16
- it("should be created fromCoordinates", () => {
17
- const line = Line2D.fromCoordinates(1, 2, 3, 4, 10);
18
- expect(line.start.x).toEqual(1);
19
- expect(line.start.y).toEqual(2);
20
- expect(line.end.x).toEqual(3);
21
- expect(line.end.y).toEqual(4);
22
- expect(line.index).toEqual(10);
23
- });
24
-
25
- it("should be created fromPoints", () => {
26
- const line = Line2D.fromPoints({ x: 1, y: 2 }, { x: 3, y: 4 }, 10);
27
- expect(line).toEqual(new Line2D(new Vec2(1, 2), new Vec2(3, 4), 10));
28
- });
29
-
30
- it("should create a single line polygon from a 2 points polygon", () => {
31
- const start = new Vec2(1, 2);
32
- const end = new Vec2(3, 4);
33
- const lines = Line2D.fromPolygon([start, end]);
34
- expect(lines.length).toEqual(1);
35
- expect(lines[0]).toEqual(new Line2D(start, end));
36
- });
37
-
38
- it("should create a 2 lines polygon from a 3 points polygon", () => {
39
- const p1 = new Vec2(1, 2);
40
- const p2 = new Vec2(3, 4);
41
- const p3 = new Vec2(5, 2);
42
- const lines = Line2D.fromPolygon([p1, p2, p3]);
43
- expect(lines.length).toEqual(2);
44
- expect(lines[0]).toEqual(new Line2D(p1, p2, 0));
45
- expect(lines[1]).toEqual(new Line2D(p2, p3, 1));
46
- });
47
-
48
- it("should create a closed 3 lines polygon from a 3 points polygon", () => {
49
- const p1 = new Vec2(1, 2);
50
- const p2 = new Vec2(3, 4);
51
- const p3 = new Vec2(5, 2);
52
- const lines = Line2D.fromPolygon([p1, p2, p3], true);
53
- expect(lines.length).toEqual(3);
54
- expect(lines[0]).toEqual(new Line2D(p1, p2, 0));
55
- expect(lines[1]).toEqual(new Line2D(p2, p3, 1));
56
- expect(lines[2]).toEqual(new Line2D(p3, p1, 2));
57
- });
58
-
59
- test("center should return the center of the line", () => {
60
- const line = Line2D.fromCoordinates(-2, -2, 2, 2);
61
- expect(line.center.x).toEqual(0);
62
- expect(line.center.y).toEqual(0);
63
- });
64
-
65
- test("resize should resize the line by the given length", () => {
66
- const line = Line2D.fromCoordinates(-2, 1, 2, 1);
67
- const originalCenter = line.center;
68
- expect(line.length).toEqual(4);
69
-
70
- const resizeDistance = 2;
71
- line.resize(resizeDistance);
72
-
73
- expect(line.length).toEqual(6);
74
- expect(line.center).toEqual(originalCenter);
75
- expect(line.start.x).toEqual(-3);
76
- expect(line.end.x).toEqual(3);
77
- });
78
-
79
- test("moveStartPoint should move p1 on the line by the given amount", () => {
80
- const line = Line2D.fromCoordinates(-2, 1, 2, 1);
81
- expect(line.length).toEqual(4);
82
-
83
- line.moveStartPoint(2);
84
- expect(line.length).toEqual(6);
85
- expect(line.start.x).toEqual(-4);
86
- });
87
-
88
- test("moveEndPoint should move p1 on the line by the given amount", () => {
89
- const line = Line2D.fromCoordinates(-2, 1, 2, 1);
90
- expect(line.length).toEqual(4);
91
-
92
- line.moveEndPoint(2);
93
- expect(line.length).toEqual(6);
94
- expect(line.end.x).toEqual(4);
95
- });
96
-
97
- test("flip should swap the end points", () => {
98
- const line = Line2D.fromCoordinates(-2, 1, 2, 1);
99
- const original = line.clone();
100
- line.flip();
101
- expect(line.start.equals(original.end)).toBe(true);
102
- expect(line.end.equals(original.start)).toBe(true);
103
- });
104
-
105
- test("rotate should rotate the endpoints around the line center", () => {
106
- const line = Line2D.fromCoordinates(10, 0, 20, 0);
107
- line.rotate(Math.PI / 2); // 90 degrees counterclockwise
108
- expect(line.start.x).toEqual(15);
109
- expect(line.start.y).toEqual(-5);
110
- expect(line.end.x).toEqual(15);
111
- expect(line.end.y).toEqual(5);
112
- });
113
-
114
- test("translate should rotate the endpoints around the line center", () => {
115
- const line = Line2D.fromCoordinates(10, 0, 20, 0);
116
- line.translate({ x: 10, y: 100 });
117
- expect(line.start.x).toEqual(20);
118
- expect(line.start.y).toEqual(100);
119
- expect(line.end.x).toEqual(30);
120
- expect(line.end.y).toEqual(100);
121
- });
122
-
123
- test.each([
124
- [Line2D.fromCoordinates(5, 5, 15, 15), 5, 5, true],
125
- [Line2D.fromCoordinates(5, 5, 15, 15), 10, 10, true],
126
- [Line2D.fromCoordinates(5, 5, 15, 15), 15, 15, true],
127
- [Line2D.fromCoordinates(5, 5, 15, 15), 16, 16, false],
128
- [Line2D.fromCoordinates(5, 5, 15, 15), 10, 16, false],
129
- [Line2D.fromCoordinates(5, 5, 15, 15), 10, 4, false],
130
- [Line2D.fromCoordinates(5, 5, 15, 15), 4, 4, false],
131
- [Line2D.fromCoordinates(5, 5, 15, 15), 15, 16, false],
132
- ])("Line.isPointOnLineSection should return true if the point is on the line section", (line: Line2D, x, y, expected: boolean) => {
133
- expect(line.isPointOnLineSection({x, y})).toBe(expected);
134
- });
135
-
136
- test.each([
137
- [Line2D.fromCoordinates(5, 5, 15, 5), 10, 6, .9, false],
138
- [Line2D.fromCoordinates(5, 5, 15, 5), 10, 6, 1, true],
139
- ])("Line.isPointCloseToAndBesideLineSection should return true if the point is within expected distance of the line section", (line: Line2D, x, y, tolerance, expected: boolean) => {
140
- expect(line.isPointCloseToAndBesideLineSection({x, y}, tolerance)).toBe(expected);
141
- });
142
-
143
- test.each([
144
- [Line2D.fromCoordinates(5, 5, 15, 15), 5, 5, true],
145
- [Line2D.fromCoordinates(5, 5, 15, 15), 10, 10, true],
146
- [Line2D.fromCoordinates(5, 5, 15, 15), 15, 15, true],
147
- [Line2D.fromCoordinates(5, 5, 15, 15), 16, 16, false],
148
- [Line2D.fromCoordinates(5, 5, 15, 15), 10, 16, true],
149
- [Line2D.fromCoordinates(5, 5, 15, 15), 10, 4, true],
150
- [Line2D.fromCoordinates(5, 5, 15, 15), 4, 4, false],
151
- [Line2D.fromCoordinates(5, 5, 15, 15), 15, 16, false],
152
- ])("Line.isPointBesideLineSection should return true if the point is beside the line section", (line: Line2D, x, y, expected: boolean) => {
153
- expect(line.isPointBesideLineSection({x, y})).toBe(expected);
154
- });
155
-
156
- test.each([
157
- [Line2D.fromCoordinates(5, 5, 15, 15), 5, 5, 0],
158
- [Line2D.fromCoordinates(5, 5, 15, 15), 10, 10, 0],
159
- [Line2D.fromCoordinates(5, 5, 15, 15), 15, 15, 0],
160
- [Line2D.fromCoordinates(5, 5, 15, 15), 16, 16, 0],
161
- [Line2D.fromCoordinates(5, 5, 15, 15), 10, 16, 4.242640687119285],
162
- [Line2D.fromCoordinates(5, 5, 15, 15), 10, 4, 4.242640687119285],
163
- [Line2D.fromCoordinates(5, 5, 15, 15), 4, 4, 0],
164
- [Line2D.fromCoordinates(5, 5, 15, 15), 10, 11, 0.7071067811865476],
165
- ])("Line.distanceToPointOnInfiniteLine should return true if the point is beside the line section. Line: (%s, x: %s, y: %s) expected: %s", (line: Line2D, x, y, expected: number) => {
166
- expect(line.distanceToPointOnInfiniteLine({x, y})).toBe(expected);
167
- });
168
-
169
- test.each([
170
- [Line2D.fromCoordinates(5, 5, 15, 15), 5, 5, true],
171
- [Line2D.fromCoordinates(5, 5, 15, 15), 10, 10, true],
172
- [Line2D.fromCoordinates(5, 5, 15, 15), 15, 15, true],
173
- [Line2D.fromCoordinates(5, 5, 15, 15), 16, 16, true],
174
- [Line2D.fromCoordinates(5, 5, 15, 15), 4, 4, true],
175
- [Line2D.fromCoordinates(5, 5, 15, 15), 15, 16, false],
176
- ])("Line.isPointOnInfiniteLine should return true if the point is on the infinite line", (line: Line2D, x, y, expected: boolean) => {
177
- expect(line.isPointOnInfiniteLine({x, y})).toBe(expected);
178
- });
179
-
180
- test.each([
181
- [Line2D.fromCoordinates(10, 5, 15, 5), Line2D.fromCoordinates(15, 5, 20, 5), true], // Other on the right, touching
182
- [Line2D.fromCoordinates(5, 5, 15, 15), Line2D.fromCoordinates(15, 15, 16, 16), true], // Other on the right, touching, angle
183
- [Line2D.fromCoordinates(10, 5, 15, 5), Line2D.fromCoordinates(15, 5, 20, 6), false], // Other on the right, touching but lines are not collinear
184
- [Line2D.fromCoordinates(10, 5, 15, 5), Line2D.fromCoordinates(14, 5, 20, 5), true], // Other on the right, overlapping
185
- [Line2D.fromCoordinates(10, 5, 15, 5), Line2D.fromCoordinates(9, 5, 20, 5), true], // Other completely covers Line
186
- [Line2D.fromCoordinates(10, 5, 15, 5), Line2D.fromCoordinates(16, 5, 20, 5), false], // Other on the left, with gap
187
- ])("Line.canJoinLine should return true if the point is on the line %s, other: %s, expected: %s" , (line: Line2D, other: Line2D, expected: boolean) => {
188
- expect(line.isCollinearWithTouchOrOverlap(other)).toBe(expected);
189
- });
190
-
191
- test.each([
192
- [Line2D.fromCoordinates(10, 5, 15, 5), Line2D.fromCoordinates(15, 5, 20, 5), Line2D.fromCoordinates(10, 5, 20, 5)], // Other on the right, touching
193
- [Line2D.fromCoordinates(5, 5, 15, 15), Line2D.fromCoordinates(15, 15, 16, 16), Line2D.fromCoordinates(5, 5, 16, 16)], // Other on the right, touching, angle
194
- [Line2D.fromCoordinates(10, 5, 15, 5), Line2D.fromCoordinates(15, 5, 20, 6), null], // Other on the right, touching but lines are not collinear
195
- [Line2D.fromCoordinates(10, 5, 15, 5), Line2D.fromCoordinates(14, 5, 20, 5), Line2D.fromCoordinates(10, 5, 20, 5)], // Other on the right, overlapping
196
- [Line2D.fromCoordinates(10, 5, 15, 5), Line2D.fromCoordinates(9, 5, 20, 5), Line2D.fromCoordinates(9, 5, 20, 5)], // Other completely covers Line
197
- [Line2D.fromCoordinates(10, 5, 15, 5), Line2D.fromCoordinates(16, 5, 20, 5), null], // Other on the left, with gap
198
- ])("Line.joinLine returns correctly joined lines", (line: Line2D, other: Line2D, expected: Line2D) => {
199
- const result = Line2D.joinLine(line, other);
200
- if (result === null) {
201
- expect(result).toBe(null);
202
- } else {
203
- expect(result.start.x).toEqual(expected.start.x);
204
- expect(result.start.y).toEqual(expected.start.y);
205
- expect(result.end.x).toEqual(expected.end.x);
206
- expect(result.end.y).toEqual(expected.end.y);
207
- }
208
- });
209
-
210
- test("joinLines returns correctly joined lines", () => {
211
- const gr1_Line1 = Line2D.fromCoordinates(15, 0, 20, 0);
212
- const gr1_Line2 = Line2D.fromCoordinates(20, 0, 55, 0);
213
-
214
- const gr2_Line1 = Line2D.fromCoordinates(915, 0, 920, 0);
215
- const gr2_Line2 = Line2D.fromCoordinates(920, 0, 955, 0);
216
-
217
- const result = Line2D.joinLines([gr1_Line1, gr1_Line2, gr2_Line1, gr2_Line2]);
218
- expect(result.length).toEqual(2);
219
-
220
- const gr1 = result.filter(l => l.start.equals(gr1_Line1.start) && l.end.equals(gr1_Line2.end));
221
- expect(gr1.length).toEqual(1);
222
-
223
- const gr2 = result.filter(l => l.start.equals(gr2_Line1.start) && l.end.equals(gr2_Line2.end));
224
- expect(gr2.length).toEqual(1);
225
- });
226
-
227
- test("closestPointOnInfiniteLine returns the closes point to the infinite line", () => {
228
- const line = Line2D.fromCoordinates(0, 0, 10, 0);
229
- const point = new Vector2(11, 1);
230
- const closest = line.closestPointOnInfiniteLine(point);
231
- expect(closest.x).toEqual(11);
232
- expect(closest.y).toEqual(0);
233
- });
234
-
235
- test("clipOverflow clip the overlapping sections from the other line", () => {
236
- const line = Line2D.fromCoordinates(0, 0, 10, 0);
237
- const other = Line2D.fromCoordinates(-5, 0, 15, 0);
238
- line.trimExcess(other);
239
- expect(other.start).toEqual(line.start);
240
- expect(other.end).toEqual(line.end);
241
- });
242
-
243
- test("clipOverflow clip the overlapping sections from the other line", () => {
244
- const line = Line2D.fromCoordinates(0, 0, 15, 0);
245
- const other = Line2D.fromCoordinates(1, 0, 10, 0);
246
- line.extendToEnds(other, 1);
247
- expect(other.start).toEqual(line.start); // Only the first point is extended because it's within tolerance
248
- expect(other.end.x).toEqual(10); // The second point is not extended because it's outside tolerance
249
- });
250
-
251
- test.each([
252
- [new Vector2(15, 0), new Vector2(7.5, 7.5)],
253
- [new Vector2(2, 2), new Vector2(2, 2)],
254
- [new Vector2(-1, -5), new Vector2(0, 0)],
255
- [new Vector2(20, 30), new Vector2(15, 15)],
256
- ])("Line.closestPointOnLine should return a point laying directly on the line", (source: Vector2, expected: Vector2) => {
257
- const line = Line2D.fromCoordinates(0, 0, 15, 15);
258
- const closest = line.closestPointOnLine(source);
259
- expect(closest).toEqual(expected);
260
- });
261
-
262
- test.each([
263
- [Line2D.fromCoordinates(10, 0, 20, 0), Line2D.fromCoordinates(0, 0, 10, 0), "Touch from the left but not overlapping", false],
264
- [Line2D.fromCoordinates(10, 0, 20, 0), Line2D.fromCoordinates(20, 0, 30, 0), "Touch from the right but not overlapping", false],
265
- [Line2D.fromCoordinates(10, 0, 20, 0), Line2D.fromCoordinates(22, 0, 30, 0), "Not touch, no overlap", false],
266
- [Line2D.fromCoordinates(10, 0, 20, 0), Line2D.fromCoordinates(0, 1, 11, 0), "Not a real overlap, lines are not collinear", false],
267
- [Line2D.fromCoordinates(10, 0, 20, 0), Line2D.fromCoordinates(0, 0, 11, 0), "Overlap from the left", true],
268
- [Line2D.fromCoordinates(10, 0, 20, 0), Line2D.fromCoordinates(19, 0, 30, 0), "Overlap from the right", true],
269
- [Line2D.fromCoordinates(10, 0, 20, 0), Line2D.fromCoordinates(11, 0, 19, 0), "Line completely covers Other", true],
270
- [Line2D.fromCoordinates(10, 0, 20, 0), Line2D.fromCoordinates(0, 0, 30, 0), "Line is completely covered by Other", true],
271
- ])("Line.overlaps should return true if the lines overlap. Line: %s, other: %s, description: %s expected: %s", (line: Line2D, other: Line2D, description: string, expected: boolean) => {
272
- expect(line.overlaps(other)).toBe(expected);
273
- });
274
-
275
- test.each([
276
- [Line2D.fromCoordinates(10, 0, 20, 0), Line2D.fromCoordinates(0, 0, 10, 0), "Touch from the left but not overlapping", null],
277
- [Line2D.fromCoordinates(10, 0, 20, 0), Line2D.fromCoordinates(20, 0, 30, 0), "Touch from the right but not overlapping", null],
278
- [Line2D.fromCoordinates(10, 0, 20, 0), Line2D.fromCoordinates(22, 0, 30, 0), "Not touch, no overlap", null],
279
- [Line2D.fromCoordinates(10, 0, 20, 0), Line2D.fromCoordinates(0, 1, 11, 0), "Not a real overlap, lines are not collinear", null],
280
- [Line2D.fromCoordinates(10, 0, 20, 0), Line2D.fromCoordinates(0, 0, 11, 0), "Overlap from the left", Line2D.fromCoordinates(10, 0, 11, 0)],
281
- [Line2D.fromCoordinates(10, 0, 20, 0), Line2D.fromCoordinates(19, 0, 30, 0), "Overlap from the right", Line2D.fromCoordinates(19, 0, 20, 0)],
282
- [Line2D.fromCoordinates(10, 0, 20, 0), Line2D.fromCoordinates(11, 0, 19, 0), "Line completely covers Other", Line2D.fromCoordinates(11, 0, 19, 0)],
283
- [Line2D.fromCoordinates(10, 0, 20, 0), Line2D.fromCoordinates(0, 0, 30, 0), "Line is completely covered by Other", Line2D.fromCoordinates(10, 0, 20, 0)],
284
- [Line2D.fromCoordinates(3600, 1350, 3600, 2050), Line2D.fromCoordinates(3600, 1950, 3600, 2650), "Vertical Line is covered by Other on bottom", Line2D.fromCoordinates(3600, 1950, 3600, 2050)],
285
- ])("Line.getOverlap should return overlap. Line: %s, other: %s, description: %s expected: %s", (line: Line2D, other: Line2D, description: string, expected: Line2D) => {
286
- const result = line.getOverlap(other);
287
- if (expected) {
288
- expect(result.start.equals(expected.start)).toBe(true);
289
- expect(result.end.equals(expected.end)).toBe(true);
290
- } else {
291
- expect(result).toBeNull();
292
- }
293
- });
294
-
295
- test.each([
296
- [
297
- Line2D.fromCoordinates(3550, 2400, 150, 2400),
298
- [Line2D.fromCoordinates(650, 2400, 150, 2400), Line2D.fromCoordinates(3550, 2400, 3050, 2400), Line2D.fromCoordinates(2404, 2400, 1604, 2400)],
299
- "Horizontal line with 2 clips on on the ends and one middle",
300
- [Line2D.fromCoordinates(3050, 2400, 2404, 2400), Line2D.fromCoordinates(1604, 2400, 650, 2400)],
301
- ],
302
- [
303
- Line2D.fromCoordinates(3600, 150, 3600, 2450),
304
- [Line2D.fromCoordinates(3600, 927, 3600, 1427)],
305
- "Vertical line with 1 clip in the middle middle",
306
- [Line2D.fromCoordinates(3600, 150, 3600, 927), Line2D.fromCoordinates(3600, 1427, 3600, 2450)],
307
- ],
308
- [
309
- Line2D.fromCoordinates(6050, 3100, 3800, 3100),
310
- [Line2D.fromCoordinates(6150, 3100, 3700, 3100)],
311
- "Clip line overlaps the source line on both ends",
312
- [],
313
- ],
314
- ])("Line.clipLines should return clipLines. Line: %s, others: %s, description: %s expected: %s", (line: Line2D, others: Line2D[], description: string, expected: Line2D[]) => {
315
- const result = Line2D.clipLines(line, others);
316
- expect(result.length).toEqual(expected.length);
317
- expected.forEach((e, i) => {
318
- expect(result[i].equals(e)).toBe(true);
319
- });
320
- });
321
-
322
- test.each([
323
- [
324
- Line2D.fromCoordinates(0, 50, 100, 50),
325
- Line2D.fromCoordinates(50, 0, 50, 100),
326
- "Horizontal with vertical, intersected in the middle",
327
- { x: 50, y: 50 }
328
- ],
329
- [
330
- Line2D.fromCoordinates(0, 50, 100, 50),
331
- Line2D.fromCoordinates(50, 0, 51, 100),
332
- "Horizontal with vertical, intersected in the middle, but the angle in not 90 degrees",
333
- null
334
- ],
335
- [
336
- Line2D.fromCoordinates(0, 50, 100, 50),
337
- Line2D.fromCoordinates(50, 0, 50, 49),
338
- "Horizontal with vertical, 1 unit away from intersection",
339
- null
340
- ],
341
- ])("Line.hasIntersectionWithAngle should return expected intersection. Line: %s, others: %s, description: %s expected: %s", (line: Line2D, other: Line2D, description: string, expected: Point2) => {
342
- const result = line.hasIntersectionWithAngle(other, Math.PI / 2);
343
- expect(result).toEqual(expected);
344
- });
345
-
346
- test("Line.chunk should split lines in to multiple with expected length", () => {
347
- const size = 10;
348
- const line = Line2D.fromCoordinates(0, 0, 88, 0);
349
- const chunks = line.chunk(size);
350
- expect(chunks.length).toEqual(9);
351
-
352
- expect(chunks[0].length).toEqual(size);
353
- expect(chunks[0].start.equals(line.start)).toBe(true);
354
-
355
- expect(chunks[chunks.length - 1].length).toEqual(8);
356
- expect(chunks[chunks.length - 1].end.equals(line.end)).toBe(true);
357
- });
358
- });
@@ -1,28 +0,0 @@
1
- import { Line3D } from "../Line3D";
2
- import { Vec3 } from "../Vec3";
3
-
4
- describe("Line3d.jointLine", () => {
5
- describe.each([
6
- { message: "Same direction - Lines aren't parallel", a: new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0)), b: new Line3D(new Vec3(10, 0, 0), new Vec3(20, 0, 1)), expected: null },
7
- { message: "Same direction - Lines don't overlap" ,a: new Line3D(new Vec3(0, 0, 0), new Vec3(5, 0, 0)), b: new Line3D(new Vec3(11, 0, 0), new Vec3(12, 0, 0)), expected: null},
8
- { message: "Same direction - This line entirely covers the other line", a: new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0)), b: new Line3D(new Vec3(1, 0, 0), new Vec3(9, 0, 0)), expected: new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0)) },
9
- { message: "Same direction - The other line entirely covers this line", a: new Line3D(new Vec3(1, 0, 0), new Vec3(9, 0, 0)), b: new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0)), expected: new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0)) },
10
- { message: "Same direction - This line is overlapped by the start of the other line", a: new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0)), b: new Line3D(new Vec3(5, 0, 0), new Vec3(15, 0, 0)), expected: new Line3D(new Vec3(0, 0, 0), new Vec3(15, 0, 0)) },
11
- { message: "Same direction - This line is overlapped by the end of the other line", a: new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0)), b: new Line3D(new Vec3(-5, 0, 0), new Vec3(5, 0, 0)), expected: new Line3D(new Vec3(-5, 0, 0), new Vec3(10, 0, 0)) },
12
-
13
- { message: "Opposite direction - Lines aren't parallel", a: new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0)), b: new Line3D(new Vec3(20, 0, 0), new Vec3(10, 0, 1)), expected: null },
14
- { message: "Opposite direction - Lines don't overlap", a: new Line3D(new Vec3(0, 0, 0), new Vec3(5, 0, 0)), b: new Line3D(new Vec3(12, 0, 0), new Vec3(11, 0, 0)), expected: null },
15
- { message: "Opposite direction - This line entirely covers the other line", a: new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0)), b: new Line3D(new Vec3(9, 0, 0), new Vec3(1, 0, 0)), expected: new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0)) },
16
- { message: "Opposite direction - The other line entirely covers this line", a: new Line3D(new Vec3(1, 0, 0), new Vec3(9, 0, 0)), b: new Line3D(new Vec3(10, 0, 0), new Vec3(0, 0, 0)), expected: new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0)) },
17
- { message: "Opposite direction - This line is overlapped by the start of the other line", a: new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0)), b: new Line3D(new Vec3(15, 0, 0), new Vec3(5, 0, 0)), expected: new Line3D(new Vec3(0, 0, 0), new Vec3(15, 0, 0)) },
18
- { message: "Opposite direction - This line is overlapped by the end of the other line", a: new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0)), b: new Line3D(new Vec3(5, 0, 0), new Vec3(-5, 0, 0)), expected: new Line3D(new Vec3(-5, 0, 0), new Vec3(10, 0, 0)) },
19
-
20
- { message: "Angle - Lines aren't parallel", a: new Line3D(new Vec3(0, 0, 0), new Vec3(10, 9, 0)), b: new Line3D(new Vec3(5, 5, 0), new Vec3(15, 15, 0)), expected: null },
21
- { message: "Angle - This line is overlapped by the start of the other line", a: new Line3D(new Vec3(0, 0, 0), new Vec3(10, 10, 0)), b: new Line3D(new Vec3(5, 5, 0), new Vec3(15, 15, 0)), expected: new Line3D(new Vec3(0, 0, 0), new Vec3(15, 15, 0)) },
22
- ])("joint", ({message, a, b, expected }) => {
23
- const result = a.joinLine(b);
24
- test(`${message} - expected ${JSON.stringify(expected)}, received: ${JSON.stringify(result)}`, () => {
25
- expect(result).toEqual(expected);
26
- });
27
- });
28
- });
@@ -1,72 +0,0 @@
1
- import { Line3D } from "../Line3D";
2
- import { Vec3 } from "../Vec3";
3
-
4
- describe("Line3d.jointLines", () => {
5
- describe.each([
6
- {
7
- message: "Single line",
8
- source: [
9
- new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0)),
10
- ], expected: [
11
- new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0)),
12
- ]
13
- },
14
- {
15
- message: "2 lines with gap",
16
- source: [
17
- new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0)),
18
- new Line3D(new Vec3(11, 0, 0), new Vec3(20, 0, 0)),
19
- ], expected: [
20
- new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0)),
21
- new Line3D(new Vec3(11, 0, 0), new Vec3(20, 0, 0)),
22
- ]
23
- },
24
- {
25
- message: "Three lines touching",
26
- source: [
27
- new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0)),
28
- new Line3D(new Vec3(10, 0, 0), new Vec3(20, 0, 0)),
29
- new Line3D(new Vec3(20, 0, 0), new Vec3(30, 0, 0)),
30
- ], expected: [
31
- new Line3D(new Vec3(0, 0, 0), new Vec3(30, 0, 0)),
32
- ]
33
- },
34
- {
35
- message: "Three lines touching, not ordered",
36
- source: [
37
- new Line3D(new Vec3(10, 0, 0), new Vec3(20, 0, 0)),
38
- new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0)),
39
- new Line3D(new Vec3(20, 0, 0), new Vec3(30, 0, 0)),
40
- ], expected: [
41
- new Line3D(new Vec3(0, 0, 0), new Vec3(30, 0, 0)),
42
- ]
43
- },
44
- {
45
- message: "Sources is composed of complex overlapping, covering and duplicated lines",
46
- source: [
47
- new Line3D(new Vec3(10, 0, 0), new Vec3(20, 0, 0)), // Group 1
48
- new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0)),
49
- new Line3D(new Vec3(20, 0, 0), new Vec3(30, 0, 0)),
50
- new Line3D(new Vec3(10, 0, 0), new Vec3(20, 0, 0)),
51
- new Line3D(new Vec3(-5, 0, 0), new Vec3(10, 0, 0)),
52
- new Line3D(new Vec3(29, 0, 0), new Vec3(35, 0, 0)),
53
-
54
- new Line3D(new Vec3(100 + 10, 0, 0), new Vec3(100 + 20, 0, 0)), // Group 2 - same axes but shifted by x: 100
55
- new Line3D(new Vec3(100, 0, 0), new Vec3(100 + 10, 0, 0)),
56
- new Line3D(new Vec3(100 + 20, 0, 0), new Vec3(100 + 30, 0, 0)),
57
- new Line3D(new Vec3(100 + 10, 0, 0), new Vec3(100 + 20, 0, 0)),
58
- new Line3D(new Vec3(100 + -5, 0, 0), new Vec3(100 + 10, 0, 0)),
59
- new Line3D(new Vec3(100 + 29, 0, 0), new Vec3(100 + 35, 0, 0)),
60
- ], expected: [
61
- new Line3D(new Vec3(-5, 0, 0), new Vec3(35, 0, 0)),
62
- new Line3D(new Vec3(100 + -5, 0, 0), new Vec3(100 + 35, 0, 0)),
63
- ]
64
- },
65
- ])("jointLines", ({ message, source, expected }) => {
66
- const result = Line3D.joinLines(source);
67
- result.sort((a, b) => a.start.x - b.start.x); // Order of the result is not guaranteed
68
- test(`${message} - expected ${JSON.stringify(expected)}, received: ${JSON.stringify(result)}`, () => {
69
- expect(result).toEqual(expected);
70
- });
71
- });
72
- });
@@ -1,350 +0,0 @@
1
- import { Line3D } from "../Line3D";
2
- import { Vec3 } from "../Vec3";
3
-
4
- const defaultLine = () => new Line3D(new Vec3(-10, 0, 0), new Vec3(10, 0, 0));
5
-
6
- describe("Line3d", () => {
7
- it("should create a line with expected values", () => {
8
- const line = new Line3D(new Vec3(1, 2, 3), new Vec3(4, 5, 6));
9
- expect(line.start).toEqual(new Vec3(1, 2, 3));
10
- expect(line.end).toEqual(new Vec3(4, 5, 6));
11
- });
12
-
13
- it("should create a single line polygon from a 2 points polygon", () => {
14
- const start = new Vec3(1, 2, 20);
15
- const end = new Vec3(3, 4, 20);
16
- const lines = Line3D.fromPolygon([start, end]);
17
- expect(lines.length).toEqual(1);
18
- expect(lines[0]).toEqual(new Line3D(start, end));
19
- });
20
-
21
- it("should create a 2 lines polygon from a 3 points polygon", () => {
22
- const p1 = new Vec3(1, 2, 20);
23
- const p2 = new Vec3(3, 4, 20);
24
- const p3 = new Vec3(5, 2, 20);
25
- const lines = Line3D.fromPolygon([p1, p2, p3]);
26
- expect(lines.length).toEqual(2);
27
- expect(lines[0]).toEqual(new Line3D(p1, p2));
28
- expect(lines[1]).toEqual(new Line3D(p2, p3));
29
- });
30
-
31
- it("should create a closed 3 lines polygon from a 3 points polygon", () => {
32
- const p1 = new Vec3(1, 2, 20);
33
- const p2 = new Vec3(3, 4, 20);
34
- const p3 = new Vec3(5, 2, 20);
35
- const lines = Line3D.fromPolygon([p1, p2, p3], true);
36
- expect(lines.length).toEqual(3);
37
- expect(lines[0]).toEqual(new Line3D(p1, p2));
38
- expect(lines[1]).toEqual(new Line3D(p2, p3));
39
- expect(lines[2]).toEqual(new Line3D(p3, p1));
40
- });
41
-
42
- it("should return the expected center", () => {
43
- const line = defaultLine();
44
- expect(line.center).toEqual(new Vec3(0, 0, 0));
45
- });
46
-
47
- it("should resize should resize the line by the given length", () => {
48
- const line = defaultLine();
49
- const originalCenter = line.center;
50
- expect(line.length).toEqual(20);
51
-
52
- const resizeDistance = 2;
53
- line.resize(resizeDistance);
54
-
55
- expect(line.length).toEqual(22);
56
- expect(line.center).toEqual(originalCenter);
57
- expect(line.start.x).toEqual(-11);
58
- expect(line.end.x).toEqual(11);
59
- });
60
-
61
- it("should setLength to required", () => {
62
- const line = new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0));
63
- const originalCenter = line.center;
64
- expect(line.length).toEqual(10);
65
-
66
- const newSize = 2;
67
- line.setLength(newSize);
68
-
69
- expect(line.length).toEqual(newSize);
70
- expect(line.center).toEqual(originalCenter);
71
- expect(line.start.x).toEqual(4);
72
- expect(line.end.x).toEqual(6);
73
- });
74
-
75
- it("should project the line on another", () => {
76
- // Arrange
77
- const other = new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0));
78
- const line = new Line3D(new Vec3(-1, 1, 0), new Vec3(10, 1, 0));
79
-
80
- // Act
81
- const projected = line.projectOn(other, false);
82
-
83
- // Assert
84
- expect(projected.start).toEqual(new Vec3(-1, 0, 0));
85
- expect(projected.end).toEqual(new Vec3(10, 0, 0));
86
- });
87
-
88
- it("should project and clamp the line on another", () => {
89
- // Arrange
90
- const other = new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0));
91
- const line = new Line3D(new Vec3(-1, 1, 0), new Vec3(10, 1, 0));
92
-
93
- // Act
94
- const projected = line.projectOn(other, true);
95
-
96
- // Assert
97
- expect(projected.start).toEqual(new Vec3(0, 0, 0));
98
- expect(projected.end).toEqual(new Vec3(10, 0, 0));
99
- });
100
-
101
- it("should contain point", () => {
102
- // Arrange
103
- const line = new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0));
104
-
105
- // Act
106
- const contains = line.containsPoint(new Vec3(5, 0, 0));
107
-
108
- // Assert
109
- expect(contains).toBeTruthy();
110
- });
111
-
112
- it("should not contain point", () => {
113
- // Arrange
114
- const line = new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0));
115
-
116
- // Act
117
- const contains = line.containsPoint(new Vec3(5, 1, 0));
118
-
119
- // Assert
120
- expect(contains).toBeFalsy();
121
- });
122
-
123
- it.each([
124
- ["lines are the same", new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0)), new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0)), true],
125
- ["overlap from right", new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0)), new Line3D(new Vec3(5, 0, 0), new Vec3(11, 0, 0)), true],
126
- ["overlap from left", new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0)), new Line3D(new Vec3(-5, 0, 0), new Vec3(5, 0, 0)), true],
127
- ["second inside the first", new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0)), new Line3D(new Vec3(5, 0, 0), new Vec3(6, 0, 0)), true],
128
- ["fist inside the second", new Line3D(new Vec3(5, 0, 0), new Vec3(6, 0, 0)), new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0)), true],
129
- ["no overlap", new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0)), new Line3D(new Vec3(11, 0, 0), new Vec3(12, 0, 0)), false],
130
- ["no overlap, but touching ends", new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0)), new Line3D(new Vec3(10, 0, 0), new Vec3(12, 0, 0)), false],
131
- ["not parallel", new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0)), new Line3D(new Vec3(5, 0, 0), new Vec3(10, 1, 0)), false],
132
- ])("should detect overlap of two lines - %s", (reason, line1, line2, expected) => {
133
- // Act
134
- const result = line1.overlaps(line2);
135
-
136
- // Assert
137
- expect(result).toEqual(expected);
138
- });
139
-
140
- it("should trim the line and return two offcuts, clip well within source", () => {
141
- // Arrange
142
- const source = new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0));
143
- const clip = new Line3D(new Vec3(3, 0, 0), new Vec3(7, 0, 0));
144
-
145
- // Act
146
- const result = source.clipLine(clip);
147
- const groupResult = source.clipLines([clip]);
148
-
149
- // Assert
150
- expect(result.length).toEqual(2);
151
-
152
- expect(result[0].start).toEqual(new Vec3(0, 0, 0));
153
- expect(result[0].end).toEqual(new Vec3(3, 0, 0));
154
-
155
- expect(result[1].start).toEqual(new Vec3(7, 0, 0));
156
- expect(result[1].end).toEqual(new Vec3(10, 0, 0));
157
-
158
- expect(groupResult.sort((a, b) => a.start.x - b.start.x)).toEqual(result.sort((a, b) => a.start.x - b.start.x));
159
- });
160
-
161
- it("should trim the lines even if the clips are overlapping and return two offcuts", () => {
162
- // Arrange
163
- const source = new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0));
164
- const clips = [
165
- new Line3D(new Vec3(-3, 0, 0), new Vec3(2, 0, 0)),
166
- new Line3D(new Vec3(3, 0, 0), new Vec3(6, 0, 0)),
167
- new Line3D(new Vec3(4, 0, 0), new Vec3(7, 0, 0)),
168
- ];
169
-
170
- // Act
171
- const result = source.clipLines(clips);
172
-
173
- // Assert
174
- result.sort((a, b) => a.start.x - b.start.x); // Order from the clipping is not guaranteed
175
- expect(result).toEqual([
176
- new Line3D(new Vec3(2, 0, 0), new Vec3(3, 0, 0)),
177
- new Line3D(new Vec3(7, 0, 0), new Vec3(10, 0, 0)),
178
- ]);
179
- });
180
-
181
- it.each([
182
- { tolerance: 0 },
183
- { tolerance: 1 },
184
- ])("should trim the line and return two offcuts even if the source and trim run in opposite direction and are not perfectly parallel when sufficient tolerance is provided", ({ tolerance }) => {
185
- // Arrange
186
- const source = new Line3D(new Vec3(
187
- 1907.0952296605503,
188
- 0,
189
- 5258.129694575135
190
- ), new Vec3(
191
- 1907.0952296605506,
192
- 0,
193
- 4302.1493774205865
194
- ));
195
- const clip = new Line3D(new Vec3(
196
- 1907.0952296605503,
197
- 0,
198
- 4762.083899346474
199
- ), new Vec3(
200
- 1907.0952296605503,
201
- 0,
202
- 4954.083899346474
203
- ));
204
-
205
- // Act
206
- const result = source.clipLine(clip, tolerance);
207
-
208
- // Assert
209
- if (tolerance === 0) {
210
- expect(result).toEqual([source]);
211
- } else {
212
- expect(result).toEqual([
213
- new Line3D(new Vec3(1907.0952296605503, 0, 5258.129694575135), new Vec3(1907.0952296605503, 0, 4954.083899346474)),
214
- new Line3D(new Vec3(1907.0952296605503, 0, 4762.083899346474), new Vec3(1907.0952296605506, 0, 4302.1493774205865)),
215
- ]);
216
- }
217
- });
218
-
219
-
220
- it("should trim the line and return right side offcuts, clip is completely contained in source", () => {
221
- // Arrange
222
- const source = new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0));
223
- const clip = new Line3D(new Vec3(0, 0, 0), new Vec3(7, 0, 0));
224
-
225
- // Act
226
- const result = source.clipLine(clip);
227
- const groupResult = source.clipLines([clip]);
228
-
229
- // Assert
230
- expect(result.length).toEqual(1);
231
- expect(result[0].start).toEqual(new Vec3(7, 0, 0));
232
- expect(result[0].end).toEqual(new Vec3(10, 0, 0));
233
- expect(result).toEqual(groupResult);
234
- });
235
-
236
- it("should trim the line and return right side offcuts, clip overlapping from left", () => {
237
- // Arrange
238
- const source = new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0));
239
- const clip = new Line3D(new Vec3(-1, 0, 0), new Vec3(7, 0, 0));
240
-
241
- // Act
242
- const result = source.clipLine(clip);
243
- const groupResult = source.clipLines([clip]);
244
-
245
- // Assert
246
- expect(result.length).toEqual(1);
247
- expect(result[0].start).toEqual(new Vec3(7, 0, 0));
248
- expect(result[0].end).toEqual(new Vec3(10, 0, 0));
249
- expect(result).toEqual(groupResult);
250
- });
251
-
252
- it("should trim the line and return left side off-cut, clip is completely contained in source", () => {
253
- // Arrange
254
- const source = new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0));
255
- const clip = new Line3D(new Vec3(5, 0, 0), new Vec3(10, 0, 0));
256
-
257
- // Act
258
- const result = source.clipLine(clip);
259
- const groupResult = source.clipLines([clip]);
260
-
261
- // Assert
262
- expect(result.length).toEqual(1);
263
- expect(result[0].start).toEqual(new Vec3(0, 0, 0));
264
- expect(result[0].end).toEqual(new Vec3(5, 0, 0));
265
- expect(result).toEqual(groupResult);
266
- });
267
-
268
- it("should trim the line and return left side off-cut, clip overlapping from right", () => {
269
- // Arrange
270
- const source = new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0));
271
- const clip = new Line3D(new Vec3(5, 0, 0), new Vec3(15, 0, 0));
272
-
273
- // Act
274
- const result = source.clipLine(clip);
275
- const groupResult = source.clipLines([clip]);
276
-
277
- // Assert
278
- expect(result.length).toEqual(1);
279
- expect(result[0].start).toEqual(new Vec3(0, 0, 0));
280
- expect(result[0].end).toEqual(new Vec3(5, 0, 0));
281
- expect(result).toEqual(groupResult);
282
- });
283
-
284
- it("should trim the line and return no off-cut as it matches the source entirely", () => {
285
- // Arrange
286
- const source = new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0));
287
- const clip = new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0));
288
-
289
- // Act
290
- const result = source.clipLine(clip);
291
- const groupResult = source.clipLines([clip]);
292
-
293
- // Assert
294
- expect(result.length).toEqual(0);
295
- expect(result).toEqual(groupResult);
296
- });
297
-
298
- it("should trim the line and return no off-cut as it overlaps the source", () => {
299
- // Arrange
300
- const source = new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0));
301
- const clip = new Line3D(new Vec3(-1, 0, 0), new Vec3(11, 0, 0));
302
-
303
- // Act
304
- const result = source.clipLine(clip);
305
- const groupResult = source.clipLines([clip]);
306
-
307
- // Assert
308
- expect(result.length).toEqual(0);
309
- expect(result).toEqual(groupResult);
310
- });
311
-
312
- it("should trim the line with opposite direction", () => {
313
- // Arrange
314
- const source = new Line3D(new Vec3(6, 0, 0), new Vec3(10, 0, 0));
315
- const clip = new Line3D(new Vec3(7, 0, 0), new Vec3(4, 0, 0));
316
-
317
- // Act
318
- const result = source.clipLine(clip);
319
- const groupResult = source.clipLines([clip]);
320
-
321
- // Assert
322
- expect(result).toEqual([new Line3D(new Vec3(7, 0, 0), new Vec3(10, 0, 0))]);
323
- expect(result).toEqual(groupResult);
324
- });
325
-
326
- it.each([
327
- // Arrange
328
- { a: new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0)), b: new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0)), expected: true },
329
- { a: new Line3D(new Vec3(10, 0, 0), new Vec3(0, 0, 0)), b: new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0)), expected: true },
330
- { a: new Line3D(new Vec3(0, 0, 0), new Vec3(10, 1, 0)), b: new Line3D(new Vec3(0, 0, 0), new Vec3(10, 0, 0)), expected: false },
331
- ])("should determine if the lines are parallel %j", ({ a, b, expected }) => {
332
- // Act
333
- const areParallel = a.isParallelTo(b);
334
- // Assert
335
- expect(areParallel).toBe(expected);
336
- });
337
-
338
- it("chunk should split the line in to multiple with expected length", () => {
339
- const size = 10;
340
- const line = new Line3D(new Vec3(0, 0, 0), new Vec3(88, 0, 0));
341
- const chunks = line.chunk(size);
342
- expect(chunks.length).toEqual(9);
343
-
344
- expect(chunks[0].length).toEqual(size);
345
- expect(chunks[0].start.equals(line.start)).toBe(true);
346
-
347
- expect(chunks[chunks.length - 1].length).toEqual(8);
348
- expect(chunks[chunks.length - 1].end.equals(line.end)).toBe(true);
349
- });
350
- });
package/tsconfig-cjs.json DELETED
@@ -1,9 +0,0 @@
1
- {
2
- "extends": "./tsconfig.json",
3
- "compilerOptions": {
4
- "module": "commonjs",
5
- "outDir": "./cjs",
6
- "declaration": false,
7
- "declarationDir": null
8
- }
9
- }
package/tsconfig.json DELETED
@@ -1,13 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "outDir": "./esm",
4
- "declaration": true,
5
- "declarationDir": "./types",
6
- "importHelpers": true,
7
- "target": "ESNext",
8
- "module": "ESNext",
9
- "moduleResolution": "node",
10
- "lib": [ "esnext", "dom" ]
11
- },
12
- "exclude": ["src/**/*.test.ts", "src/**/*.spec.ts"]
13
- }