pimath 0.0.33 → 0.0.36
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/dist/pi.js +6468 -1
- package/dist/pi.js.map +1 -1
- package/dist/pi.min.js +2 -0
- package/dist/pi.min.js.map +1 -0
- package/docs/assets/search.js +1 -1
- package/docs/classes/algebra.Equation.html +9 -9
- package/docs/classes/algebra.LinearSystem.html +1 -1
- package/docs/classes/algebra.Logicalset.html +2 -2
- package/docs/classes/algebra.Monom.html +37 -37
- package/docs/classes/algebra.Polynom.html +10 -10
- package/docs/classes/algebra.PolynomExpFactor.html +1 -1
- package/docs/classes/algebra.PolynomExpProduct.html +1 -1
- package/docs/classes/algebra.Rational.html +2 -2
- package/docs/classes/coefficients.Fraction.html +4 -4
- package/docs/classes/coefficients.Nthroot.html +1 -1
- package/docs/classes/geometry.Circle.html +2 -2
- package/docs/classes/geometry.Line.html +2 -2
- package/docs/classes/geometry.Point.html +1 -1
- package/docs/classes/geometry.Triangle.html +5 -5
- package/docs/classes/geometry.Vector.html +1 -1
- package/docs/classes/numeric.Numeric.html +5 -5
- package/docs/classes/shutingyard.Shutingyard.html +4 -4
- package/docs/enums/geometry.LinePropriety.html +1 -0
- package/docs/enums/shutingyard.ShutingyardMode.html +1 -1
- package/docs/enums/shutingyard.ShutingyardType.html +1 -1
- package/docs/interfaces/geometry.remarquableLines.html +1 -1
- package/docs/modules/algebra.html +1 -1
- package/docs/modules/coefficients.html +1 -1
- package/docs/modules/geometry.html +1 -1
- package/docs/modules/random.Random.html +1 -1
- package/docs/modules/random.html +1 -1
- package/docs/modules/shutingyard.html +1 -1
- package/esm/main.d.ts +41 -1
- package/esm/main.js +34 -20
- package/esm/main.js.map +1 -1
- package/esm/maths/algebra/equation.d.ts +63 -18
- package/esm/maths/algebra/equation.js +599 -503
- package/esm/maths/algebra/equation.js.map +1 -1
- package/esm/maths/algebra/linearSystem.d.ts +1 -1
- package/esm/maths/algebra/linearSystem.js +157 -104
- package/esm/maths/algebra/linearSystem.js.map +1 -1
- package/esm/maths/algebra/logicalset.d.ts +11 -0
- package/esm/maths/algebra/logicalset.js +18 -6
- package/esm/maths/algebra/logicalset.js.map +1 -1
- package/esm/maths/algebra/monom.d.ts +142 -1
- package/esm/maths/algebra/monom.js +633 -405
- package/esm/maths/algebra/monom.js.map +1 -1
- package/esm/maths/algebra/polynom.d.ts +52 -3
- package/esm/maths/algebra/polynom.js +1003 -720
- package/esm/maths/algebra/polynom.js.map +1 -1
- package/esm/maths/algebra/rational.d.ts +13 -1
- package/esm/maths/algebra/rational.js +98 -83
- package/esm/maths/algebra/rational.js.map +1 -1
- package/esm/maths/coefficients/fraction.d.ts +18 -0
- package/esm/maths/coefficients/fraction.js +390 -332
- package/esm/maths/coefficients/fraction.js.map +1 -1
- package/esm/maths/coefficients/nthroot.d.ts +3 -0
- package/esm/maths/coefficients/nthroot.js +48 -33
- package/esm/maths/coefficients/nthroot.js.map +1 -1
- package/esm/maths/expressions/numexp.js +13 -5
- package/esm/maths/expressions/numexp.js.map +1 -1
- package/esm/maths/expressions/polynomexp.bkp.d.ts +2 -2
- package/esm/maths/expressions/polynomexp.bkp.js +95 -95
- package/esm/maths/expressions/polynomexp.bkp.js.map +1 -1
- package/esm/maths/expressions/polynomexp.d.ts +2 -2
- package/esm/maths/expressions/polynomexp.js +27 -14
- package/esm/maths/expressions/polynomexp.js.map +1 -1
- package/esm/maths/geometry/circle.d.ts +20 -8
- package/esm/maths/geometry/circle.js +148 -50
- package/esm/maths/geometry/circle.js.map +1 -1
- package/esm/maths/geometry/line.d.ts +11 -4
- package/esm/maths/geometry/line.js +251 -193
- package/esm/maths/geometry/line.js.map +1 -1
- package/esm/maths/geometry/point.d.ts +13 -1
- package/esm/maths/geometry/point.js +124 -76
- package/esm/maths/geometry/point.js.map +1 -1
- package/esm/maths/geometry/triangle.d.ts +23 -1
- package/esm/maths/geometry/triangle.js +197 -158
- package/esm/maths/geometry/triangle.js.map +1 -1
- package/esm/maths/geometry/vector.d.ts +5 -1
- package/esm/maths/geometry/vector.js +139 -115
- package/esm/maths/geometry/vector.js.map +1 -1
- package/esm/maths/numeric.d.ts +17 -0
- package/esm/maths/numeric.js +40 -0
- package/esm/maths/numeric.js.map +1 -1
- package/esm/maths/{random/index.d.ts → randomization/random.d.ts} +3 -2
- package/esm/maths/{random/index.js → randomization/random.js} +6 -2
- package/esm/maths/randomization/random.js.map +1 -0
- package/esm/maths/{random → randomization}/randomCore.d.ts +0 -0
- package/esm/maths/randomization/randomCore.js +22 -0
- package/esm/maths/randomization/randomCore.js.map +1 -0
- package/esm/maths/{random → randomization}/rndFraction.d.ts +4 -1
- package/esm/maths/randomization/rndFraction.js +40 -0
- package/esm/maths/randomization/rndFraction.js.map +1 -0
- package/esm/maths/randomization/rndHelpers.d.ts +25 -0
- package/esm/maths/{random → randomization}/rndHelpers.js +20 -0
- package/esm/maths/randomization/rndHelpers.js.map +1 -0
- package/esm/maths/{random → randomization}/rndMonom.d.ts +4 -1
- package/esm/maths/randomization/rndMonom.js +53 -0
- package/esm/maths/randomization/rndMonom.js.map +1 -0
- package/esm/maths/{random → randomization}/rndPolynom.d.ts +4 -1
- package/esm/maths/randomization/rndPolynom.js +75 -0
- package/esm/maths/randomization/rndPolynom.js.map +1 -0
- package/esm/maths/{random → randomization}/rndTypes.d.ts +0 -0
- package/esm/maths/{random → randomization}/rndTypes.js +0 -0
- package/esm/maths/randomization/rndTypes.js.map +1 -0
- package/esm/maths/shutingyard.d.ts +21 -0
- package/esm/maths/shutingyard.js +86 -9
- package/esm/maths/shutingyard.js.map +1 -1
- package/package.json +2 -2
- package/public/index.html +47 -0
- package/src/main.ts +17 -15
- package/src/maths/algebra/equation.ts +144 -129
- package/src/maths/algebra/linearSystem.ts +2 -2
- package/src/maths/algebra/monom.ts +1 -1
- package/src/maths/algebra/polynom.ts +136 -136
- package/src/maths/algebra/rational.ts +1 -1
- package/src/maths/expressions/numexp.ts +1 -1
- package/src/maths/expressions/polynomexp.bkp.ts +2 -2
- package/src/maths/expressions/polynomexp.ts +2 -2
- package/src/maths/geometry/circle.ts +172 -77
- package/src/maths/geometry/line.ts +4 -3
- package/src/maths/geometry/point.ts +26 -3
- package/src/maths/geometry/triangle.ts +1 -1
- package/src/maths/geometry/vector.ts +1 -1
- package/src/maths/numeric.ts +15 -0
- package/src/maths/{random/index.ts → randomization/random.ts} +3 -2
- package/src/maths/{random → randomization}/randomCore.ts +0 -0
- package/src/maths/{random → randomization}/rndFraction.ts +2 -2
- package/src/maths/{random → randomization}/rndHelpers.ts +0 -0
- package/src/maths/{random → randomization}/rndMonom.ts +2 -2
- package/src/maths/{random → randomization}/rndPolynom.ts +3 -3
- package/src/maths/{random → randomization}/rndTypes.ts +0 -0
- package/tests/algebra/monom.test.ts +1 -1
- package/tests/algebra/polynom.test.ts +8 -9
- package/tests/geometry/circle.test.ts +33 -0
- package/tsconfig.json +2 -2
- package/webpack-production-min.config.js +26 -0
- package/webpack-production.config.js +1 -1
- package/dev/pi.js +0 -5392
- package/dev/pi.js.map +0 -1
- package/esm/maths/algebra/index.d.ts +0 -7
- package/esm/maths/algebra/index.js +0 -20
- package/esm/maths/algebra/index.js.map +0 -1
- package/esm/maths/coefficients/index.d.ts +0 -2
- package/esm/maths/coefficients/index.js +0 -15
- package/esm/maths/coefficients/index.js.map +0 -1
- package/esm/maths/geometry/index.d.ts +0 -5
- package/esm/maths/geometry/index.js +0 -18
- package/esm/maths/geometry/index.js.map +0 -1
- package/esm/maths/random/index.js.map +0 -1
- package/esm/maths/random/randomCore.js +0 -22
- package/esm/maths/random/randomCore.js.map +0 -1
- package/esm/maths/random/rndFraction.js +0 -37
- package/esm/maths/random/rndFraction.js.map +0 -1
- package/esm/maths/random/rndHelpers.d.ts +0 -8
- package/esm/maths/random/rndHelpers.js.map +0 -1
- package/esm/maths/random/rndMonom.js +0 -46
- package/esm/maths/random/rndMonom.js.map +0 -1
- package/esm/maths/random/rndPolynom.js +0 -63
- package/esm/maths/random/rndPolynom.js.map +0 -1
- package/esm/maths/random/rndTypes.js.map +0 -1
- package/src/maths/algebra/index.ts +0 -7
- package/src/maths/coefficients/index.ts +0 -2
- package/src/maths/geometry/index.ts +0 -5
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
import {literalType, Monom} from './monom';
|
|
6
6
|
import {Shutingyard, ShutingyardType, Token} from '../shutingyard';
|
|
7
7
|
import {Numeric} from '../numeric';
|
|
8
|
-
import {Fraction} from "../coefficients";
|
|
9
|
-
|
|
8
|
+
import {Fraction} from "../coefficients/fraction";
|
|
9
|
+
|
|
10
|
+
export type PolynomParsingType = string | Polynom | number | Fraction | Monom
|
|
10
11
|
|
|
11
|
-
export type PolynomParsingType = string|Polynom|number|Fraction|Monom
|
|
12
12
|
/**
|
|
13
13
|
* Polynom class can handle polynoms, reorder, resolve, ...
|
|
14
14
|
* ```
|
|
@@ -120,6 +120,82 @@ export class Polynom {
|
|
|
120
120
|
return this.variables.length;
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
+
static addToken = (stack: Polynom[], element: Token): void => {
|
|
124
|
+
|
|
125
|
+
switch (element.tokenType) {
|
|
126
|
+
case ShutingyardType.COEFFICIENT:
|
|
127
|
+
stack.push(new Polynom(element.token))
|
|
128
|
+
break
|
|
129
|
+
|
|
130
|
+
case ShutingyardType.VARIABLE:
|
|
131
|
+
stack.push(new Polynom().add(new Monom(element.token)))
|
|
132
|
+
break
|
|
133
|
+
|
|
134
|
+
case ShutingyardType.CONSTANT:
|
|
135
|
+
// TODO: add constant support to Polynom parsing.
|
|
136
|
+
console.log('Actually, not supported - will be added later !')
|
|
137
|
+
break
|
|
138
|
+
|
|
139
|
+
case ShutingyardType.OPERATION:
|
|
140
|
+
if (stack.length >= 2) {
|
|
141
|
+
const b = stack.pop(),
|
|
142
|
+
a = stack.pop()
|
|
143
|
+
|
|
144
|
+
if (element.token === '+') {
|
|
145
|
+
stack.push(a.add(b))
|
|
146
|
+
} else if (element.token === '-') {
|
|
147
|
+
stack.push(a.subtract(b))
|
|
148
|
+
} else if (element.token === '*') {
|
|
149
|
+
stack.push(a.multiply(b))
|
|
150
|
+
} else if (element.token === '/') {
|
|
151
|
+
if (b.degree().isStrictlyPositive()) {
|
|
152
|
+
console.log('divide by a polynom -> should create a rational polynom !')
|
|
153
|
+
} else {
|
|
154
|
+
stack.push(a.divide(b.monoms[0].coefficient))
|
|
155
|
+
|
|
156
|
+
}
|
|
157
|
+
} else if (element.token === '^') {
|
|
158
|
+
if (b.degree().isStrictlyPositive()) {
|
|
159
|
+
console.error('Cannot elevate a polynom with another polynom !')
|
|
160
|
+
} else {
|
|
161
|
+
if (b.monoms[0].coefficient.isRelative()) {
|
|
162
|
+
// Integer power
|
|
163
|
+
stack.push(a.pow(b.monoms[0].coefficient.value))
|
|
164
|
+
} else {
|
|
165
|
+
// Only allow power if the previous polynom is only a monom, without coefficient.
|
|
166
|
+
if (a.monoms.length === 1 && a.monoms[0].coefficient.isOne()) {
|
|
167
|
+
for (let letter in a.monoms[0].literal) {
|
|
168
|
+
a.monoms[0].literal[letter].multiply(b.monoms[0].coefficient)
|
|
169
|
+
}
|
|
170
|
+
stack.push(a)
|
|
171
|
+
} else {
|
|
172
|
+
console.error('Cannot have power with fraction')
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
} else {
|
|
178
|
+
console.log('Stack size: ', stack.length)
|
|
179
|
+
if (element.token === '-') {
|
|
180
|
+
stack.push(stack.pop().opposed())
|
|
181
|
+
} else {
|
|
182
|
+
console.log('While parsing, cannot apply ', element.token, 'to', stack[0].tex)
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
break
|
|
186
|
+
|
|
187
|
+
case ShutingyardType.MONOM:
|
|
188
|
+
// Should never appear.
|
|
189
|
+
console.error('The monom token should not appear here')
|
|
190
|
+
break;
|
|
191
|
+
|
|
192
|
+
case ShutingyardType.FUNCTION:
|
|
193
|
+
// Should never appear.
|
|
194
|
+
console.log('The function token should not appear here - might be introduced later.')
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
123
199
|
// ------------------------------------------
|
|
124
200
|
/**
|
|
125
201
|
* Parse a string to a polynom.
|
|
@@ -131,12 +207,12 @@ export class Polynom {
|
|
|
131
207
|
this._monoms = []
|
|
132
208
|
this._factors = []
|
|
133
209
|
|
|
134
|
-
if(typeof inputStr === 'string') {
|
|
210
|
+
if (typeof inputStr === 'string') {
|
|
135
211
|
return this._parseString(inputStr, ...values)
|
|
136
|
-
}else if(typeof inputStr === 'number' || inputStr instanceof Fraction || inputStr instanceof Monom){
|
|
212
|
+
} else if (typeof inputStr === 'number' || inputStr instanceof Fraction || inputStr instanceof Monom) {
|
|
137
213
|
this._monoms.push(new Monom(inputStr))
|
|
138
|
-
}else if(inputStr instanceof Polynom){
|
|
139
|
-
for(const m of inputStr.monoms){
|
|
214
|
+
} else if (inputStr instanceof Polynom) {
|
|
215
|
+
for (const m of inputStr.monoms) {
|
|
140
216
|
this._monoms.push(m.clone())
|
|
141
217
|
}
|
|
142
218
|
}
|
|
@@ -144,59 +220,6 @@ export class Polynom {
|
|
|
144
220
|
return this
|
|
145
221
|
};
|
|
146
222
|
|
|
147
|
-
private _parseString(inputStr: string, ...values:unknown[]): Polynom{
|
|
148
|
-
if (values === undefined || values.length === 0) {
|
|
149
|
-
inputStr = '' + inputStr;
|
|
150
|
-
this._rawString = inputStr;
|
|
151
|
-
|
|
152
|
-
// Parse the polynom using the shutting yard algorithm
|
|
153
|
-
if (inputStr !== '' && !isNaN(Number(inputStr))) {
|
|
154
|
-
this.empty();
|
|
155
|
-
// It's a simple number.
|
|
156
|
-
let m = new Monom(inputStr);
|
|
157
|
-
// m.coefficient = new Fraction(inputStr);
|
|
158
|
-
// m.literalStr = '';
|
|
159
|
-
this.add(m);
|
|
160
|
-
return this;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
// Parse the string.
|
|
164
|
-
return this.shutingYardToReducedPolynom(inputStr);
|
|
165
|
-
} else if (/^[a-z]/.test(inputStr)) {
|
|
166
|
-
// We assume the inputStr contains only letters.
|
|
167
|
-
this.empty();
|
|
168
|
-
|
|
169
|
-
let fractions = values.map(x => new Fraction(x));
|
|
170
|
-
// Multiple setLetter version
|
|
171
|
-
if (inputStr.length > 1) {
|
|
172
|
-
// TODO: check that the number of values given correspond to the letters (+1 eventually)
|
|
173
|
-
let letters = inputStr.split(''),
|
|
174
|
-
i = 0;
|
|
175
|
-
for (let F of fractions) {
|
|
176
|
-
let m = new Monom();
|
|
177
|
-
m.coefficient = F.clone();
|
|
178
|
-
m.literalStr = letters[i] || '';
|
|
179
|
-
this.add(m);
|
|
180
|
-
i++;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
// Single setLetter version
|
|
184
|
-
else {
|
|
185
|
-
let n = fractions.length - 1;
|
|
186
|
-
for (let F of fractions) {
|
|
187
|
-
let m = new Monom()
|
|
188
|
-
m.coefficient = F.clone();
|
|
189
|
-
m.literalStr = `${inputStr}^${n}`
|
|
190
|
-
this.add(m);
|
|
191
|
-
n--;
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
return this;
|
|
195
|
-
} else {
|
|
196
|
-
return this.zero();
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
223
|
|
|
201
224
|
// ------------------------------------------
|
|
202
225
|
// Creation / parsing functions
|
|
@@ -972,6 +995,59 @@ export class Polynom {
|
|
|
972
995
|
return M;
|
|
973
996
|
}
|
|
974
997
|
|
|
998
|
+
private _parseString(inputStr: string, ...values: unknown[]): Polynom {
|
|
999
|
+
if (values === undefined || values.length === 0) {
|
|
1000
|
+
inputStr = '' + inputStr;
|
|
1001
|
+
this._rawString = inputStr;
|
|
1002
|
+
|
|
1003
|
+
// Parse the polynom using the shutting yard algorithm
|
|
1004
|
+
if (inputStr !== '' && !isNaN(Number(inputStr))) {
|
|
1005
|
+
this.empty();
|
|
1006
|
+
// It's a simple number.
|
|
1007
|
+
let m = new Monom(inputStr);
|
|
1008
|
+
// m.coefficient = new Fraction(inputStr);
|
|
1009
|
+
// m.literalStr = '';
|
|
1010
|
+
this.add(m);
|
|
1011
|
+
return this;
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
// Parse the string.
|
|
1015
|
+
return this.shutingYardToReducedPolynom(inputStr);
|
|
1016
|
+
} else if (/^[a-z]/.test(inputStr)) {
|
|
1017
|
+
// We assume the inputStr contains only letters.
|
|
1018
|
+
this.empty();
|
|
1019
|
+
|
|
1020
|
+
let fractions = values.map(x => new Fraction(x));
|
|
1021
|
+
// Multiple setLetter version
|
|
1022
|
+
if (inputStr.length > 1) {
|
|
1023
|
+
// TODO: check that the number of values given correspond to the letters (+1 eventually)
|
|
1024
|
+
let letters = inputStr.split(''),
|
|
1025
|
+
i = 0;
|
|
1026
|
+
for (let F of fractions) {
|
|
1027
|
+
let m = new Monom();
|
|
1028
|
+
m.coefficient = F.clone();
|
|
1029
|
+
m.literalStr = letters[i] || '';
|
|
1030
|
+
this.add(m);
|
|
1031
|
+
i++;
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
// Single setLetter version
|
|
1035
|
+
else {
|
|
1036
|
+
let n = fractions.length - 1;
|
|
1037
|
+
for (let F of fractions) {
|
|
1038
|
+
let m = new Monom()
|
|
1039
|
+
m.coefficient = F.clone();
|
|
1040
|
+
m.literalStr = `${inputStr}^${n}`
|
|
1041
|
+
this.add(m);
|
|
1042
|
+
n--;
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
return this;
|
|
1046
|
+
} else {
|
|
1047
|
+
return this.zero();
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
|
|
975
1051
|
private genDisplay = (output?: string, forceSign?: boolean, wrapParentheses?: boolean): string => {
|
|
976
1052
|
let P: string = '';
|
|
977
1053
|
|
|
@@ -997,82 +1073,6 @@ export class Polynom {
|
|
|
997
1073
|
return P;
|
|
998
1074
|
};
|
|
999
1075
|
|
|
1000
|
-
|
|
1001
|
-
static addToken = (stack: Polynom[], element: Token): void => {
|
|
1002
|
-
|
|
1003
|
-
switch(element.tokenType){
|
|
1004
|
-
case ShutingyardType.COEFFICIENT:
|
|
1005
|
-
stack.push(new Polynom( element.token ))
|
|
1006
|
-
break
|
|
1007
|
-
|
|
1008
|
-
case ShutingyardType.VARIABLE:
|
|
1009
|
-
stack.push(new Polynom().add(new Monom(element.token)))
|
|
1010
|
-
break
|
|
1011
|
-
|
|
1012
|
-
case ShutingyardType.CONSTANT:
|
|
1013
|
-
// TODO: add constant support to Polynom parsing.
|
|
1014
|
-
console.log('Actually, not supported - will be added later !')
|
|
1015
|
-
break
|
|
1016
|
-
|
|
1017
|
-
case ShutingyardType.OPERATION:
|
|
1018
|
-
if(stack.length>=2){
|
|
1019
|
-
const b = stack.pop(),
|
|
1020
|
-
a = stack.pop()
|
|
1021
|
-
|
|
1022
|
-
if(element.token === '+'){
|
|
1023
|
-
stack.push(a.add(b))
|
|
1024
|
-
}else if(element.token === '-'){
|
|
1025
|
-
stack.push(a.subtract(b))
|
|
1026
|
-
}else if(element.token === '*'){
|
|
1027
|
-
stack.push(a.multiply(b))
|
|
1028
|
-
}else if(element.token === '/'){
|
|
1029
|
-
if(b.degree().isStrictlyPositive()){
|
|
1030
|
-
console.log('divide by a polynom -> should create a rational polynom !')
|
|
1031
|
-
}else {
|
|
1032
|
-
stack.push(a.divide(b.monoms[0].coefficient))
|
|
1033
|
-
|
|
1034
|
-
}
|
|
1035
|
-
}else if(element.token === '^'){
|
|
1036
|
-
if(b.degree().isStrictlyPositive()) {
|
|
1037
|
-
console.error('Cannot elevate a polynom with another polynom !')
|
|
1038
|
-
}else {
|
|
1039
|
-
if(b.monoms[0].coefficient.isRelative()) {
|
|
1040
|
-
// Integer power
|
|
1041
|
-
stack.push(a.pow(b.monoms[0].coefficient.value))
|
|
1042
|
-
}else{
|
|
1043
|
-
// Only allow power if the previous polynom is only a monom, without coefficient.
|
|
1044
|
-
if(a.monoms.length===1 && a.monoms[0].coefficient.isOne()){
|
|
1045
|
-
for (let letter in a.monoms[0].literal) {
|
|
1046
|
-
a.monoms[0].literal[letter].multiply(b.monoms[0].coefficient)
|
|
1047
|
-
}
|
|
1048
|
-
stack.push(a)
|
|
1049
|
-
}else {
|
|
1050
|
-
console.error('Cannot have power with fraction')
|
|
1051
|
-
}
|
|
1052
|
-
}
|
|
1053
|
-
}
|
|
1054
|
-
}
|
|
1055
|
-
}else{
|
|
1056
|
-
console.log('Stack size: ', stack.length)
|
|
1057
|
-
if(element.token === '-'){
|
|
1058
|
-
stack.push(stack.pop().opposed())
|
|
1059
|
-
}else{
|
|
1060
|
-
console.log('While parsing, cannot apply ', element.token, 'to', stack[0].tex)
|
|
1061
|
-
}
|
|
1062
|
-
}
|
|
1063
|
-
break
|
|
1064
|
-
|
|
1065
|
-
case ShutingyardType.MONOM:
|
|
1066
|
-
// Should never appear.
|
|
1067
|
-
console.error('The monom token should not appear here')
|
|
1068
|
-
break;
|
|
1069
|
-
|
|
1070
|
-
case ShutingyardType.FUNCTION:
|
|
1071
|
-
// Should never appear.
|
|
1072
|
-
console.log('The function token should not appear here - might be introduced later.')
|
|
1073
|
-
break;
|
|
1074
|
-
}
|
|
1075
|
-
}
|
|
1076
1076
|
/**
|
|
1077
1077
|
* Main parse using a shutting yard class
|
|
1078
1078
|
* @param inputStr
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {Shutingyard, ShutingyardMode, ShutingyardType, tokenConstant} from "../shutingyard";
|
|
2
|
-
import {Fraction} from "../coefficients";
|
|
2
|
+
import {Fraction} from "../coefficients/fraction";
|
|
3
3
|
|
|
4
4
|
export class NumExp {
|
|
5
5
|
private _rpn: { token: string, tokenType: string }[]
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {Polynom, PolynomParsingType} from "../algebra";
|
|
2
|
-
import {Fraction, FractionParsingType} from "../coefficients";
|
|
1
|
+
import {Polynom, PolynomParsingType} from "../algebra/polynom";
|
|
2
|
+
import {Fraction, FractionParsingType} from "../coefficients/fraction";
|
|
3
3
|
|
|
4
4
|
type PolynomExpMathFunctionType = { name: string; fn: Function, tex: string }
|
|
5
5
|
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import {Point} from "./point";
|
|
2
|
-
import {
|
|
3
|
-
import {Equation, Monom, Polynom} from "../algebra";
|
|
4
|
-
import {Line} from "./line";
|
|
2
|
+
import {Line, LinePropriety} from "./line";
|
|
5
3
|
import {Vector} from "./vector";
|
|
6
4
|
import {Triangle} from "./triangle";
|
|
5
|
+
import {Numeric} from "../numeric";
|
|
6
|
+
import {Fraction} from "../coefficients/fraction";
|
|
7
|
+
import {Equation} from "../algebra/equation";
|
|
8
|
+
import {Polynom} from "../algebra/polynom";
|
|
9
|
+
import {Monom} from "../algebra/monom";
|
|
7
10
|
|
|
8
11
|
export class Circle {
|
|
9
|
-
private _center: Point;
|
|
10
|
-
private _squareRadius: Fraction;
|
|
11
|
-
private _cartesian: Equation;
|
|
12
|
-
private _exists: boolean;
|
|
13
|
-
|
|
14
12
|
constructor(...values: unknown[]) {
|
|
15
13
|
this._exists = false
|
|
16
14
|
|
|
@@ -19,30 +17,42 @@ export class Circle {
|
|
|
19
17
|
}
|
|
20
18
|
}
|
|
21
19
|
|
|
20
|
+
private _center: Point;
|
|
22
21
|
|
|
23
22
|
get center(): Point {
|
|
24
23
|
return this._center;
|
|
25
24
|
}
|
|
26
25
|
|
|
27
|
-
|
|
28
|
-
get exists(): boolean {
|
|
29
|
-
return this._exists;
|
|
30
|
-
}
|
|
26
|
+
private _squareRadius: Fraction;
|
|
31
27
|
|
|
32
28
|
get squareRadius(): Fraction {
|
|
33
29
|
return this._squareRadius
|
|
34
30
|
}
|
|
35
31
|
|
|
36
|
-
|
|
32
|
+
private _cartesian: Equation;
|
|
33
|
+
|
|
34
|
+
get cartesian(): Equation {
|
|
35
|
+
return this._cartesian
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
private _exists: boolean;
|
|
39
|
+
|
|
40
|
+
get exists(): boolean {
|
|
41
|
+
return this._exists;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
get radius(): { tex: string, display: string, value: number } {
|
|
37
45
|
if (this._squareRadius.isSquare()) {
|
|
38
46
|
return {
|
|
39
47
|
tex: this._squareRadius.clone().sqrt().tex,
|
|
40
48
|
display: this._squareRadius.clone().sqrt().display,
|
|
49
|
+
value: this._squareRadius.clone().sqrt().value
|
|
41
50
|
}
|
|
42
51
|
} else {
|
|
43
52
|
return {
|
|
44
53
|
tex: `\\sqrt{${this._squareRadius.tex}}`,
|
|
45
|
-
display: `sqrt(${this._squareRadius.display})
|
|
54
|
+
display: `sqrt(${this._squareRadius.display})`,
|
|
55
|
+
value: this._squareRadius.clone().sqrt().value
|
|
46
56
|
}
|
|
47
57
|
}
|
|
48
58
|
return this._squareRadius
|
|
@@ -72,14 +82,100 @@ export class Circle {
|
|
|
72
82
|
return this._cartesian.tex
|
|
73
83
|
}
|
|
74
84
|
|
|
75
|
-
|
|
76
85
|
// TODO: reformat code for better display.
|
|
77
86
|
get display(): string {
|
|
78
87
|
return this._cartesian.display
|
|
79
88
|
}
|
|
80
89
|
|
|
81
|
-
|
|
82
|
-
|
|
90
|
+
/**
|
|
91
|
+
* Get the relative position between circle and line. It corresponds to the number of intersection.
|
|
92
|
+
* @param {Line} L
|
|
93
|
+
* @returns {number}
|
|
94
|
+
*/
|
|
95
|
+
relativePosition = (L: Line): number => {
|
|
96
|
+
let distance = L.distanceTo(this.center), radius = Math.sqrt(this._squareRadius.value)
|
|
97
|
+
|
|
98
|
+
if (distance.value - radius > 0.0000000001) {
|
|
99
|
+
return 0 // external
|
|
100
|
+
} else if (Math.abs(distance.value - radius) < 0.0000000001) {
|
|
101
|
+
return 1 // tangent
|
|
102
|
+
} else {
|
|
103
|
+
return 2 // external
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
lineIntersection = (L: Line): Point[] => {
|
|
108
|
+
let intersectionPoints: Point[] = [], solX: Fraction
|
|
109
|
+
|
|
110
|
+
if (this._cartesian === null) {
|
|
111
|
+
return []
|
|
112
|
+
}
|
|
113
|
+
const equX = this._cartesian.clone(), lineX = L.equation.clone().isolate('x'),
|
|
114
|
+
lineY = L.equation.clone().isolate('y')
|
|
115
|
+
|
|
116
|
+
if (lineX instanceof Equation && lineY instanceof Equation) {
|
|
117
|
+
equX.replaceBy('y', lineY.right).simplify()
|
|
118
|
+
equX.solve()
|
|
119
|
+
|
|
120
|
+
for (let x of equX.solutions) {
|
|
121
|
+
if (x.exact === false && isNaN(x.value)) {
|
|
122
|
+
continue
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
solX = new Fraction(x.exact === false ? x.value : x.exact)
|
|
126
|
+
intersectionPoints.push(new Point(solX.clone(), lineY.right.evaluate(solX)))
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return intersectionPoints
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
tangents = (P: Point | Fraction): Line[] => {
|
|
134
|
+
if (P instanceof Fraction) {
|
|
135
|
+
return this._tangentsWithSlope(P)
|
|
136
|
+
} else if (this.isPointOnCircle(P)) {
|
|
137
|
+
return this._tangentsThroughOnePointOnTheCircle(P)
|
|
138
|
+
} else if (this.center.distanceTo(P).value > this.radius.value) {
|
|
139
|
+
//TODO: Must check it's outside the circle
|
|
140
|
+
return this._tangentsThroughOnePointOutsideTheCircle(P)
|
|
141
|
+
} else {
|
|
142
|
+
console.log('No tangents as the point is inside !')
|
|
143
|
+
}
|
|
144
|
+
return []
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
isPointOnCircle = (P: Point): Boolean => {
|
|
148
|
+
return this._cartesian.test({x: P.x, y: P.y})
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
getPointsOnCircle = (numberIsInteger?: boolean): Point[] => {
|
|
152
|
+
if (numberIsInteger === undefined) {
|
|
153
|
+
numberIsInteger = false
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// It means searching for pythagorician triples that make a perfect square.
|
|
157
|
+
// (x-4)^2 + (y+3)^2 = 15
|
|
158
|
+
|
|
159
|
+
let triplets = Numeric.pythagoricianTripletsWithTarget(this._squareRadius.value, true)
|
|
160
|
+
|
|
161
|
+
let points: Point[] = [], pt
|
|
162
|
+
triplets.forEach(triplet => {
|
|
163
|
+
// Allow positive / negative values
|
|
164
|
+
// x-a = t => x = a + t
|
|
165
|
+
// x-a = -t => x = a - t
|
|
166
|
+
|
|
167
|
+
for (let k of [[1, 1], [-1, 1], [-1, -1], [1, -1]]) {
|
|
168
|
+
pt = new Point(
|
|
169
|
+
this.center.x.clone().add(k[0] * triplet[0]),
|
|
170
|
+
this.center.y.clone().add(k[1] * triplet[1])
|
|
171
|
+
)
|
|
172
|
+
// Check if the point is not already in points.
|
|
173
|
+
if (!pt.isInListOfPoints(points)) {
|
|
174
|
+
points.push(pt)
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
})
|
|
178
|
+
return points
|
|
83
179
|
}
|
|
84
180
|
|
|
85
181
|
clone(): Circle {
|
|
@@ -89,6 +185,59 @@ export class Circle {
|
|
|
89
185
|
return this
|
|
90
186
|
}
|
|
91
187
|
|
|
188
|
+
private _tangentsThroughOnePointOnTheCircle = (P: Point): Line[] => {
|
|
189
|
+
let CT = new Vector(this._center, P)
|
|
190
|
+
return [new Line(P, CT, LinePropriety.Perpendicular)]
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
private _tangentsThroughOnePointOutsideTheCircle = (P: Point): Line[] => {
|
|
194
|
+
// y = mx + h
|
|
195
|
+
// px, py => h = -m px + py => mx - y -m.px + py = 0 =>
|
|
196
|
+
// Centre: cx, cy, radius: r
|
|
197
|
+
// (m.cx - cy -m.px + py)^2 = r^2 * (m^2 + 1)
|
|
198
|
+
// (m(cx-py) - (cy - py))^2 = r^2 * (m^2 + 1)
|
|
199
|
+
|
|
200
|
+
let cx_px = this.center.x.clone().subtract(P.x), cy_py = this.center.y.clone().subtract(P.y),
|
|
201
|
+
polyLeft = new Polynom('x'), polyRight = new Polynom('x^2+1')
|
|
202
|
+
|
|
203
|
+
polyLeft.multiply(cx_px).subtract(cy_py).pow(2)
|
|
204
|
+
polyRight.multiply(this.squareRadius)
|
|
205
|
+
|
|
206
|
+
let equ = new Equation(polyLeft, polyRight)
|
|
207
|
+
equ.moveLeft().simplify().solve()
|
|
208
|
+
|
|
209
|
+
return equ.solutions.map(sol => {
|
|
210
|
+
// h = -m px + py
|
|
211
|
+
let h, equ = new Equation('y', 'x')
|
|
212
|
+
|
|
213
|
+
if (sol.exact instanceof Fraction) {
|
|
214
|
+
h = P.x.clone().opposed().multiply(sol.exact).add(P.y)
|
|
215
|
+
equ.right.multiply(sol.exact).add(h)
|
|
216
|
+
} else {
|
|
217
|
+
h = P.x.clone().opposed().multiply(sol.value).add(P.y)
|
|
218
|
+
equ.right.multiply(sol.value).add(h)
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return new Line(equ)
|
|
222
|
+
})
|
|
223
|
+
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
private _tangentsWithSlope = (slope: Fraction): Line[] => {
|
|
227
|
+
// d(C;t)=r => ac1+bc2 + x = +- sqrt(a^2 + b^2)*r
|
|
228
|
+
// x = -ac1-bc2 +- sqrt(a^2 + b^2)*r
|
|
229
|
+
// y = a/bx + h => ax-by + H = 0
|
|
230
|
+
|
|
231
|
+
const a = slope.numerator, b = -slope.denominator, c1 = this._center.x.clone(), c2 = this._center.y.clone(),
|
|
232
|
+
r = this._squareRadius
|
|
233
|
+
|
|
234
|
+
let sq = this._squareRadius.clone().multiply(slope.numerator ** 2 + slope.denominator ** 2),
|
|
235
|
+
x1 = c1.clone().multiply(a).opposed().subtract(c2.clone().multiply(b)).add(sq.clone().sqrt()),
|
|
236
|
+
x2 = c1.clone().multiply(a).opposed().subtract(c2.clone().multiply(b)).subtract(sq.clone().sqrt())
|
|
237
|
+
|
|
238
|
+
return [new Line(a, b, x1), new Line(a, b, x2)]
|
|
239
|
+
}
|
|
240
|
+
|
|
92
241
|
private _reset(): Circle {
|
|
93
242
|
this._center = null
|
|
94
243
|
this._squareRadius = null
|
|
@@ -128,7 +277,7 @@ export class Circle {
|
|
|
128
277
|
}
|
|
129
278
|
|
|
130
279
|
// Calculate once the different values.
|
|
131
|
-
if(this._exists) {
|
|
280
|
+
if (this._exists) {
|
|
132
281
|
this._calculateCartesian()
|
|
133
282
|
|
|
134
283
|
// If the square radius is zero or positive, the circle exists.
|
|
@@ -141,10 +290,7 @@ export class Circle {
|
|
|
141
290
|
}
|
|
142
291
|
|
|
143
292
|
private _calculateCartesian() {
|
|
144
|
-
this._cartesian = (new Equation(
|
|
145
|
-
new Polynom(`(x-(${this._center.x.display}))^2+(y-(${this._center.y.display}))^2`),
|
|
146
|
-
new Polynom(`${this._squareRadius.display}`)
|
|
147
|
-
)).moveLeft()
|
|
293
|
+
this._cartesian = (new Equation(new Polynom(`(x-(${this._center.x.display}))^2+(y-(${this._center.y.display}))^2`), new Polynom(`${this._squareRadius.display}`))).moveLeft()
|
|
148
294
|
}
|
|
149
295
|
|
|
150
296
|
private _parseCopyCircle(circle: Circle): Circle {
|
|
@@ -183,9 +329,7 @@ export class Circle {
|
|
|
183
329
|
|
|
184
330
|
if (equ.degree('x').value === 2 && equ.degree('y').value === 2) {
|
|
185
331
|
// Both must be of degree 2.
|
|
186
|
-
let x2 = equ.left.monomByDegree(2, 'x'),
|
|
187
|
-
y2 = equ.left.monomByDegree(2, 'y'),
|
|
188
|
-
x1: Monom, y1: Monom, c: Monom
|
|
332
|
+
let x2 = equ.left.monomByDegree(2, 'x'), y2 = equ.left.monomByDegree(2, 'y'), x1: Monom, y1: Monom, c: Monom
|
|
189
333
|
|
|
190
334
|
// Both square monoms must have the same coefficient.
|
|
191
335
|
if (x2.coefficient.isEqual(y2.coefficient)) {
|
|
@@ -196,10 +340,7 @@ export class Circle {
|
|
|
196
340
|
|
|
197
341
|
c = equ.left.monomByDegree(0)
|
|
198
342
|
|
|
199
|
-
this._center = new Point(
|
|
200
|
-
x1.coefficient.clone().divide(2).opposed(),
|
|
201
|
-
y1.coefficient.clone().divide(2).opposed()
|
|
202
|
-
)
|
|
343
|
+
this._center = new Point(x1.coefficient.clone().divide(2).opposed(), y1.coefficient.clone().divide(2).opposed())
|
|
203
344
|
|
|
204
345
|
this._squareRadius = c.coefficient.clone().opposed()
|
|
205
346
|
.add(this._center.x.clone().pow(2))
|
|
@@ -207,7 +348,7 @@ export class Circle {
|
|
|
207
348
|
|
|
208
349
|
this._calculateCartesian()
|
|
209
350
|
this._exists = true
|
|
210
|
-
}else{
|
|
351
|
+
} else {
|
|
211
352
|
// The circle is not a valid circle
|
|
212
353
|
this._center = null
|
|
213
354
|
this._squareRadius = null
|
|
@@ -218,57 +359,11 @@ export class Circle {
|
|
|
218
359
|
}
|
|
219
360
|
|
|
220
361
|
private _parseThroughtThreePoints(A: Point, B: Point, C: Point): Circle {
|
|
221
|
-
let T = new Triangle(A, B, C),
|
|
222
|
-
mAB = T.remarquables.mediators.AB.clone(),
|
|
362
|
+
let T = new Triangle(A, B, C), mAB = T.remarquables.mediators.AB.clone(),
|
|
223
363
|
mAC = T.remarquables.mediators.AC.clone()
|
|
224
364
|
this.parse(mAB.intersection(mAC).point, A)
|
|
225
365
|
|
|
226
366
|
return this
|
|
227
367
|
}
|
|
228
368
|
|
|
229
|
-
/**
|
|
230
|
-
* Get the relative position between circle and line. It corresponds to the number of intersection.
|
|
231
|
-
* @param {Line} L
|
|
232
|
-
* @returns {number}
|
|
233
|
-
*/
|
|
234
|
-
relativePosition = (L: Line): number => {
|
|
235
|
-
let distance = L.distanceTo(this.center),
|
|
236
|
-
radius = Math.sqrt(this._squareRadius.value)
|
|
237
|
-
|
|
238
|
-
if (distance.value - radius > 0.0000000001) {
|
|
239
|
-
return 0 // external
|
|
240
|
-
} else if (Math.abs(distance.value - radius) < 0.0000000001) {
|
|
241
|
-
return 1 // tangent
|
|
242
|
-
} else {
|
|
243
|
-
return 2 // external
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
lineIntersection = (L: Line): Point[] => {
|
|
248
|
-
let intersectionPoints: Point[] = [], solX: Fraction
|
|
249
|
-
|
|
250
|
-
if(this._cartesian===null){return []}
|
|
251
|
-
const equX = this._cartesian.clone(),
|
|
252
|
-
lineX = L.equation.clone().isolate('x'),
|
|
253
|
-
lineY = L.equation.clone().isolate('y')
|
|
254
|
-
|
|
255
|
-
if (lineX instanceof Equation && lineY instanceof Equation) {
|
|
256
|
-
equX.replaceBy('y', lineY.right).simplify()
|
|
257
|
-
equX.solve()
|
|
258
|
-
|
|
259
|
-
for(let x of equX.solutions){
|
|
260
|
-
if(x.exact===false && isNaN(x.value)){continue}
|
|
261
|
-
|
|
262
|
-
solX = new Fraction(x.exact===false?x.value:x.exact)
|
|
263
|
-
intersectionPoints.push(
|
|
264
|
-
new Point(
|
|
265
|
-
solX.clone(),
|
|
266
|
-
lineY.right.evaluate(solX)
|
|
267
|
-
)
|
|
268
|
-
)
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
return intersectionPoints
|
|
273
|
-
}
|
|
274
369
|
}
|