pimath 0.0.120 → 0.0.121
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/.eslintrc.js +23 -23
- package/.idea/PI.iml +7 -1
- package/dev/pimath.js +7929 -0
- package/dev/pimath.js.map +1 -0
- package/dist/{pi.js → pimath.js} +7612 -7840
- package/dist/pimath.js.map +1 -0
- package/dist/pimath.min.js +2 -0
- package/dist/pimath.min.js.map +1 -0
- package/docs/assets/main.js +3 -3
- package/docs/assets/search.js +1 -1
- package/docs/assets/style.css +450 -363
- package/docs/classes/Logicalset.Logicalset.html +119 -110
- package/docs/classes/Polynom.Rational.html +230 -227
- package/docs/classes/Vector-1.Vector.html +319 -273
- package/docs/classes/Vector.Point.html +189 -190
- package/docs/classes/algebra_equation.Equation.html +489 -446
- package/docs/classes/algebra_linearSystem.LinearSystem.html +228 -217
- package/docs/classes/algebra_monom.Monom.html +564 -507
- package/docs/classes/algebra_polynom.Polynom.html +774 -753
- package/docs/classes/coefficients_fraction.Fraction.html +573 -565
- package/docs/classes/geometry_circle.Circle.html +299 -299
- package/docs/classes/geometry_line.Line.html +511 -451
- package/docs/classes/geometry_triangle.Triangle.html +273 -264
- package/docs/classes/numeric.Numeric.html +138 -132
- package/docs/classes/shutingyard.Shutingyard.html +144 -133
- package/docs/enums/algebra_equation.PARTICULAR_SOLUTION.html +47 -46
- package/docs/enums/geometry_line.LinePropriety.html +58 -58
- package/docs/enums/shutingyard.ShutingyardMode.html +62 -58
- package/docs/enums/shutingyard.ShutingyardType.html +74 -70
- package/docs/index.html +31 -33
- package/docs/interfaces/algebra_equation.ISolution.html +61 -59
- package/docs/interfaces/algebra_polynom.IEuclidian.html +47 -46
- package/docs/interfaces/geometry_triangle.remarquableLines.html +74 -74
- package/docs/modules/Logicalset.html +33 -38
- package/docs/modules/Polynom.html +33 -38
- package/docs/modules/Vector-1.html +33 -38
- package/docs/modules/Vector.html +33 -38
- package/docs/modules/algebra_equation.html +35 -41
- package/docs/modules/algebra_linearSystem.html +31 -37
- package/docs/modules/algebra_monom.html +33 -39
- package/docs/modules/algebra_polynom.html +35 -41
- package/docs/modules/coefficients_fraction.html +33 -39
- package/docs/modules/geometry_circle.html +31 -37
- package/docs/modules/geometry_line.html +33 -39
- package/docs/modules/geometry_triangle.html +33 -39
- package/docs/modules/numeric.html +31 -37
- package/docs/modules/shutingyard.html +41 -47
- package/docs/types/algebra_monom.literalType.html +33 -37
- package/docs/types/algebra_polynom.PolynomParsingType.html +33 -37
- package/docs/types/coefficients_fraction.FractionParsingType.html +32 -36
- package/docs/types/shutingyard.Token.html +38 -42
- package/docs/types/shutingyard.tokenType.html +40 -44
- package/docs/variables/shutingyard.tokenConstant.html +37 -41
- package/esm/index.d.ts +38 -41
- package/esm/index.js +43 -46
- package/esm/index.js.map +1 -1
- package/esm/maths/algebra/equation.d.ts +119 -117
- package/esm/maths/algebra/equation.js +796 -785
- package/esm/maths/algebra/equation.js.map +1 -1
- package/esm/maths/algebra/linearSystem.d.ts +39 -38
- package/esm/maths/algebra/linearSystem.js +278 -262
- package/esm/maths/algebra/linearSystem.js.map +1 -1
- package/esm/maths/algebra/logicalset.d.ts +28 -28
- package/esm/maths/algebra/logicalset.js +157 -157
- package/esm/maths/algebra/monom.d.ts +206 -206
- package/esm/maths/algebra/monom.js +908 -908
- package/esm/maths/algebra/monom.js.map +1 -1
- package/esm/maths/algebra/polynom.d.ts +157 -157
- package/esm/maths/algebra/polynom.js +1277 -1277
- package/esm/maths/algebra/rational.d.ts +45 -45
- package/esm/maths/algebra/rational.js +183 -183
- package/esm/maths/algebra/study/rationalStudy.d.ts +28 -28
- package/esm/maths/algebra/study/rationalStudy.js +243 -243
- package/esm/maths/algebra/study.d.ts +142 -142
- package/esm/maths/algebra/study.js +377 -377
- package/esm/maths/algebra/study.js.map +1 -1
- package/esm/maths/coefficients/fraction.d.ts +90 -90
- package/esm/maths/coefficients/fraction.js +516 -516
- package/esm/maths/coefficients/fraction.js.map +1 -1
- package/esm/maths/coefficients/nthRoot.d.ts +23 -23
- package/esm/maths/coefficients/nthRoot.js +136 -136
- package/esm/maths/geometry/circle.d.ts +45 -45
- package/esm/maths/geometry/circle.js +323 -323
- package/esm/maths/geometry/line.d.ts +99 -99
- package/esm/maths/geometry/line.js +481 -481
- package/esm/maths/geometry/line.js.map +1 -1
- package/esm/maths/geometry/point.d.ts +34 -34
- package/esm/maths/geometry/point.js +166 -166
- package/esm/maths/geometry/point.js.map +1 -1
- package/esm/maths/geometry/triangle.d.ts +85 -85
- package/esm/maths/geometry/triangle.js +268 -268
- package/esm/maths/geometry/vector.d.ts +41 -41
- package/esm/maths/geometry/vector.js +197 -197
- package/esm/maths/geometry/vector.js.map +1 -1
- package/esm/maths/numeric.d.ts +28 -28
- package/esm/maths/numeric.js +180 -180
- package/esm/maths/numexp.d.ts +19 -0
- package/esm/maths/numexp.js +186 -0
- package/esm/maths/numexp.js.map +1 -0
- package/esm/maths/randomization/random.d.ts +23 -23
- package/esm/maths/randomization/random.js +78 -78
- package/esm/maths/randomization/random.js.map +1 -1
- package/esm/maths/randomization/randomCore.d.ts +7 -7
- package/esm/maths/randomization/randomCore.js +21 -21
- package/esm/maths/randomization/rndFraction.d.ts +12 -12
- package/esm/maths/randomization/rndFraction.js +43 -43
- package/esm/maths/randomization/rndGeometryLine.d.ts +12 -12
- package/esm/maths/randomization/rndGeometryLine.js +45 -45
- package/esm/maths/randomization/rndGeometryPoint.d.ts +12 -12
- package/esm/maths/randomization/rndGeometryPoint.js +60 -60
- package/esm/maths/randomization/rndHelpers.d.ts +23 -23
- package/esm/maths/randomization/rndHelpers.js +76 -76
- package/esm/maths/randomization/rndMonom.d.ts +12 -12
- package/esm/maths/randomization/rndMonom.js +52 -52
- package/esm/maths/randomization/rndPolynom.d.ts +13 -13
- package/esm/maths/randomization/rndPolynom.js +74 -74
- package/esm/maths/randomization/rndTypes.d.ts +34 -34
- package/esm/maths/randomization/rndTypes.js +2 -2
- package/esm/maths/shutingyard.d.ts +59 -59
- package/esm/maths/shutingyard.js +442 -442
- package/esm/maths/shutingyard.js.map +1 -1
- package/package.json +11 -11
- package/public/index.html +50 -81
- package/public/playground.html +7 -8
- package/src/index.ts +2 -5
- package/src/maths/algebra/equation.ts +16 -0
- package/src/maths/algebra/linearSystem.ts +20 -0
- package/src/maths/algebra/study.ts +1 -1
- package/src/maths/{expressions/numexp.ts → numexp.ts} +2 -2
- package/tests/algebra/equation.test.ts +19 -5
- package/tests/algebra/linear.test.ts +3 -11
- package/tests/algebra/polynom.test.ts +7 -8
- package/tests/algebra/rationnal.test.ts +1 -1
- package/tests/algebra/study.test.ts +2 -9
- package/tests/coefficients/fraction.test.ts +8 -8
- package/tests/custom.test.ts +33 -37
- package/tests/numeric.test.ts +1 -2
- package/tests/numexp.test.ts +1 -5
- package/tests/shutingyard.test.ts +3 -3
- package/webpack-production-min.config.js +1 -1
- package/webpack-production.config.js +1 -1
- package/webpack.config.js +1 -1
- package/dist/pi.js.map +0 -1
- package/dist/pi.min.js +0 -2
- package/dist/pi.min.js.map +0 -1
- package/docs/classes/expressions_numexp.NumExp.html +0 -236
- package/docs/classes/expressions_polynomexp.PolynomExpFactor.html +0 -317
- package/docs/classes/expressions_polynomexp.PolynomExpProduct.html +0 -285
- package/docs/modules/expressions_numexp.html +0 -71
- package/docs/modules/expressions_polynomexp.html +0 -73
- package/docs/modules.html +0 -76
- package/graph.svg +0 -1033
- package/src/maths/expressions/ExpressionTree.ts +0 -172
- package/src/maths/expressions/expression.ts +0 -286
- package/src/maths/expressions/expressionFactor.ts +0 -190
- package/src/maths/expressions/expressionMember.ts +0 -233
- package/src/maths/expressions/expressionOperators.ts +0 -49
- package/src/maths/expressions/expressionParser.ts +0 -295
- package/src/maths/expressions/factors/ExpFactor.ts +0 -39
- package/src/maths/expressions/factors/ExpFactorConstant.ts +0 -60
- package/src/maths/expressions/factors/ExpFactorExponential.ts +0 -26
- package/src/maths/expressions/factors/ExpFactorNumber.ts +0 -72
- package/src/maths/expressions/factors/ExpFactorPower.ts +0 -42
- package/src/maths/expressions/factors/ExpFactorTrigo.ts +0 -53
- package/src/maths/expressions/factors/ExpFactorVariable.ts +0 -45
- package/src/maths/expressions/internals.ts +0 -14
- package/src/maths/expressions/polynomexp.bkp.ts +0 -221
- package/src/maths/expressions/polynomexp.ts +0 -310
- package/tests/expressions/expressions.test.ts +0 -145
- package/tests/expressions/expressiontree.test.ts +0 -11
- package/tests/polynomexp.test.ts +0 -12
|
@@ -1,324 +1,324 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Circle = void 0;
|
|
4
|
-
const point_1 = require("./point");
|
|
5
|
-
const line_1 = require("./line");
|
|
6
|
-
const vector_1 = require("./vector");
|
|
7
|
-
const triangle_1 = require("./triangle");
|
|
8
|
-
const numeric_1 = require("../numeric");
|
|
9
|
-
const fraction_1 = require("../coefficients/fraction");
|
|
10
|
-
const equation_1 = require("../algebra/equation");
|
|
11
|
-
const polynom_1 = require("../algebra/polynom");
|
|
12
|
-
class Circle {
|
|
13
|
-
constructor(...values) {
|
|
14
|
-
/**
|
|
15
|
-
* Get the relative position between circle and line. It corresponds to the number of intersection.
|
|
16
|
-
* @param {Line} L
|
|
17
|
-
* @returns {number}
|
|
18
|
-
*/
|
|
19
|
-
this.relativePosition = (L) => {
|
|
20
|
-
let distance = L.distanceTo(this.center), radius = Math.sqrt(this._squareRadius.value);
|
|
21
|
-
if (distance.value - radius > 0.0000000001) {
|
|
22
|
-
return 0; // external
|
|
23
|
-
}
|
|
24
|
-
else if (Math.abs(distance.value - radius) < 0.0000000001) {
|
|
25
|
-
return 1; // tangent
|
|
26
|
-
}
|
|
27
|
-
else {
|
|
28
|
-
return 2; // external
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
this.lineIntersection = (L) => {
|
|
32
|
-
let intersectionPoints = [], solX;
|
|
33
|
-
if (this._cartesian === null) {
|
|
34
|
-
return [];
|
|
35
|
-
}
|
|
36
|
-
const equX = this._cartesian.clone(), lineX = L.equation.clone().isolate('x'), lineY = L.equation.clone().isolate('y');
|
|
37
|
-
if (lineX instanceof equation_1.Equation && lineY instanceof equation_1.Equation) {
|
|
38
|
-
equX.replaceBy('y', lineY.right).simplify();
|
|
39
|
-
equX.solve();
|
|
40
|
-
for (let x of equX.solutions) {
|
|
41
|
-
if (x.exact === false && isNaN(x.value)) {
|
|
42
|
-
continue;
|
|
43
|
-
}
|
|
44
|
-
solX = new fraction_1.Fraction(x.exact === false ? x.value : x.exact);
|
|
45
|
-
intersectionPoints.push(new point_1.Point(solX.clone(), lineY.right.evaluate(solX)));
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
return intersectionPoints;
|
|
49
|
-
};
|
|
50
|
-
this.tangents = (P) => {
|
|
51
|
-
if (P instanceof fraction_1.Fraction) {
|
|
52
|
-
return this._tangentsWithSlope(P);
|
|
53
|
-
}
|
|
54
|
-
else if (this.isPointOnCircle(P)) {
|
|
55
|
-
return this._tangentsThroughOnePointOnTheCircle(P);
|
|
56
|
-
}
|
|
57
|
-
else if (this.center.distanceTo(P).value > this.radius.value) {
|
|
58
|
-
//TODO: Must check it's outside the circle
|
|
59
|
-
return this._tangentsThroughOnePointOutsideTheCircle(P);
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
console.log('No tangents as the point is inside !');
|
|
63
|
-
}
|
|
64
|
-
return [];
|
|
65
|
-
};
|
|
66
|
-
this.isPointOnCircle = (P) => {
|
|
67
|
-
return this._cartesian.test({ x: P.x, y: P.y });
|
|
68
|
-
};
|
|
69
|
-
this.getPointsOnCircle = (numberIsInteger) => {
|
|
70
|
-
if (numberIsInteger === undefined) {
|
|
71
|
-
numberIsInteger = false;
|
|
72
|
-
}
|
|
73
|
-
// It means searching for pythagorician triples that make a perfect square.
|
|
74
|
-
// (x-4)^2 + (y+3)^2 = 15
|
|
75
|
-
let triplets = numeric_1.Numeric.pythagoricianTripletsWithTarget(this._squareRadius.value, true);
|
|
76
|
-
let points = [], pt;
|
|
77
|
-
triplets.forEach(triplet => {
|
|
78
|
-
// Allow positive / negative values
|
|
79
|
-
// x-a = t => x = a + t
|
|
80
|
-
// x-a = -t => x = a - t
|
|
81
|
-
for (let k of [[1, 1], [-1, 1], [-1, -1], [1, -1]]) {
|
|
82
|
-
pt = new point_1.Point(this.center.x.clone().add(k[0] * triplet[0]), this.center.y.clone().add(k[1] * triplet[1]));
|
|
83
|
-
// Check if the point is not already in points.
|
|
84
|
-
if (!pt.isInListOfPoints(points)) {
|
|
85
|
-
points.push(pt);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
|
-
return points;
|
|
90
|
-
};
|
|
91
|
-
this._tangentsThroughOnePointOnTheCircle = (P) => {
|
|
92
|
-
let CT = new vector_1.Vector(this._center, P);
|
|
93
|
-
return [new line_1.Line(P, CT, line_1.LinePropriety.Perpendicular)];
|
|
94
|
-
};
|
|
95
|
-
this._tangentsThroughOnePointOutsideTheCircle = (P) => {
|
|
96
|
-
// y = mx + h
|
|
97
|
-
// px, py => h = -m px + py => mx - y -m.px + py = 0 =>
|
|
98
|
-
// Centre: cx, cy, radius: r
|
|
99
|
-
// (m.cx - cy -m.px + py)^2 = r^2 * (m^2 + 1)
|
|
100
|
-
// (m(cx-py) - (cy - py))^2 = r^2 * (m^2 + 1)
|
|
101
|
-
let cx_px = this.center.x.clone().subtract(P.x), cy_py = this.center.y.clone().subtract(P.y), polyLeft = new polynom_1.Polynom('x'), polyRight = new polynom_1.Polynom('x^2+1');
|
|
102
|
-
polyLeft.multiply(cx_px).subtract(cy_py).pow(2);
|
|
103
|
-
polyRight.multiply(this.squareRadius);
|
|
104
|
-
let equ = new equation_1.Equation(polyLeft, polyRight);
|
|
105
|
-
equ.moveLeft().simplify().solve();
|
|
106
|
-
return equ.solutions.map(sol => {
|
|
107
|
-
// h = -m px + py
|
|
108
|
-
let h, equ = new equation_1.Equation('y', 'x');
|
|
109
|
-
if (sol.exact instanceof fraction_1.Fraction) {
|
|
110
|
-
h = P.x.clone().opposed().multiply(sol.exact).add(P.y);
|
|
111
|
-
equ.right.multiply(sol.exact).add(h);
|
|
112
|
-
}
|
|
113
|
-
else {
|
|
114
|
-
h = P.x.clone().opposed().multiply(sol.value).add(P.y);
|
|
115
|
-
equ.right.multiply(sol.value).add(h);
|
|
116
|
-
}
|
|
117
|
-
return new line_1.Line(equ);
|
|
118
|
-
});
|
|
119
|
-
};
|
|
120
|
-
this._tangentsWithSlope = (slope) => {
|
|
121
|
-
// d(C;t)=r => ac1+bc2 + x = +- sqrt(a^2 + b^2)*r
|
|
122
|
-
// x = -ac1-bc2 +- sqrt(a^2 + b^2)*r
|
|
123
|
-
// y = a/bx + h => ax-by + H = 0
|
|
124
|
-
const a = slope.numerator, b = -slope.denominator, c1 = this._center.x.clone(), c2 = this._center.y.clone(), r = this._squareRadius;
|
|
125
|
-
let sq = this._squareRadius.clone().multiply(slope.numerator ** 2 + slope.denominator ** 2), x1 = c1.clone().multiply(a).opposed().subtract(c2.clone().multiply(b)).add(sq.clone().sqrt()), x2 = c1.clone().multiply(a).opposed().subtract(c2.clone().multiply(b)).subtract(sq.clone().sqrt());
|
|
126
|
-
return [new line_1.Line(a, b, x1), new line_1.Line(a, b, x2)];
|
|
127
|
-
};
|
|
128
|
-
this._exists = false;
|
|
129
|
-
if (values !== undefined) {
|
|
130
|
-
this.parse(...values);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
get center() {
|
|
134
|
-
return this._center;
|
|
135
|
-
}
|
|
136
|
-
get squareRadius() {
|
|
137
|
-
return this._squareRadius;
|
|
138
|
-
}
|
|
139
|
-
get cartesian() {
|
|
140
|
-
return this._cartesian;
|
|
141
|
-
}
|
|
142
|
-
get exists() {
|
|
143
|
-
return this._exists;
|
|
144
|
-
}
|
|
145
|
-
get radius() {
|
|
146
|
-
if (this._squareRadius.isSquare()) {
|
|
147
|
-
return {
|
|
148
|
-
tex: this._squareRadius.clone().sqrt().tex,
|
|
149
|
-
display: this._squareRadius.clone().sqrt().display,
|
|
150
|
-
value: this._squareRadius.clone().sqrt().value
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
else {
|
|
154
|
-
return {
|
|
155
|
-
tex: `\\sqrt{${this._squareRadius.tex}}`,
|
|
156
|
-
display: `sqrt(${this._squareRadius.display})`,
|
|
157
|
-
value: this._squareRadius.clone().sqrt().value
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
return this._squareRadius;
|
|
161
|
-
}
|
|
162
|
-
get tex() {
|
|
163
|
-
if (this._exists) {
|
|
164
|
-
let cx, cy;
|
|
165
|
-
if (this._center.x.isZero()) {
|
|
166
|
-
cx = 'x^2';
|
|
167
|
-
}
|
|
168
|
-
else {
|
|
169
|
-
cx = `\\left(x${this._center.x.isNegative() ? '+' : '-'}${this._center.x.clone().abs().tex}\\right)^2`;
|
|
170
|
-
}
|
|
171
|
-
if (this._center.y.isZero()) {
|
|
172
|
-
cy = 'y^2';
|
|
173
|
-
}
|
|
174
|
-
else {
|
|
175
|
-
cy = `\\left(y${this._center.y.isNegative() ? '+' : '-'}${this._center.y.clone().abs().tex}\\right)^2`;
|
|
176
|
-
}
|
|
177
|
-
return `${cx}+${cy}=${this._squareRadius.tex}`;
|
|
178
|
-
}
|
|
179
|
-
else {
|
|
180
|
-
return `\\text{le cercle n'existe pas.}`;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
get developed() {
|
|
184
|
-
return this._cartesian.tex;
|
|
185
|
-
}
|
|
186
|
-
get display() {
|
|
187
|
-
if (this._exists) {
|
|
188
|
-
let cx, cy;
|
|
189
|
-
if (this._center.x.isZero()) {
|
|
190
|
-
cx = 'x^2';
|
|
191
|
-
}
|
|
192
|
-
else {
|
|
193
|
-
cx = `(x${this._center.x.isNegative() ? '+' : '-'}${this._center.x.clone().abs().tex})^2`;
|
|
194
|
-
}
|
|
195
|
-
if (this._center.y.isZero()) {
|
|
196
|
-
cy = 'y^2';
|
|
197
|
-
}
|
|
198
|
-
else {
|
|
199
|
-
cy = `(y${this._center.y.isNegative() ? '+' : '-'}${this._center.y.clone().abs().tex})^2`;
|
|
200
|
-
}
|
|
201
|
-
return `${cx}+${cy}=${this._squareRadius.display}`;
|
|
202
|
-
}
|
|
203
|
-
else {
|
|
204
|
-
return `\\text{le cercle n'existe pas.}`;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
clone() {
|
|
208
|
-
this._center = this._center.clone();
|
|
209
|
-
this._squareRadius = this._squareRadius.clone();
|
|
210
|
-
this._calculateCartesian();
|
|
211
|
-
return this;
|
|
212
|
-
}
|
|
213
|
-
_reset() {
|
|
214
|
-
this._center = null;
|
|
215
|
-
this._squareRadius = null;
|
|
216
|
-
this._cartesian = null;
|
|
217
|
-
this._exists = false;
|
|
218
|
-
return this;
|
|
219
|
-
}
|
|
220
|
-
parse(...values) {
|
|
221
|
-
// Data can be given in these formats:
|
|
222
|
-
// one value, a string -> make it an Equation
|
|
223
|
-
// one value, an Equation
|
|
224
|
-
// one value, a circle -> clone it
|
|
225
|
-
// two values: two points (center and pointThrough)
|
|
226
|
-
// two values: point and Fraction (center and radius)
|
|
227
|
-
// three values: Point, Fraction, Boolean (center, square radius, true)
|
|
228
|
-
this._reset();
|
|
229
|
-
if (typeof values[0] === 'string') {
|
|
230
|
-
this._parseEquation(new equation_1.Equation(values[0]));
|
|
231
|
-
}
|
|
232
|
-
else if (values[0] instanceof equation_1.Equation) {
|
|
233
|
-
this._parseEquation(values[0]);
|
|
234
|
-
}
|
|
235
|
-
else if (values[0] instanceof Circle) {
|
|
236
|
-
this._parseCopyCircle(values[0]);
|
|
237
|
-
}
|
|
238
|
-
else if (values[0] instanceof point_1.Point && values.length > 1) {
|
|
239
|
-
if (values[1] instanceof point_1.Point) {
|
|
240
|
-
if (values[2] instanceof point_1.Point) {
|
|
241
|
-
this._parseThroughtThreePoints(values[0], values[1], values[2]);
|
|
242
|
-
}
|
|
243
|
-
else {
|
|
244
|
-
this._parseCenterAndPointThrough(values[0], values[1]);
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
else if (values[1] instanceof fraction_1.Fraction || typeof values[1] === 'number') {
|
|
248
|
-
this._parseCenterAndRadius(values[0], values[1], (typeof values[2] === "boolean") ? values[2] : false);
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
// Calculate once the different values.
|
|
252
|
-
if (this._exists) {
|
|
253
|
-
this._calculateCartesian();
|
|
254
|
-
// If the square radius is zero or positive, the circle exists.
|
|
255
|
-
if (this._squareRadius !== undefined && this._squareRadius.isNegative()) {
|
|
256
|
-
this._exists = false;
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
return this;
|
|
260
|
-
}
|
|
261
|
-
_calculateCartesian() {
|
|
262
|
-
this._cartesian = (new equation_1.Equation(new polynom_1.Polynom(`(x-(${this._center.x.display}))^2+(y-(${this._center.y.display}))^2`), new polynom_1.Polynom(`${this._squareRadius.display}`))).moveLeft();
|
|
263
|
-
}
|
|
264
|
-
_parseCopyCircle(circle) {
|
|
265
|
-
this._center = circle.center.clone();
|
|
266
|
-
this._squareRadius = circle.squareRadius.clone();
|
|
267
|
-
this._calculateCartesian();
|
|
268
|
-
this._exists = circle.exists;
|
|
269
|
-
return this;
|
|
270
|
-
}
|
|
271
|
-
_parseCenterAndRadius(center, radius, square) {
|
|
272
|
-
this._center = center.clone();
|
|
273
|
-
if (square) {
|
|
274
|
-
this._squareRadius = (new fraction_1.Fraction(radius));
|
|
275
|
-
}
|
|
276
|
-
else {
|
|
277
|
-
this._squareRadius = new fraction_1.Fraction(radius).pow(2);
|
|
278
|
-
}
|
|
279
|
-
this._exists = true;
|
|
280
|
-
return this;
|
|
281
|
-
}
|
|
282
|
-
_parseCenterAndPointThrough(center, pointThrough) {
|
|
283
|
-
this._center = center.clone();
|
|
284
|
-
this._squareRadius = new vector_1.Vector(this._center, pointThrough).normSquare;
|
|
285
|
-
this._exists = true;
|
|
286
|
-
return this;
|
|
287
|
-
}
|
|
288
|
-
_parseEquation(equ) {
|
|
289
|
-
this._exists = false;
|
|
290
|
-
// Move everything to the left.
|
|
291
|
-
equ.moveLeft();
|
|
292
|
-
if (equ.degree('x').value === 2 && equ.degree('y').value === 2) {
|
|
293
|
-
// Both must be of degree 2.
|
|
294
|
-
let x2 = equ.left.monomByDegree(2, 'x'), y2 = equ.left.monomByDegree(2, 'y'), x1, y1, c;
|
|
295
|
-
// Both square monoms must have the same coefficient.
|
|
296
|
-
if (x2.coefficient.isEqual(y2.coefficient)) {
|
|
297
|
-
equ.divide(x2.coefficient);
|
|
298
|
-
x1 = equ.left.monomByDegree(1, 'x');
|
|
299
|
-
y1 = equ.left.monomByDegree(1, 'y');
|
|
300
|
-
c = equ.left.monomByDegree(0);
|
|
301
|
-
this._center = new point_1.Point(x1.coefficient.clone().divide(2).opposed(), y1.coefficient.clone().divide(2).opposed());
|
|
302
|
-
this._squareRadius = c.coefficient.clone().opposed()
|
|
303
|
-
.add(this._center.x.clone().pow(2))
|
|
304
|
-
.add(this._center.y.clone().pow(2));
|
|
305
|
-
this._calculateCartesian();
|
|
306
|
-
this._exists = true;
|
|
307
|
-
}
|
|
308
|
-
else {
|
|
309
|
-
// The circle is not a valid circle
|
|
310
|
-
this._center = null;
|
|
311
|
-
this._squareRadius = null;
|
|
312
|
-
this._exists = false;
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
return this;
|
|
316
|
-
}
|
|
317
|
-
_parseThroughtThreePoints(A, B, C) {
|
|
318
|
-
let T = new triangle_1.Triangle(A, B, C), mAB = T.remarquables.mediators.AB.clone(), mAC = T.remarquables.mediators.AC.clone();
|
|
319
|
-
this.parse(mAB.intersection(mAC).point, A);
|
|
320
|
-
return this;
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
exports.Circle = Circle;
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Circle = void 0;
|
|
4
|
+
const point_1 = require("./point");
|
|
5
|
+
const line_1 = require("./line");
|
|
6
|
+
const vector_1 = require("./vector");
|
|
7
|
+
const triangle_1 = require("./triangle");
|
|
8
|
+
const numeric_1 = require("../numeric");
|
|
9
|
+
const fraction_1 = require("../coefficients/fraction");
|
|
10
|
+
const equation_1 = require("../algebra/equation");
|
|
11
|
+
const polynom_1 = require("../algebra/polynom");
|
|
12
|
+
class Circle {
|
|
13
|
+
constructor(...values) {
|
|
14
|
+
/**
|
|
15
|
+
* Get the relative position between circle and line. It corresponds to the number of intersection.
|
|
16
|
+
* @param {Line} L
|
|
17
|
+
* @returns {number}
|
|
18
|
+
*/
|
|
19
|
+
this.relativePosition = (L) => {
|
|
20
|
+
let distance = L.distanceTo(this.center), radius = Math.sqrt(this._squareRadius.value);
|
|
21
|
+
if (distance.value - radius > 0.0000000001) {
|
|
22
|
+
return 0; // external
|
|
23
|
+
}
|
|
24
|
+
else if (Math.abs(distance.value - radius) < 0.0000000001) {
|
|
25
|
+
return 1; // tangent
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
return 2; // external
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
this.lineIntersection = (L) => {
|
|
32
|
+
let intersectionPoints = [], solX;
|
|
33
|
+
if (this._cartesian === null) {
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
const equX = this._cartesian.clone(), lineX = L.equation.clone().isolate('x'), lineY = L.equation.clone().isolate('y');
|
|
37
|
+
if (lineX instanceof equation_1.Equation && lineY instanceof equation_1.Equation) {
|
|
38
|
+
equX.replaceBy('y', lineY.right).simplify();
|
|
39
|
+
equX.solve();
|
|
40
|
+
for (let x of equX.solutions) {
|
|
41
|
+
if (x.exact === false && isNaN(x.value)) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
solX = new fraction_1.Fraction(x.exact === false ? x.value : x.exact);
|
|
45
|
+
intersectionPoints.push(new point_1.Point(solX.clone(), lineY.right.evaluate(solX)));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return intersectionPoints;
|
|
49
|
+
};
|
|
50
|
+
this.tangents = (P) => {
|
|
51
|
+
if (P instanceof fraction_1.Fraction) {
|
|
52
|
+
return this._tangentsWithSlope(P);
|
|
53
|
+
}
|
|
54
|
+
else if (this.isPointOnCircle(P)) {
|
|
55
|
+
return this._tangentsThroughOnePointOnTheCircle(P);
|
|
56
|
+
}
|
|
57
|
+
else if (this.center.distanceTo(P).value > this.radius.value) {
|
|
58
|
+
//TODO: Must check it's outside the circle
|
|
59
|
+
return this._tangentsThroughOnePointOutsideTheCircle(P);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
console.log('No tangents as the point is inside !');
|
|
63
|
+
}
|
|
64
|
+
return [];
|
|
65
|
+
};
|
|
66
|
+
this.isPointOnCircle = (P) => {
|
|
67
|
+
return this._cartesian.test({ x: P.x, y: P.y });
|
|
68
|
+
};
|
|
69
|
+
this.getPointsOnCircle = (numberIsInteger) => {
|
|
70
|
+
if (numberIsInteger === undefined) {
|
|
71
|
+
numberIsInteger = false;
|
|
72
|
+
}
|
|
73
|
+
// It means searching for pythagorician triples that make a perfect square.
|
|
74
|
+
// (x-4)^2 + (y+3)^2 = 15
|
|
75
|
+
let triplets = numeric_1.Numeric.pythagoricianTripletsWithTarget(this._squareRadius.value, true);
|
|
76
|
+
let points = [], pt;
|
|
77
|
+
triplets.forEach(triplet => {
|
|
78
|
+
// Allow positive / negative values
|
|
79
|
+
// x-a = t => x = a + t
|
|
80
|
+
// x-a = -t => x = a - t
|
|
81
|
+
for (let k of [[1, 1], [-1, 1], [-1, -1], [1, -1]]) {
|
|
82
|
+
pt = new point_1.Point(this.center.x.clone().add(k[0] * triplet[0]), this.center.y.clone().add(k[1] * triplet[1]));
|
|
83
|
+
// Check if the point is not already in points.
|
|
84
|
+
if (!pt.isInListOfPoints(points)) {
|
|
85
|
+
points.push(pt);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
return points;
|
|
90
|
+
};
|
|
91
|
+
this._tangentsThroughOnePointOnTheCircle = (P) => {
|
|
92
|
+
let CT = new vector_1.Vector(this._center, P);
|
|
93
|
+
return [new line_1.Line(P, CT, line_1.LinePropriety.Perpendicular)];
|
|
94
|
+
};
|
|
95
|
+
this._tangentsThroughOnePointOutsideTheCircle = (P) => {
|
|
96
|
+
// y = mx + h
|
|
97
|
+
// px, py => h = -m px + py => mx - y -m.px + py = 0 =>
|
|
98
|
+
// Centre: cx, cy, radius: r
|
|
99
|
+
// (m.cx - cy -m.px + py)^2 = r^2 * (m^2 + 1)
|
|
100
|
+
// (m(cx-py) - (cy - py))^2 = r^2 * (m^2 + 1)
|
|
101
|
+
let cx_px = this.center.x.clone().subtract(P.x), cy_py = this.center.y.clone().subtract(P.y), polyLeft = new polynom_1.Polynom('x'), polyRight = new polynom_1.Polynom('x^2+1');
|
|
102
|
+
polyLeft.multiply(cx_px).subtract(cy_py).pow(2);
|
|
103
|
+
polyRight.multiply(this.squareRadius);
|
|
104
|
+
let equ = new equation_1.Equation(polyLeft, polyRight);
|
|
105
|
+
equ.moveLeft().simplify().solve();
|
|
106
|
+
return equ.solutions.map(sol => {
|
|
107
|
+
// h = -m px + py
|
|
108
|
+
let h, equ = new equation_1.Equation('y', 'x');
|
|
109
|
+
if (sol.exact instanceof fraction_1.Fraction) {
|
|
110
|
+
h = P.x.clone().opposed().multiply(sol.exact).add(P.y);
|
|
111
|
+
equ.right.multiply(sol.exact).add(h);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
h = P.x.clone().opposed().multiply(sol.value).add(P.y);
|
|
115
|
+
equ.right.multiply(sol.value).add(h);
|
|
116
|
+
}
|
|
117
|
+
return new line_1.Line(equ);
|
|
118
|
+
});
|
|
119
|
+
};
|
|
120
|
+
this._tangentsWithSlope = (slope) => {
|
|
121
|
+
// d(C;t)=r => ac1+bc2 + x = +- sqrt(a^2 + b^2)*r
|
|
122
|
+
// x = -ac1-bc2 +- sqrt(a^2 + b^2)*r
|
|
123
|
+
// y = a/bx + h => ax-by + H = 0
|
|
124
|
+
const a = slope.numerator, b = -slope.denominator, c1 = this._center.x.clone(), c2 = this._center.y.clone(), r = this._squareRadius;
|
|
125
|
+
let sq = this._squareRadius.clone().multiply(slope.numerator ** 2 + slope.denominator ** 2), x1 = c1.clone().multiply(a).opposed().subtract(c2.clone().multiply(b)).add(sq.clone().sqrt()), x2 = c1.clone().multiply(a).opposed().subtract(c2.clone().multiply(b)).subtract(sq.clone().sqrt());
|
|
126
|
+
return [new line_1.Line(a, b, x1), new line_1.Line(a, b, x2)];
|
|
127
|
+
};
|
|
128
|
+
this._exists = false;
|
|
129
|
+
if (values !== undefined) {
|
|
130
|
+
this.parse(...values);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
get center() {
|
|
134
|
+
return this._center;
|
|
135
|
+
}
|
|
136
|
+
get squareRadius() {
|
|
137
|
+
return this._squareRadius;
|
|
138
|
+
}
|
|
139
|
+
get cartesian() {
|
|
140
|
+
return this._cartesian;
|
|
141
|
+
}
|
|
142
|
+
get exists() {
|
|
143
|
+
return this._exists;
|
|
144
|
+
}
|
|
145
|
+
get radius() {
|
|
146
|
+
if (this._squareRadius.isSquare()) {
|
|
147
|
+
return {
|
|
148
|
+
tex: this._squareRadius.clone().sqrt().tex,
|
|
149
|
+
display: this._squareRadius.clone().sqrt().display,
|
|
150
|
+
value: this._squareRadius.clone().sqrt().value
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
return {
|
|
155
|
+
tex: `\\sqrt{${this._squareRadius.tex}}`,
|
|
156
|
+
display: `sqrt(${this._squareRadius.display})`,
|
|
157
|
+
value: this._squareRadius.clone().sqrt().value
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
return this._squareRadius;
|
|
161
|
+
}
|
|
162
|
+
get tex() {
|
|
163
|
+
if (this._exists) {
|
|
164
|
+
let cx, cy;
|
|
165
|
+
if (this._center.x.isZero()) {
|
|
166
|
+
cx = 'x^2';
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
cx = `\\left(x${this._center.x.isNegative() ? '+' : '-'}${this._center.x.clone().abs().tex}\\right)^2`;
|
|
170
|
+
}
|
|
171
|
+
if (this._center.y.isZero()) {
|
|
172
|
+
cy = 'y^2';
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
cy = `\\left(y${this._center.y.isNegative() ? '+' : '-'}${this._center.y.clone().abs().tex}\\right)^2`;
|
|
176
|
+
}
|
|
177
|
+
return `${cx}+${cy}=${this._squareRadius.tex}`;
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
return `\\text{le cercle n'existe pas.}`;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
get developed() {
|
|
184
|
+
return this._cartesian.tex;
|
|
185
|
+
}
|
|
186
|
+
get display() {
|
|
187
|
+
if (this._exists) {
|
|
188
|
+
let cx, cy;
|
|
189
|
+
if (this._center.x.isZero()) {
|
|
190
|
+
cx = 'x^2';
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
cx = `(x${this._center.x.isNegative() ? '+' : '-'}${this._center.x.clone().abs().tex})^2`;
|
|
194
|
+
}
|
|
195
|
+
if (this._center.y.isZero()) {
|
|
196
|
+
cy = 'y^2';
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
cy = `(y${this._center.y.isNegative() ? '+' : '-'}${this._center.y.clone().abs().tex})^2`;
|
|
200
|
+
}
|
|
201
|
+
return `${cx}+${cy}=${this._squareRadius.display}`;
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
return `\\text{le cercle n'existe pas.}`;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
clone() {
|
|
208
|
+
this._center = this._center.clone();
|
|
209
|
+
this._squareRadius = this._squareRadius.clone();
|
|
210
|
+
this._calculateCartesian();
|
|
211
|
+
return this;
|
|
212
|
+
}
|
|
213
|
+
_reset() {
|
|
214
|
+
this._center = null;
|
|
215
|
+
this._squareRadius = null;
|
|
216
|
+
this._cartesian = null;
|
|
217
|
+
this._exists = false;
|
|
218
|
+
return this;
|
|
219
|
+
}
|
|
220
|
+
parse(...values) {
|
|
221
|
+
// Data can be given in these formats:
|
|
222
|
+
// one value, a string -> make it an Equation
|
|
223
|
+
// one value, an Equation
|
|
224
|
+
// one value, a circle -> clone it
|
|
225
|
+
// two values: two points (center and pointThrough)
|
|
226
|
+
// two values: point and Fraction (center and radius)
|
|
227
|
+
// three values: Point, Fraction, Boolean (center, square radius, true)
|
|
228
|
+
this._reset();
|
|
229
|
+
if (typeof values[0] === 'string') {
|
|
230
|
+
this._parseEquation(new equation_1.Equation(values[0]));
|
|
231
|
+
}
|
|
232
|
+
else if (values[0] instanceof equation_1.Equation) {
|
|
233
|
+
this._parseEquation(values[0]);
|
|
234
|
+
}
|
|
235
|
+
else if (values[0] instanceof Circle) {
|
|
236
|
+
this._parseCopyCircle(values[0]);
|
|
237
|
+
}
|
|
238
|
+
else if (values[0] instanceof point_1.Point && values.length > 1) {
|
|
239
|
+
if (values[1] instanceof point_1.Point) {
|
|
240
|
+
if (values[2] instanceof point_1.Point) {
|
|
241
|
+
this._parseThroughtThreePoints(values[0], values[1], values[2]);
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
this._parseCenterAndPointThrough(values[0], values[1]);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
else if (values[1] instanceof fraction_1.Fraction || typeof values[1] === 'number') {
|
|
248
|
+
this._parseCenterAndRadius(values[0], values[1], (typeof values[2] === "boolean") ? values[2] : false);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
// Calculate once the different values.
|
|
252
|
+
if (this._exists) {
|
|
253
|
+
this._calculateCartesian();
|
|
254
|
+
// If the square radius is zero or positive, the circle exists.
|
|
255
|
+
if (this._squareRadius !== undefined && this._squareRadius.isNegative()) {
|
|
256
|
+
this._exists = false;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return this;
|
|
260
|
+
}
|
|
261
|
+
_calculateCartesian() {
|
|
262
|
+
this._cartesian = (new equation_1.Equation(new polynom_1.Polynom(`(x-(${this._center.x.display}))^2+(y-(${this._center.y.display}))^2`), new polynom_1.Polynom(`${this._squareRadius.display}`))).moveLeft();
|
|
263
|
+
}
|
|
264
|
+
_parseCopyCircle(circle) {
|
|
265
|
+
this._center = circle.center.clone();
|
|
266
|
+
this._squareRadius = circle.squareRadius.clone();
|
|
267
|
+
this._calculateCartesian();
|
|
268
|
+
this._exists = circle.exists;
|
|
269
|
+
return this;
|
|
270
|
+
}
|
|
271
|
+
_parseCenterAndRadius(center, radius, square) {
|
|
272
|
+
this._center = center.clone();
|
|
273
|
+
if (square) {
|
|
274
|
+
this._squareRadius = (new fraction_1.Fraction(radius));
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
this._squareRadius = new fraction_1.Fraction(radius).pow(2);
|
|
278
|
+
}
|
|
279
|
+
this._exists = true;
|
|
280
|
+
return this;
|
|
281
|
+
}
|
|
282
|
+
_parseCenterAndPointThrough(center, pointThrough) {
|
|
283
|
+
this._center = center.clone();
|
|
284
|
+
this._squareRadius = new vector_1.Vector(this._center, pointThrough).normSquare;
|
|
285
|
+
this._exists = true;
|
|
286
|
+
return this;
|
|
287
|
+
}
|
|
288
|
+
_parseEquation(equ) {
|
|
289
|
+
this._exists = false;
|
|
290
|
+
// Move everything to the left.
|
|
291
|
+
equ.moveLeft();
|
|
292
|
+
if (equ.degree('x').value === 2 && equ.degree('y').value === 2) {
|
|
293
|
+
// Both must be of degree 2.
|
|
294
|
+
let x2 = equ.left.monomByDegree(2, 'x'), y2 = equ.left.monomByDegree(2, 'y'), x1, y1, c;
|
|
295
|
+
// Both square monoms must have the same coefficient.
|
|
296
|
+
if (x2.coefficient.isEqual(y2.coefficient)) {
|
|
297
|
+
equ.divide(x2.coefficient);
|
|
298
|
+
x1 = equ.left.monomByDegree(1, 'x');
|
|
299
|
+
y1 = equ.left.monomByDegree(1, 'y');
|
|
300
|
+
c = equ.left.monomByDegree(0);
|
|
301
|
+
this._center = new point_1.Point(x1.coefficient.clone().divide(2).opposed(), y1.coefficient.clone().divide(2).opposed());
|
|
302
|
+
this._squareRadius = c.coefficient.clone().opposed()
|
|
303
|
+
.add(this._center.x.clone().pow(2))
|
|
304
|
+
.add(this._center.y.clone().pow(2));
|
|
305
|
+
this._calculateCartesian();
|
|
306
|
+
this._exists = true;
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
// The circle is not a valid circle
|
|
310
|
+
this._center = null;
|
|
311
|
+
this._squareRadius = null;
|
|
312
|
+
this._exists = false;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
return this;
|
|
316
|
+
}
|
|
317
|
+
_parseThroughtThreePoints(A, B, C) {
|
|
318
|
+
let T = new triangle_1.Triangle(A, B, C), mAB = T.remarquables.mediators.AB.clone(), mAC = T.remarquables.mediators.AC.clone();
|
|
319
|
+
this.parse(mAB.intersection(mAC).point, A);
|
|
320
|
+
return this;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
exports.Circle = Circle;
|
|
324
324
|
//# sourceMappingURL=circle.js.map
|