pimath 0.0.17 → 0.0.18
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/dev/index.html +37 -9
- package/dev/pi.js +849 -804
- package/dev/pi.js.map +1 -1
- package/dist/pi.js +1 -1
- package/dist/pi.js.map +1 -1
- package/esm/maths/algebra/equation.js +2 -2
- package/esm/maths/algebra/equation.js.map +1 -1
- package/esm/maths/algebra/monom.d.ts +1 -1
- package/esm/maths/algebra/monom.js +27 -18
- package/esm/maths/algebra/monom.js.map +1 -1
- package/esm/maths/algebra/polynom.d.ts +0 -1
- package/esm/maths/algebra/polynom.js +5 -9
- package/esm/maths/algebra/polynom.js.map +1 -1
- package/esm/maths/geometry/circle.d.ts +12 -0
- package/esm/maths/geometry/circle.js +72 -10
- package/esm/maths/geometry/circle.js.map +1 -1
- package/esm/maths/geometry/line.d.ts +18 -4
- package/esm/maths/geometry/line.js +95 -39
- package/esm/maths/geometry/line.js.map +1 -1
- package/esm/maths/geometry/point.d.ts +1 -0
- package/esm/maths/geometry/point.js +6 -0
- package/esm/maths/geometry/point.js.map +1 -1
- package/esm/maths/geometry/vector.d.ts +0 -1
- package/esm/maths/geometry/vector.js +1 -4
- package/esm/maths/geometry/vector.js.map +1 -1
- package/package.json +1 -1
- package/src/maths/algebra/equation.ts +2 -2
- package/src/maths/algebra/monom.ts +40 -25
- package/src/maths/algebra/polynom.ts +5 -10
- package/src/maths/geometry/circle.ts +106 -19
- package/src/maths/geometry/line.ts +144 -57
- package/src/maths/geometry/point.ts +9 -0
- package/src/maths/geometry/vector.ts +1 -5
- package/tests/algebra/monom.test.ts +25 -7
- package/tsconfig.json +1 -1
|
@@ -33,10 +33,6 @@ export class Monom {
|
|
|
33
33
|
// ------------------------------------------
|
|
34
34
|
// Getter and setter
|
|
35
35
|
// ------------------------------------------
|
|
36
|
-
get isMonom() {
|
|
37
|
-
return true;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
36
|
/**
|
|
41
37
|
* Get the coefficient as fraction
|
|
42
38
|
*/
|
|
@@ -311,10 +307,10 @@ export class Monom {
|
|
|
311
307
|
|
|
312
308
|
let stack: Monom[] = [], m, pow, letter, q1, q2
|
|
313
309
|
|
|
314
|
-
if(rpn.length===0){
|
|
310
|
+
if (rpn.length === 0) {
|
|
315
311
|
this.zero()
|
|
316
312
|
return this
|
|
317
|
-
}else if(rpn.length===1){
|
|
313
|
+
} else if (rpn.length === 1) {
|
|
318
314
|
const element = rpn[0]
|
|
319
315
|
|
|
320
316
|
this.one()
|
|
@@ -324,9 +320,8 @@ export class Monom {
|
|
|
324
320
|
this.setLetter(element.token, 1)
|
|
325
321
|
}
|
|
326
322
|
return this
|
|
327
|
-
}else{
|
|
323
|
+
} else {
|
|
328
324
|
// Reset the monom
|
|
329
|
-
this.one()
|
|
330
325
|
for (const element of rpn) {
|
|
331
326
|
if (element.tokenType === 'coefficient') {
|
|
332
327
|
let M = new Monom().one()
|
|
@@ -343,16 +338,15 @@ export class Monom {
|
|
|
343
338
|
q2 = (stack.pop()) || new Monom().zero()
|
|
344
339
|
q1 = (stack.pop()) || new Monom().zero()
|
|
345
340
|
|
|
346
|
-
if(q1.isZero() && q2.isZero()){
|
|
347
|
-
this.opposed()
|
|
348
|
-
break
|
|
349
|
-
}
|
|
350
341
|
stack.push(q1.subtract(q2))
|
|
342
|
+
|
|
351
343
|
break;
|
|
352
344
|
case '*':
|
|
353
345
|
// Get the last element in the stack
|
|
354
|
-
|
|
355
|
-
|
|
346
|
+
q2 = (stack.pop()) || new Monom().one()
|
|
347
|
+
q1 = (stack.pop()) || new Monom().one()
|
|
348
|
+
|
|
349
|
+
stack.push(q1.multiply(q2))
|
|
356
350
|
break
|
|
357
351
|
case '^':
|
|
358
352
|
// get the two last elements in the stack
|
|
@@ -361,16 +355,20 @@ export class Monom {
|
|
|
361
355
|
|
|
362
356
|
letter = m.variables[0]
|
|
363
357
|
|
|
364
|
-
if(letter!==undefined) {
|
|
358
|
+
if (letter !== undefined) {
|
|
365
359
|
m.setLetter(letter, pow)
|
|
366
360
|
}
|
|
367
|
-
|
|
361
|
+
|
|
362
|
+
stack.push(m)
|
|
363
|
+
// this.multiply(m.clone())
|
|
368
364
|
break
|
|
369
365
|
}
|
|
370
366
|
}
|
|
371
367
|
}
|
|
372
368
|
}
|
|
373
369
|
|
|
370
|
+
this.one()
|
|
371
|
+
this.multiply(stack[0])
|
|
374
372
|
return this
|
|
375
373
|
}
|
|
376
374
|
/**
|
|
@@ -388,6 +386,14 @@ export class Monom {
|
|
|
388
386
|
return F;
|
|
389
387
|
};
|
|
390
388
|
|
|
389
|
+
makeSame = (M: Monom):Monom => {
|
|
390
|
+
// Copy the literal parts.
|
|
391
|
+
for (let k in M._literal) {
|
|
392
|
+
this.setLetter(k, M._literal[k].clone());
|
|
393
|
+
}
|
|
394
|
+
return this
|
|
395
|
+
}
|
|
396
|
+
|
|
391
397
|
/**
|
|
392
398
|
* Create a zero value monom
|
|
393
399
|
*/
|
|
@@ -439,6 +445,9 @@ export class Monom {
|
|
|
439
445
|
add = (...M: Monom[]): Monom => {
|
|
440
446
|
for (let m of M) {
|
|
441
447
|
if (this.isSameAs(m)) {
|
|
448
|
+
if(this.isZero()){
|
|
449
|
+
this.makeSame(m)
|
|
450
|
+
}
|
|
442
451
|
this._coefficient.add(m.coefficient);
|
|
443
452
|
} else {
|
|
444
453
|
console.log('Add: Is not similar: ', m.display);
|
|
@@ -454,7 +463,10 @@ export class Monom {
|
|
|
454
463
|
subtract = (...M: Monom[]): Monom => {
|
|
455
464
|
for (let m of M) {
|
|
456
465
|
if (this.isSameAs(m)) {
|
|
457
|
-
this.
|
|
466
|
+
if(this.isZero()){
|
|
467
|
+
this.makeSame(m)
|
|
468
|
+
}
|
|
469
|
+
this._coefficient.add(m.clone().coefficient.opposed());
|
|
458
470
|
} else {
|
|
459
471
|
console.log('Subtract: Is not similar: ', m.display);
|
|
460
472
|
}
|
|
@@ -571,14 +583,17 @@ export class Monom {
|
|
|
571
583
|
M2: string[] = M.variables,
|
|
572
584
|
K: string[] = M1.concat(M2.filter((item) => M1.indexOf(item) < 0));
|
|
573
585
|
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
586
|
+
// To compare, both must be different than zero.
|
|
587
|
+
if (!this.isZero() && !M.isZero()) {
|
|
588
|
+
for (let key of K) {
|
|
589
|
+
// The setLetter is not available in one of the monom
|
|
590
|
+
if (this._literal[key] === undefined || M.literal[key] === undefined) {
|
|
591
|
+
return false;
|
|
592
|
+
}
|
|
593
|
+
// The setLetter does not have the isSame power in each monoms.
|
|
594
|
+
if (!this._literal[key].isEqual(M.literal[key])) {
|
|
595
|
+
return false;
|
|
596
|
+
}
|
|
582
597
|
}
|
|
583
598
|
}
|
|
584
599
|
|
|
@@ -34,11 +34,6 @@ export class Polynom {
|
|
|
34
34
|
return this;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
get isPolynom() {
|
|
38
|
-
return true;
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
|
|
42
37
|
// ------------------------------------------
|
|
43
38
|
// Getter and setter
|
|
44
39
|
// ------------------------------------------
|
|
@@ -365,9 +360,9 @@ export class Polynom {
|
|
|
365
360
|
add = (...values: any[]): Polynom => {
|
|
366
361
|
|
|
367
362
|
for (let value of values) {
|
|
368
|
-
if (value
|
|
363
|
+
if (value instanceof Polynom) {
|
|
369
364
|
this._monoms = this._monoms.concat(value.monoms);
|
|
370
|
-
} else if (value
|
|
365
|
+
} else if (value instanceof Monom) {
|
|
371
366
|
this._monoms.push(value.clone());
|
|
372
367
|
} else if (Number.isSafeInteger(value)) {
|
|
373
368
|
this._monoms.push(new Monom(value.toString()));
|
|
@@ -382,9 +377,9 @@ export class Polynom {
|
|
|
382
377
|
subtract = (...values: any[]): Polynom => {
|
|
383
378
|
|
|
384
379
|
for (let value of values) {
|
|
385
|
-
if (value
|
|
380
|
+
if (value instanceof Polynom) {
|
|
386
381
|
this._monoms = this._monoms.concat(value.clone().opposed().monoms);
|
|
387
|
-
} else if (value
|
|
382
|
+
} else if (value instanceof Monom) {
|
|
388
383
|
this._monoms.push(value.clone().opposed());
|
|
389
384
|
} else if (Number.isSafeInteger(value)) {
|
|
390
385
|
this._monoms.push(new Monom(value.toString()).opposed());
|
|
@@ -1100,7 +1095,7 @@ export class Polynom {
|
|
|
1100
1095
|
// Reduce the polynom.
|
|
1101
1096
|
const M = this.clone().reduce();
|
|
1102
1097
|
for (const m of M._monoms) {
|
|
1103
|
-
if (m.degree(letter)
|
|
1098
|
+
if (m.degree(letter).isEqual(degree)) {
|
|
1104
1099
|
return m.clone();
|
|
1105
1100
|
}
|
|
1106
1101
|
}
|
|
@@ -1,47 +1,134 @@
|
|
|
1
1
|
import {Point} from "./point";
|
|
2
|
-
import {Fraction} from "../coefficients
|
|
3
|
-
import {Equation} from "../algebra
|
|
4
|
-
import {
|
|
2
|
+
import {Fraction} from "../coefficients";
|
|
3
|
+
import {Equation, Monom, Polynom} from "../algebra";
|
|
4
|
+
import {Line} from "./line";
|
|
5
|
+
import {Vector} from "./vector";
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
export class Circle {
|
|
8
9
|
private _center: Point;
|
|
9
10
|
private _radius: Fraction;
|
|
11
|
+
private _squareRadius: Fraction;
|
|
12
|
+
private _cartesian: Equation;
|
|
10
13
|
private _exists: boolean;
|
|
14
|
+
|
|
11
15
|
constructor(...values: any) {
|
|
12
16
|
this._exists = false
|
|
13
17
|
|
|
14
|
-
if(values!==undefined){
|
|
18
|
+
if (values !== undefined) {
|
|
19
|
+
this.parse(...values)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
get center(): Point {
|
|
25
|
+
return this._center;
|
|
15
26
|
}
|
|
16
27
|
|
|
17
28
|
private parse(...values: any) {
|
|
18
|
-
if(values.length===
|
|
29
|
+
if (values.length === 1 && typeof values[0] === 'string') {
|
|
30
|
+
this.checkCircle(new Equation(values[0]))
|
|
31
|
+
} else if (values.length >= 2) {
|
|
19
32
|
this._center = new Point(values[0])
|
|
20
|
-
|
|
33
|
+
|
|
34
|
+
if(values[1] instanceof Point){
|
|
35
|
+
// Go through this point
|
|
36
|
+
this._squareRadius = new Vector(this._center, values[1]).normSquare
|
|
37
|
+
}else {
|
|
38
|
+
if (values[2] === true) {
|
|
39
|
+
this._squareRadius = new Fraction(values[1])
|
|
40
|
+
} else {
|
|
41
|
+
this._radius = new Fraction(values[1])
|
|
42
|
+
this._squareRadius = this._radius.clone().pow(2)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
this._cartesian = (new Equation(
|
|
46
|
+
new Polynom(`(x-(${this._center.x.display}))^2+(y-(${this._center.y.display}))^2`),
|
|
47
|
+
new Polynom(`${this._squareRadius.display}`)
|
|
48
|
+
)).moveLeft()
|
|
21
49
|
}
|
|
22
50
|
}
|
|
23
51
|
|
|
52
|
+
get radius(): { tex: string, display: string } {
|
|
53
|
+
if (this._squareRadius.isSquare()) {
|
|
54
|
+
return {
|
|
55
|
+
tex: this._squareRadius.clone().sqrt().tex,
|
|
56
|
+
display: this._squareRadius.clone().sqrt().display,
|
|
57
|
+
}
|
|
58
|
+
} else {
|
|
59
|
+
return {
|
|
60
|
+
tex: `\\sqrt{${this._squareRadius.tex}}`,
|
|
61
|
+
display: `sqrt(${this._squareRadius.display})`
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return this._squareRadius
|
|
65
|
+
}
|
|
66
|
+
|
|
24
67
|
get tex(): string {
|
|
25
68
|
let cx, cy
|
|
26
|
-
if(this._center.x.isZero()){
|
|
69
|
+
if (this._center.x.isZero()) {
|
|
27
70
|
cx = 'x^2'
|
|
28
|
-
}else{
|
|
29
|
-
cx = `\\left(x
|
|
71
|
+
} else {
|
|
72
|
+
cx = `\\left(x${this._center.x.isNegative()?'+':'-'}${this._center.x.clone().abs().tex}\\right)^2`
|
|
30
73
|
}
|
|
31
|
-
if(this._center.y.isZero()){
|
|
74
|
+
if (this._center.y.isZero()) {
|
|
32
75
|
cy = 'y^2'
|
|
33
|
-
}else{
|
|
34
|
-
cy = `\\left(y
|
|
76
|
+
} else {
|
|
77
|
+
cy = `\\left(y${this._center.y.isNegative()?'+':'-'}${this._center.y.clone().abs().tex}\\right)^2`
|
|
78
|
+
}
|
|
79
|
+
return `${cx}+${cy}=${this._squareRadius.tex}`
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
get developed(): string {
|
|
83
|
+
return this._cartesian.tex
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
checkCircle = (P: Equation): boolean => {
|
|
87
|
+
if (P.degree('x').value === 2 && P.degree('y').value === 2) {
|
|
88
|
+
// Both must be of degree 2.
|
|
89
|
+
let x2 = P.left.monomByDegree(2, 'x'),
|
|
90
|
+
y2 = P.left.monomByDegree(2, 'y'),
|
|
91
|
+
x1: Monom, y1: Monom, c: Monom
|
|
92
|
+
|
|
93
|
+
// Both square monoms must have the same coefficient.
|
|
94
|
+
if (x2.coefficient.isEqual(y2.coefficient)) {
|
|
95
|
+
P.divide(x2.coefficient)
|
|
96
|
+
|
|
97
|
+
x1 = P.left.monomByDegree(1, 'x')
|
|
98
|
+
y1 = P.left.monomByDegree(1, 'y')
|
|
99
|
+
|
|
100
|
+
c = P.left.monomByDegree(0)
|
|
101
|
+
|
|
102
|
+
this._center = new Point(
|
|
103
|
+
x1.coefficient.clone().divide(2).opposed(),
|
|
104
|
+
y1.coefficient.clone().divide(2).opposed()
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
this._squareRadius = c.coefficient.clone().opposed()
|
|
108
|
+
.add(this._center.x.clone().pow(2))
|
|
109
|
+
.add(this._center.y.clone().pow(2))
|
|
110
|
+
|
|
111
|
+
}
|
|
35
112
|
}
|
|
36
|
-
|
|
113
|
+
|
|
114
|
+
return false
|
|
37
115
|
}
|
|
38
116
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
117
|
+
/**
|
|
118
|
+
* Get the relative position between circle and line. It corresponds to the number of intersection.
|
|
119
|
+
* @param {Line} L
|
|
120
|
+
* @returns {number}
|
|
121
|
+
*/
|
|
122
|
+
relativePosition = (L: Line): number => {
|
|
123
|
+
let distance = L.distanceTo(this.center),
|
|
124
|
+
radius = Math.sqrt(this._squareRadius.value)
|
|
44
125
|
|
|
45
|
-
|
|
126
|
+
if (distance.value-radius>0.0000000001) {
|
|
127
|
+
return 0 // external
|
|
128
|
+
} else if (Math.abs(distance.value-radius)<0.0000000001) {
|
|
129
|
+
return 1 // tangent
|
|
130
|
+
} else {
|
|
131
|
+
return 2 // external
|
|
132
|
+
}
|
|
46
133
|
}
|
|
47
134
|
}
|
|
@@ -2,12 +2,17 @@
|
|
|
2
2
|
* This class works for 2d line in a plane.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import {Fraction} from "../coefficients
|
|
5
|
+
import {Fraction} from "../coefficients";
|
|
6
6
|
import {Vector} from "./vector";
|
|
7
7
|
import {Point} from "./point";
|
|
8
|
-
import {Polynom} from "../algebra
|
|
8
|
+
import {Equation, Polynom} from "../algebra";
|
|
9
9
|
import {Numeric} from "../numeric";
|
|
10
|
-
|
|
10
|
+
|
|
11
|
+
enum LinePropriety {
|
|
12
|
+
None,
|
|
13
|
+
Parallel,
|
|
14
|
+
Perpendicular
|
|
15
|
+
}
|
|
11
16
|
|
|
12
17
|
export class Line {
|
|
13
18
|
// A line is defined as the canonical form
|
|
@@ -20,19 +25,30 @@ export class Line {
|
|
|
20
25
|
private _n: Vector;
|
|
21
26
|
private _exists: boolean
|
|
22
27
|
|
|
28
|
+
private _referencePropriety: LinePropriety
|
|
29
|
+
private _referenceLine: Line
|
|
30
|
+
|
|
31
|
+
static PERPENDICULAR = LinePropriety.Perpendicular
|
|
32
|
+
static PARALLEL = LinePropriety.Parallel
|
|
33
|
+
|
|
23
34
|
constructor(...values: any) {
|
|
24
35
|
|
|
25
36
|
this._exists = false;
|
|
26
37
|
|
|
27
|
-
if (values
|
|
38
|
+
if (values.length > 0) {
|
|
28
39
|
this.parse(...values);
|
|
29
40
|
}
|
|
30
41
|
|
|
31
42
|
return this;
|
|
32
43
|
}
|
|
33
44
|
|
|
34
|
-
get isLine():boolean {
|
|
35
|
-
|
|
45
|
+
get isLine(): boolean {
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
get exists(): boolean {
|
|
50
|
+
return this._exists;
|
|
51
|
+
}
|
|
36
52
|
|
|
37
53
|
// ------------------------------------------
|
|
38
54
|
// Getter and setter
|
|
@@ -40,6 +56,7 @@ export class Line {
|
|
|
40
56
|
get equation(): Equation {
|
|
41
57
|
return new Equation(new Polynom().parse('xy', this._a, this._b, this._c), new Polynom('0')).simplify();
|
|
42
58
|
}
|
|
59
|
+
|
|
43
60
|
get tex(): { canonical: string, mxh: string, parametric: string } {
|
|
44
61
|
// canonical => ax + by + c = 0
|
|
45
62
|
// mxh => y = -a/b x - c/b
|
|
@@ -47,7 +64,7 @@ export class Line {
|
|
|
47
64
|
|
|
48
65
|
let canonical = this.equation;
|
|
49
66
|
// Make sur the first item is positive.
|
|
50
|
-
if(this._a.isNegative()){
|
|
67
|
+
if (this._a.isNegative()) {
|
|
51
68
|
canonical.multiply(-1);
|
|
52
69
|
}
|
|
53
70
|
|
|
@@ -102,6 +119,10 @@ export class Line {
|
|
|
102
119
|
return new Vector(this._a, this._b);
|
|
103
120
|
}
|
|
104
121
|
|
|
122
|
+
get director(): Vector {
|
|
123
|
+
return this._d.clone()
|
|
124
|
+
}
|
|
125
|
+
|
|
105
126
|
set d(value: Vector) {
|
|
106
127
|
this._d = value;
|
|
107
128
|
}
|
|
@@ -117,61 +138,96 @@ export class Line {
|
|
|
117
138
|
// ------------------------------------------
|
|
118
139
|
// Creation / parsing functions
|
|
119
140
|
// ------------------------------------------
|
|
120
|
-
|
|
141
|
+
/**
|
|
142
|
+
* Parse data to a line
|
|
143
|
+
* @param {any} values
|
|
144
|
+
* @returns {Line}
|
|
145
|
+
*/
|
|
146
|
+
parse = (...values: unknown[]): Line => {
|
|
121
147
|
this._exists = false;
|
|
122
148
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
149
|
+
// Nothing is given...
|
|
150
|
+
if (values.length === 0) {
|
|
151
|
+
return this
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// One value only: already a line (clone it), an Equation, a string (as Equation)
|
|
155
|
+
if (values.length === 1) {
|
|
156
|
+
if (values[0] instanceof Line) {
|
|
157
|
+
// Already a Line
|
|
158
|
+
return values[0].clone()
|
|
159
|
+
} else if (values[0] instanceof Equation) {
|
|
160
|
+
// It's an Equation
|
|
161
|
+
return this.parseEquation(values[0])
|
|
162
|
+
} else if (typeof values[0] === "string") {
|
|
163
|
+
// It's a string - create an Equation from it.
|
|
164
|
+
try {
|
|
165
|
+
let E = new Equation(values[0])
|
|
166
|
+
return this.parse(E)
|
|
167
|
+
} catch (e) {
|
|
168
|
+
return this
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (values.length === 2) {
|
|
174
|
+
if (values[0] instanceof Point && values[1] instanceof Vector) {
|
|
127
175
|
return this.parseByPointAndVector(values[0], values[1]);
|
|
128
|
-
} else if (values[0]
|
|
176
|
+
} else if (values[0] instanceof Point && values[1] instanceof Point) {
|
|
129
177
|
return this.parseByPointAndVector(values[0], new Vector(values[0], values[1]));
|
|
178
|
+
} else if (values[0] instanceof Vector && values[1] instanceof Point) {
|
|
179
|
+
return this.parseByPointAndNormal(values[1], values[0])
|
|
130
180
|
}
|
|
131
|
-
}
|
|
132
|
-
// It's a already a line - clone it !
|
|
133
|
-
if(values[0].isLine){
|
|
134
|
-
return values[0].clone();
|
|
135
|
-
}
|
|
181
|
+
}
|
|
136
182
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
183
|
+
if (values.length === 3) {
|
|
184
|
+
if (
|
|
185
|
+
(values[0] instanceof Fraction || typeof values[0] === 'number')
|
|
186
|
+
&&
|
|
187
|
+
(values[1] instanceof Fraction || typeof values[1] === 'number')
|
|
188
|
+
&&
|
|
189
|
+
(values[2] instanceof Fraction || typeof values[2] === 'number')
|
|
190
|
+
) {
|
|
191
|
+
return this.parseByCoefficient(values[0], values[1], values[2]);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
142
194
|
|
|
143
|
-
|
|
144
|
-
|
|
195
|
+
// TODO: Add the ability to create line from a normal vector
|
|
196
|
+
console.log('Someting wrong happend while creating the line')
|
|
197
|
+
return this;
|
|
198
|
+
}
|
|
145
199
|
|
|
146
|
-
|
|
147
|
-
|
|
200
|
+
parseEquation = (equ: Equation): Line => {
|
|
201
|
+
// Reorder the eequation
|
|
202
|
+
equ.reorder(true)
|
|
148
203
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
if(letters.has(elem)){
|
|
152
|
-
letters.delete(elem)}
|
|
153
|
-
}
|
|
204
|
+
// It must contain either x, y or both.
|
|
205
|
+
let letters = new Set(equ.letters());
|
|
154
206
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
207
|
+
// No 'x', no 'y' in the equations
|
|
208
|
+
if (!(letters.has('x') || letters.has('y'))) {
|
|
209
|
+
return this
|
|
210
|
+
}
|
|
159
211
|
|
|
160
|
-
|
|
161
|
-
|
|
212
|
+
// Another letter in the equation ?
|
|
213
|
+
for (let elem of ['x', 'y']) {
|
|
214
|
+
if (letters.has(elem)) {
|
|
215
|
+
letters.delete(elem)
|
|
162
216
|
}
|
|
163
217
|
}
|
|
164
|
-
// TODO: Add the ability to create line from a normal vector
|
|
165
|
-
console.log('Someting wrong happend while creating the line')
|
|
166
|
-
return this;
|
|
167
|
-
}
|
|
168
218
|
|
|
169
|
-
|
|
219
|
+
if (letters.size > 0) {
|
|
220
|
+
return this
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Everything should be ok now...
|
|
224
|
+
return this.parseByCoefficient(equ.left.monomByLetter('x').coefficient, equ.left.monomByLetter('y').coefficient, equ.left.monomByDegree(0).coefficient)
|
|
225
|
+
}
|
|
226
|
+
parseByCoefficient = (a: Fraction | number, b: Fraction | number, c: Fraction | number): Line => {
|
|
170
227
|
this._a = new Fraction(a);
|
|
171
228
|
this._b = new Fraction(b);
|
|
172
229
|
this._c = new Fraction(c);
|
|
173
230
|
|
|
174
|
-
// TODO: initialize direction and reference point
|
|
175
231
|
this._d = new Vector(this._b.clone(), this._a.clone().opposed());
|
|
176
232
|
this._OA = new Point(new Fraction().zero(), this._c.clone());
|
|
177
233
|
this._n = this._d.clone().normal();
|
|
@@ -205,6 +261,31 @@ export class Line {
|
|
|
205
261
|
return this;
|
|
206
262
|
}
|
|
207
263
|
|
|
264
|
+
parseByPointAndNormal = (P: Point, n: Vector): Line => {
|
|
265
|
+
return this.parseByCoefficient(
|
|
266
|
+
n.x,
|
|
267
|
+
n.y,
|
|
268
|
+
P.x.clone().multiply(n.x)
|
|
269
|
+
.add(P.y.clone().multiply(n.y)).opposed()
|
|
270
|
+
)
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
parseByPointAndLine = (P: Point, L: Line, orientation?: LinePropriety): Line => {
|
|
274
|
+
|
|
275
|
+
if (orientation === undefined) {
|
|
276
|
+
orientation = LinePropriety.Parallel
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
if (orientation === LinePropriety.Parallel) {
|
|
280
|
+
return this.parseByPointAndNormal(P, L.normal)
|
|
281
|
+
} else if (orientation === LinePropriety.Perpendicular) {
|
|
282
|
+
return this.parseByPointAndNormal(P, L.director)
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
this._exists = false
|
|
286
|
+
return this
|
|
287
|
+
}
|
|
288
|
+
|
|
208
289
|
clone = (): Line => {
|
|
209
290
|
this._a = this._a.clone();
|
|
210
291
|
this._b = this._b.clone();
|
|
@@ -214,6 +295,7 @@ export class Line {
|
|
|
214
295
|
this._OA = this._OA.clone();
|
|
215
296
|
this._n = this._n.clone();
|
|
216
297
|
|
|
298
|
+
this._exists = this.exists
|
|
217
299
|
return this;
|
|
218
300
|
}
|
|
219
301
|
// ------------------------------------------
|
|
@@ -320,7 +402,7 @@ export class Line {
|
|
|
320
402
|
)
|
|
321
403
|
|
|
322
404
|
// There is an intersection point
|
|
323
|
-
if(iPt.hasIntersection) {
|
|
405
|
+
if (iPt.hasIntersection) {
|
|
324
406
|
return iPt.point.x.value >= Math.min(A.x.value, B.x.value)
|
|
325
407
|
&& iPt.point.x.value <= Math.max(A.x.value, B.x.value)
|
|
326
408
|
&& iPt.point.y.value >= Math.min(A.y.value, B.y.value)
|
|
@@ -328,36 +410,41 @@ export class Line {
|
|
|
328
410
|
}
|
|
329
411
|
return false;
|
|
330
412
|
}
|
|
413
|
+
|
|
331
414
|
// ------------------------------------------
|
|
332
415
|
// Special functions
|
|
333
416
|
// ------------------------------------------
|
|
334
|
-
canonicalAsFloatCoefficient(decimals: number): string{
|
|
335
|
-
if(decimals===undefined){
|
|
417
|
+
canonicalAsFloatCoefficient(decimals: number): string {
|
|
418
|
+
if (decimals === undefined) {
|
|
336
419
|
decimals = 2;
|
|
337
420
|
}
|
|
338
421
|
|
|
339
422
|
let ca = this._a.value,
|
|
340
423
|
cb = this._b.value,
|
|
341
|
-
cc= this._c.value,
|
|
424
|
+
cc = this._c.value,
|
|
342
425
|
canonical = '';
|
|
343
426
|
|
|
344
|
-
if(!this._a.isZero()){
|
|
345
|
-
if(this._a.isOne()){
|
|
427
|
+
if (!this._a.isZero()) {
|
|
428
|
+
if (this._a.isOne()) {
|
|
346
429
|
canonical = 'x'
|
|
347
|
-
}else if(this._a.clone().opposed().isOne()){
|
|
430
|
+
} else if (this._a.clone().opposed().isOne()) {
|
|
348
431
|
canonical = '-x'
|
|
349
|
-
}else{
|
|
350
|
-
canonical = this._a.value.toFixed(decimals)+'x'
|
|
432
|
+
} else {
|
|
433
|
+
canonical = this._a.value.toFixed(decimals) + 'x'
|
|
351
434
|
}
|
|
352
435
|
}
|
|
353
436
|
|
|
354
|
-
if(!this._b.isZero()){
|
|
355
|
-
if(this._b.isPositive()){
|
|
437
|
+
if (!this._b.isZero()) {
|
|
438
|
+
if (this._b.isPositive()) {
|
|
439
|
+
canonical += '+'
|
|
440
|
+
}
|
|
356
441
|
canonical += this._b.value.toFixed(decimals) + 'y'
|
|
357
442
|
}
|
|
358
443
|
|
|
359
|
-
if(!this._c.isZero()){
|
|
360
|
-
if(this._c.isPositive()){
|
|
444
|
+
if (!this._c.isZero()) {
|
|
445
|
+
if (this._c.isPositive()) {
|
|
446
|
+
canonical += '+'
|
|
447
|
+
}
|
|
361
448
|
canonical += this._c.value.toFixed(decimals)
|
|
362
449
|
}
|
|
363
450
|
|
|
@@ -53,6 +53,15 @@ export class Point {
|
|
|
53
53
|
return `\\left(${pts.join(';')}\\right)`
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
get display(): string {
|
|
57
|
+
let pts = [];
|
|
58
|
+
|
|
59
|
+
pts.push(this._x.tex);
|
|
60
|
+
pts.push(this._y.tex);
|
|
61
|
+
|
|
62
|
+
return `(${pts.join(';')})`
|
|
63
|
+
}
|
|
64
|
+
|
|
56
65
|
// ------------------------------------------
|
|
57
66
|
// Creation / parsing functions
|
|
58
67
|
// ------------------------------------------
|