geometric-library 1.3.0 → 1.4.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/README.md +49 -23
- package/dist/cjs/abstracts/{Angle.js → angle/Angle.js} +11 -11
- package/dist/cjs/abstracts/angle/Angle.types.js +2 -0
- package/dist/cjs/abstracts/angle/index.js +18 -0
- package/dist/cjs/abstracts/{Figure.js → figure/Figure.js} +45 -30
- package/dist/cjs/abstracts/figure/Figure.types.js +2 -0
- package/dist/cjs/abstracts/figure/index.js +18 -0
- package/dist/cjs/abstracts/{Flag.js → flag/Flag.js} +1 -0
- package/dist/cjs/abstracts/flag/Flag.types.js +2 -0
- package/dist/cjs/abstracts/flag/index.js +18 -0
- package/dist/cjs/abstracts/index.js +22 -0
- package/dist/cjs/abstracts/{Magnitude.js → magnitude/Magnitude.js} +6 -2
- package/dist/cjs/abstracts/magnitude/Magnitude.types.js +2 -0
- package/dist/cjs/abstracts/magnitude/index.js +18 -0
- package/dist/cjs/abstracts/{Point.js → point/Point.js} +8 -7
- package/dist/cjs/abstracts/point/Point.types.js +2 -0
- package/dist/cjs/abstracts/point/index.js +18 -0
- package/dist/cjs/abstracts/{Vector.js → vector/Vector.js} +16 -15
- package/dist/cjs/abstracts/vector/Vector.types.js +2 -0
- package/dist/cjs/abstracts/vector/index.js +18 -0
- package/dist/cjs/figures/arc-curve/ArcCurve.js +174 -0
- package/dist/cjs/figures/arc-curve/ArcCurve.types.js +2 -0
- package/dist/cjs/figures/arc-curve/index.js +18 -0
- package/dist/cjs/figures/{Circle.js → circle/Circle.js} +8 -9
- package/dist/cjs/figures/circle/Circle.types.js +2 -0
- package/dist/cjs/figures/circle/index.js +18 -0
- package/dist/cjs/figures/{CubicBezierCurve.js → cubic-bezier-curve/CubicBezierCurve.js} +22 -17
- package/dist/cjs/figures/cubic-bezier-curve/CubicBezierCurve.types.js +2 -0
- package/dist/cjs/figures/cubic-bezier-curve/index.js +18 -0
- package/dist/cjs/figures/ellipse/Ellipse.js +129 -0
- package/dist/cjs/figures/ellipse/Ellipse.types.js +2 -0
- package/dist/cjs/figures/ellipse/index.js +18 -0
- package/dist/cjs/figures/index.js +23 -0
- package/dist/cjs/figures/{Line.js → line/Line.js} +78 -59
- package/dist/cjs/figures/line/Line.types.js +2 -0
- package/dist/cjs/figures/line/index.js +18 -0
- package/dist/cjs/figures/polygon/Polygon.js +51 -0
- package/dist/cjs/figures/polygon/Polygon.types.js +2 -0
- package/dist/cjs/figures/polygon/index.js +18 -0
- package/dist/cjs/figures/{QuadraticBezierCurve.js → quadratic-bezier-curve/QuadraticBezierCurve.js} +12 -8
- package/dist/cjs/figures/quadratic-bezier-curve/QuadraticBezierCurve.types.js +2 -0
- package/dist/cjs/figures/quadratic-bezier-curve/index.js +18 -0
- package/dist/cjs/index.js +2 -29
- package/dist/cjs/utilities/{Calculator.js → calculator/Calculator.js} +9 -1
- package/dist/cjs/utilities/calculator/index.js +17 -0
- package/dist/cjs/utilities/index.js +20 -8
- package/dist/esm/abstracts/{Angle.js → angle/Angle.js} +4 -4
- package/dist/esm/abstracts/angle/Angle.types.js +1 -0
- package/dist/esm/abstracts/angle/index.js +2 -0
- package/dist/esm/abstracts/{Figure.js → figure/Figure.js} +37 -22
- package/dist/esm/abstracts/figure/Figure.types.js +1 -0
- package/dist/esm/abstracts/figure/index.js +2 -0
- package/dist/esm/abstracts/{Flag.js → flag/Flag.js} +1 -0
- package/dist/esm/abstracts/flag/Flag.types.js +1 -0
- package/dist/esm/abstracts/flag/index.js +2 -0
- package/dist/esm/abstracts/index.js +6 -0
- package/dist/esm/abstracts/{Magnitude.js → magnitude/Magnitude.js} +5 -1
- package/dist/esm/abstracts/magnitude/Magnitude.types.js +1 -0
- package/dist/esm/abstracts/magnitude/index.js +2 -0
- package/dist/esm/abstracts/{Point.js → point/Point.js} +2 -1
- package/dist/esm/abstracts/point/Point.types.js +1 -0
- package/dist/esm/abstracts/point/index.js +2 -0
- package/dist/esm/abstracts/{Vector.js → vector/Vector.js} +3 -2
- package/dist/esm/abstracts/vector/Vector.types.js +1 -0
- package/dist/esm/abstracts/vector/index.js +2 -0
- package/dist/esm/figures/{ArcCurve.js → arc-curve/ArcCurve.js} +50 -8
- package/dist/esm/figures/arc-curve/ArcCurve.types.js +1 -0
- package/dist/esm/figures/arc-curve/index.js +2 -0
- package/dist/esm/figures/{Circle.js → circle/Circle.js} +3 -4
- package/dist/esm/figures/circle/Circle.types.js +1 -0
- package/dist/esm/figures/circle/index.js +2 -0
- package/dist/esm/figures/{CubicBezierCurve.js → cubic-bezier-curve/CubicBezierCurve.js} +11 -6
- package/dist/esm/figures/cubic-bezier-curve/CubicBezierCurve.types.js +1 -0
- package/dist/esm/figures/cubic-bezier-curve/index.js +2 -0
- package/dist/esm/figures/{Ellipse.js → ellipse/Ellipse.js} +24 -6
- package/dist/esm/figures/ellipse/Ellipse.types.js +1 -0
- package/dist/esm/figures/ellipse/index.js +2 -0
- package/dist/esm/figures/index.js +7 -0
- package/dist/esm/figures/{Line.js → line/Line.js} +57 -38
- package/dist/esm/figures/line/Line.types.js +1 -0
- package/dist/esm/figures/line/index.js +2 -0
- package/dist/esm/figures/polygon/Polygon.js +47 -0
- package/dist/esm/figures/polygon/Polygon.types.js +1 -0
- package/dist/esm/figures/polygon/index.js +2 -0
- package/dist/esm/figures/{QuadraticBezierCurve.js → quadratic-bezier-curve/QuadraticBezierCurve.js} +7 -3
- package/dist/esm/figures/quadratic-bezier-curve/QuadraticBezierCurve.types.js +1 -0
- package/dist/esm/figures/quadratic-bezier-curve/index.js +2 -0
- package/dist/esm/index.js +2 -14
- package/dist/esm/utilities/{Calculator.js → calculator/Calculator.js} +9 -1
- package/dist/esm/utilities/calculator/index.js +1 -0
- package/dist/esm/utilities/index.js +4 -6
- package/dist/types/abstracts/{Angle.d.ts → angle/Angle.d.ts} +2 -1
- package/dist/types/abstracts/angle/Angle.types.d.ts +16 -0
- package/dist/types/abstracts/angle/index.d.ts +2 -0
- package/dist/types/abstracts/{Figure.d.ts → figure/Figure.d.ts} +4 -4
- package/dist/types/abstracts/figure/Figure.types.d.ts +14 -0
- package/dist/types/abstracts/figure/index.d.ts +2 -0
- package/dist/types/abstracts/{Flag.d.ts → flag/Flag.d.ts} +2 -1
- package/dist/types/abstracts/flag/Flag.types.d.ts +8 -0
- package/dist/types/abstracts/flag/index.d.ts +2 -0
- package/dist/types/abstracts/index.d.ts +6 -0
- package/dist/types/abstracts/{Magnitude.d.ts → magnitude/Magnitude.d.ts} +3 -1
- package/dist/types/abstracts/magnitude/Magnitude.types.d.ts +8 -0
- package/dist/types/abstracts/magnitude/index.d.ts +2 -0
- package/dist/types/abstracts/{Point.d.ts → point/Point.d.ts} +2 -1
- package/dist/types/abstracts/point/Point.types.d.ts +13 -0
- package/dist/types/abstracts/point/index.d.ts +2 -0
- package/dist/types/abstracts/{Vector.d.ts → vector/Vector.d.ts} +3 -1
- package/dist/types/abstracts/vector/Vector.types.d.ts +19 -0
- package/dist/types/abstracts/vector/index.d.ts +2 -0
- package/dist/types/figures/{ArcCurve.d.ts → arc-curve/ArcCurve.d.ts} +7 -2
- package/dist/types/figures/arc-curve/ArcCurve.types.d.ts +11 -0
- package/dist/types/figures/arc-curve/index.d.ts +2 -0
- package/dist/types/figures/{Circle.d.ts → circle/Circle.d.ts} +3 -2
- package/dist/types/figures/circle/Circle.types.d.ts +9 -0
- package/dist/types/figures/circle/index.d.ts +2 -0
- package/dist/types/figures/{CubicBezierCurve.d.ts → cubic-bezier-curve/CubicBezierCurve.d.ts} +4 -2
- package/dist/types/figures/cubic-bezier-curve/CubicBezierCurve.types.d.ts +8 -0
- package/dist/types/figures/cubic-bezier-curve/index.d.ts +2 -0
- package/dist/types/figures/{Ellipse.d.ts → ellipse/Ellipse.d.ts} +5 -2
- package/dist/types/figures/ellipse/Ellipse.types.d.ts +16 -0
- package/dist/types/figures/ellipse/index.d.ts +2 -0
- package/dist/types/figures/index.d.ts +7 -0
- package/dist/types/figures/{Line.d.ts → line/Line.d.ts} +6 -4
- package/dist/types/figures/line/Line.types.d.ts +30 -0
- package/dist/types/figures/line/index.d.ts +2 -0
- package/dist/types/figures/polygon/Polygon.d.ts +17 -0
- package/dist/types/figures/polygon/Polygon.types.d.ts +8 -0
- package/dist/types/figures/polygon/index.d.ts +2 -0
- package/dist/types/figures/{QuadraticBezierCurve.d.ts → quadratic-bezier-curve/QuadraticBezierCurve.d.ts} +4 -2
- package/dist/types/figures/quadratic-bezier-curve/QuadraticBezierCurve.types.d.ts +8 -0
- package/dist/types/figures/quadratic-bezier-curve/index.d.ts +2 -0
- package/dist/types/index.d.ts +2 -14
- package/dist/types/types/index.d.ts +0 -129
- package/dist/types/utilities/{Calculator.d.ts → calculator/Calculator.d.ts} +4 -0
- package/dist/types/utilities/calculator/index.d.ts +1 -0
- package/dist/types/utilities/index.d.ts +2 -4
- package/package.json +24 -18
- package/dist/cjs/figures/ArcCurve.js +0 -132
- package/dist/cjs/figures/Ellipse.js +0 -111
- package/dist/cjs/figures/Polygon.js +0 -17
- package/dist/esm/figures/Polygon.js +0 -13
- package/dist/types/figures/Polygon.d.ts +0 -7
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { Point } from './Point';
|
|
4
|
-
import { Vector } from './Vector';
|
|
1
|
+
import { Point, Vector } from '..';
|
|
2
|
+
import { Calculator } from '../../utilities/calculator';
|
|
5
3
|
export class Figure {
|
|
6
4
|
angles = [];
|
|
7
5
|
isRelative = false;
|
|
@@ -19,23 +17,22 @@ export class Figure {
|
|
|
19
17
|
get values() {
|
|
20
18
|
return this._values;
|
|
21
19
|
}
|
|
22
|
-
/**
|
|
23
|
-
* @todo Figure out a better way to type narrow than iterating again.
|
|
24
|
-
*/
|
|
25
20
|
set values(values) {
|
|
26
21
|
this._values = values;
|
|
27
22
|
const [points, vectors, magnitudes, angles] = values.reduce((result, value) => {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
23
|
+
switch (value.kind) {
|
|
24
|
+
case 'point':
|
|
25
|
+
result[0].push(value);
|
|
26
|
+
break;
|
|
27
|
+
case 'vector':
|
|
28
|
+
result[1].push(value);
|
|
29
|
+
break;
|
|
30
|
+
case 'magnitude':
|
|
31
|
+
result[2].push(value);
|
|
32
|
+
break;
|
|
33
|
+
case 'angle':
|
|
34
|
+
result[3].push(value);
|
|
35
|
+
break;
|
|
39
36
|
}
|
|
40
37
|
return result;
|
|
41
38
|
}, [[], [], [], []]);
|
|
@@ -74,10 +71,13 @@ export class Figure {
|
|
|
74
71
|
point.reflect(perpendicularRoot);
|
|
75
72
|
});
|
|
76
73
|
vectors.forEach((vector) => {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
74
|
+
const referenceProjection = about.getPerpendicularProjection(points[0]);
|
|
75
|
+
const referencePoint = points[0].clone().reflect(referenceProjection);
|
|
76
|
+
const endPoint = points[0].clone().translate(vector);
|
|
77
|
+
const endProjection = about.getPerpendicularProjection(endPoint);
|
|
78
|
+
const positionalPoint = endPoint.reflect(endProjection);
|
|
79
|
+
const reflectedVector = new Vector([referencePoint, positionalPoint]);
|
|
80
|
+
vector.replace(reflectedVector);
|
|
81
81
|
});
|
|
82
82
|
return this;
|
|
83
83
|
}
|
|
@@ -130,6 +130,21 @@ export class Figure {
|
|
|
130
130
|
});
|
|
131
131
|
return this;
|
|
132
132
|
}
|
|
133
|
+
scaleXY(factorX, factorY, about = new Point([0, 0])) {
|
|
134
|
+
const { points, vectors } = this;
|
|
135
|
+
if (!points) {
|
|
136
|
+
throw new Error(Figure.getNoPointsErrorMessage('scaleXY'));
|
|
137
|
+
}
|
|
138
|
+
points.forEach((point) => {
|
|
139
|
+
const scaledX = +Calculator.add(about.x, Calculator.sub(point.x, about.x).mul(factorX));
|
|
140
|
+
const scaledY = +Calculator.add(about.y, Calculator.sub(point.y, about.y).mul(factorY));
|
|
141
|
+
point.replace(new Point([scaledX, scaledY]));
|
|
142
|
+
});
|
|
143
|
+
vectors.forEach((vector) => {
|
|
144
|
+
vector.replace(new Vector([+Calculator.mul(vector.dx, factorX), +Calculator.mul(vector.dy, factorY)]));
|
|
145
|
+
});
|
|
146
|
+
return this;
|
|
147
|
+
}
|
|
133
148
|
translate(vector) {
|
|
134
149
|
const { points } = this;
|
|
135
150
|
if (!points) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import { Calculator } from '
|
|
1
|
+
import { Calculator } from '../../utilities/calculator';
|
|
2
2
|
export class Magnitude {
|
|
3
|
+
kind = 'magnitude';
|
|
3
4
|
_value;
|
|
4
5
|
constructor(value) {
|
|
5
6
|
this._value = value;
|
|
6
7
|
}
|
|
8
|
+
get value() {
|
|
9
|
+
return this._value;
|
|
10
|
+
}
|
|
7
11
|
clone() {
|
|
8
12
|
return new Magnitude(+this);
|
|
9
13
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { Angle, Figure, Point } from '../../abstracts';
|
|
2
|
+
import { CubicBezierCurve } from '../cubic-bezier-curve/CubicBezierCurve';
|
|
3
|
+
import { Ellipse } from '../ellipse/Ellipse';
|
|
4
|
+
import { Calculator } from '../../utilities/calculator';
|
|
5
5
|
export class ArcCurve extends Figure {
|
|
6
6
|
ellipse;
|
|
7
7
|
largeArcFlag;
|
|
@@ -34,7 +34,7 @@ export class ArcCurve extends Figure {
|
|
|
34
34
|
const [minTheta, maxTheta] = this.computeThetaRange();
|
|
35
35
|
return ellipse.criticalPoints.filter((point) => {
|
|
36
36
|
const { P0, P1 } = this;
|
|
37
|
-
if ((point.x
|
|
37
|
+
if ((Calculator.isEqual(point.x, P0.x) && Calculator.isEqual(point.y, P0.y)) || (Calculator.isEqual(point.x, P1.x) && Calculator.isEqual(point.y, P1.y))) {
|
|
38
38
|
return false;
|
|
39
39
|
}
|
|
40
40
|
const theta = ellipse.computeThetaForPoint(point);
|
|
@@ -51,7 +51,7 @@ export class ArcCurve extends Figure {
|
|
|
51
51
|
return this.points[1];
|
|
52
52
|
}
|
|
53
53
|
clone() {
|
|
54
|
-
const values = this.values.map((value) => (typeof value === 'object' && 'clone' in value ? value.clone() : value));
|
|
54
|
+
const values = this.values.map((value) => (typeof value === 'object' && 'clone' in value ? value.clone() : /* v8 ignore next */ value));
|
|
55
55
|
return new ArcCurve(values);
|
|
56
56
|
}
|
|
57
57
|
reflect(about) {
|
|
@@ -59,6 +59,30 @@ export class ArcCurve extends Figure {
|
|
|
59
59
|
this.sweepFlag.invert();
|
|
60
60
|
return this;
|
|
61
61
|
}
|
|
62
|
+
toCubicBezierCurves() {
|
|
63
|
+
const [minTheta, maxTheta] = this.computeThetaRange();
|
|
64
|
+
const p0Theta = this.ellipse.computeThetaForPoint(this.P0);
|
|
65
|
+
const p0IsMin = Calculator.isEqual(+p0Theta.radians, +minTheta.radians);
|
|
66
|
+
const span = +Calculator.sub(maxTheta.radians, minTheta.radians);
|
|
67
|
+
const halfPi = Math.PI / 2;
|
|
68
|
+
const numSegments = Math.max(1, Math.ceil(span / halfPi));
|
|
69
|
+
const segmentAngle = span / numSegments;
|
|
70
|
+
const curves = [];
|
|
71
|
+
for (let i = 0; i < numSegments; i++) {
|
|
72
|
+
let t1Rad;
|
|
73
|
+
let t2Rad;
|
|
74
|
+
if (p0IsMin) {
|
|
75
|
+
t1Rad = +Calculator.add(minTheta.radians, Calculator.mul(segmentAngle, i));
|
|
76
|
+
t2Rad = +Calculator.add(minTheta.radians, Calculator.mul(segmentAngle, i + 1));
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
t1Rad = +Calculator.sub(maxTheta.radians, Calculator.mul(segmentAngle, i));
|
|
80
|
+
t2Rad = +Calculator.sub(maxTheta.radians, Calculator.mul(segmentAngle, i + 1));
|
|
81
|
+
}
|
|
82
|
+
curves.push(this.computeBezierSegment(new Angle(t1Rad, 'radians'), new Angle(t2Rad, 'radians')));
|
|
83
|
+
}
|
|
84
|
+
return curves;
|
|
85
|
+
}
|
|
62
86
|
adjustRadii() {
|
|
63
87
|
const { rx, ry } = this;
|
|
64
88
|
const P0_prime = this.computeP0Prime();
|
|
@@ -73,6 +97,18 @@ export class ArcCurve extends Figure {
|
|
|
73
97
|
ry.replace(+Calculator.mul(+ry, radii_check.sqrt()));
|
|
74
98
|
}
|
|
75
99
|
}
|
|
100
|
+
computeBezierSegment(theta1, theta2) {
|
|
101
|
+
const { ellipse } = this;
|
|
102
|
+
const alpha = +Calculator.sub(theta2.radians, theta1.radians);
|
|
103
|
+
const k = +Calculator.mul(4, Calculator.tan(Calculator.div(alpha, 4))).div(3);
|
|
104
|
+
const p0 = ellipse.computePointForTheta(theta1);
|
|
105
|
+
const p3 = ellipse.computePointForTheta(theta2);
|
|
106
|
+
const [t1x, t1y] = this.computeTangentForTheta(theta1);
|
|
107
|
+
const [t2x, t2y] = this.computeTangentForTheta(theta2);
|
|
108
|
+
const p1 = new Point([+Calculator.add(p0.x, Calculator.mul(k, t1x)), +Calculator.add(p0.y, Calculator.mul(k, t1y))]);
|
|
109
|
+
const p2 = new Point([+Calculator.sub(p3.x, Calculator.mul(k, t2x)), +Calculator.sub(p3.y, Calculator.mul(k, t2y))]);
|
|
110
|
+
return new CubicBezierCurve([p0, p1, p2, p3]);
|
|
111
|
+
}
|
|
76
112
|
computeCenter() {
|
|
77
113
|
const { P0, P1, phi } = this;
|
|
78
114
|
const center_prime = this.computeCenterPrime();
|
|
@@ -99,7 +135,7 @@ export class ArcCurve extends Figure {
|
|
|
99
135
|
.sub(rx_sq.mul(y1_prime_sq))
|
|
100
136
|
.sub(ry_sq.mul(x1_prime_sq))
|
|
101
137
|
.div(rx_sq.mul(y1_prime_sq).add(ry_sq.mul(x1_prime_sq)));
|
|
102
|
-
sq = +sq < 0 ? new Calculator(0) : sq;
|
|
138
|
+
sq = +sq < 0 ? /* v8 ignore next */ new Calculator(0) : sq;
|
|
103
139
|
const coef = sign.mul(sq.sqrt());
|
|
104
140
|
const cx_prime = coef.mul(Calculator.mul(+rx, y1_prime).div(+ry));
|
|
105
141
|
const cy_prime = coef.mul(Calculator.mul(+ry, x1_prime).div(+rx).neg());
|
|
@@ -115,11 +151,17 @@ export class ArcCurve extends Figure {
|
|
|
115
151
|
const y1_prime = Calculator.mul(phi.sin, mx).neg().add(Calculator.mul(phi.cos, my));
|
|
116
152
|
return new Point([+x1_prime, +y1_prime]);
|
|
117
153
|
}
|
|
154
|
+
computeTangentForTheta(theta) {
|
|
155
|
+
const { phi, rx, ry } = this.ellipse;
|
|
156
|
+
const tx = +Calculator.neg(Calculator.mul(+rx, theta.sin).mul(phi.cos)).sub(Calculator.mul(+ry, theta.cos).mul(phi.sin));
|
|
157
|
+
const ty = +Calculator.neg(Calculator.mul(+rx, theta.sin).mul(phi.sin)).add(Calculator.mul(+ry, theta.cos).mul(phi.cos));
|
|
158
|
+
return [tx, ty];
|
|
159
|
+
}
|
|
118
160
|
computeThetaRange() {
|
|
119
161
|
const { P0, P1, ellipse, sweepFlag } = this;
|
|
120
162
|
const theta1 = ellipse.computeThetaForPoint(P0);
|
|
121
163
|
const theta2 = ellipse.computeThetaForPoint(P1);
|
|
122
|
-
if (+theta2
|
|
164
|
+
if (Calculator.isNearZero(+theta2) && !sweepFlag.value) {
|
|
123
165
|
theta2.replace(360, 'degrees');
|
|
124
166
|
}
|
|
125
167
|
const thetaRange = [theta1, theta2].sort((a, b) => +Calculator.sub(a.radians, b.radians));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Ellipse } from '
|
|
3
|
-
import {
|
|
4
|
-
import { Angle } from '../abstracts/Angle';
|
|
1
|
+
import { Angle, Point } from '../../abstracts';
|
|
2
|
+
import { Ellipse } from '../ellipse/Ellipse';
|
|
3
|
+
import { Calculator } from '../../utilities/calculator';
|
|
5
4
|
export class Circle extends Ellipse {
|
|
6
5
|
_radius;
|
|
7
6
|
constructor(values) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { Figure } from '../abstracts/Figure';
|
|
1
|
+
import { Figure, Point } from '../../abstracts';
|
|
2
|
+
import { Calculator } from '../../utilities/calculator';
|
|
4
3
|
export class CubicBezierCurve extends Figure {
|
|
5
4
|
_criticalPoints;
|
|
6
5
|
constructor(values) {
|
|
@@ -58,6 +57,11 @@ export class CubicBezierCurve extends Figure {
|
|
|
58
57
|
this.recompute();
|
|
59
58
|
return this;
|
|
60
59
|
}
|
|
60
|
+
scaleXY(factorX, factorY, about) {
|
|
61
|
+
super.scaleXY(factorX, factorY, about);
|
|
62
|
+
this.recompute();
|
|
63
|
+
return this;
|
|
64
|
+
}
|
|
61
65
|
translate(vector) {
|
|
62
66
|
super.translate(vector);
|
|
63
67
|
this.recompute();
|
|
@@ -70,7 +74,8 @@ export class CubicBezierCurve extends Figure {
|
|
|
70
74
|
}
|
|
71
75
|
const criticalPoints = tValues.reduce((criticalPoints, t) => {
|
|
72
76
|
const criticalPoint = this.getPointAtParameter(t);
|
|
73
|
-
|
|
77
|
+
if (criticalPoint)
|
|
78
|
+
criticalPoints.push(criticalPoint);
|
|
74
79
|
return criticalPoints;
|
|
75
80
|
}, []);
|
|
76
81
|
return criticalPoints;
|
|
@@ -92,7 +97,7 @@ export class CubicBezierCurve extends Figure {
|
|
|
92
97
|
for (let n = 0; n < signs.length; n++) {
|
|
93
98
|
const sign = signs[n];
|
|
94
99
|
let tValue;
|
|
95
|
-
if (+a
|
|
100
|
+
if (Calculator.isNearZero(+a)) {
|
|
96
101
|
// 1st degree equation to avoid n/0
|
|
97
102
|
tValue = c.neg().div(b);
|
|
98
103
|
}
|
|
@@ -111,7 +116,7 @@ export class CubicBezierCurve extends Figure {
|
|
|
111
116
|
if (!tValues.length) {
|
|
112
117
|
return;
|
|
113
118
|
}
|
|
114
|
-
return tValues.filter((value, index, array) => index === array.findIndex((v) => +value
|
|
119
|
+
return tValues.filter((value, index, array) => index === array.findIndex((v) => Calculator.isEqual(+value, +v)));
|
|
115
120
|
}
|
|
116
121
|
getCoordinateAtParameter(t, axis) {
|
|
117
122
|
const { P0, P1, P2, P3 } = this;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,8 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
1
|
+
import { Angle, Figure, Point, Vector } from '../../abstracts';
|
|
2
|
+
import { CubicBezierCurve } from '../cubic-bezier-curve/CubicBezierCurve';
|
|
3
|
+
import { Calculator } from '../../utilities/calculator';
|
|
4
|
+
import { Line } from '../line/Line';
|
|
5
|
+
const KAPPA = 0.5522847498307936;
|
|
6
|
+
const xAxis = new Line([new Point([0, 0]), new Point([1, 0])]);
|
|
7
|
+
const unitCircleCubicBezierCurves = [
|
|
8
|
+
new CubicBezierCurve([new Point([1, 0]), new Point([1, KAPPA]), new Point([KAPPA, 1]), new Point([0, 1])]),
|
|
9
|
+
new CubicBezierCurve([new Point([0, 1]), new Point([-KAPPA, 1]), new Point([-1, KAPPA]), new Point([-1, 0])]),
|
|
10
|
+
new CubicBezierCurve([new Point([-1, 0]), new Point([-1, -KAPPA]), new Point([-KAPPA, -1]), new Point([0, -1])]),
|
|
11
|
+
new CubicBezierCurve([new Point([0, -1]), new Point([KAPPA, -1]), new Point([1, -KAPPA]), new Point([1, 0])])
|
|
12
|
+
];
|
|
6
13
|
export class Ellipse extends Figure {
|
|
7
14
|
_center;
|
|
8
15
|
_criticalPoints;
|
|
@@ -28,7 +35,7 @@ export class Ellipse extends Figure {
|
|
|
28
35
|
return this._criticalPoints;
|
|
29
36
|
}
|
|
30
37
|
get isCircle() {
|
|
31
|
-
return +this.rx
|
|
38
|
+
return Calculator.isEqual(+this.rx, +this.ry);
|
|
32
39
|
}
|
|
33
40
|
get phi() {
|
|
34
41
|
return this._phi;
|
|
@@ -83,6 +90,17 @@ export class Ellipse extends Figure {
|
|
|
83
90
|
this.recompute();
|
|
84
91
|
return this;
|
|
85
92
|
}
|
|
93
|
+
toCubicBezierCurves() {
|
|
94
|
+
const { rx, ry, phi, center } = this;
|
|
95
|
+
const curves = unitCircleCubicBezierCurves.map((curve) => {
|
|
96
|
+
return curve
|
|
97
|
+
.clone()
|
|
98
|
+
.scaleXY(+rx, +ry)
|
|
99
|
+
.rotate(phi)
|
|
100
|
+
.translate(new Vector([center.x, center.y]));
|
|
101
|
+
});
|
|
102
|
+
return curves;
|
|
103
|
+
}
|
|
86
104
|
translate(vector) {
|
|
87
105
|
this._center.translate(vector);
|
|
88
106
|
this.recompute();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { Point } from '../abstracts/Point';
|
|
4
|
-
import { Vector } from '../abstracts/Vector';
|
|
5
|
-
import { Figure } from '../abstracts/Figure';
|
|
1
|
+
import { Angle, Figure, Point, Vector } from '../../abstracts';
|
|
2
|
+
import { Calculator } from '../../utilities/calculator';
|
|
6
3
|
export class Line extends Figure {
|
|
7
4
|
_P0;
|
|
8
5
|
_P1;
|
|
9
6
|
_V;
|
|
7
|
+
_dirty = true;
|
|
10
8
|
_reciprocal;
|
|
11
9
|
_slope;
|
|
12
10
|
_xIntercept;
|
|
@@ -24,10 +22,6 @@ export class Line extends Figure {
|
|
|
24
22
|
this._P1 = anchor;
|
|
25
23
|
}
|
|
26
24
|
this._P0 = P0;
|
|
27
|
-
this._slope = this.computeSlope();
|
|
28
|
-
this._yIntercept = this.computeYIntercept();
|
|
29
|
-
this._reciprocal = this.computeReciprocal();
|
|
30
|
-
this._xIntercept = this.computeXIntercept();
|
|
31
25
|
this.points = [this.P0, this.P1];
|
|
32
26
|
this.vectors = [this.V];
|
|
33
27
|
}
|
|
@@ -80,33 +74,41 @@ export class Line extends Figure {
|
|
|
80
74
|
return typeof slope === 'undefined';
|
|
81
75
|
}
|
|
82
76
|
get reciprocal() {
|
|
77
|
+
this.ensureComputed();
|
|
83
78
|
return this._reciprocal;
|
|
84
79
|
}
|
|
85
80
|
get slope() {
|
|
81
|
+
this.ensureComputed();
|
|
86
82
|
return this._slope;
|
|
87
83
|
}
|
|
88
84
|
get xIntercept() {
|
|
85
|
+
this.ensureComputed();
|
|
89
86
|
return this._xIntercept;
|
|
90
87
|
}
|
|
91
88
|
get yIntercept() {
|
|
89
|
+
this.ensureComputed();
|
|
92
90
|
return this._yIntercept;
|
|
93
91
|
}
|
|
94
|
-
angleTo(
|
|
95
|
-
if (
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
92
|
+
angleTo(reference) {
|
|
93
|
+
if ('slope' in reference) {
|
|
94
|
+
const line = reference;
|
|
95
|
+
if (this.isParallelTo(line)) {
|
|
96
|
+
return new Angle(0, 'radians');
|
|
97
|
+
}
|
|
98
|
+
if (this.isPerpendicularTo(line)) {
|
|
99
|
+
return new Angle(+Calculator.div(Math.PI, 2), 'radians');
|
|
100
|
+
}
|
|
101
|
+
if (typeof this.slope === 'undefined') {
|
|
102
|
+
return new Angle(+Calculator.atan(line.slope), 'radians');
|
|
103
|
+
}
|
|
104
|
+
if (typeof line.slope === 'undefined') {
|
|
105
|
+
return new Angle(+Calculator.atan(this.slope), 'radians');
|
|
106
|
+
}
|
|
107
|
+
const thisSlope = new Calculator(this.slope);
|
|
108
|
+
const lineSlope = new Calculator(line.slope);
|
|
109
|
+
return new Angle(+lineSlope.sub(thisSlope).div(thisSlope.mul(lineSlope).add(1)).abs().atan(), 'radians');
|
|
110
|
+
}
|
|
111
|
+
return this.V.angleTo(reference);
|
|
110
112
|
}
|
|
111
113
|
clone() {
|
|
112
114
|
const values = this.values.map((value) => value.clone());
|
|
@@ -134,9 +136,11 @@ export class Line extends Figure {
|
|
|
134
136
|
perpendicularProjection = new Point([point.x, P0.y]);
|
|
135
137
|
}
|
|
136
138
|
else {
|
|
137
|
-
const
|
|
138
|
-
const
|
|
139
|
-
|
|
139
|
+
const perpendicularSlope = +Calculator.div(-1, slope);
|
|
140
|
+
const perpendicularYIntercept = +Calculator.sub(point.y, Calculator.mul(perpendicularSlope, point.x));
|
|
141
|
+
const x = +Calculator.sub(perpendicularYIntercept, this.yIntercept).div(Calculator.sub(slope, perpendicularSlope));
|
|
142
|
+
const y = +Calculator.mul(slope, x).add(this.yIntercept);
|
|
143
|
+
perpendicularProjection = new Point([x, y]);
|
|
140
144
|
}
|
|
141
145
|
return perpendicularProjection;
|
|
142
146
|
}
|
|
@@ -174,11 +178,17 @@ export class Line extends Figure {
|
|
|
174
178
|
return +Calculator.mul(slope, x).add(yIntercept);
|
|
175
179
|
}
|
|
176
180
|
hasPoint(P) {
|
|
181
|
+
if (this.isVertical) {
|
|
182
|
+
return Calculator.isEqual(P.x, this.P0.x);
|
|
183
|
+
}
|
|
177
184
|
const potentialY = this.getYValueAtX(P.x);
|
|
178
|
-
return typeof potentialY === 'number' && potentialY
|
|
185
|
+
return typeof potentialY === 'number' && Calculator.isEqual(potentialY, P.y);
|
|
179
186
|
}
|
|
180
187
|
isParallelTo(line) {
|
|
181
|
-
|
|
188
|
+
if (typeof this.slope === 'undefined' || typeof line.slope === 'undefined') {
|
|
189
|
+
return typeof this.slope === typeof line.slope;
|
|
190
|
+
}
|
|
191
|
+
return Calculator.isEqual(this.slope, line.slope);
|
|
182
192
|
}
|
|
183
193
|
isPerpendicularTo(line) {
|
|
184
194
|
if (this.isVertical) {
|
|
@@ -187,34 +197,39 @@ export class Line extends Figure {
|
|
|
187
197
|
if (this.isHorizontal) {
|
|
188
198
|
return line.isVertical;
|
|
189
199
|
}
|
|
200
|
+
/* v8 ignore next 3 */
|
|
190
201
|
if (line.isVertical) {
|
|
191
202
|
return this.isHorizontal;
|
|
192
203
|
}
|
|
204
|
+
/* v8 ignore next 3 */
|
|
193
205
|
if (line.isHorizontal) {
|
|
194
206
|
return this.isVertical;
|
|
195
207
|
}
|
|
196
|
-
|
|
197
|
-
const lineSlope = new Calculator(line.slope);
|
|
198
|
-
return +thisSlope === +Calculator.div(-1, lineSlope);
|
|
208
|
+
return Calculator.isEqual(this.slope, +Calculator.div(-1, line.slope));
|
|
199
209
|
}
|
|
200
210
|
reflect(about) {
|
|
201
211
|
super.reflect(about);
|
|
202
|
-
this.
|
|
212
|
+
this._dirty = true;
|
|
203
213
|
return this;
|
|
204
214
|
}
|
|
205
215
|
rotate(phi, about) {
|
|
206
216
|
super.rotate(phi, about);
|
|
207
|
-
this.
|
|
217
|
+
this._dirty = true;
|
|
208
218
|
return this;
|
|
209
219
|
}
|
|
210
220
|
scale(factor, about) {
|
|
211
221
|
super.scale(factor, about);
|
|
212
|
-
this.
|
|
222
|
+
this._dirty = true;
|
|
223
|
+
return this;
|
|
224
|
+
}
|
|
225
|
+
scaleXY(factorX, factorY, about) {
|
|
226
|
+
super.scaleXY(factorX, factorY, about);
|
|
227
|
+
this._dirty = true;
|
|
213
228
|
return this;
|
|
214
229
|
}
|
|
215
230
|
translate(vector) {
|
|
216
231
|
super.translate(vector);
|
|
217
|
-
this.
|
|
232
|
+
this._dirty = true;
|
|
218
233
|
return this;
|
|
219
234
|
}
|
|
220
235
|
computeReciprocal() {
|
|
@@ -251,7 +266,11 @@ export class Line extends Figure {
|
|
|
251
266
|
}
|
|
252
267
|
return +Calculator.sub(P0.y, Calculator.mul(slope, P0.x));
|
|
253
268
|
}
|
|
254
|
-
|
|
269
|
+
ensureComputed() {
|
|
270
|
+
if (!this._dirty) {
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
this._dirty = false;
|
|
255
274
|
this._slope = this.computeSlope();
|
|
256
275
|
this._yIntercept = this.computeYIntercept();
|
|
257
276
|
this._reciprocal = this.computeReciprocal();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|