geometric-library 1.3.0
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/LICENSE +21 -0
- package/README.md +61 -0
- package/dist/cjs/abstracts/Angle.js +60 -0
- package/dist/cjs/abstracts/Figure.js +147 -0
- package/dist/cjs/abstracts/Flag.js +27 -0
- package/dist/cjs/abstracts/Magnitude.js +25 -0
- package/dist/cjs/abstracts/Point.js +50 -0
- package/dist/cjs/abstracts/Vector.js +74 -0
- package/dist/cjs/figures/ArcCurve.js +132 -0
- package/dist/cjs/figures/Circle.js +43 -0
- package/dist/cjs/figures/CubicBezierCurve.js +149 -0
- package/dist/cjs/figures/Ellipse.js +111 -0
- package/dist/cjs/figures/Line.js +264 -0
- package/dist/cjs/figures/Polygon.js +17 -0
- package/dist/cjs/figures/QuadraticBezierCurve.js +104 -0
- package/dist/cjs/index.js +48 -0
- package/dist/cjs/types/index.js +2 -0
- package/dist/cjs/utilities/Calculator.js +153 -0
- package/dist/cjs/utilities/index.js +10 -0
- package/dist/esm/abstracts/Angle.js +56 -0
- package/dist/esm/abstracts/Figure.js +143 -0
- package/dist/esm/abstracts/Flag.js +23 -0
- package/dist/esm/abstracts/Magnitude.js +21 -0
- package/dist/esm/abstracts/Point.js +46 -0
- package/dist/esm/abstracts/Vector.js +70 -0
- package/dist/esm/figures/ArcCurve.js +128 -0
- package/dist/esm/figures/Circle.js +39 -0
- package/dist/esm/figures/CubicBezierCurve.js +145 -0
- package/dist/esm/figures/Ellipse.js +107 -0
- package/dist/esm/figures/Line.js +260 -0
- package/dist/esm/figures/Polygon.js +13 -0
- package/dist/esm/figures/QuadraticBezierCurve.js +100 -0
- package/dist/esm/index.js +17 -0
- package/dist/esm/types/index.js +1 -0
- package/dist/esm/utilities/Calculator.js +149 -0
- package/dist/esm/utilities/index.js +7 -0
- package/dist/types/abstracts/Angle.d.ts +18 -0
- package/dist/types/abstracts/Figure.d.ts +22 -0
- package/dist/types/abstracts/Flag.d.ts +10 -0
- package/dist/types/abstracts/Magnitude.d.ts +9 -0
- package/dist/types/abstracts/Point.d.ts +14 -0
- package/dist/types/abstracts/Vector.d.ts +20 -0
- package/dist/types/figures/ArcCurve.d.ts +23 -0
- package/dist/types/figures/Circle.d.ts +12 -0
- package/dist/types/figures/CubicBezierCurve.d.ts +23 -0
- package/dist/types/figures/Ellipse.d.ts +26 -0
- package/dist/types/figures/Line.d.ts +44 -0
- package/dist/types/figures/Polygon.d.ts +7 -0
- package/dist/types/figures/QuadraticBezierCurve.d.ts +21 -0
- package/dist/types/index.d.ts +16 -0
- package/dist/types/types/index.d.ts +144 -0
- package/dist/types/utilities/Calculator.d.ts +49 -0
- package/dist/types/utilities/index.d.ts +6 -0
- package/package.json +60 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CubicBezierCurve = void 0;
|
|
4
|
+
const Calculator_1 = require("../utilities/Calculator");
|
|
5
|
+
const Point_1 = require("../abstracts/Point");
|
|
6
|
+
const Figure_1 = require("../abstracts/Figure");
|
|
7
|
+
class CubicBezierCurve extends Figure_1.Figure {
|
|
8
|
+
_criticalPoints;
|
|
9
|
+
constructor(values) {
|
|
10
|
+
super(values);
|
|
11
|
+
this._criticalPoints = this.computeCriticalPoints();
|
|
12
|
+
}
|
|
13
|
+
get boundingBox() {
|
|
14
|
+
const [P0, , , P3] = this.values;
|
|
15
|
+
const points = [P0, P3, ...this._criticalPoints];
|
|
16
|
+
return Figure_1.Figure.computeBoundingBox(points);
|
|
17
|
+
}
|
|
18
|
+
get criticalPoints() {
|
|
19
|
+
return this._criticalPoints;
|
|
20
|
+
}
|
|
21
|
+
get P0() {
|
|
22
|
+
return this.points[0];
|
|
23
|
+
}
|
|
24
|
+
get P1() {
|
|
25
|
+
if (this.isRelative) {
|
|
26
|
+
return this.P0.clone().translate(this.vectors[0]);
|
|
27
|
+
}
|
|
28
|
+
return this.points[1];
|
|
29
|
+
}
|
|
30
|
+
get P2() {
|
|
31
|
+
if (this.isRelative) {
|
|
32
|
+
return this.P0.clone().translate(this.vectors[1]);
|
|
33
|
+
}
|
|
34
|
+
return this.points[2];
|
|
35
|
+
}
|
|
36
|
+
get P3() {
|
|
37
|
+
if (this.isRelative) {
|
|
38
|
+
return this.P0.clone().translate(this.vectors[2]);
|
|
39
|
+
}
|
|
40
|
+
return this.points[3];
|
|
41
|
+
}
|
|
42
|
+
clone() {
|
|
43
|
+
const values = this.values.map((value) => value.clone());
|
|
44
|
+
return new CubicBezierCurve(values);
|
|
45
|
+
}
|
|
46
|
+
recompute() {
|
|
47
|
+
this._criticalPoints = this.computeCriticalPoints();
|
|
48
|
+
}
|
|
49
|
+
reflect(about) {
|
|
50
|
+
super.reflect(about);
|
|
51
|
+
this.recompute();
|
|
52
|
+
return this;
|
|
53
|
+
}
|
|
54
|
+
rotate(phi, about) {
|
|
55
|
+
super.rotate(phi, about);
|
|
56
|
+
this.recompute();
|
|
57
|
+
return this;
|
|
58
|
+
}
|
|
59
|
+
scale(factor, about) {
|
|
60
|
+
super.scale(factor, about);
|
|
61
|
+
this.recompute();
|
|
62
|
+
return this;
|
|
63
|
+
}
|
|
64
|
+
translate(vector) {
|
|
65
|
+
super.translate(vector);
|
|
66
|
+
this.recompute();
|
|
67
|
+
return this;
|
|
68
|
+
}
|
|
69
|
+
computeCriticalPoints() {
|
|
70
|
+
const tValues = this.computeCriticalPointsTValues();
|
|
71
|
+
if (!tValues) {
|
|
72
|
+
return [];
|
|
73
|
+
}
|
|
74
|
+
const criticalPoints = tValues.reduce((criticalPoints, t) => {
|
|
75
|
+
const criticalPoint = this.getPointAtParameter(t);
|
|
76
|
+
criticalPoint && criticalPoints.push(criticalPoint);
|
|
77
|
+
return criticalPoints;
|
|
78
|
+
}, []);
|
|
79
|
+
return criticalPoints;
|
|
80
|
+
}
|
|
81
|
+
computeCriticalPointsTValues() {
|
|
82
|
+
const axii = ['x', 'y'];
|
|
83
|
+
const { P0, P1, P2, P3 } = this;
|
|
84
|
+
const signs = [1, -1];
|
|
85
|
+
const tValues = [];
|
|
86
|
+
for (let i = 0; i < axii.length; i++) {
|
|
87
|
+
const axis = axii[i];
|
|
88
|
+
const p0 = new Calculator_1.Calculator(P0[axis]);
|
|
89
|
+
const p1 = new Calculator_1.Calculator(P1[axis]);
|
|
90
|
+
const p2 = new Calculator_1.Calculator(P2[axis]);
|
|
91
|
+
const p3 = new Calculator_1.Calculator(P3[axis]);
|
|
92
|
+
const a = p3.sub(p2.mul(3)).add(p1.mul(3)).sub(p0).mul(3);
|
|
93
|
+
const b = p2.sub(p1.mul(2)).add(p0).mul(6);
|
|
94
|
+
const c = p1.sub(p0).mul(3);
|
|
95
|
+
for (let n = 0; n < signs.length; n++) {
|
|
96
|
+
const sign = signs[n];
|
|
97
|
+
let tValue;
|
|
98
|
+
if (+a === 0) {
|
|
99
|
+
// 1st degree equation to avoid n/0
|
|
100
|
+
tValue = c.neg().div(b);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
// 2nd degree equation
|
|
104
|
+
tValue = b
|
|
105
|
+
.neg()
|
|
106
|
+
.add(Calculator_1.Calculator.mul(sign, b.pow(2).sub(a.mul(c).mul(4)).sqrt()))
|
|
107
|
+
.div(a.mul(2));
|
|
108
|
+
}
|
|
109
|
+
if (this.isValidParameter(tValue)) {
|
|
110
|
+
tValues.push(tValue);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (!tValues.length) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
return tValues.filter((value, index, array) => index === array.findIndex((v) => +value === +v));
|
|
118
|
+
}
|
|
119
|
+
getCoordinateAtParameter(t, axis) {
|
|
120
|
+
const { P0, P1, P2, P3 } = this;
|
|
121
|
+
const p0 = P0[axis];
|
|
122
|
+
const p1 = P1[axis];
|
|
123
|
+
const p2 = P2[axis];
|
|
124
|
+
const p3 = P3[axis];
|
|
125
|
+
// parametric cubic bezier equation
|
|
126
|
+
const coordinate = Calculator_1.Calculator.sub(1, t)
|
|
127
|
+
.pow(3)
|
|
128
|
+
.mul(p0)
|
|
129
|
+
.add(Calculator_1.Calculator.sub(1, t).pow(2).mul(3).mul(t).mul(p1))
|
|
130
|
+
.add(Calculator_1.Calculator.sub(1, t).mul(3).mul(t.pow(2)).mul(p2))
|
|
131
|
+
.add(t.pow(3).mul(p3));
|
|
132
|
+
if (!coordinate.isFinite()) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
return coordinate;
|
|
136
|
+
}
|
|
137
|
+
getPointAtParameter(t) {
|
|
138
|
+
const x = this.getCoordinateAtParameter(t, 'x');
|
|
139
|
+
const y = this.getCoordinateAtParameter(t, 'y');
|
|
140
|
+
if (typeof x === 'undefined' || typeof y === 'undefined') {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
return new Point_1.Point([+x, +y]);
|
|
144
|
+
}
|
|
145
|
+
isValidParameter(t) {
|
|
146
|
+
return t.isFinite() && +t > 0 && +t < 1;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
exports.CubicBezierCurve = CubicBezierCurve;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Ellipse = void 0;
|
|
4
|
+
const Calculator_1 = require("../utilities/Calculator");
|
|
5
|
+
const Angle_1 = require("../abstracts/Angle");
|
|
6
|
+
const Point_1 = require("../abstracts/Point");
|
|
7
|
+
const Figure_1 = require("../abstracts/Figure");
|
|
8
|
+
const utilities_1 = require("../utilities");
|
|
9
|
+
class Ellipse extends Figure_1.Figure {
|
|
10
|
+
_center;
|
|
11
|
+
_criticalPoints;
|
|
12
|
+
_phi;
|
|
13
|
+
_rx;
|
|
14
|
+
_ry;
|
|
15
|
+
constructor(values) {
|
|
16
|
+
super(values);
|
|
17
|
+
const [center, rx, ry, phi] = values;
|
|
18
|
+
this._center = center;
|
|
19
|
+
this._rx = rx;
|
|
20
|
+
this._ry = ry;
|
|
21
|
+
this._phi = phi;
|
|
22
|
+
this._criticalPoints = this.computeCriticalPoints({ center, rx, ry, phi });
|
|
23
|
+
}
|
|
24
|
+
get boundingBox() {
|
|
25
|
+
return Figure_1.Figure.computeBoundingBox(this.criticalPoints);
|
|
26
|
+
}
|
|
27
|
+
get center() {
|
|
28
|
+
return this._center;
|
|
29
|
+
}
|
|
30
|
+
get criticalPoints() {
|
|
31
|
+
return this._criticalPoints;
|
|
32
|
+
}
|
|
33
|
+
get isCircle() {
|
|
34
|
+
return +this.rx === +this.ry;
|
|
35
|
+
}
|
|
36
|
+
get phi() {
|
|
37
|
+
return this._phi;
|
|
38
|
+
}
|
|
39
|
+
get rx() {
|
|
40
|
+
return this._rx;
|
|
41
|
+
}
|
|
42
|
+
get ry() {
|
|
43
|
+
return this._ry;
|
|
44
|
+
}
|
|
45
|
+
clone() {
|
|
46
|
+
const values = this.values.map((value) => value.clone());
|
|
47
|
+
return new Ellipse(values);
|
|
48
|
+
}
|
|
49
|
+
computePointForTheta(theta, ellipse = this) {
|
|
50
|
+
const { center, rx, ry, phi } = ellipse;
|
|
51
|
+
const x = +Calculator_1.Calculator.mul(+rx, phi.cos).mul(theta.cos).sub(Calculator_1.Calculator.mul(+ry, phi.sin).mul(theta.sin)).add(center.x);
|
|
52
|
+
const y = +Calculator_1.Calculator.mul(+rx, phi.sin).mul(theta.cos).add(Calculator_1.Calculator.mul(+ry, phi.cos).mul(theta.sin)).add(center.y);
|
|
53
|
+
return new Point_1.Point([x, y]);
|
|
54
|
+
}
|
|
55
|
+
computeThetaForPoint({ x, y }) {
|
|
56
|
+
const { center, phi, rx, ry } = this;
|
|
57
|
+
const { x: cx, y: cy } = center;
|
|
58
|
+
const dy = Calculator_1.Calculator.sub(y, cy);
|
|
59
|
+
const dx = Calculator_1.Calculator.sub(x, cx);
|
|
60
|
+
const sinTheta = dy.mul(phi.cos).sub(dx.mul(phi.sin)).div(+ry);
|
|
61
|
+
const cosTheta = dx.mul(phi.cos).add(dy.mul(phi.sin)).div(+rx);
|
|
62
|
+
const theta = new Angle_1.Angle(+Calculator_1.Calculator.atan2(sinTheta, cosTheta), 'radians').normalize();
|
|
63
|
+
return theta;
|
|
64
|
+
}
|
|
65
|
+
reflect(about) {
|
|
66
|
+
super.reflect(about);
|
|
67
|
+
if (!this.isCircle && 'V' in about) {
|
|
68
|
+
const alpha = about.angleTo(utilities_1.xAxis);
|
|
69
|
+
this._phi.replace(+Calculator_1.Calculator.mul(2, alpha.radians).sub(this.phi.radians), 'radians');
|
|
70
|
+
this._phi.normalize();
|
|
71
|
+
}
|
|
72
|
+
this.recompute();
|
|
73
|
+
return this;
|
|
74
|
+
}
|
|
75
|
+
rotate(alpha, about) {
|
|
76
|
+
this._center.rotate(alpha, about);
|
|
77
|
+
if (!this.isCircle) {
|
|
78
|
+
this._phi.replace(+Calculator_1.Calculator.add(this.phi.radians, alpha.radians), 'radians');
|
|
79
|
+
this._phi.normalize();
|
|
80
|
+
}
|
|
81
|
+
this.recompute();
|
|
82
|
+
return this;
|
|
83
|
+
}
|
|
84
|
+
scale(factor, about = new Point_1.Point([0, 0])) {
|
|
85
|
+
super.scale(factor, about);
|
|
86
|
+
this.recompute();
|
|
87
|
+
return this;
|
|
88
|
+
}
|
|
89
|
+
translate(vector) {
|
|
90
|
+
this._center.translate(vector);
|
|
91
|
+
this.recompute();
|
|
92
|
+
return this;
|
|
93
|
+
}
|
|
94
|
+
computeCriticalPoints(ellipse = this) {
|
|
95
|
+
const { rx, ry, phi } = ellipse;
|
|
96
|
+
const { computePointForTheta } = this;
|
|
97
|
+
const xThetaPrincipal = new Angle_1.Angle(+Calculator_1.Calculator.neg(+ry).mul(phi.tan).div(+rx).atan(), 'radians');
|
|
98
|
+
const yThetaPrincipal = new Angle_1.Angle(+Calculator_1.Calculator.mul(+ry, phi.cot).div(+rx).atan(), 'radians');
|
|
99
|
+
const xThetaSecondary = new Angle_1.Angle(+Calculator_1.Calculator.add(+xThetaPrincipal, Math.PI), 'radians');
|
|
100
|
+
const yThetaSecondary = new Angle_1.Angle(+Calculator_1.Calculator.add(+yThetaPrincipal, Math.PI), 'radians');
|
|
101
|
+
const firstPoint = computePointForTheta(xThetaPrincipal, ellipse);
|
|
102
|
+
const secondPoint = computePointForTheta(yThetaPrincipal, ellipse);
|
|
103
|
+
const thirdPoint = computePointForTheta(xThetaSecondary, ellipse);
|
|
104
|
+
const fourthPoint = computePointForTheta(yThetaSecondary, ellipse);
|
|
105
|
+
return [firstPoint, secondPoint, thirdPoint, fourthPoint];
|
|
106
|
+
}
|
|
107
|
+
recompute() {
|
|
108
|
+
this._criticalPoints = this.computeCriticalPoints();
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
exports.Ellipse = Ellipse;
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Line = void 0;
|
|
4
|
+
const Calculator_1 = require("../utilities/Calculator");
|
|
5
|
+
const Angle_1 = require("../abstracts/Angle");
|
|
6
|
+
const Point_1 = require("../abstracts/Point");
|
|
7
|
+
const Vector_1 = require("../abstracts/Vector");
|
|
8
|
+
const Figure_1 = require("../abstracts/Figure");
|
|
9
|
+
class Line extends Figure_1.Figure {
|
|
10
|
+
_P0;
|
|
11
|
+
_P1;
|
|
12
|
+
_V;
|
|
13
|
+
_reciprocal;
|
|
14
|
+
_slope;
|
|
15
|
+
_xIntercept;
|
|
16
|
+
_yIntercept;
|
|
17
|
+
constructor(values) {
|
|
18
|
+
super(values);
|
|
19
|
+
const [P0, anchor] = values;
|
|
20
|
+
if (anchor instanceof Vector_1.Vector) {
|
|
21
|
+
this._V = anchor;
|
|
22
|
+
this._P1 = P0.clone().translate(anchor);
|
|
23
|
+
// anchor instanceof Point
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
this._V = new Vector_1.Vector([P0, anchor]);
|
|
27
|
+
this._P1 = anchor;
|
|
28
|
+
}
|
|
29
|
+
this._P0 = P0;
|
|
30
|
+
this._slope = this.computeSlope();
|
|
31
|
+
this._yIntercept = this.computeYIntercept();
|
|
32
|
+
this._reciprocal = this.computeReciprocal();
|
|
33
|
+
this._xIntercept = this.computeXIntercept();
|
|
34
|
+
this.points = [this.P0, this.P1];
|
|
35
|
+
this.vectors = [this.V];
|
|
36
|
+
}
|
|
37
|
+
get P0() {
|
|
38
|
+
return this._P0;
|
|
39
|
+
}
|
|
40
|
+
get P1() {
|
|
41
|
+
return this._P1;
|
|
42
|
+
}
|
|
43
|
+
get V() {
|
|
44
|
+
return this._V;
|
|
45
|
+
}
|
|
46
|
+
// STANDARD EQUATION PARAMETERS (ax + by - c = 0)
|
|
47
|
+
get a() {
|
|
48
|
+
const { slope, isVertical, isHorizontal } = this;
|
|
49
|
+
if (isVertical) {
|
|
50
|
+
return 1;
|
|
51
|
+
}
|
|
52
|
+
if (isHorizontal) {
|
|
53
|
+
return 0;
|
|
54
|
+
}
|
|
55
|
+
return slope >= 0 ? slope : -slope;
|
|
56
|
+
}
|
|
57
|
+
get b() {
|
|
58
|
+
const { slope, isVertical, isHorizontal } = this;
|
|
59
|
+
if (isVertical) {
|
|
60
|
+
return 0;
|
|
61
|
+
}
|
|
62
|
+
if (isHorizontal) {
|
|
63
|
+
return 1;
|
|
64
|
+
}
|
|
65
|
+
return slope >= 0 ? -1 : 1;
|
|
66
|
+
}
|
|
67
|
+
get c() {
|
|
68
|
+
const { slope, isVertical, isHorizontal, yIntercept, xIntercept } = this;
|
|
69
|
+
if (isVertical) {
|
|
70
|
+
return xIntercept;
|
|
71
|
+
}
|
|
72
|
+
if (isHorizontal) {
|
|
73
|
+
return yIntercept;
|
|
74
|
+
}
|
|
75
|
+
return slope >= 0 ? -yIntercept : yIntercept;
|
|
76
|
+
}
|
|
77
|
+
get isHorizontal() {
|
|
78
|
+
const { slope, isVertical } = this;
|
|
79
|
+
return !isVertical && slope === 0;
|
|
80
|
+
}
|
|
81
|
+
get isVertical() {
|
|
82
|
+
const { slope } = this;
|
|
83
|
+
return typeof slope === 'undefined';
|
|
84
|
+
}
|
|
85
|
+
get reciprocal() {
|
|
86
|
+
return this._reciprocal;
|
|
87
|
+
}
|
|
88
|
+
get slope() {
|
|
89
|
+
return this._slope;
|
|
90
|
+
}
|
|
91
|
+
get xIntercept() {
|
|
92
|
+
return this._xIntercept;
|
|
93
|
+
}
|
|
94
|
+
get yIntercept() {
|
|
95
|
+
return this._yIntercept;
|
|
96
|
+
}
|
|
97
|
+
angleTo(line) {
|
|
98
|
+
if (this.isParallelTo(line)) {
|
|
99
|
+
return new Angle_1.Angle(0, 'radians');
|
|
100
|
+
}
|
|
101
|
+
if (this.isPerpendicularTo(line)) {
|
|
102
|
+
return new Angle_1.Angle(+Calculator_1.Calculator.div(Math.PI, 2), 'radians');
|
|
103
|
+
}
|
|
104
|
+
if (typeof this.slope === 'undefined') {
|
|
105
|
+
return new Angle_1.Angle(+Calculator_1.Calculator.atan(line.slope), 'radians');
|
|
106
|
+
}
|
|
107
|
+
if (typeof line.slope === 'undefined') {
|
|
108
|
+
return new Angle_1.Angle(+Calculator_1.Calculator.atan(this.slope), 'radians');
|
|
109
|
+
}
|
|
110
|
+
const thisSlope = new Calculator_1.Calculator(this.slope);
|
|
111
|
+
const lineSlope = new Calculator_1.Calculator(line.slope);
|
|
112
|
+
return new Angle_1.Angle(+lineSlope.sub(thisSlope).div(thisSlope.mul(lineSlope).add(1)).abs().atan(), 'radians');
|
|
113
|
+
}
|
|
114
|
+
clone() {
|
|
115
|
+
const values = this.values.map((value) => value.clone());
|
|
116
|
+
return new Line(values);
|
|
117
|
+
}
|
|
118
|
+
getIntersectionPoint(line) {
|
|
119
|
+
if (this.isParallelTo(line)) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const denominator = Calculator_1.Calculator.mul(this.a, line.b).sub(Calculator_1.Calculator.mul(line.a, this.b));
|
|
123
|
+
const x = +Calculator_1.Calculator.mul(this.b, line.c).sub(Calculator_1.Calculator.mul(line.b, this.c)).div(denominator);
|
|
124
|
+
const y = +Calculator_1.Calculator.mul(this.c, line.a).sub(Calculator_1.Calculator.mul(line.c, this.a)).div(denominator);
|
|
125
|
+
return new Point_1.Point([x, y]);
|
|
126
|
+
}
|
|
127
|
+
getPerpendicularProjection(point) {
|
|
128
|
+
const { P0, slope, isVertical, isHorizontal } = this;
|
|
129
|
+
let perpendicularProjection;
|
|
130
|
+
if (this.hasPoint(point)) {
|
|
131
|
+
return point.clone();
|
|
132
|
+
}
|
|
133
|
+
if (isVertical) {
|
|
134
|
+
perpendicularProjection = new Point_1.Point([P0.x, point.y]);
|
|
135
|
+
}
|
|
136
|
+
else if (isHorizontal) {
|
|
137
|
+
perpendicularProjection = new Point_1.Point([point.x, P0.y]);
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
const x = new Calculator_1.Calculator(1);
|
|
141
|
+
const y = x.mul(1).div(slope).neg().add(Calculator_1.Calculator.div(point.x, slope)).add(point.y);
|
|
142
|
+
perpendicularProjection = new Point_1.Point([+x, +y]);
|
|
143
|
+
}
|
|
144
|
+
return perpendicularProjection;
|
|
145
|
+
}
|
|
146
|
+
getPerpendicularThrough(point) {
|
|
147
|
+
if (this.hasPoint(point)) {
|
|
148
|
+
const phi = new Angle_1.Angle(+Calculator_1.Calculator.div(Math.PI, 2), 'radians');
|
|
149
|
+
return this.clone().rotate(phi, point);
|
|
150
|
+
}
|
|
151
|
+
return new Line([point, this.getPerpendicularProjection(point)]);
|
|
152
|
+
}
|
|
153
|
+
getPointAtParameter(t) {
|
|
154
|
+
const { P0, V } = this;
|
|
155
|
+
const x = +Calculator_1.Calculator.add(P0.x, Calculator_1.Calculator.mul(V.dx, t));
|
|
156
|
+
const y = +Calculator_1.Calculator.add(P0.y, Calculator_1.Calculator.mul(V.dy, t));
|
|
157
|
+
return new Point_1.Point([x, y]);
|
|
158
|
+
}
|
|
159
|
+
getXValueAtY(y) {
|
|
160
|
+
const { reciprocal, xIntercept } = this;
|
|
161
|
+
if (typeof reciprocal === 'undefined') {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
if (typeof xIntercept === 'undefined') {
|
|
165
|
+
return +Calculator_1.Calculator.mul(reciprocal, y);
|
|
166
|
+
}
|
|
167
|
+
return +Calculator_1.Calculator.mul(reciprocal, y).add(xIntercept);
|
|
168
|
+
}
|
|
169
|
+
getYValueAtX(x) {
|
|
170
|
+
const { slope, yIntercept } = this;
|
|
171
|
+
if (typeof slope === 'undefined') {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
if (typeof yIntercept === 'undefined') {
|
|
175
|
+
return +Calculator_1.Calculator.mul(slope, x);
|
|
176
|
+
}
|
|
177
|
+
return +Calculator_1.Calculator.mul(slope, x).add(yIntercept);
|
|
178
|
+
}
|
|
179
|
+
hasPoint(P) {
|
|
180
|
+
const potentialY = this.getYValueAtX(P.x);
|
|
181
|
+
return typeof potentialY === 'number' && potentialY === P.y;
|
|
182
|
+
}
|
|
183
|
+
isParallelTo(line) {
|
|
184
|
+
return this.slope == line.slope;
|
|
185
|
+
}
|
|
186
|
+
isPerpendicularTo(line) {
|
|
187
|
+
if (this.isVertical) {
|
|
188
|
+
return line.isHorizontal;
|
|
189
|
+
}
|
|
190
|
+
if (this.isHorizontal) {
|
|
191
|
+
return line.isVertical;
|
|
192
|
+
}
|
|
193
|
+
if (line.isVertical) {
|
|
194
|
+
return this.isHorizontal;
|
|
195
|
+
}
|
|
196
|
+
if (line.isHorizontal) {
|
|
197
|
+
return this.isVertical;
|
|
198
|
+
}
|
|
199
|
+
const thisSlope = new Calculator_1.Calculator(this.slope);
|
|
200
|
+
const lineSlope = new Calculator_1.Calculator(line.slope);
|
|
201
|
+
return +thisSlope === +Calculator_1.Calculator.div(-1, lineSlope);
|
|
202
|
+
}
|
|
203
|
+
reflect(about) {
|
|
204
|
+
super.reflect(about);
|
|
205
|
+
this.recompute();
|
|
206
|
+
return this;
|
|
207
|
+
}
|
|
208
|
+
rotate(phi, about) {
|
|
209
|
+
super.rotate(phi, about);
|
|
210
|
+
this.recompute();
|
|
211
|
+
return this;
|
|
212
|
+
}
|
|
213
|
+
scale(factor, about) {
|
|
214
|
+
super.scale(factor, about);
|
|
215
|
+
this.recompute();
|
|
216
|
+
return this;
|
|
217
|
+
}
|
|
218
|
+
translate(vector) {
|
|
219
|
+
super.translate(vector);
|
|
220
|
+
this.recompute();
|
|
221
|
+
return this;
|
|
222
|
+
}
|
|
223
|
+
computeReciprocal() {
|
|
224
|
+
const { P0, P1 } = this;
|
|
225
|
+
const reciprocal = Calculator_1.Calculator.sub(P1.x, P0.x).div(Calculator_1.Calculator.sub(P1.y, P0.y));
|
|
226
|
+
if (reciprocal.isFinite()) {
|
|
227
|
+
return +reciprocal;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
computeSlope() {
|
|
231
|
+
const { P0, P1 } = this;
|
|
232
|
+
const slope = Calculator_1.Calculator.sub(P1.y, P0.y).div(Calculator_1.Calculator.sub(P1.x, P0.x));
|
|
233
|
+
if (slope.isFinite()) {
|
|
234
|
+
return +slope;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
computeXIntercept() {
|
|
238
|
+
const { P0, reciprocal, isHorizontal, isVertical } = this;
|
|
239
|
+
if (isVertical) {
|
|
240
|
+
return P0.x;
|
|
241
|
+
}
|
|
242
|
+
if (isHorizontal) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
return +Calculator_1.Calculator.sub(P0.x, Calculator_1.Calculator.mul(reciprocal, P0.y));
|
|
246
|
+
}
|
|
247
|
+
computeYIntercept() {
|
|
248
|
+
const { P0, slope, isVertical, isHorizontal } = this;
|
|
249
|
+
if (isVertical) {
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
if (isHorizontal) {
|
|
253
|
+
return P0.y;
|
|
254
|
+
}
|
|
255
|
+
return +Calculator_1.Calculator.sub(P0.y, Calculator_1.Calculator.mul(slope, P0.x));
|
|
256
|
+
}
|
|
257
|
+
recompute() {
|
|
258
|
+
this._slope = this.computeSlope();
|
|
259
|
+
this._yIntercept = this.computeYIntercept();
|
|
260
|
+
this._reciprocal = this.computeReciprocal();
|
|
261
|
+
this._xIntercept = this.computeXIntercept();
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
exports.Line = Line;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Polygon = void 0;
|
|
4
|
+
const Figure_1 = require("../abstracts/Figure");
|
|
5
|
+
class Polygon extends Figure_1.Figure {
|
|
6
|
+
constructor(values) {
|
|
7
|
+
super(values);
|
|
8
|
+
}
|
|
9
|
+
get sides() {
|
|
10
|
+
return this.points.length;
|
|
11
|
+
}
|
|
12
|
+
clone() {
|
|
13
|
+
const values = this.values.map((value) => value.clone());
|
|
14
|
+
return new Polygon(values);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.Polygon = Polygon;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.QuadraticBezierCurve = void 0;
|
|
4
|
+
const Calculator_1 = require("../utilities/Calculator");
|
|
5
|
+
const Point_1 = require("../abstracts/Point");
|
|
6
|
+
const Figure_1 = require("../abstracts/Figure");
|
|
7
|
+
class QuadraticBezierCurve extends Figure_1.Figure {
|
|
8
|
+
_criticalPoints;
|
|
9
|
+
constructor(values) {
|
|
10
|
+
super(values);
|
|
11
|
+
this._criticalPoints = this.computeCriticalPoints();
|
|
12
|
+
}
|
|
13
|
+
get boundingBox() {
|
|
14
|
+
const [P0, , P2] = this.values;
|
|
15
|
+
const points = [P0, P2, ...this._criticalPoints];
|
|
16
|
+
return Figure_1.Figure.computeBoundingBox(points);
|
|
17
|
+
}
|
|
18
|
+
get criticalPoints() {
|
|
19
|
+
return this._criticalPoints;
|
|
20
|
+
}
|
|
21
|
+
get P0() {
|
|
22
|
+
return this.points[0];
|
|
23
|
+
}
|
|
24
|
+
get P1() {
|
|
25
|
+
if (this.isRelative) {
|
|
26
|
+
return this.P0.clone().translate(this.vectors[0]);
|
|
27
|
+
}
|
|
28
|
+
return this.points[1];
|
|
29
|
+
}
|
|
30
|
+
get P2() {
|
|
31
|
+
if (this.isRelative) {
|
|
32
|
+
return this.P0.clone().translate(this.vectors[1]);
|
|
33
|
+
}
|
|
34
|
+
return this.points[2];
|
|
35
|
+
}
|
|
36
|
+
clone() {
|
|
37
|
+
const values = this.values.map((value) => value.clone());
|
|
38
|
+
return new QuadraticBezierCurve(values);
|
|
39
|
+
}
|
|
40
|
+
recompute() {
|
|
41
|
+
this._criticalPoints = this.computeCriticalPoints();
|
|
42
|
+
}
|
|
43
|
+
reflect(about) {
|
|
44
|
+
super.reflect(about);
|
|
45
|
+
this.recompute();
|
|
46
|
+
return this;
|
|
47
|
+
}
|
|
48
|
+
rotate(phi, about) {
|
|
49
|
+
super.rotate(phi, about);
|
|
50
|
+
this.recompute();
|
|
51
|
+
return this;
|
|
52
|
+
}
|
|
53
|
+
scale(factor, about) {
|
|
54
|
+
super.scale(factor, about);
|
|
55
|
+
this.recompute();
|
|
56
|
+
return this;
|
|
57
|
+
}
|
|
58
|
+
translate(vector) {
|
|
59
|
+
super.translate(vector);
|
|
60
|
+
this.recompute();
|
|
61
|
+
return this;
|
|
62
|
+
}
|
|
63
|
+
computeCriticalPoints() {
|
|
64
|
+
const t = this.getCriticalPointTValue();
|
|
65
|
+
if (typeof t === 'undefined') {
|
|
66
|
+
return [];
|
|
67
|
+
}
|
|
68
|
+
const point = this.getPointAtParameter(t);
|
|
69
|
+
if (!point) {
|
|
70
|
+
return [];
|
|
71
|
+
}
|
|
72
|
+
return [point];
|
|
73
|
+
}
|
|
74
|
+
getCoordinateAtParameter(t, axis) {
|
|
75
|
+
const { P0, P1, P2 } = this;
|
|
76
|
+
const coordinate = Calculator_1.Calculator.sub(1, t).pow(2).mul(P0[axis]).add(Calculator_1.Calculator.sub(1, t).mul(2).mul(t).mul(P1[axis])).add(t.pow(2).mul(P2[axis]));
|
|
77
|
+
if (coordinate.isFinite()) {
|
|
78
|
+
return coordinate;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
getCriticalPointTValue() {
|
|
82
|
+
const axii = ['x', 'y'];
|
|
83
|
+
const { P0, P1, P2 } = this;
|
|
84
|
+
let value;
|
|
85
|
+
for (let i = 0; i < axii.length; i++) {
|
|
86
|
+
const axis = axii[i];
|
|
87
|
+
const potentialValue = Calculator_1.Calculator.sub(P0[axis], P1[axis]).div(Calculator_1.Calculator.sub(P0[axis], Calculator_1.Calculator.mul(P1[axis], 2)).add(P2[axis]));
|
|
88
|
+
if (+potentialValue > 0 && +potentialValue < 1) {
|
|
89
|
+
value = potentialValue;
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return value;
|
|
94
|
+
}
|
|
95
|
+
getPointAtParameter(t) {
|
|
96
|
+
const x = this.getCoordinateAtParameter(t, 'x');
|
|
97
|
+
const y = this.getCoordinateAtParameter(t, 'y');
|
|
98
|
+
if (typeof x === 'undefined' || typeof y === 'undefined') {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
return new Point_1.Point([+x, +y]);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
exports.QuadraticBezierCurve = QuadraticBezierCurve;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.Calculator = exports.QuadraticBezierCurve = exports.Polygon = exports.Line = exports.Ellipse = exports.CubicBezierCurve = exports.Circle = exports.ArcCurve = exports.Vector = exports.Point = exports.Magnitude = exports.Flag = exports.Figure = exports.Angle = void 0;
|
|
18
|
+
/* v8 ignore */
|
|
19
|
+
var Angle_1 = require("./abstracts/Angle");
|
|
20
|
+
Object.defineProperty(exports, "Angle", { enumerable: true, get: function () { return Angle_1.Angle; } });
|
|
21
|
+
var Figure_1 = require("./abstracts/Figure");
|
|
22
|
+
Object.defineProperty(exports, "Figure", { enumerable: true, get: function () { return Figure_1.Figure; } });
|
|
23
|
+
var Flag_1 = require("./abstracts/Flag");
|
|
24
|
+
Object.defineProperty(exports, "Flag", { enumerable: true, get: function () { return Flag_1.Flag; } });
|
|
25
|
+
var Magnitude_1 = require("./abstracts/Magnitude");
|
|
26
|
+
Object.defineProperty(exports, "Magnitude", { enumerable: true, get: function () { return Magnitude_1.Magnitude; } });
|
|
27
|
+
var Point_1 = require("./abstracts/Point");
|
|
28
|
+
Object.defineProperty(exports, "Point", { enumerable: true, get: function () { return Point_1.Point; } });
|
|
29
|
+
var Vector_js_1 = require("./abstracts/Vector.js");
|
|
30
|
+
Object.defineProperty(exports, "Vector", { enumerable: true, get: function () { return Vector_js_1.Vector; } });
|
|
31
|
+
var ArcCurve_1 = require("./figures/ArcCurve");
|
|
32
|
+
Object.defineProperty(exports, "ArcCurve", { enumerable: true, get: function () { return ArcCurve_1.ArcCurve; } });
|
|
33
|
+
var Circle_1 = require("./figures/Circle");
|
|
34
|
+
Object.defineProperty(exports, "Circle", { enumerable: true, get: function () { return Circle_1.Circle; } });
|
|
35
|
+
var CubicBezierCurve_1 = require("./figures/CubicBezierCurve");
|
|
36
|
+
Object.defineProperty(exports, "CubicBezierCurve", { enumerable: true, get: function () { return CubicBezierCurve_1.CubicBezierCurve; } });
|
|
37
|
+
var Ellipse_1 = require("./figures/Ellipse");
|
|
38
|
+
Object.defineProperty(exports, "Ellipse", { enumerable: true, get: function () { return Ellipse_1.Ellipse; } });
|
|
39
|
+
var Line_1 = require("./figures/Line");
|
|
40
|
+
Object.defineProperty(exports, "Line", { enumerable: true, get: function () { return Line_1.Line; } });
|
|
41
|
+
var Polygon_1 = require("./figures/Polygon");
|
|
42
|
+
Object.defineProperty(exports, "Polygon", { enumerable: true, get: function () { return Polygon_1.Polygon; } });
|
|
43
|
+
var QuadraticBezierCurve_1 = require("./figures/QuadraticBezierCurve");
|
|
44
|
+
Object.defineProperty(exports, "QuadraticBezierCurve", { enumerable: true, get: function () { return QuadraticBezierCurve_1.QuadraticBezierCurve; } });
|
|
45
|
+
var Calculator_1 = require("./utilities/Calculator");
|
|
46
|
+
Object.defineProperty(exports, "Calculator", { enumerable: true, get: function () { return Calculator_1.Calculator; } });
|
|
47
|
+
__exportStar(require("./utilities"), exports);
|
|
48
|
+
__exportStar(require("./types"), exports);
|