@khanacademy/kmath 1.0.0 → 2.0.1
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/es/index.js +145 -0
- package/dist/es/index.js.map +1 -0
- package/dist/index.js +34 -709
- package/dist/index.js.map +1 -1
- package/package.json +6 -13
package/dist/index.js
CHANGED
|
@@ -1,64 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
import _ from 'underscore';
|
|
3
|
-
import { approximateEqual, approximateDeepEqual } from '@khanacademy/perseus-core';
|
|
4
|
-
import $ from 'jquery';
|
|
1
|
+
'use strict';
|
|
5
2
|
|
|
6
|
-
|
|
7
|
-
const libVersion = "1.0.0";
|
|
8
|
-
addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
9
4
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
function
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
tolerance = DEFAULT_TOLERANCE;
|
|
24
|
-
}
|
|
25
|
-
return Math.abs(x - y) < tolerance;
|
|
26
|
-
}
|
|
27
|
-
function sign$1(x, tolerance) {
|
|
28
|
-
return equal$4(x, 0, tolerance) ? 0 : Math.abs(x) / x;
|
|
29
|
-
}
|
|
30
|
-
function isInteger(num, tolerance) {
|
|
31
|
-
return equal$4(Math.round(num), num, tolerance);
|
|
32
|
-
}
|
|
33
|
-
function round$2(num, precision) {
|
|
34
|
-
const factor = Math.pow(10, precision);
|
|
35
|
-
return Math.round(num * factor) / factor;
|
|
36
|
-
}
|
|
37
|
-
function roundTo$2(num, increment) {
|
|
38
|
-
return Math.round(num / increment) * increment;
|
|
39
|
-
}
|
|
40
|
-
function floorTo$2(num, increment) {
|
|
41
|
-
return Math.floor(num / increment) * increment;
|
|
42
|
-
}
|
|
43
|
-
function ceilTo$2(num, increment) {
|
|
44
|
-
return Math.ceil(num / increment) * increment;
|
|
45
|
-
}
|
|
46
|
-
function toFraction(decimal, tolerance = EPSILON, maxDenominator = 1000) {
|
|
47
|
-
let n = [1, 0];
|
|
48
|
-
let d = [0, 1];
|
|
49
|
-
let a = Math.floor(decimal);
|
|
50
|
-
let rem = decimal - a;
|
|
51
|
-
while (d[0] <= maxDenominator) {
|
|
52
|
-
if (equal$4(n[0] / d[0], decimal, tolerance)) {
|
|
53
|
-
return [n[0], d[0]];
|
|
54
|
-
}
|
|
55
|
-
n = [a * n[0] + n[1], n[0]];
|
|
56
|
-
d = [a * d[0] + d[1], d[0]];
|
|
57
|
-
a = Math.floor(1 / rem);
|
|
58
|
-
rem = 1 / rem - a;
|
|
59
|
-
}
|
|
60
|
-
return [decimal, 1];
|
|
61
|
-
}
|
|
5
|
+
var perseusUtils = require('@khanacademy/perseus-utils');
|
|
6
|
+
var _ = require('underscore');
|
|
7
|
+
var perseusCore = require('@khanacademy/perseus-core');
|
|
8
|
+
var $ = require('jquery');
|
|
9
|
+
|
|
10
|
+
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
11
|
+
|
|
12
|
+
var ___default = /*#__PURE__*/_interopDefaultCompat(_);
|
|
13
|
+
var $__default = /*#__PURE__*/_interopDefaultCompat($);
|
|
14
|
+
|
|
15
|
+
const libName="@khanacademy/kmath";const libVersion="2.0.1";perseusUtils.addLibraryVersionToPerseusDebug(libName,libVersion);
|
|
16
|
+
|
|
17
|
+
const DEFAULT_TOLERANCE=1e-9;const EPSILON=Math.pow(2,-42);function is$2(x){return ___default.default.isNumber(x)&&!___default.default.isNaN(x)}function equal$4(x,y,tolerance){if(x==null||y==null){return x===y}if(x===y){return true}if(tolerance==null){tolerance=DEFAULT_TOLERANCE;}return Math.abs(x-y)<tolerance}function sign$1(x,tolerance){return equal$4(x,0,tolerance)?0:Math.abs(x)/x}function isInteger(num,tolerance){return equal$4(Math.round(num),num,tolerance)}function round$2(num,precision){const factor=Math.pow(10,precision);return Math.round(num*factor)/factor}function roundTo$2(num,increment){return Math.round(num/increment)*increment}function floorTo$2(num,increment){return Math.floor(num/increment)*increment}function ceilTo$2(num,increment){return Math.ceil(num/increment)*increment}function toFraction(decimal,tolerance=EPSILON,maxDenominator=1e3){let n=[1,0];let d=[0,1];let a=Math.floor(decimal);let rem=decimal-a;while(d[0]<=maxDenominator){if(equal$4(n[0]/d[0],decimal,tolerance)){return [n[0],d[0]]}n=[a*n[0]+n[1],n[0]];d=[a*d[0]+d[1],d[0]];a=Math.floor(1/rem);rem=1/rem-a;}return [decimal,1]}
|
|
62
18
|
|
|
63
19
|
var number = /*#__PURE__*/Object.freeze({
|
|
64
20
|
__proto__: null,
|
|
@@ -75,124 +31,7 @@ var number = /*#__PURE__*/Object.freeze({
|
|
|
75
31
|
toFraction: toFraction
|
|
76
32
|
});
|
|
77
33
|
|
|
78
|
-
function arraySum(array) {
|
|
79
|
-
return array.reduce((memo, arg) => memo + arg, 0);
|
|
80
|
-
}
|
|
81
|
-
function arrayProduct(array) {
|
|
82
|
-
return array.reduce((memo, arg) => memo * arg, 1);
|
|
83
|
-
}
|
|
84
|
-
function zip(...arrays) {
|
|
85
|
-
const n = Math.min(...arrays.map(a => a.length));
|
|
86
|
-
const results = [];
|
|
87
|
-
for (let i = 0; i < n; i++) {
|
|
88
|
-
results.push(arrays.map(a => a[i]));
|
|
89
|
-
}
|
|
90
|
-
return results;
|
|
91
|
-
}
|
|
92
|
-
function map(pair, f) {
|
|
93
|
-
return [f(pair[0], 0), f(pair[1], 1)];
|
|
94
|
-
}
|
|
95
|
-
function is$1(vec, dimension) {
|
|
96
|
-
if (!Array.isArray(vec)) {
|
|
97
|
-
return false;
|
|
98
|
-
}
|
|
99
|
-
if (dimension !== undefined && vec.length !== dimension) {
|
|
100
|
-
return false;
|
|
101
|
-
}
|
|
102
|
-
return vec.every(is$2);
|
|
103
|
-
}
|
|
104
|
-
function normalize(v) {
|
|
105
|
-
return scale(v, 1 / length(v));
|
|
106
|
-
}
|
|
107
|
-
function length(v) {
|
|
108
|
-
return Math.sqrt(dot(v, v));
|
|
109
|
-
}
|
|
110
|
-
function dot(a, b) {
|
|
111
|
-
const zipped = zip(a, b);
|
|
112
|
-
const multiplied = zipped.map(arrayProduct);
|
|
113
|
-
return arraySum(multiplied);
|
|
114
|
-
}
|
|
115
|
-
function add$1(...vecs) {
|
|
116
|
-
const zipped = zip(...vecs);
|
|
117
|
-
return zipped.map(arraySum);
|
|
118
|
-
}
|
|
119
|
-
function subtract(v1, v2) {
|
|
120
|
-
return zip(v1, v2).map(dim => dim[0] - dim[1]);
|
|
121
|
-
}
|
|
122
|
-
function negate(v) {
|
|
123
|
-
return v.map(x => {
|
|
124
|
-
return -x;
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
function scale(v1, scalar) {
|
|
128
|
-
return v1.map(x => {
|
|
129
|
-
return x * scalar;
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
function equal$3(v1, v2, tolerance) {
|
|
133
|
-
return v1.length === v2.length && zip(v1, v2).every(pair => equal$4(pair[0], pair[1], tolerance));
|
|
134
|
-
}
|
|
135
|
-
function codirectional(v1, v2, tolerance) {
|
|
136
|
-
if (equal$4(length(v1), 0, tolerance) || equal$4(length(v2), 0, tolerance)) {
|
|
137
|
-
return true;
|
|
138
|
-
}
|
|
139
|
-
v1 = normalize(v1);
|
|
140
|
-
v2 = normalize(v2);
|
|
141
|
-
return equal$3(v1, v2, tolerance);
|
|
142
|
-
}
|
|
143
|
-
function collinear$1(v1, v2, tolerance) {
|
|
144
|
-
return codirectional(v1, v2, tolerance) || codirectional(v1, negate(v2), tolerance);
|
|
145
|
-
}
|
|
146
|
-
function polarRadFromCart$1(v) {
|
|
147
|
-
const radius = length(v);
|
|
148
|
-
let theta = Math.atan2(v[1], v[0]);
|
|
149
|
-
if (theta < 0) {
|
|
150
|
-
theta += 2 * Math.PI;
|
|
151
|
-
}
|
|
152
|
-
return [radius, theta];
|
|
153
|
-
}
|
|
154
|
-
function polarDegFromCart$1(v) {
|
|
155
|
-
const polar = polarRadFromCart$1(v);
|
|
156
|
-
return [polar[0], polar[1] * 180 / Math.PI];
|
|
157
|
-
}
|
|
158
|
-
function cartFromPolarRad$1(radius, theta = 0) {
|
|
159
|
-
return [radius * Math.cos(theta), radius * Math.sin(theta)];
|
|
160
|
-
}
|
|
161
|
-
function cartFromPolarDeg$1(radius, theta = 0) {
|
|
162
|
-
return cartFromPolarRad$1(radius, theta * Math.PI / 180);
|
|
163
|
-
}
|
|
164
|
-
function rotateRad$1(v, theta) {
|
|
165
|
-
const polar = polarRadFromCart$1(v);
|
|
166
|
-
const angle = polar[1] + theta;
|
|
167
|
-
return cartFromPolarRad$1(polar[0], angle);
|
|
168
|
-
}
|
|
169
|
-
function rotateDeg$1(v, theta) {
|
|
170
|
-
const polar = polarDegFromCart$1(v);
|
|
171
|
-
const angle = polar[1] + theta;
|
|
172
|
-
return cartFromPolarDeg$1(polar[0], angle);
|
|
173
|
-
}
|
|
174
|
-
function angleRad(v1, v2) {
|
|
175
|
-
return Math.acos(dot(v1, v2) / (length(v1) * length(v2)));
|
|
176
|
-
}
|
|
177
|
-
function angleDeg(v1, v2) {
|
|
178
|
-
return angleRad(v1, v2) * 180 / Math.PI;
|
|
179
|
-
}
|
|
180
|
-
function projection(v1, v2) {
|
|
181
|
-
const scalar = dot(v1, v2) / dot(v2, v2);
|
|
182
|
-
return scale(v2, scalar);
|
|
183
|
-
}
|
|
184
|
-
function round$1(vec, precision) {
|
|
185
|
-
return vec.map((elem, i) => round$2(elem, precision[i] || precision));
|
|
186
|
-
}
|
|
187
|
-
function roundTo$1(vec, increment) {
|
|
188
|
-
return vec.map((elem, i) => roundTo$2(elem, increment[i] || increment));
|
|
189
|
-
}
|
|
190
|
-
function floorTo$1(vec, increment) {
|
|
191
|
-
return vec.map((elem, i) => floorTo$2(elem, increment[i] || increment));
|
|
192
|
-
}
|
|
193
|
-
function ceilTo$1(vec, increment) {
|
|
194
|
-
return vec.map((elem, i) => ceilTo$2(elem, increment[i] || increment));
|
|
195
|
-
}
|
|
34
|
+
function arraySum(array){return array.reduce((memo,arg)=>memo+arg,0)}function arrayProduct(array){return array.reduce((memo,arg)=>memo*arg,1)}function zip(...arrays){const n=Math.min(...arrays.map(a=>a.length));const results=[];for(let i=0;i<n;i++){results.push(arrays.map(a=>a[i]));}return results}function map(pair,f){return [f(pair[0],0),f(pair[1],1)]}function is$1(vec,dimension){if(!Array.isArray(vec)){return false}if(dimension!==undefined&&vec.length!==dimension){return false}return vec.every(is$2)}function normalize(v){return scale(v,1/length(v))}function length(v){return Math.sqrt(dot(v,v))}function dot(a,b){const zipped=zip(a,b);const multiplied=zipped.map(arrayProduct);return arraySum(multiplied)}function add$1(...vecs){const zipped=zip(...vecs);return zipped.map(arraySum)}function subtract(v1,v2){return zip(v1,v2).map(dim=>dim[0]-dim[1])}function negate(v){return v.map(x=>{return -x})}function scale(v1,scalar){return v1.map(x=>{return x*scalar})}function equal$3(v1,v2,tolerance){return v1.length===v2.length&&zip(v1,v2).every(pair=>equal$4(pair[0],pair[1],tolerance))}function codirectional(v1,v2,tolerance){if(equal$4(length(v1),0,tolerance)||equal$4(length(v2),0,tolerance)){return true}v1=normalize(v1);v2=normalize(v2);return equal$3(v1,v2,tolerance)}function collinear$1(v1,v2,tolerance){return codirectional(v1,v2,tolerance)||codirectional(v1,negate(v2),tolerance)}function polarRadFromCart$1(v){const radius=length(v);let theta=Math.atan2(v[1],v[0]);if(theta<0){theta+=2*Math.PI;}return [radius,theta]}function polarDegFromCart$1(v){const polar=polarRadFromCart$1(v);return [polar[0],polar[1]*180/Math.PI]}function cartFromPolarRad$1(radius,theta=0){return [radius*Math.cos(theta),radius*Math.sin(theta)]}function cartFromPolarDeg$1(radius,theta=0){return cartFromPolarRad$1(radius,theta*Math.PI/180)}function rotateRad$1(v,theta){const polar=polarRadFromCart$1(v);const angle=polar[1]+theta;return cartFromPolarRad$1(polar[0],angle)}function rotateDeg$1(v,theta){const polar=polarDegFromCart$1(v);const angle=polar[1]+theta;return cartFromPolarDeg$1(polar[0],angle)}function angleRad(v1,v2){return Math.acos(dot(v1,v2)/(length(v1)*length(v2)))}function angleDeg(v1,v2){return angleRad(v1,v2)*180/Math.PI}function projection(v1,v2){const scalar=dot(v1,v2)/dot(v2,v2);return scale(v2,scalar)}function round$1(vec,precision){return vec.map((elem,i)=>round$2(elem,precision[i]||precision))}function roundTo$1(vec,increment){return vec.map((elem,i)=>roundTo$2(elem,increment[i]||increment))}function floorTo$1(vec,increment){return vec.map((elem,i)=>floorTo$2(elem,increment[i]||increment))}function ceilTo$1(vec,increment){return vec.map((elem,i)=>ceilTo$2(elem,increment[i]||increment))}
|
|
196
35
|
|
|
197
36
|
var vector$1 = /*#__PURE__*/Object.freeze({
|
|
198
37
|
__proto__: null,
|
|
@@ -224,61 +63,7 @@ var vector$1 = /*#__PURE__*/Object.freeze({
|
|
|
224
63
|
zip: zip
|
|
225
64
|
});
|
|
226
65
|
|
|
227
|
-
function rotateRad(point, theta, center) {
|
|
228
|
-
if (center === undefined) {
|
|
229
|
-
return rotateRad$1(point, theta);
|
|
230
|
-
} else {
|
|
231
|
-
return add$1(center, rotateRad$1(subtract(point, center), theta));
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
function rotateDeg(point, theta, center) {
|
|
235
|
-
if (center === undefined) {
|
|
236
|
-
return rotateDeg$1(point, theta);
|
|
237
|
-
} else {
|
|
238
|
-
return add$1(center, rotateDeg$1(subtract(point, center), theta));
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
function distanceToPoint$1(point1, point2) {
|
|
242
|
-
return length(subtract(point1, point2));
|
|
243
|
-
}
|
|
244
|
-
function distanceToLine(point, line) {
|
|
245
|
-
const lv = subtract(line[1], line[0]);
|
|
246
|
-
const pv = subtract(point, line[0]);
|
|
247
|
-
const projectedPv = projection(pv, lv);
|
|
248
|
-
const distancePv = subtract(projectedPv, pv);
|
|
249
|
-
return length(distancePv);
|
|
250
|
-
}
|
|
251
|
-
function reflectOverLine(point, line) {
|
|
252
|
-
const lv = subtract(line[1], line[0]);
|
|
253
|
-
const pv = subtract(point, line[0]);
|
|
254
|
-
const projectedPv = projection(pv, lv);
|
|
255
|
-
const reflectedPv = subtract(scale(projectedPv, 2), pv);
|
|
256
|
-
return add$1(line[0], reflectedPv);
|
|
257
|
-
}
|
|
258
|
-
function compare(point1, point2, equalityTolerance) {
|
|
259
|
-
if (point1.length !== point2.length) {
|
|
260
|
-
return point1.length - point2.length;
|
|
261
|
-
}
|
|
262
|
-
for (let i = 0; i < point1.length; i++) {
|
|
263
|
-
if (!equal$4(point1[i], point2[i], equalityTolerance)) {
|
|
264
|
-
return point1[i] - point2[i];
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
return 0;
|
|
268
|
-
}
|
|
269
|
-
const is = is$1;
|
|
270
|
-
const addVector = add$1;
|
|
271
|
-
const addVectors = add$1;
|
|
272
|
-
const subtractVector = subtract;
|
|
273
|
-
const equal$2 = equal$3;
|
|
274
|
-
const polarRadFromCart = polarRadFromCart$1;
|
|
275
|
-
const polarDegFromCart = polarDegFromCart$1;
|
|
276
|
-
const cartFromPolarRad = cartFromPolarRad$1;
|
|
277
|
-
const cartFromPolarDeg = cartFromPolarDeg$1;
|
|
278
|
-
const round = round$1;
|
|
279
|
-
const roundTo = roundTo$1;
|
|
280
|
-
const floorTo = floorTo$1;
|
|
281
|
-
const ceilTo = ceilTo$1;
|
|
66
|
+
function rotateRad(point,theta,center){if(center===undefined){return rotateRad$1(point,theta)}else {return add$1(center,rotateRad$1(subtract(point,center),theta))}}function rotateDeg(point,theta,center){if(center===undefined){return rotateDeg$1(point,theta)}else {return add$1(center,rotateDeg$1(subtract(point,center),theta))}}function distanceToPoint$1(point1,point2){return length(subtract(point1,point2))}function distanceToLine(point,line){const lv=subtract(line[1],line[0]);const pv=subtract(point,line[0]);const projectedPv=projection(pv,lv);const distancePv=subtract(projectedPv,pv);return length(distancePv)}function reflectOverLine(point,line){const lv=subtract(line[1],line[0]);const pv=subtract(point,line[0]);const projectedPv=projection(pv,lv);const reflectedPv=subtract(scale(projectedPv,2),pv);return add$1(line[0],reflectedPv)}function compare(point1,point2,equalityTolerance){if(point1.length!==point2.length){return point1.length-point2.length}for(let i=0;i<point1.length;i++){if(!equal$4(point1[i],point2[i],equalityTolerance)){return point1[i]-point2[i]}}return 0}const is=is$1;const addVector=add$1;const addVectors=add$1;const subtractVector=subtract;const equal$2=equal$3;const polarRadFromCart=polarRadFromCart$1;const polarDegFromCart=polarDegFromCart$1;const cartFromPolarRad=cartFromPolarRad$1;const cartFromPolarDeg=cartFromPolarDeg$1;const round=round$1;const roundTo=roundTo$1;const floorTo=floorTo$1;const ceilTo=ceilTo$1;
|
|
282
67
|
|
|
283
68
|
var point = /*#__PURE__*/Object.freeze({
|
|
284
69
|
__proto__: null,
|
|
@@ -303,27 +88,7 @@ var point = /*#__PURE__*/Object.freeze({
|
|
|
303
88
|
subtractVector: subtractVector
|
|
304
89
|
});
|
|
305
90
|
|
|
306
|
-
function distanceToPoint(line, point$1) {
|
|
307
|
-
return distanceToLine(point$1, line);
|
|
308
|
-
}
|
|
309
|
-
function reflectPoint(line, point$1) {
|
|
310
|
-
return reflectOverLine(point$1, line);
|
|
311
|
-
}
|
|
312
|
-
function midpoint(line) {
|
|
313
|
-
return [(line[0][0] + line[1][0]) / 2, (line[0][1] + line[1][1]) / 2];
|
|
314
|
-
}
|
|
315
|
-
function equal$1(line1, line2, tolerance) {
|
|
316
|
-
const v1 = subtract(line1[1], line1[0]);
|
|
317
|
-
const v2 = subtract(line2[1], line2[0]);
|
|
318
|
-
if (!collinear$1(v1, v2, tolerance)) {
|
|
319
|
-
return false;
|
|
320
|
-
}
|
|
321
|
-
if (equal$2(line1[0], line2[0])) {
|
|
322
|
-
return true;
|
|
323
|
-
}
|
|
324
|
-
const line1ToLine2Vector = subtract(line2[0], line1[0]);
|
|
325
|
-
return collinear$1(v1, line1ToLine2Vector, tolerance);
|
|
326
|
-
}
|
|
91
|
+
function distanceToPoint(line,point$1){return distanceToLine(point$1,line)}function reflectPoint(line,point$1){return reflectOverLine(point$1,line)}function midpoint(line){return [(line[0][0]+line[1][0])/2,(line[0][1]+line[1][1])/2]}function equal$1(line1,line2,tolerance){const v1=subtract(line1[1],line1[0]);const v2=subtract(line2[1],line2[0]);if(!collinear$1(v1,v2,tolerance)){return false}if(equal$2(line1[0],line2[0])){return true}const line1ToLine2Vector=subtract(line2[0],line1[0]);return collinear$1(v1,line1ToLine2Vector,tolerance)}
|
|
327
92
|
|
|
328
93
|
var line = /*#__PURE__*/Object.freeze({
|
|
329
94
|
__proto__: null,
|
|
@@ -333,411 +98,16 @@ var line = /*#__PURE__*/Object.freeze({
|
|
|
333
98
|
reflectPoint: reflectPoint
|
|
334
99
|
});
|
|
335
100
|
|
|
336
|
-
function equal(ray1, ray2, tolerance)
|
|
337
|
-
const v1 = subtract(ray1[1], ray1[0]);
|
|
338
|
-
const v2 = subtract(ray2[1], ray2[0]);
|
|
339
|
-
const sameOrigin = equal$2(ray1[0], ray2[0]);
|
|
340
|
-
const codirectional$1 = codirectional(v1, v2, tolerance);
|
|
341
|
-
return sameOrigin && codirectional$1;
|
|
342
|
-
}
|
|
101
|
+
function equal(ray1,ray2,tolerance){const v1=subtract(ray1[1],ray1[0]);const v2=subtract(ray2[1],ray2[0]);const sameOrigin=equal$2(ray1[0],ray2[0]);const codirectional$1=codirectional(v1,v2,tolerance);return sameOrigin&&codirectional$1}
|
|
343
102
|
|
|
344
103
|
var ray = /*#__PURE__*/Object.freeze({
|
|
345
104
|
__proto__: null,
|
|
346
105
|
equal: equal
|
|
347
106
|
});
|
|
348
107
|
|
|
349
|
-
const KhanMath = {
|
|
350
|
-
cleanMath: function (expr) {
|
|
351
|
-
return typeof expr === "string" ? expr.replace(/\+\s*-/g, "- ").replace(/-\s*-/g, "+ ").replace(/\^1/g, "") : expr;
|
|
352
|
-
},
|
|
353
|
-
bound: function (num) {
|
|
354
|
-
if (num === 0) {
|
|
355
|
-
return num;
|
|
356
|
-
}
|
|
357
|
-
if (num < 0) {
|
|
358
|
-
return -KhanMath.bound(-num);
|
|
359
|
-
}
|
|
360
|
-
return Math.max(1e-6, Math.min(num, 1e20));
|
|
361
|
-
},
|
|
362
|
-
factorial: function (x) {
|
|
363
|
-
if (x <= 1) {
|
|
364
|
-
return x;
|
|
365
|
-
}
|
|
366
|
-
return x * KhanMath.factorial(x - 1);
|
|
367
|
-
},
|
|
368
|
-
getGCD: function (a, b) {
|
|
369
|
-
if (arguments.length > 2) {
|
|
370
|
-
const rest = [].slice.call(arguments, 1);
|
|
371
|
-
return KhanMath.getGCD(a, KhanMath.getGCD(...rest));
|
|
372
|
-
}
|
|
373
|
-
let mod;
|
|
374
|
-
a = Math.abs(a);
|
|
375
|
-
b = Math.abs(b);
|
|
376
|
-
while (b) {
|
|
377
|
-
mod = a % b;
|
|
378
|
-
a = b;
|
|
379
|
-
b = mod;
|
|
380
|
-
}
|
|
381
|
-
return a;
|
|
382
|
-
},
|
|
383
|
-
getLCM: function (a, b) {
|
|
384
|
-
if (arguments.length > 2) {
|
|
385
|
-
const rest = [].slice.call(arguments, 1);
|
|
386
|
-
return KhanMath.getLCM(a, KhanMath.getLCM(...rest));
|
|
387
|
-
}
|
|
388
|
-
return Math.abs(a * b) / KhanMath.getGCD(a, b);
|
|
389
|
-
},
|
|
390
|
-
primes: [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97],
|
|
391
|
-
isPrime: function (n) {
|
|
392
|
-
if (n <= 1) {
|
|
393
|
-
return false;
|
|
394
|
-
}
|
|
395
|
-
if (n < 101) {
|
|
396
|
-
return !!$.grep(KhanMath.primes, function (p, i) {
|
|
397
|
-
return Math.abs(p - n) <= 0.5;
|
|
398
|
-
}).length;
|
|
399
|
-
}
|
|
400
|
-
if (n <= 1 || n > 2 && n % 2 === 0) {
|
|
401
|
-
return false;
|
|
402
|
-
}
|
|
403
|
-
for (let i = 3, sqrt = Math.sqrt(n); i <= sqrt; i += 2) {
|
|
404
|
-
if (n % i === 0) {
|
|
405
|
-
return false;
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
return true;
|
|
409
|
-
},
|
|
410
|
-
getPrimeFactorization: function (number) {
|
|
411
|
-
if (number === 1) {
|
|
412
|
-
return [];
|
|
413
|
-
}
|
|
414
|
-
if (KhanMath.isPrime(number)) {
|
|
415
|
-
return [number];
|
|
416
|
-
}
|
|
417
|
-
const maxf = Math.sqrt(number);
|
|
418
|
-
for (let f = 2; f <= maxf; f++) {
|
|
419
|
-
if (number % f === 0) {
|
|
420
|
-
return $.merge(KhanMath.getPrimeFactorization(f), KhanMath.getPrimeFactorization(number / f));
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
},
|
|
424
|
-
roundToNearest: function (increment, num) {
|
|
425
|
-
return Math.round(num / increment) * increment;
|
|
426
|
-
},
|
|
427
|
-
roundTo: function (precision, num) {
|
|
428
|
-
const factor = Math.pow(10, precision).toFixed(5);
|
|
429
|
-
return Math.round((num * factor).toFixed(5)) / factor;
|
|
430
|
-
},
|
|
431
|
-
toFixedApprox: function (num, precision) {
|
|
432
|
-
const fixedStr = num.toFixed(precision);
|
|
433
|
-
if (equal$4(+fixedStr, num)) {
|
|
434
|
-
return fixedStr;
|
|
435
|
-
}
|
|
436
|
-
return "\\approx " + fixedStr;
|
|
437
|
-
},
|
|
438
|
-
roundToApprox: function (num, precision) {
|
|
439
|
-
const fixed = KhanMath.roundTo(precision, num);
|
|
440
|
-
if (equal$4(fixed, num)) {
|
|
441
|
-
return String(fixed);
|
|
442
|
-
}
|
|
443
|
-
return KhanMath.toFixedApprox(num, precision);
|
|
444
|
-
},
|
|
445
|
-
toFraction: function (decimal, tolerance) {
|
|
446
|
-
if (tolerance == null) {
|
|
447
|
-
tolerance = Math.pow(2, -46);
|
|
448
|
-
}
|
|
449
|
-
if (decimal < 0 || decimal > 1) {
|
|
450
|
-
let fract = decimal % 1;
|
|
451
|
-
fract += fract < 0 ? 1 : 0;
|
|
452
|
-
const nd = KhanMath.toFraction(fract, tolerance);
|
|
453
|
-
nd[0] += Math.round(decimal - fract) * nd[1];
|
|
454
|
-
return nd;
|
|
455
|
-
}
|
|
456
|
-
if (Math.abs(Math.round(Number(decimal)) - decimal) <= tolerance) {
|
|
457
|
-
return [Math.round(decimal), 1];
|
|
458
|
-
}
|
|
459
|
-
let loN = 0;
|
|
460
|
-
let loD = 1;
|
|
461
|
-
let hiN = 1;
|
|
462
|
-
let hiD = 1;
|
|
463
|
-
let midN = 1;
|
|
464
|
-
let midD = 2;
|
|
465
|
-
while (true) {
|
|
466
|
-
if (Math.abs(Number(midN / midD) - decimal) <= tolerance) {
|
|
467
|
-
return [midN, midD];
|
|
468
|
-
}
|
|
469
|
-
if (midN / midD < decimal) {
|
|
470
|
-
loN = midN;
|
|
471
|
-
loD = midD;
|
|
472
|
-
} else {
|
|
473
|
-
hiN = midN;
|
|
474
|
-
hiD = midD;
|
|
475
|
-
}
|
|
476
|
-
midN = loN + hiN;
|
|
477
|
-
midD = loD + hiD;
|
|
478
|
-
}
|
|
479
|
-
},
|
|
480
|
-
getNumericFormat: function (text) {
|
|
481
|
-
text = $.trim(text);
|
|
482
|
-
text = text.replace(/\u2212/, "-").replace(/([+-])\s+/g, "$1");
|
|
483
|
-
if (text.match(/^[+-]?\d+$/)) {
|
|
484
|
-
return "integer";
|
|
485
|
-
}
|
|
486
|
-
if (text.match(/^[+-]?\d+\s+\d+\s*\/\s*\d+$/)) {
|
|
487
|
-
return "mixed";
|
|
488
|
-
}
|
|
489
|
-
const fraction = text.match(/^[+-]?(\d+)\s*\/\s*(\d+)$/);
|
|
490
|
-
if (fraction) {
|
|
491
|
-
return parseFloat(fraction[1]) > parseFloat(fraction[2]) ? "improper" : "proper";
|
|
492
|
-
}
|
|
493
|
-
if (text.replace(/[,. ]/g, "").match(/^\d+$/)) {
|
|
494
|
-
return "decimal";
|
|
495
|
-
}
|
|
496
|
-
if (text.match(/(pi?|\u03c0|t(?:au)?|\u03c4|pau)/)) {
|
|
497
|
-
return "pi";
|
|
498
|
-
}
|
|
499
|
-
return null;
|
|
500
|
-
},
|
|
501
|
-
toNumericString: function (number$1, format) {
|
|
502
|
-
if (number$1 == null) {
|
|
503
|
-
return "";
|
|
504
|
-
}
|
|
505
|
-
if (number$1 === 0) {
|
|
506
|
-
return "0";
|
|
507
|
-
}
|
|
508
|
-
if (format === "percent") {
|
|
509
|
-
return number$1 * 100 + "%";
|
|
510
|
-
}
|
|
511
|
-
if (format === "pi") {
|
|
512
|
-
const fraction = toFraction(number$1 / Math.PI);
|
|
513
|
-
const numerator = Math.abs(fraction[0]);
|
|
514
|
-
const denominator = fraction[1];
|
|
515
|
-
if (isInteger(numerator)) {
|
|
516
|
-
const sign = number$1 < 0 ? "-" : "";
|
|
517
|
-
const pi = "\u03C0";
|
|
518
|
-
return sign + (numerator === 1 ? "" : numerator) + pi + (denominator === 1 ? "" : "/" + denominator);
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
if (_(["proper", "improper", "mixed", "fraction"]).contains(format)) {
|
|
522
|
-
const fraction = toFraction(number$1);
|
|
523
|
-
const numerator = Math.abs(fraction[0]);
|
|
524
|
-
const denominator = fraction[1];
|
|
525
|
-
const sign = number$1 < 0 ? "-" : "";
|
|
526
|
-
if (denominator === 1) {
|
|
527
|
-
return sign + numerator;
|
|
528
|
-
}
|
|
529
|
-
if (format === "mixed") {
|
|
530
|
-
const modulus = numerator % denominator;
|
|
531
|
-
const integer = (numerator - modulus) / denominator;
|
|
532
|
-
return sign + (integer ? integer + " " : "") + modulus + "/" + denominator;
|
|
533
|
-
}
|
|
534
|
-
return sign + numerator + "/" + denominator;
|
|
535
|
-
}
|
|
536
|
-
return String(number$1);
|
|
537
|
-
}
|
|
538
|
-
};
|
|
539
|
-
function sum(array) {
|
|
540
|
-
return array.reduce(add, 0);
|
|
541
|
-
}
|
|
542
|
-
function add(a, b) {
|
|
543
|
-
return a + b;
|
|
544
|
-
}
|
|
108
|
+
const KhanMath={cleanMath:function(expr){return typeof expr==="string"?expr.replace(/\+\s*-/g,"- ").replace(/-\s*-/g,"+ ").replace(/\^1/g,""):expr},bound:function(num){if(num===0){return num}if(num<0){return -KhanMath.bound(-num)}return Math.max(1e-6,Math.min(num,1e20))},factorial:function(x){if(x<=1){return x}return x*KhanMath.factorial(x-1)},getGCD:function(a,b){if(arguments.length>2){const rest=[].slice.call(arguments,1);return KhanMath.getGCD(a,KhanMath.getGCD(...rest))}let mod;a=Math.abs(a);b=Math.abs(b);while(b){mod=a%b;a=b;b=mod;}return a},getLCM:function(a,b){if(arguments.length>2){const rest=[].slice.call(arguments,1);return KhanMath.getLCM(a,KhanMath.getLCM(...rest))}return Math.abs(a*b)/KhanMath.getGCD(a,b)},primes:[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97],isPrime:function(n){if(n<=1){return false}if(n<101){return !!$__default.default.grep(KhanMath.primes,function(p,i){return Math.abs(p-n)<=.5}).length}if(n<=1||n>2&&n%2===0){return false}for(let i=3,sqrt=Math.sqrt(n);i<=sqrt;i+=2){if(n%i===0){return false}}return true},getPrimeFactorization:function(number){if(number===1){return []}if(KhanMath.isPrime(number)){return [number]}const maxf=Math.sqrt(number);for(let f=2;f<=maxf;f++){if(number%f===0){return $__default.default.merge(KhanMath.getPrimeFactorization(f),KhanMath.getPrimeFactorization(number/f))}}},roundToNearest:function(increment,num){return Math.round(num/increment)*increment},roundTo:function(precision,num){const factor=Math.pow(10,precision).toFixed(5);return Math.round((num*factor).toFixed(5))/factor},toFixedApprox:function(num,precision){const fixedStr=num.toFixed(precision);if(equal$4(+fixedStr,num)){return fixedStr}return "\\approx "+fixedStr},roundToApprox:function(num,precision){const fixed=KhanMath.roundTo(precision,num);if(equal$4(fixed,num)){return String(fixed)}return KhanMath.toFixedApprox(num,precision)},toFraction:function(decimal,tolerance){if(tolerance==null){tolerance=Math.pow(2,-46);}if(decimal<0||decimal>1){let fract=decimal%1;fract+=fract<0?1:0;const nd=KhanMath.toFraction(fract,tolerance);nd[0]+=Math.round(decimal-fract)*nd[1];return nd}if(Math.abs(Math.round(Number(decimal))-decimal)<=tolerance){return [Math.round(decimal),1]}let loN=0;let loD=1;let hiN=1;let hiD=1;let midN=1;let midD=2;while(true){if(Math.abs(Number(midN/midD)-decimal)<=tolerance){return [midN,midD]}if(midN/midD<decimal){loN=midN;loD=midD;}else {hiN=midN;hiD=midD;}midN=loN+hiN;midD=loD+hiD;}},getNumericFormat:function(text){text=$__default.default.trim(text);text=text.replace(/\u2212/,"-").replace(/([+-])\s+/g,"$1");if(text.match(/^[+-]?\d+$/)){return "integer"}if(text.match(/^[+-]?\d+\s+\d+\s*\/\s*\d+$/)){return "mixed"}const fraction=text.match(/^[+-]?(\d+)\s*\/\s*(\d+)$/);if(fraction){return parseFloat(fraction[1])>parseFloat(fraction[2])?"improper":"proper"}if(text.replace(/[,. ]/g,"").match(/^\d+$/)){return "decimal"}if(text.match(/(pi?|\u03c0|t(?:au)?|\u03c4|pau)/)){return "pi"}return null},toNumericString:function(number$1,format){if(number$1==null){return ""}if(number$1===0){return "0"}if(format==="percent"){return number$1*100+"%"}if(format==="pi"){const fraction=toFraction(number$1/Math.PI);const numerator=Math.abs(fraction[0]);const denominator=fraction[1];if(isInteger(numerator)){const sign=number$1<0?"-":"";const pi="π";return sign+(numerator===1?"":numerator)+pi+(denominator===1?"":"/"+denominator)}}if(___default.default(["proper","improper","mixed","fraction"]).contains(format)){const fraction=toFraction(number$1);const numerator=Math.abs(fraction[0]);const denominator=fraction[1];const sign=number$1<0?"-":"";if(denominator===1){return sign+numerator}if(format==="mixed"){const modulus=numerator%denominator;const integer=(numerator-modulus)/denominator;return sign+(integer?integer+" ":"")+modulus+"/"+denominator}return sign+numerator+"/"+denominator}return String(number$1)}};function sum(array){return array.reduce(add,0)}function add(a,b){return a+b}
|
|
545
109
|
|
|
546
|
-
function sign(val) {
|
|
547
|
-
if (approximateEqual(val, 0)) {
|
|
548
|
-
return 0;
|
|
549
|
-
}
|
|
550
|
-
return val > 0 ? 1 : -1;
|
|
551
|
-
}
|
|
552
|
-
function ccw(a, b, c) {
|
|
553
|
-
return (b[0] - a[0]) * (c[1] - a[1]) - (c[0] - a[0]) * (b[1] - a[1]);
|
|
554
|
-
}
|
|
555
|
-
function collinear(a, b, c) {
|
|
556
|
-
return approximateEqual(ccw(a, b, c), 0);
|
|
557
|
-
}
|
|
558
|
-
function pointInRect(a, b, c) {
|
|
559
|
-
return c[0] <= Math.max(a[0], b[0]) && c[0] >= Math.min(a[0], b[0]) && c[1] <= Math.max(a[1], b[1]) && c[1] >= Math.min(a[1], b[1]);
|
|
560
|
-
}
|
|
561
|
-
function intersects(ab, cd) {
|
|
562
|
-
const triplets = [[ab[0], ab[1], cd[0]], [ab[0], ab[1], cd[1]], [cd[0], cd[1], ab[0]], [cd[0], cd[1], ab[1]]];
|
|
563
|
-
const orientations = _.map(triplets, function (triplet) {
|
|
564
|
-
return sign(ccw(...triplet));
|
|
565
|
-
});
|
|
566
|
-
if (orientations[0] !== orientations[1] && orientations[2] !== orientations[3]) {
|
|
567
|
-
return true;
|
|
568
|
-
}
|
|
569
|
-
for (let i = 0; i < 4; i++) {
|
|
570
|
-
if (orientations[i] === 0 && pointInRect(...triplets[i])) {
|
|
571
|
-
return true;
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
return false;
|
|
575
|
-
}
|
|
576
|
-
function polygonSidesIntersect(vertices) {
|
|
577
|
-
for (let i = 0; i < vertices.length; i++) {
|
|
578
|
-
for (let k = i + 1; k < vertices.length; k++) {
|
|
579
|
-
if (equal$2(vertices[i], vertices[k])) {
|
|
580
|
-
return true;
|
|
581
|
-
}
|
|
582
|
-
const iNext = (i + 1) % vertices.length;
|
|
583
|
-
const kNext = (k + 1) % vertices.length;
|
|
584
|
-
if (iNext === k || kNext === i) {
|
|
585
|
-
continue;
|
|
586
|
-
}
|
|
587
|
-
const side1 = [vertices[i], vertices[iNext]];
|
|
588
|
-
const side2 = [vertices[k], vertices[kNext]];
|
|
589
|
-
if (intersects(side1, side2)) {
|
|
590
|
-
return true;
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
return false;
|
|
595
|
-
}
|
|
596
|
-
function vector(a, b) {
|
|
597
|
-
return _.map(_.zip(a, b), function (pair) {
|
|
598
|
-
return pair[0] - pair[1];
|
|
599
|
-
});
|
|
600
|
-
}
|
|
601
|
-
function reverseVector(vector) {
|
|
602
|
-
return [-vector[0], -vector[1]];
|
|
603
|
-
}
|
|
604
|
-
function clockwise(points) {
|
|
605
|
-
const segments = _.zip(points, points.slice(1).concat(points.slice(0, 1)));
|
|
606
|
-
const areas = _.map(segments, function (segment) {
|
|
607
|
-
const p1 = segment[0];
|
|
608
|
-
const p2 = segment[1];
|
|
609
|
-
return (p2[0] - p1[0]) * (p2[1] + p1[1]);
|
|
610
|
-
});
|
|
611
|
-
return sum(areas) > 0;
|
|
612
|
-
}
|
|
613
|
-
function magnitude(v) {
|
|
614
|
-
return Math.sqrt(_.reduce(v, function (memo, el) {
|
|
615
|
-
return memo + Math.pow(el, 2);
|
|
616
|
-
}, 0));
|
|
617
|
-
}
|
|
618
|
-
function dotProduct(a, b) {
|
|
619
|
-
return _.reduce(_.zip(a, b), function (memo, pair) {
|
|
620
|
-
return memo + pair[0] * pair[1];
|
|
621
|
-
}, 0);
|
|
622
|
-
}
|
|
623
|
-
function sideLengths(coords) {
|
|
624
|
-
const segments = _.zip(coords, rotate(coords));
|
|
625
|
-
return segments.map(function (segment) {
|
|
626
|
-
return magnitude(vector(...segment));
|
|
627
|
-
});
|
|
628
|
-
}
|
|
629
|
-
function angleMeasures(coords) {
|
|
630
|
-
const triplets = _.zip(rotate(coords, -1), coords, rotate(coords, 1));
|
|
631
|
-
const offsets = _.map(triplets, function (triplet) {
|
|
632
|
-
const p = vector(triplet[1], triplet[0]);
|
|
633
|
-
const q = vector(triplet[2], triplet[1]);
|
|
634
|
-
const raw = Math.acos(dotProduct(p, q) / (magnitude(p) * magnitude(q)));
|
|
635
|
-
return sign(ccw(...triplet)) > 0 ? raw : -raw;
|
|
636
|
-
});
|
|
637
|
-
const sum = _.reduce(offsets, function (memo, arg) {
|
|
638
|
-
return memo + arg;
|
|
639
|
-
}, 0);
|
|
640
|
-
return _.map(offsets, function (offset) {
|
|
641
|
-
return sum > 0 ? Math.PI - offset : Math.PI + offset;
|
|
642
|
-
});
|
|
643
|
-
}
|
|
644
|
-
function similar(coords1, coords2, tolerance) {
|
|
645
|
-
if (coords1.length !== coords2.length) {
|
|
646
|
-
return false;
|
|
647
|
-
}
|
|
648
|
-
const n = coords1.length;
|
|
649
|
-
const angles1 = angleMeasures(coords1);
|
|
650
|
-
const angles2 = angleMeasures(coords2);
|
|
651
|
-
const sides1 = sideLengths(coords1);
|
|
652
|
-
const sides2 = sideLengths(coords2);
|
|
653
|
-
for (let i = 0; i < 2 * n; i++) {
|
|
654
|
-
let angles = angles2.slice();
|
|
655
|
-
let sides = sides2.slice();
|
|
656
|
-
if (i >= n) {
|
|
657
|
-
angles.reverse();
|
|
658
|
-
sides.reverse();
|
|
659
|
-
sides = rotate(sides, 1);
|
|
660
|
-
}
|
|
661
|
-
angles = rotate(angles, i);
|
|
662
|
-
sides = rotate(sides, i);
|
|
663
|
-
if (approximateDeepEqual(angles1, angles)) {
|
|
664
|
-
const sidePairs = _.zip(sides1, sides);
|
|
665
|
-
const factors = _.map(sidePairs, function (pair) {
|
|
666
|
-
return pair[0] / pair[1];
|
|
667
|
-
});
|
|
668
|
-
const same = _.all(factors, function (factor) {
|
|
669
|
-
return approximateEqual(factors[0], factor);
|
|
670
|
-
});
|
|
671
|
-
const congruentEnough = _.all(sidePairs, function (pair) {
|
|
672
|
-
return equal$4(pair[0], pair[1], tolerance);
|
|
673
|
-
});
|
|
674
|
-
if (same && congruentEnough) {
|
|
675
|
-
return true;
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
return false;
|
|
680
|
-
}
|
|
681
|
-
function lawOfCosines(a, b, c) {
|
|
682
|
-
return Math.acos((a * a + b * b - c * c) / (2 * a * b)) * 180 / Math.PI;
|
|
683
|
-
}
|
|
684
|
-
function canonicalSineCoefficients([amplitude, angularFrequency, phase, verticalOffset]) {
|
|
685
|
-
if (amplitude < 0) {
|
|
686
|
-
amplitude *= -1;
|
|
687
|
-
angularFrequency *= -1;
|
|
688
|
-
phase *= -1;
|
|
689
|
-
}
|
|
690
|
-
const period = 2 * Math.PI;
|
|
691
|
-
if (angularFrequency < 0) {
|
|
692
|
-
angularFrequency *= -1;
|
|
693
|
-
phase *= -1;
|
|
694
|
-
phase += period / 2;
|
|
695
|
-
}
|
|
696
|
-
while (phase > 0) {
|
|
697
|
-
phase -= period;
|
|
698
|
-
}
|
|
699
|
-
while (phase < 0) {
|
|
700
|
-
phase += period;
|
|
701
|
-
}
|
|
702
|
-
return [amplitude, angularFrequency, phase, verticalOffset];
|
|
703
|
-
}
|
|
704
|
-
function rotate(array, n) {
|
|
705
|
-
n = typeof n === "undefined" ? 1 : n % array.length;
|
|
706
|
-
return array.slice(n).concat(array.slice(0, n));
|
|
707
|
-
}
|
|
708
|
-
function getLineEquation(first, second) {
|
|
709
|
-
if (approximateEqual(first[0], second[0])) {
|
|
710
|
-
return "x = " + first[0].toFixed(3);
|
|
711
|
-
}
|
|
712
|
-
const m = (second[1] - first[1]) / (second[0] - first[0]);
|
|
713
|
-
const b = first[1] - m * first[0];
|
|
714
|
-
return "y = " + m.toFixed(3) + "x + " + b.toFixed(3);
|
|
715
|
-
}
|
|
716
|
-
function getLineIntersection(firstPoints, secondPoints) {
|
|
717
|
-
const x1 = firstPoints[0][0];
|
|
718
|
-
const y1 = firstPoints[0][1];
|
|
719
|
-
const x2 = firstPoints[1][0];
|
|
720
|
-
const y2 = firstPoints[1][1];
|
|
721
|
-
const x3 = secondPoints[0][0];
|
|
722
|
-
const y3 = secondPoints[0][1];
|
|
723
|
-
const x4 = secondPoints[1][0];
|
|
724
|
-
const y4 = secondPoints[1][1];
|
|
725
|
-
const determinant = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
|
|
726
|
-
if (Math.abs(determinant) < 1e-9) {
|
|
727
|
-
return null;
|
|
728
|
-
}
|
|
729
|
-
const x = ((x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4)) / determinant;
|
|
730
|
-
const y = ((x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4)) / determinant;
|
|
731
|
-
return [x, y];
|
|
732
|
-
}
|
|
733
|
-
function getLineIntersectionString(firstPoints, secondPoints) {
|
|
734
|
-
const intersection = getLineIntersection(firstPoints, secondPoints);
|
|
735
|
-
if (intersection === null) {
|
|
736
|
-
return "Lines are parallel";
|
|
737
|
-
}
|
|
738
|
-
const [x, y] = intersection;
|
|
739
|
-
return "Intersection: (" + x.toFixed(3) + ", " + y.toFixed(3) + ")";
|
|
740
|
-
}
|
|
110
|
+
function sign(val){if(perseusCore.approximateEqual(val,0)){return 0}return val>0?1:-1}function ccw(a,b,c){return (b[0]-a[0])*(c[1]-a[1])-(c[0]-a[0])*(b[1]-a[1])}function collinear(a,b,c){return perseusCore.approximateEqual(ccw(a,b,c),0)}function pointInRect(a,b,c){return c[0]<=Math.max(a[0],b[0])&&c[0]>=Math.min(a[0],b[0])&&c[1]<=Math.max(a[1],b[1])&&c[1]>=Math.min(a[1],b[1])}function intersects(ab,cd){const triplets=[[ab[0],ab[1],cd[0]],[ab[0],ab[1],cd[1]],[cd[0],cd[1],ab[0]],[cd[0],cd[1],ab[1]]];const orientations=___default.default.map(triplets,function(triplet){return sign(ccw(...triplet))});if(orientations[0]!==orientations[1]&&orientations[2]!==orientations[3]){return true}for(let i=0;i<4;i++){if(orientations[i]===0&&pointInRect(...triplets[i])){return true}}return false}function polygonSidesIntersect(vertices){for(let i=0;i<vertices.length;i++){for(let k=i+1;k<vertices.length;k++){if(equal$2(vertices[i],vertices[k])){return true}const iNext=(i+1)%vertices.length;const kNext=(k+1)%vertices.length;if(iNext===k||kNext===i){continue}const side1=[vertices[i],vertices[iNext]];const side2=[vertices[k],vertices[kNext]];if(intersects(side1,side2)){return true}}}return false}function vector(a,b){return ___default.default.map(___default.default.zip(a,b),function(pair){return pair[0]-pair[1]})}function reverseVector(vector){return [-vector[0],-vector[1]]}function clockwise(points){const segments=___default.default.zip(points,points.slice(1).concat(points.slice(0,1)));const areas=___default.default.map(segments,function(segment){const p1=segment[0];const p2=segment[1];return (p2[0]-p1[0])*(p2[1]+p1[1])});return sum(areas)>0}function magnitude(v){return Math.sqrt(___default.default.reduce(v,function(memo,el){return memo+Math.pow(el,2)},0))}function dotProduct(a,b){return ___default.default.reduce(___default.default.zip(a,b),function(memo,pair){return memo+pair[0]*pair[1]},0)}function sideLengths(coords){const segments=___default.default.zip(coords,rotate(coords));return segments.map(function(segment){return magnitude(vector(...segment))})}function angleMeasures(coords){const triplets=___default.default.zip(rotate(coords,-1),coords,rotate(coords,1));const offsets=___default.default.map(triplets,function(triplet){const p=vector(triplet[1],triplet[0]);const q=vector(triplet[2],triplet[1]);const raw=Math.acos(dotProduct(p,q)/(magnitude(p)*magnitude(q)));return sign(ccw(...triplet))>0?raw:-raw});const sum=___default.default.reduce(offsets,function(memo,arg){return memo+arg},0);return ___default.default.map(offsets,function(offset){return sum>0?Math.PI-offset:Math.PI+offset})}function similar(coords1,coords2,tolerance){if(coords1.length!==coords2.length){return false}const n=coords1.length;const angles1=angleMeasures(coords1);const angles2=angleMeasures(coords2);const sides1=sideLengths(coords1);const sides2=sideLengths(coords2);for(let i=0;i<2*n;i++){let angles=angles2.slice();let sides=sides2.slice();if(i>=n){angles.reverse();sides.reverse();sides=rotate(sides,1);}angles=rotate(angles,i);sides=rotate(sides,i);if(perseusCore.approximateDeepEqual(angles1,angles)){const sidePairs=___default.default.zip(sides1,sides);const factors=___default.default.map(sidePairs,function(pair){return pair[0]/pair[1]});const same=___default.default.all(factors,function(factor){return perseusCore.approximateEqual(factors[0],factor)});const congruentEnough=___default.default.all(sidePairs,function(pair){return equal$4(pair[0],pair[1],tolerance)});if(same&&congruentEnough){return true}}}return false}function lawOfCosines(a,b,c){return Math.acos((a*a+b*b-c*c)/(2*a*b))*180/Math.PI}function canonicalSineCoefficients([amplitude,angularFrequency,phase,verticalOffset]){if(amplitude<0){amplitude*=-1;angularFrequency*=-1;phase*=-1;}const period=2*Math.PI;if(angularFrequency<0){angularFrequency*=-1;phase*=-1;phase+=period/2;}while(phase>0){phase-=period;}while(phase<0){phase+=period;}return [amplitude,angularFrequency,phase,verticalOffset]}function rotate(array,n){n=typeof n==="undefined"?1:n%array.length;return array.slice(n).concat(array.slice(0,n))}function getLineEquation(first,second){if(perseusCore.approximateEqual(first[0],second[0])){return "x = "+first[0].toFixed(3)}const m=(second[1]-first[1])/(second[0]-first[0]);const b=first[1]-m*first[0];return "y = "+m.toFixed(3)+"x + "+b.toFixed(3)}function getLineIntersection(firstPoints,secondPoints){const x1=firstPoints[0][0];const y1=firstPoints[0][1];const x2=firstPoints[1][0];const y2=firstPoints[1][1];const x3=secondPoints[0][0];const y3=secondPoints[0][1];const x4=secondPoints[1][0];const y4=secondPoints[1][1];const determinant=(x1-x2)*(y3-y4)-(y1-y2)*(x3-x4);if(Math.abs(determinant)<1e-9){return null}const x=((x1*y2-y1*x2)*(x3-x4)-(x1-x2)*(x3*y4-y3*x4))/determinant;const y=((x1*y2-y1*x2)*(y3-y4)-(y1-y2)*(x3*y4-y3*x4))/determinant;return [x,y]}function getLineIntersectionString(firstPoints,secondPoints){const intersection=getLineIntersection(firstPoints,secondPoints);if(intersection===null){return "Lines are parallel"}const[x,y]=intersection;return "Intersection: ("+x.toFixed(3)+", "+y.toFixed(3)+")"}
|
|
741
111
|
|
|
742
112
|
var geometry = /*#__PURE__*/Object.freeze({
|
|
743
113
|
__proto__: null,
|
|
@@ -760,41 +130,7 @@ var geometry = /*#__PURE__*/Object.freeze({
|
|
|
760
130
|
vector: vector
|
|
761
131
|
});
|
|
762
132
|
|
|
763
|
-
function convertDegreesToRadians(degrees) {
|
|
764
|
-
return degrees / 180 * Math.PI;
|
|
765
|
-
}
|
|
766
|
-
function convertRadiansToDegrees(radians) {
|
|
767
|
-
const degree = radians / Math.PI * 180;
|
|
768
|
-
return Number(degree.toPrecision(15));
|
|
769
|
-
}
|
|
770
|
-
function calculateAngleInDegrees([x, y]) {
|
|
771
|
-
return Math.atan2(y, x) * 180 / Math.PI;
|
|
772
|
-
}
|
|
773
|
-
function polar(r, th) {
|
|
774
|
-
if (typeof r === "number") {
|
|
775
|
-
r = [r, r];
|
|
776
|
-
}
|
|
777
|
-
th = th * Math.PI / 180;
|
|
778
|
-
return [r[0] * Math.cos(th), r[1] * Math.sin(th)];
|
|
779
|
-
}
|
|
780
|
-
const getAngleFromVertex = (point, vertex) => {
|
|
781
|
-
const x = point[0] - vertex[0];
|
|
782
|
-
const y = point[1] - vertex[1];
|
|
783
|
-
if (!x && !y) {
|
|
784
|
-
return 0;
|
|
785
|
-
}
|
|
786
|
-
return (180 + Math.atan2(-y, -x) * 180 / Math.PI + 360) % 360;
|
|
787
|
-
};
|
|
788
|
-
const getClockwiseAngle = (coords, allowReflexAngles = false) => {
|
|
789
|
-
const coordsCopy = [...coords];
|
|
790
|
-
const areClockwise = clockwise([coordsCopy[0], coordsCopy[2], coordsCopy[1]]);
|
|
791
|
-
const shouldReverseCoords = !areClockwise || allowReflexAngles;
|
|
792
|
-
const clockwiseCoords = shouldReverseCoords ? coordsCopy.reverse() : coordsCopy;
|
|
793
|
-
const startAngle = getAngleFromVertex(clockwiseCoords[0], clockwiseCoords[1]);
|
|
794
|
-
const endAngle = getAngleFromVertex(clockwiseCoords[2], clockwiseCoords[1]);
|
|
795
|
-
const angle = (startAngle + 360 - endAngle) % 360;
|
|
796
|
-
return angle;
|
|
797
|
-
};
|
|
133
|
+
function convertDegreesToRadians(degrees){return degrees/180*Math.PI}function convertRadiansToDegrees(radians){const degree=radians/Math.PI*180;return Number(degree.toPrecision(15))}function calculateAngleInDegrees([x,y]){return Math.atan2(y,x)*180/Math.PI}function polar(r,th){if(typeof r==="number"){r=[r,r];}th=th*Math.PI/180;return [r[0]*Math.cos(th),r[1]*Math.sin(th)]}const getAngleFromVertex=(point,vertex)=>{const x=point[0]-vertex[0];const y=point[1]-vertex[1];if(!x&&!y){return 0}return (180+Math.atan2(-y,-x)*180/Math.PI+360)%360};const getClockwiseAngle=(coords,allowReflexAngles=false)=>{const coordsCopy=[...coords];const areClockwise=clockwise([coordsCopy[0],coordsCopy[2],coordsCopy[1]]);const shouldReverseCoords=!areClockwise||allowReflexAngles;const clockwiseCoords=shouldReverseCoords?coordsCopy.reverse():coordsCopy;const startAngle=getAngleFromVertex(clockwiseCoords[0],clockwiseCoords[1]);const endAngle=getAngleFromVertex(clockwiseCoords[2],clockwiseCoords[1]);const angle=(startAngle+360-endAngle)%360;return angle};
|
|
798
134
|
|
|
799
135
|
var angles = /*#__PURE__*/Object.freeze({
|
|
800
136
|
__proto__: null,
|
|
@@ -806,28 +142,7 @@ var angles = /*#__PURE__*/Object.freeze({
|
|
|
806
142
|
polar: polar
|
|
807
143
|
});
|
|
808
144
|
|
|
809
|
-
function getSinusoidCoefficients(coords) {
|
|
810
|
-
const p1 = coords[0];
|
|
811
|
-
const p2 = coords[1];
|
|
812
|
-
const amplitude = p2[1] - p1[1];
|
|
813
|
-
const angularFrequency = Math.PI / (2 * (p2[0] - p1[0]));
|
|
814
|
-
const phase = p1[0] * angularFrequency;
|
|
815
|
-
const verticalOffset = p1[1];
|
|
816
|
-
return [amplitude, angularFrequency, phase, verticalOffset];
|
|
817
|
-
}
|
|
818
|
-
function getQuadraticCoefficients(coords) {
|
|
819
|
-
const p1 = coords[0];
|
|
820
|
-
const p2 = coords[1];
|
|
821
|
-
const p3 = coords[2];
|
|
822
|
-
const denom = (p1[0] - p2[0]) * (p1[0] - p3[0]) * (p2[0] - p3[0]);
|
|
823
|
-
if (denom === 0) {
|
|
824
|
-
return;
|
|
825
|
-
}
|
|
826
|
-
const a = (p3[0] * (p2[1] - p1[1]) + p2[0] * (p1[1] - p3[1]) + p1[0] * (p3[1] - p2[1])) / denom;
|
|
827
|
-
const b = (p3[0] * p3[0] * (p1[1] - p2[1]) + p2[0] * p2[0] * (p3[1] - p1[1]) + p1[0] * p1[0] * (p2[1] - p3[1])) / denom;
|
|
828
|
-
const c = (p2[0] * p3[0] * (p2[0] - p3[0]) * p1[1] + p3[0] * p1[0] * (p3[0] - p1[0]) * p2[1] + p1[0] * p2[0] * (p1[0] - p2[0]) * p3[1]) / denom;
|
|
829
|
-
return [a, b, c];
|
|
830
|
-
}
|
|
145
|
+
function getSinusoidCoefficients(coords){const p1=coords[0];const p2=coords[1];const amplitude=p2[1]-p1[1];const angularFrequency=Math.PI/(2*(p2[0]-p1[0]));const phase=p1[0]*angularFrequency;const verticalOffset=p1[1];return [amplitude,angularFrequency,phase,verticalOffset]}function getQuadraticCoefficients(coords){const p1=coords[0];const p2=coords[1];const p3=coords[2];const denom=(p1[0]-p2[0])*(p1[0]-p3[0])*(p2[0]-p3[0]);if(denom===0){return}const a=(p3[0]*(p2[1]-p1[1])+p2[0]*(p1[1]-p3[1])+p1[0]*(p3[1]-p2[1]))/denom;const b=(p3[0]*p3[0]*(p1[1]-p2[1])+p2[0]*p2[0]*(p3[1]-p1[1])+p1[0]*p1[0]*(p2[1]-p3[1]))/denom;const c=(p2[0]*p3[0]*(p2[0]-p3[0])*p1[1]+p3[0]*p1[0]*(p3[0]-p1[0])*p2[1]+p1[0]*p2[0]*(p1[0]-p2[0])*p3[1])/denom;return [a,b,c]}
|
|
831
146
|
|
|
832
147
|
var coefficients = /*#__PURE__*/Object.freeze({
|
|
833
148
|
__proto__: null,
|
|
@@ -835,5 +150,15 @@ var coefficients = /*#__PURE__*/Object.freeze({
|
|
|
835
150
|
getSinusoidCoefficients: getSinusoidCoefficients
|
|
836
151
|
});
|
|
837
152
|
|
|
838
|
-
|
|
153
|
+
exports.KhanMath = KhanMath;
|
|
154
|
+
exports.angles = angles;
|
|
155
|
+
exports.coefficients = coefficients;
|
|
156
|
+
exports.geometry = geometry;
|
|
157
|
+
exports.libVersion = libVersion;
|
|
158
|
+
exports.line = line;
|
|
159
|
+
exports.number = number;
|
|
160
|
+
exports.point = point;
|
|
161
|
+
exports.ray = ray;
|
|
162
|
+
exports.sum = sum;
|
|
163
|
+
exports.vector = vector$1;
|
|
839
164
|
//# sourceMappingURL=index.js.map
|