pimath 0.0.126 → 0.0.127
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/package.json +1 -1
- package/src/maths/algebra/polynom.ts +9 -16
- package/src/maths/geometry/line.ts +22 -25
- package/src/maths/geometry/point.ts +43 -29
- package/src/maths/randomization/random.ts +7 -0
- package/src/maths/randomization/rndGeometryCircle.ts +50 -0
- package/src/maths/randomization/rndTypes.ts +10 -4
- package/tests/algebra/polynom.test.ts +10 -0
- package/tests/geometry/circle.test.ts +222 -1
- package/tests/numeric.test.ts +19 -3
package/package.json
CHANGED
|
@@ -23,6 +23,13 @@ export interface IEuclidian {
|
|
|
23
23
|
*/
|
|
24
24
|
export class Polynom {
|
|
25
25
|
private _rawString: string;
|
|
26
|
+
private _dirty_factors: boolean
|
|
27
|
+
private _dirty_zeroes: boolean
|
|
28
|
+
private _euclidianCache: { [Key: string]: IEuclidian }
|
|
29
|
+
private _factors: Polynom[];
|
|
30
|
+
private _monoms: Monom[];
|
|
31
|
+
private _texString: string;
|
|
32
|
+
private _zeroes: ISolution[]
|
|
26
33
|
|
|
27
34
|
/**
|
|
28
35
|
*
|
|
@@ -40,8 +47,6 @@ export class Polynom {
|
|
|
40
47
|
return this;
|
|
41
48
|
}
|
|
42
49
|
|
|
43
|
-
private _dirty_factors: boolean
|
|
44
|
-
|
|
45
50
|
// ------------------------------------------
|
|
46
51
|
get dirty_factors(): boolean {
|
|
47
52
|
return this._dirty_factors;
|
|
@@ -51,8 +56,6 @@ export class Polynom {
|
|
|
51
56
|
this._dirty_factors = value;
|
|
52
57
|
}
|
|
53
58
|
|
|
54
|
-
private _dirty_zeroes: boolean
|
|
55
|
-
|
|
56
59
|
get dirty_zeroes(): boolean {
|
|
57
60
|
return this._dirty_zeroes;
|
|
58
61
|
}
|
|
@@ -61,8 +64,6 @@ export class Polynom {
|
|
|
61
64
|
this._dirty_zeroes = value;
|
|
62
65
|
}
|
|
63
66
|
|
|
64
|
-
private _euclidianCache: { [Key: string]: IEuclidian }
|
|
65
|
-
|
|
66
67
|
get euclidianCache(): { [p: string]: IEuclidian } {
|
|
67
68
|
return this._euclidianCache;
|
|
68
69
|
}
|
|
@@ -71,8 +72,6 @@ export class Polynom {
|
|
|
71
72
|
this._euclidianCache = value;
|
|
72
73
|
}
|
|
73
74
|
|
|
74
|
-
private _factors: Polynom[];
|
|
75
|
-
|
|
76
75
|
get factors(): Polynom[] {
|
|
77
76
|
return this.factorize()
|
|
78
77
|
}
|
|
@@ -82,8 +81,6 @@ export class Polynom {
|
|
|
82
81
|
this._factors = value;
|
|
83
82
|
}
|
|
84
83
|
|
|
85
|
-
private _monoms: Monom[];
|
|
86
|
-
|
|
87
84
|
// ------------------------------------------
|
|
88
85
|
get monoms() {
|
|
89
86
|
return this._monoms;
|
|
@@ -93,14 +90,10 @@ export class Polynom {
|
|
|
93
90
|
this._monoms = M;
|
|
94
91
|
}
|
|
95
92
|
|
|
96
|
-
private _texString: string;
|
|
97
|
-
|
|
98
93
|
get texString(): string {
|
|
99
94
|
return this._texString;
|
|
100
95
|
}
|
|
101
96
|
|
|
102
|
-
private _zeroes: ISolution[]
|
|
103
|
-
|
|
104
97
|
get zeroes(): ISolution[] {
|
|
105
98
|
return this.getZeroes()
|
|
106
99
|
}
|
|
@@ -495,11 +488,11 @@ export class Polynom {
|
|
|
495
488
|
// Get the greatest monom divided by the max monom of the divider
|
|
496
489
|
newM = reminder.monomByDegree(undefined, letter).clone().divide(maxMP);
|
|
497
490
|
|
|
498
|
-
if (newM.isZero())
|
|
491
|
+
if (newM.isZero()) continue;
|
|
499
492
|
|
|
500
493
|
// Get the new quotient and reminder.
|
|
501
494
|
quotient.add(newM);
|
|
502
|
-
reminder.subtract(P.clone().multiply(newM));
|
|
495
|
+
reminder.subtract(P.clone().multiply(newM)).reduce();
|
|
503
496
|
|
|
504
497
|
// Check if the reminder is zero.
|
|
505
498
|
if (newM.degree(letter).isZero()) break
|
|
@@ -9,7 +9,6 @@ import {Fraction} from "../coefficients/fraction";
|
|
|
9
9
|
import {Equation} from "../algebra/equation";
|
|
10
10
|
import {Polynom} from "../algebra/polynom";
|
|
11
11
|
import {Random} from "../randomization/random";
|
|
12
|
-
import {LinearSystem} from "../algebra/linearSystem";
|
|
13
12
|
import {Monom} from "../algebra/monom";
|
|
14
13
|
|
|
15
14
|
export enum LinePropriety {
|
|
@@ -26,7 +25,20 @@ export class Line {
|
|
|
26
25
|
private _referencePropriety: LinePropriety
|
|
27
26
|
private _referenceLine: Line
|
|
28
27
|
private _reduceBeforeDisplay: boolean
|
|
28
|
+
// ax + by + c = 0
|
|
29
|
+
private _a: Fraction;
|
|
30
|
+
private _b: Fraction;
|
|
31
|
+
private _c: Fraction;
|
|
32
|
+
private _OA: Point;
|
|
33
|
+
private _d: Vector;
|
|
34
|
+
private _n: Vector;
|
|
35
|
+
private _exists: boolean
|
|
29
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Value can be a mix of:
|
|
39
|
+
*
|
|
40
|
+
* @param values
|
|
41
|
+
*/
|
|
30
42
|
constructor(...values: unknown[]) {
|
|
31
43
|
|
|
32
44
|
this._exists = false;
|
|
@@ -39,19 +51,17 @@ export class Line {
|
|
|
39
51
|
return this;
|
|
40
52
|
}
|
|
41
53
|
|
|
42
|
-
// ax + by + c = 0
|
|
43
|
-
private _a: Fraction;
|
|
44
|
-
|
|
45
54
|
get a(): Fraction {
|
|
46
55
|
return this._a;
|
|
47
56
|
}
|
|
48
57
|
|
|
58
|
+
// ------------------------------------------
|
|
59
|
+
// Getter and setter
|
|
60
|
+
|
|
49
61
|
set a(value: Fraction) {
|
|
50
62
|
this._a = value;
|
|
51
63
|
}
|
|
52
64
|
|
|
53
|
-
private _b: Fraction;
|
|
54
|
-
|
|
55
65
|
get b(): Fraction {
|
|
56
66
|
return this._b;
|
|
57
67
|
}
|
|
@@ -60,21 +70,14 @@ export class Line {
|
|
|
60
70
|
this._b = value;
|
|
61
71
|
}
|
|
62
72
|
|
|
63
|
-
private _c: Fraction;
|
|
64
|
-
|
|
65
73
|
get c(): Fraction {
|
|
66
74
|
return this._c;
|
|
67
75
|
}
|
|
68
76
|
|
|
69
|
-
// ------------------------------------------
|
|
70
|
-
// Getter and setter
|
|
71
|
-
|
|
72
77
|
set c(value: Fraction) {
|
|
73
78
|
this._c = value;
|
|
74
79
|
}
|
|
75
80
|
|
|
76
|
-
private _OA: Point;
|
|
77
|
-
|
|
78
81
|
get OA(): Point {
|
|
79
82
|
return this._OA;
|
|
80
83
|
}
|
|
@@ -83,8 +86,6 @@ export class Line {
|
|
|
83
86
|
this._OA = value;
|
|
84
87
|
}
|
|
85
88
|
|
|
86
|
-
private _d: Vector;
|
|
87
|
-
|
|
88
89
|
get d(): Vector {
|
|
89
90
|
return this._d;
|
|
90
91
|
}
|
|
@@ -93,14 +94,10 @@ export class Line {
|
|
|
93
94
|
this._d = value;
|
|
94
95
|
}
|
|
95
96
|
|
|
96
|
-
private _n: Vector;
|
|
97
|
-
|
|
98
97
|
get n(): Vector {
|
|
99
98
|
return this._n;
|
|
100
99
|
}
|
|
101
100
|
|
|
102
|
-
private _exists: boolean
|
|
103
|
-
|
|
104
101
|
get exists(): boolean {
|
|
105
102
|
return this._exists;
|
|
106
103
|
}
|
|
@@ -108,19 +105,19 @@ export class Line {
|
|
|
108
105
|
// ------------------------------------------
|
|
109
106
|
get equation(): Equation {
|
|
110
107
|
let equ = new Equation(new Polynom().parse('xy', this._a, this._b, this._c), new Polynom('0'))
|
|
111
|
-
if(this._reduceBeforeDisplay) {
|
|
108
|
+
if (this._reduceBeforeDisplay) {
|
|
112
109
|
return equ.simplify();
|
|
113
|
-
}else{
|
|
110
|
+
} else {
|
|
114
111
|
return equ
|
|
115
112
|
}
|
|
116
113
|
}
|
|
117
114
|
|
|
118
115
|
get system(): { x: Equation, y: Equation } {
|
|
119
116
|
let e1 = new Equation(
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
117
|
+
new Polynom('x'),
|
|
118
|
+
new Polynom(this._OA.x)
|
|
119
|
+
.add(new Monom('k').multiplyByNumber(this._d.x))
|
|
120
|
+
),
|
|
124
121
|
e2 = new Equation(
|
|
125
122
|
new Polynom('y'),
|
|
126
123
|
new Polynom(this._OA.y)
|
|
@@ -73,6 +73,20 @@ export class Point {
|
|
|
73
73
|
|
|
74
74
|
// ------------------------------------------
|
|
75
75
|
// Creation / parsing functions
|
|
76
|
+
|
|
77
|
+
get key(): string {
|
|
78
|
+
return `${this.x.display};${this.y.display}`
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ------------------------------------------
|
|
82
|
+
static pmatrix = (a: any, b: any, c?: any): string => {
|
|
83
|
+
if (c === undefined) {
|
|
84
|
+
return `\\begin{pmatrix} ${a.tex ? a.tex : a} \\\\ ${b.tex ? b.tex : b} \\end{pmatrix}`;
|
|
85
|
+
} else {
|
|
86
|
+
return `\\begin{pmatrix} ${a.tex ? a.tex : a} \\\\ ${b.tex ? b.tex : b} \\\\ ${c.tex ? c.tex : c} \\end{pmatrix}`;
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
|
|
76
90
|
// ------------------------------------------
|
|
77
91
|
parse = (...values: unknown[]): Point => {
|
|
78
92
|
// Initialize the value.
|
|
@@ -103,9 +117,9 @@ export class Point {
|
|
|
103
117
|
}
|
|
104
118
|
|
|
105
119
|
// Value given as an object with {x: value, y: value}
|
|
106
|
-
if(values[0] instanceof PointXY){
|
|
107
|
-
|
|
108
|
-
|
|
120
|
+
if (values[0] instanceof PointXY) {
|
|
121
|
+
this._x = new Fraction(values[0].x).reduce()
|
|
122
|
+
this._y = new Fraction(values[0].y).reduce()
|
|
109
123
|
return this
|
|
110
124
|
} else {
|
|
111
125
|
return this.zero()
|
|
@@ -138,6 +152,8 @@ export class Point {
|
|
|
138
152
|
this.zero();
|
|
139
153
|
return this;
|
|
140
154
|
}
|
|
155
|
+
// ------------------------------------------
|
|
156
|
+
// Display functions
|
|
141
157
|
|
|
142
158
|
middleOf = (P1: Point, P2: Point): Point => {
|
|
143
159
|
this._x = P1.x.clone().add(P2.x).divide(2);
|
|
@@ -146,17 +162,6 @@ export class Point {
|
|
|
146
162
|
return this;
|
|
147
163
|
}
|
|
148
164
|
// ------------------------------------------
|
|
149
|
-
// Display functions
|
|
150
|
-
// ------------------------------------------
|
|
151
|
-
texValues = (numberOfDigits: number): string => {
|
|
152
|
-
let pts = [];
|
|
153
|
-
|
|
154
|
-
pts.push(this._x.value.toFixed(numberOfDigits === undefined ? 2 : numberOfDigits));
|
|
155
|
-
pts.push(this._y.value.toFixed(numberOfDigits === undefined ? 2 : numberOfDigits));
|
|
156
|
-
|
|
157
|
-
return `\\left(${pts.join(';')}\\right)`
|
|
158
|
-
}
|
|
159
|
-
// ------------------------------------------
|
|
160
165
|
// Mathematical operations
|
|
161
166
|
// ------------------------------------------
|
|
162
167
|
|
|
@@ -166,36 +171,45 @@ export class Point {
|
|
|
166
171
|
|
|
167
172
|
// ------------------------------------------
|
|
168
173
|
// Static functions
|
|
174
|
+
|
|
175
|
+
translate = (value: { x: number | Fraction, y: number | Fraction }): Point => {
|
|
176
|
+
this._x = this._x.add(value.x)
|
|
177
|
+
this._y = this._y.add(value.y)
|
|
178
|
+
return this
|
|
179
|
+
}
|
|
180
|
+
|
|
169
181
|
// ------------------------------------------
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
182
|
+
texValues = (numberOfDigits: number): string => {
|
|
183
|
+
let pts = [];
|
|
184
|
+
|
|
185
|
+
pts.push(this._x.value.toFixed(numberOfDigits === undefined ? 2 : numberOfDigits));
|
|
186
|
+
pts.push(this._y.value.toFixed(numberOfDigits === undefined ? 2 : numberOfDigits));
|
|
187
|
+
|
|
188
|
+
return `\\left(${pts.join(';')}\\right)`
|
|
189
|
+
}
|
|
177
190
|
|
|
178
|
-
distanceTo = (item:Point|Line): { value: number, fraction: Fraction, tex: string } => {
|
|
191
|
+
distanceTo = (item: Point | Line): { value: number, fraction: Fraction, tex: string } => {
|
|
179
192
|
let value = 0, fraction = new Fraction(), tex = ''
|
|
180
193
|
|
|
181
|
-
if(item instanceof Line){
|
|
194
|
+
if (item instanceof Line) {
|
|
182
195
|
return item.distanceTo(this)
|
|
183
|
-
}else if(item instanceof Point){
|
|
196
|
+
} else if (item instanceof Point) {
|
|
184
197
|
let V = new Vector(this, item)
|
|
185
198
|
|
|
186
199
|
value = V.norm
|
|
187
200
|
fraction = V.normSquare.sqrt()
|
|
188
201
|
tex = V.normSquare.isSquare() ? fraction.tex : `\\sqrt{\\frac{ ${V.normSquare.numerator} }{ ${V.normSquare.denominator} }}`
|
|
189
202
|
}
|
|
190
|
-
return {
|
|
203
|
+
return {value, fraction, tex}
|
|
191
204
|
}
|
|
192
205
|
|
|
193
|
-
get key(): string {
|
|
194
|
-
return `${this.x.display};${this.y.display}`
|
|
195
|
-
}
|
|
196
206
|
isInListOfPoints = (list: Point[]): boolean => {
|
|
197
|
-
const keyList = list.map(x=>x.key)
|
|
207
|
+
const keyList = list.map(x => x.key)
|
|
198
208
|
|
|
199
209
|
return keyList.includes(this.key)
|
|
200
210
|
}
|
|
211
|
+
|
|
212
|
+
isEqual = (pt: Point): boolean => {
|
|
213
|
+
return this.x.isEqual(pt.x) && this.y.isEqual(pt.y)
|
|
214
|
+
}
|
|
201
215
|
}
|
|
@@ -3,6 +3,7 @@ import {rndMonom} from "./rndMonom";
|
|
|
3
3
|
import {rndHelpers} from "./rndHelpers";
|
|
4
4
|
import {
|
|
5
5
|
randomCoefficientConfig,
|
|
6
|
+
randomGeometryCircleConfig,
|
|
6
7
|
randomGeometryLineConfig,
|
|
7
8
|
randomGeometryPointConfig,
|
|
8
9
|
randomMonomConfig,
|
|
@@ -16,6 +17,8 @@ import {Line} from "../geometry/line";
|
|
|
16
17
|
import {rndGeometryLine} from "./rndGeometryLine";
|
|
17
18
|
import {Point} from "../geometry/point";
|
|
18
19
|
import {rndGeometryPoint} from "./rndGeometryPoint";
|
|
20
|
+
import {Circle} from "../geometry/circle";
|
|
21
|
+
import {rndGeometryCircle} from "./rndGeometryCircle";
|
|
19
22
|
|
|
20
23
|
export * from "./rndTypes"
|
|
21
24
|
|
|
@@ -69,5 +72,9 @@ export namespace Random {
|
|
|
69
72
|
return (new rndGeometryPoint(config).generate())
|
|
70
73
|
}
|
|
71
74
|
|
|
75
|
+
export function circle(config?: randomGeometryCircleConfig): Circle {
|
|
76
|
+
return (new rndGeometryCircle(config).generate())
|
|
77
|
+
}
|
|
78
|
+
|
|
72
79
|
}
|
|
73
80
|
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import {randomCore} from "./randomCore";
|
|
2
|
+
import {Random, randomGeometryCircleConfig} from "./random";
|
|
3
|
+
import {Circle} from "../geometry/circle";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Create a random monom based on a based configuration
|
|
7
|
+
*/
|
|
8
|
+
export class rndGeometryCircle extends randomCore {
|
|
9
|
+
declare protected _config: randomGeometryCircleConfig
|
|
10
|
+
declare protected _defaultConfig: randomGeometryCircleConfig
|
|
11
|
+
|
|
12
|
+
generate = (): Circle => {
|
|
13
|
+
const center = Random.Geometry.point(this._config.center)
|
|
14
|
+
|
|
15
|
+
let rv, r
|
|
16
|
+
if (this._config.pointsOnCircle === 8) {
|
|
17
|
+
rv = Random.number(1, 3),
|
|
18
|
+
r = rv ** 2 + (rv + 1) ** 2
|
|
19
|
+
} else {
|
|
20
|
+
r = Random.number(1, 20)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const c = new Circle(center, r, true)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
// let pts = c.getPointsOnCircle(true)
|
|
27
|
+
//
|
|
28
|
+
// pts = Random.shuffle(pts)
|
|
29
|
+
// let ptt = pts.shift(),
|
|
30
|
+
// pt1 = pts.shift(),
|
|
31
|
+
// pt2
|
|
32
|
+
//
|
|
33
|
+
// for (let pt of pts) {
|
|
34
|
+
// if (!pt1.x.isEqual(pt.x) && !pt1.y.isEqual(pt.y) && !A.isEqual(new Point().middleOf(pt1, pt))) {
|
|
35
|
+
// pt2 = pt.clone()
|
|
36
|
+
// break
|
|
37
|
+
// }
|
|
38
|
+
// }
|
|
39
|
+
|
|
40
|
+
return c
|
|
41
|
+
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
constructor(userConfig?: randomGeometryCircleConfig) {
|
|
45
|
+
super();
|
|
46
|
+
|
|
47
|
+
this._defaultConfig = {}
|
|
48
|
+
this._config = this.mergeConfig(userConfig, this._defaultConfig)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -4,14 +4,14 @@ export type randomCoefficientConfig = {
|
|
|
4
4
|
negative?: boolean,
|
|
5
5
|
max?: number,
|
|
6
6
|
reduced?: boolean,
|
|
7
|
-
zero?:boolean,
|
|
8
|
-
natural?:boolean
|
|
7
|
+
zero?: boolean,
|
|
8
|
+
natural?: boolean
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export type randomMonomConfig = {
|
|
12
12
|
letters?: string,
|
|
13
13
|
degree?: number,
|
|
14
|
-
fraction?: boolean|randomCoefficientConfig,
|
|
14
|
+
fraction?: boolean | randomCoefficientConfig,
|
|
15
15
|
zero?: boolean
|
|
16
16
|
}
|
|
17
17
|
|
|
@@ -29,9 +29,15 @@ export type randomGeometryLineConfig = {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
export type randomGeometryPointConfig
|
|
32
|
+
export type randomGeometryPointConfig = {
|
|
33
33
|
quadrant?: number,
|
|
34
34
|
axis?: string | boolean,
|
|
35
35
|
fraction?: boolean,
|
|
36
36
|
max?: number
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export type randomGeometryCircleConfig = {
|
|
40
|
+
center?: randomGeometryPointConfig,
|
|
41
|
+
radius?: number,
|
|
42
|
+
pointsOnCircle?: number
|
|
37
43
|
}
|
|
@@ -67,6 +67,16 @@ describe('Polynom tests', () => {
|
|
|
67
67
|
expect(euclidian.reminder.tex).to.be.equal('12')
|
|
68
68
|
});
|
|
69
69
|
|
|
70
|
+
it('should calculate the quotient and reminder with similar polynom', () => {
|
|
71
|
+
let P = new Polynom('6x^5+12x^4+3x^3+x^2-7x+6'),
|
|
72
|
+
D = new Polynom('x^3+2x^2-2x-4')
|
|
73
|
+
|
|
74
|
+
let euclidian = P.euclidian(D);
|
|
75
|
+
|
|
76
|
+
expect(euclidian.quotient.display).to.be.equal('6x^(2)+15')
|
|
77
|
+
expect(euclidian.reminder.display).to.be.equal('-5x^(2)+23x+66')
|
|
78
|
+
})
|
|
79
|
+
|
|
70
80
|
it('should reduce', () => {
|
|
71
81
|
let P = new Polynom('15x-19x+24+4x-12')
|
|
72
82
|
P.reduce()
|
|
@@ -4,6 +4,8 @@ import {Circle} from "../../src/maths/geometry/circle";
|
|
|
4
4
|
import {Line} from "../../src/maths/geometry/line";
|
|
5
5
|
import {Point} from "../../src/maths/geometry/point";
|
|
6
6
|
import {Fraction} from "../../src/maths/coefficients/fraction";
|
|
7
|
+
import {Random} from "../../src/maths/randomization/random";
|
|
8
|
+
import {Vector} from "../../src/maths/geometry/vector";
|
|
7
9
|
|
|
8
10
|
describe('Circle', function () {
|
|
9
11
|
it('should calculate the intersection of a circle and a line', function () {
|
|
@@ -67,7 +69,226 @@ describe('Circle', function () {
|
|
|
67
69
|
// console.log(circle.tex)
|
|
68
70
|
})
|
|
69
71
|
|
|
70
|
-
|
|
72
|
+
it('tangentes pt ext', () => {
|
|
73
|
+
function makeCircle(): { circle: Circle, point: Point, tangents: Line[] } {
|
|
74
|
+
let A = Random.Geometry.point({axis: false}),
|
|
75
|
+
rv = Random.number(1, 3),
|
|
76
|
+
r = rv ** 2 + (rv + 1) ** 2
|
|
77
|
+
let c = new Circle(A, r, true)
|
|
78
|
+
let pts = c.getPointsOnCircle(true)
|
|
79
|
+
|
|
80
|
+
pts = Random.shuffle(pts)
|
|
81
|
+
let pt1: Point, pt2: Point, t1: Line, t2: Line, I: Point, n: Vector
|
|
82
|
+
|
|
83
|
+
pt1 = pts.shift()
|
|
84
|
+
for (let pt of pts) {
|
|
85
|
+
// Pas vertical / horizontal
|
|
86
|
+
n = new Vector(A, pt)
|
|
87
|
+
|
|
88
|
+
if (!n.x.isZero() && !n.y.isZero() && // pas vertical / horizontal
|
|
89
|
+
!pt1.x.isEqual(pt.x) && !pt1.y.isEqual(pt.y) && // pas le même point
|
|
90
|
+
!A.isEqual(new Point().middleOf(pt1, pt)) // pas l'un en face de l'autre
|
|
91
|
+
) {
|
|
92
|
+
pt2 = pt.clone()
|
|
93
|
+
|
|
94
|
+
t1 = c.tangents(pt1)[0]
|
|
95
|
+
t2 = c.tangents(pt2)[0]
|
|
96
|
+
const intersection = t1.intersection(t2)
|
|
97
|
+
|
|
98
|
+
if (intersection.hasIntersection && intersection.point.x.isRelative()) {
|
|
99
|
+
I = intersection.point
|
|
100
|
+
break
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
circle: c,
|
|
108
|
+
tangents: [t1, t2],
|
|
109
|
+
point: I
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
for (let i = 0; i < 30; i++) {
|
|
114
|
+
let {circle, tangents, point} = makeCircle()
|
|
115
|
+
console.log(`\\textbf{(exercice ${i + 1})}
|
|
116
|
+
|
|
117
|
+
Calculer l'équation cartésiennes des tangentes au cercle \\( (\\Gamma): ${circle.tex} \\) passant par le point \\(P=${point.tex} \\)
|
|
118
|
+
\\iftoggle{master}{
|
|
119
|
+
(I) \\( ${tangents[0].tex.canonical} \\quad ${tangents[1].tex.canonical} \\)
|
|
120
|
+
}{}
|
|
121
|
+
\\vfill
|
|
122
|
+
${i % 2 === 1 ? '\\newpage' : ''}
|
|
123
|
+
`)
|
|
124
|
+
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
const C = new PiMath.Geometry.Circle(circle.value),
|
|
128
|
+
pts = C.getPointsOnCircle()
|
|
129
|
+
|
|
130
|
+
code.value = `C(${C.center.x.value},${C.center.y.value})
|
|
131
|
+
c=circ C,${C.radius.value}`
|
|
132
|
+
|
|
133
|
+
let tangents = []
|
|
134
|
+
pts.forEach((pt, index) => {
|
|
135
|
+
let tg = C.tangents(pt)[0]
|
|
136
|
+
tangents.push(tg)
|
|
137
|
+
code.value += `\nT${index + 1}(${pt.x.value},${pt.y.value})->tex:T_${index + 1}=@`
|
|
138
|
+
code.value += `\nt${index + 1}=line ${tg.tex.canonical}`
|
|
139
|
+
|
|
140
|
+
tangentPerPoints.value.push(`T_${index+1}(${pt.x.tex};${pt.y.tex})\\implies ${tg.tex.canonical}`)
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
for (let i = 0; i < tangents.length; i++) {
|
|
144
|
+
for (let j = i + 1; j < tangents.length; j++) {
|
|
145
|
+
let intersection = tangents[i].intersection(tangents[j])
|
|
146
|
+
|
|
147
|
+
if (intersection.hasIntersection) {
|
|
148
|
+
if (!intersection.point.isInListOfPoints(pts)) {
|
|
149
|
+
intersection.point.name=`I_{${i + 1}-${j + 1}}`
|
|
150
|
+
intersectionPoints.value.push({
|
|
151
|
+
point: `I_{${i+1}-${j+1}}${intersection.point.tex}`,
|
|
152
|
+
tangent1: tangents[i].tex.canonical,
|
|
153
|
+
tangent2: tangents[j].tex.canonical
|
|
154
|
+
})
|
|
155
|
+
code.value += `\nI_${i + 1}_${j + 1}(${intersection.point.x.value},${intersection.point.y.value})->tex:I_{${i+1}-${i+2}}=@`
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
*/
|
|
161
|
+
})
|
|
162
|
+
it('tangentes temp tests', () => {
|
|
163
|
+
function makeCircle(): { circle: Circle, point: Point, tangent: Line, symetric: Line } {
|
|
164
|
+
let A = Random.Geometry.point({axis: false}),
|
|
165
|
+
rv = Random.number(1, 3),
|
|
166
|
+
r = rv ** 2 + (rv + 1) ** 2
|
|
167
|
+
let c = new Circle(A, r, true)
|
|
168
|
+
let pts = c.getPointsOnCircle(true)
|
|
169
|
+
|
|
170
|
+
pts = Random.shuffle(pts)
|
|
171
|
+
let pt: Point, n: Vector
|
|
172
|
+
for (let p of pts) {
|
|
173
|
+
n = new Vector(A, p)
|
|
174
|
+
if (!n.x.isZero() && !n.y.isZero()) {
|
|
175
|
+
pt = p
|
|
176
|
+
break
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const p2 = new Point(A.x.clone(), A.y.clone()).translate({x: n.x.opposed(), y: n.y.opposed()})
|
|
181
|
+
const t = new Line(n, pt)
|
|
182
|
+
const s = new Line(n, p2)
|
|
183
|
+
return {
|
|
184
|
+
circle: c,
|
|
185
|
+
point: pt,
|
|
186
|
+
tangent: t,
|
|
187
|
+
symetric: s
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
for (let i = 0; i < 30; i++) {
|
|
192
|
+
|
|
193
|
+
const data1 = makeCircle()
|
|
194
|
+
const item1 = `Calculer l'équation de la tangente au cercle d'équation \\( (\\Gamma_1): ${data1.circle.tex} \\) un cercle passant par le point \\( T=${data1.point.tex} \\).`
|
|
195
|
+
|
|
196
|
+
const data2 = makeCircle()
|
|
197
|
+
const item2 = `Calculer l'équation des tangentes au cercle d'équation \\( (\\Gamma_2): ${data2.circle.cartesian.tex} \\) de pente \\( \\displaystyle ${data2.tangent.slope.tex} \\).`
|
|
198
|
+
|
|
199
|
+
console.log(`\\textbf{(exercice ${i + 1})}
|
|
200
|
+
|
|
201
|
+
\\begin{enumerate}[(I),itemsep=10em]
|
|
202
|
+
\\item ${item1}
|
|
203
|
+
\\item ${item2}
|
|
204
|
+
\\end{enumerate}
|
|
205
|
+
\\iftoggle{master}{
|
|
206
|
+
(I) \\( ${data1.tangent.tex.canonical} \\)
|
|
207
|
+
|
|
208
|
+
(II) \\( (\\Gamma_2): ${data2.circle.tex} \\) \\\\ \\( (t_1): ${data2.tangent.tex.canonical} \\) et \\( (t_2): ${data2.symetric.tex.canonical} \\)
|
|
209
|
+
|
|
210
|
+
}{}
|
|
211
|
+
\\vfill
|
|
212
|
+
${i % 2 === 1 ? '\\newpage' : ''}
|
|
213
|
+
`)
|
|
214
|
+
|
|
215
|
+
}
|
|
216
|
+
})
|
|
217
|
+
// it('intersection temp tests', () => {
|
|
218
|
+
// for (let i = 0; i < 30; i++) {
|
|
219
|
+
// let A = Random.Geometry.point({axis: false}),
|
|
220
|
+
// rv = Random.number(1, 3),
|
|
221
|
+
// r = rv ** 2 + (rv + 1) ** 2
|
|
222
|
+
//
|
|
223
|
+
// let c = new Circle(A, r, true)
|
|
224
|
+
// let pts = c.getPointsOnCircle(true)
|
|
225
|
+
// // console.log(r, pts.length)
|
|
226
|
+
//
|
|
227
|
+
// // console.log(c.tex)
|
|
228
|
+
// // console.log(pts.map(pt => pt.display))
|
|
229
|
+
// pts = Random.shuffle(pts)
|
|
230
|
+
// let ptt = pts.shift(),
|
|
231
|
+
// pt1 = pts.shift(),
|
|
232
|
+
// pt2
|
|
233
|
+
//
|
|
234
|
+
// for (let pt of pts) {
|
|
235
|
+
// if (!pt1.x.isEqual(pt.x) && !pt1.y.isEqual(pt.y) && !A.isEqual(new Point().middleOf(pt1, pt))) {
|
|
236
|
+
// pt2 = pt.clone()
|
|
237
|
+
// break
|
|
238
|
+
// }
|
|
239
|
+
// }
|
|
240
|
+
//
|
|
241
|
+
// // console.log('Pt de tangence')
|
|
242
|
+
// // console.log(ptt.display)
|
|
243
|
+
// let t = c.tangents(ptt)[0]
|
|
244
|
+
// // console.log(t.tex.canonical)
|
|
245
|
+
//
|
|
246
|
+
// // console.log('intersection en deux points')
|
|
247
|
+
// // console.log(pt1.display, pt2.display)
|
|
248
|
+
// let d = new Line(pt1, pt2)
|
|
249
|
+
// // console.log(d.tex.canonical)
|
|
250
|
+
//
|
|
251
|
+
// let P = Random.Geometry.point()
|
|
252
|
+
// while (P.x.isEqual(c.center.x) || P.y.isEqual(c.center.y)) {
|
|
253
|
+
// P = Random.Geometry.point()
|
|
254
|
+
// }
|
|
255
|
+
// // Le point P n'est pas sur le centre.
|
|
256
|
+
// let v = new Vector(c.center, P)
|
|
257
|
+
// while (P.distanceTo(A).value <= Math.sqrt(r)) {
|
|
258
|
+
// P.x.add(v.x)
|
|
259
|
+
// P.y.add(v.y)
|
|
260
|
+
// }
|
|
261
|
+
// let p = new Line(P, v, LinePropriety.Perpendicular)
|
|
262
|
+
// // console.log(P.display)
|
|
263
|
+
// // console.log(p.display.canonical)
|
|
264
|
+
//
|
|
265
|
+
// let lignes = Random.shuffle([t, d, p])
|
|
266
|
+
//
|
|
267
|
+
// // console.log(`A${A.display}
|
|
268
|
+
// // c=circ A,${Math.sqrt(r)}
|
|
269
|
+
// // T${ptt.display}
|
|
270
|
+
// // P${pt1.display}
|
|
271
|
+
// // Q${pt2.display}
|
|
272
|
+
// // t=line ${t.display.canonical}
|
|
273
|
+
// // d=line ${d.display.canonical}
|
|
274
|
+
// // p=line ${p.display.canonical}`)
|
|
275
|
+
// console.log(`(exercice ${i + 1}): Soit \\(\\Gamma\\) un cercle et \\(d_1\\), \\(d_2\\) et \\(d_3\\) trois droites.
|
|
276
|
+
// \\mathleft
|
|
277
|
+
// \\[(\\Gamma): ${c.tex}\\]
|
|
278
|
+
// \\[(d_1): ${lignes[0].tex.canonical} \\qquad (d_2): ${lignes[1].tex.canonical} \\qquad (d_3): ${lignes[2].tex.canonical}\\]
|
|
279
|
+
//
|
|
280
|
+
// \\begin{enumerate}[label=\\Alph*]
|
|
281
|
+
// \\item déterminer les positions relatives de \\(d_1\\), \\(d_2\\) et \\(d_3\\) par rapport à \\(\\Gamma\\)
|
|
282
|
+
// \\item calculer les coordonnées du ou des points d'intersection entre le cercle et une des droites qui le coupe (au choix).
|
|
283
|
+
// \\end{enumerate}
|
|
284
|
+
// \\iftoggle{master}{\\(${t.tex.canonical}\\implies ${ptt.tex}\\) \\\\ \\(${d.tex.canonical}\\implies ${pt1.tex},\\ ${pt2.tex}\\) \\\\}{}
|
|
285
|
+
// \\vfill
|
|
286
|
+
// ${i % 2 === 1 ? '\\newpage' : ''}
|
|
287
|
+
// `)
|
|
288
|
+
//
|
|
289
|
+
// }
|
|
290
|
+
//
|
|
291
|
+
// })
|
|
71
292
|
// it('temp tests', () => {
|
|
72
293
|
// for (let i = 0; i < 30; i++) {
|
|
73
294
|
// let A = Random.Geometry.point({axis: false}),
|
package/tests/numeric.test.ts
CHANGED
|
@@ -8,7 +8,7 @@ describe('Numeric', () => { // the tests container
|
|
|
8
8
|
expect(Numeric.numberCorrection(a)).to.be.equal(0.3)
|
|
9
9
|
const b = Math.pow(10, -5)
|
|
10
10
|
|
|
11
|
-
expect(Numeric.numberCorrection(b, 1,12)).to.be.equal(0.00001)
|
|
11
|
+
expect(Numeric.numberCorrection(b, 1, 12)).to.be.equal(0.00001)
|
|
12
12
|
})
|
|
13
13
|
|
|
14
14
|
|
|
@@ -21,7 +21,23 @@ describe('Numeric', () => { // the tests container
|
|
|
21
21
|
})
|
|
22
22
|
|
|
23
23
|
it('should decompose a number in two factors', function () {
|
|
24
|
-
expect(Numeric.decompose(25).map(x=>x.join(','))).to.have.all.members(['1,25', '5,5'])
|
|
25
|
-
expect(Numeric.decompose(6).map(x=>x.join(','))).to.have.all.members(['1,6', '2,3'])
|
|
24
|
+
expect(Numeric.decompose(25).map(x => x.join(','))).to.have.all.members(['1,25', '5,5'])
|
|
25
|
+
expect(Numeric.decompose(6).map(x => x.join(','))).to.have.all.members(['1,6', '2,3'])
|
|
26
26
|
});
|
|
27
|
+
|
|
28
|
+
it('algo perso', () => {
|
|
29
|
+
for (let n = 1000; n < 10000; n++) {
|
|
30
|
+
const a = Math.trunc(n / 1000)
|
|
31
|
+
const b = Math.trunc((n - 1000 * a) / 100)
|
|
32
|
+
const c = Math.trunc((n - 1000 * a - 100 * b) / 10)
|
|
33
|
+
const d = Math.trunc(n - 1000 * a - 100 * b - 10 * c)
|
|
34
|
+
|
|
35
|
+
const p = a + b + c + d
|
|
36
|
+
const p2 = a ** 2 + b ** 2 + c ** 2 + d ** 2
|
|
37
|
+
|
|
38
|
+
if (n === p * p2 ** 2) {
|
|
39
|
+
console.log(n)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
})
|
|
27
43
|
});
|