jsxgraph 1.3.0 → 1.4.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.
Files changed (90) hide show
  1. package/README.md +2 -2
  2. package/distrib/README.md +2 -2
  3. package/distrib/geogebra.min.js +3 -3
  4. package/distrib/geonext.min.js +3 -3
  5. package/distrib/index.d.ts +651 -448
  6. package/distrib/intergeo.min.js +3 -3
  7. package/distrib/jsxgraph.css +4 -13
  8. package/distrib/jsxgraphcore.js +9 -25
  9. package/distrib/jsxgraphsrc.js +28203 -25234
  10. package/distrib/sketch.min.js +3 -3
  11. package/package.json +11 -22
  12. package/src/base/board.js +674 -469
  13. package/src/base/chart.js +1 -1
  14. package/src/base/circle.js +23 -1
  15. package/src/base/composition.js +1 -1
  16. package/src/base/constants.js +32 -11
  17. package/src/base/coords.js +4 -4
  18. package/src/base/coordselement.js +51 -24
  19. package/src/base/curve.js +308 -117
  20. package/src/base/element.js +79 -50
  21. package/src/base/foreignobject.js +463 -0
  22. package/src/base/group.js +2 -2
  23. package/src/base/image.js +12 -15
  24. package/src/base/line.js +108 -21
  25. package/src/base/point.js +24 -28
  26. package/src/base/polygon.js +75 -18
  27. package/src/base/text.js +116 -63
  28. package/src/base/ticks.js +29 -11
  29. package/src/base/transformation.js +1 -1
  30. package/src/base/turtle.js +1 -1
  31. package/src/element/arc.js +1 -1
  32. package/src/element/button.js +29 -2
  33. package/src/element/checkbox.js +31 -1
  34. package/src/element/comb.js +5 -2
  35. package/src/element/composition.js +127 -19
  36. package/src/element/conic.js +46 -5
  37. package/src/element/input.js +32 -1
  38. package/src/element/locus.js +2 -2
  39. package/src/element/measure.js +9 -4
  40. package/src/element/sector.js +46 -12
  41. package/src/element/slider.js +17 -12
  42. package/src/element/slopetriangle.js +1 -1
  43. package/src/jsxgraph.js +28 -9
  44. package/src/jxg.js +4 -3
  45. package/src/loadjsxgraph.js +3 -2
  46. package/src/math/bst.js +1 -1
  47. package/src/math/clip.js +550 -345
  48. package/src/math/complex.js +1 -1
  49. package/src/math/extrapolate.js +1 -1
  50. package/src/math/geometry.js +155 -126
  51. package/src/math/ia.js +290 -21
  52. package/src/math/math.js +30 -1
  53. package/src/math/metapost.js +1 -1
  54. package/src/math/nlp.js +25 -5
  55. package/src/math/numerics.js +183 -4
  56. package/src/math/plot.js +4 -4
  57. package/src/math/poly.js +1 -1
  58. package/src/math/probfuncs.js +2 -1
  59. package/src/math/qdt.js +68 -62
  60. package/src/math/statistics.js +58 -7
  61. package/src/math/symbolic.js +1 -1
  62. package/src/options.js +377 -114
  63. package/src/parser/ca.js +1297 -1291
  64. package/src/parser/datasource.js +1 -1
  65. package/src/parser/geonext.js +6 -6
  66. package/src/parser/jessiecode.js +275 -79
  67. package/src/parser/jessiescript.js +1 -1
  68. package/src/reader/cinderella.js +1 -1
  69. package/src/reader/file.js +1 -1
  70. package/src/reader/geogebra.js +1 -1
  71. package/src/reader/geonext.js +1 -1
  72. package/src/reader/graph.js +1 -1
  73. package/src/reader/intergeo.js +1 -1
  74. package/src/reader/sketch.js +21 -13
  75. package/src/renderer/abstract.js +21 -6
  76. package/src/renderer/canvas.js +22 -15
  77. package/src/renderer/no.js +11 -4
  78. package/src/renderer/svg.js +76 -53
  79. package/src/renderer/vml.js +36 -32
  80. package/src/server/server.js +1 -1
  81. package/src/utils/base64.js +2 -2
  82. package/src/utils/color.js +148 -3
  83. package/src/utils/dump.js +21 -15
  84. package/src/utils/env.js +63 -104
  85. package/src/utils/event.js +1 -1
  86. package/src/utils/expect.js +1 -1
  87. package/src/utils/type.js +30 -19
  88. package/src/utils/xml.js +1 -1
  89. package/src/utils/zip.js +1 -1
  90. package/CHANGELOG.md +0 -1281
package/src/base/curve.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*
2
- Copyright 2008-2021
2
+ Copyright 2008-2022
3
3
  Matthias Ehmann,
4
4
  Michael Gerhaeuser,
5
5
  Carsten Miller,
@@ -87,7 +87,7 @@ define([
87
87
  * Array holding the x-coordinates of a data plot.
88
88
  * This array can be updated during run time by overwriting
89
89
  * the method {@link JXG.Curve#updateDataArray}.
90
- * @type {array}
90
+ * @type array
91
91
  */
92
92
  this.dataX = null;
93
93
 
@@ -95,7 +95,7 @@ define([
95
95
  * Array holding the y-coordinates of a data plot.
96
96
  * This array can be updated during run time by overwriting
97
97
  * the method {@link JXG.Curve#updateDataArray}.
98
- * @type {array}
98
+ * @type array
99
99
  */
100
100
  this.dataY = null;
101
101
 
@@ -111,7 +111,7 @@ define([
111
111
  /**
112
112
  * Stores a quad tree if it is required. The quad tree is generated in the curve
113
113
  * updates and can be used to speed up the hasPoint method.
114
- * @type {JXG.Math.Quadtree}
114
+ * @type JXG.Math.Quadtree
115
115
  */
116
116
  this.qdt = null;
117
117
 
@@ -302,7 +302,7 @@ define([
302
302
  t += d;
303
303
  }
304
304
  } else if (ev_ct === 'plot' ||
305
- ev_ct === 'functiongraph') {
305
+ ev_ct === 'functiongraph') {
306
306
 
307
307
  if (!Type.exists(start) || start < 0) {
308
308
  start = 0;
@@ -311,7 +311,7 @@ define([
311
311
  if (Type.exists(this.qdt) &&
312
312
  Type.evaluate(this.visProp.useqdt) &&
313
313
  this.bezierDegree !== 3
314
- ) {
314
+ ) {
315
315
  qdt = this.qdt.query(new Coords(Const.COORDS_BY_USER, [x, y], this.board));
316
316
  points = qdt.points;
317
317
  len = points.length;
@@ -734,7 +734,7 @@ define([
734
734
  // this.updateTransform(this.points[i]);
735
735
  suspendUpdate = true;
736
736
  }
737
- // continuous x data
737
+ // continuous x data
738
738
  } else {
739
739
  if (Type.evaluate(this.visProp.doadvancedplot)) {
740
740
  // console.time("plot");
@@ -786,7 +786,7 @@ define([
786
786
  }
787
787
 
788
788
  if (Type.evaluate(this.visProp.curvetype) !== 'plot' &&
789
- Type.evaluate(this.visProp.rdpsmoothing)) {
789
+ Type.evaluate(this.visProp.rdpsmoothing)) {
790
790
  // console.time("rdp");
791
791
  this.points = Numerics.RamerDouglasPeucker(this.points, 0.2);
792
792
  this.numberPoints = this.points.length;
@@ -1009,7 +1009,7 @@ define([
1009
1009
  obj;
1010
1010
 
1011
1011
  // Read dependencies found by the JessieCode parser
1012
- obj = {'xterm': 1, 'yterm': 1};
1012
+ obj = { 'xterm': 1, 'yterm': 1 };
1013
1013
  for (fstr in obj) {
1014
1014
  if (obj.hasOwnProperty(fstr) && this.hasOwnProperty(fstr) && this[fstr].origin) {
1015
1015
  isJessieCode = true;
@@ -1035,38 +1035,38 @@ define([
1035
1035
  by = 0.95 * this.board.canvasHeight;
1036
1036
 
1037
1037
  switch (Type.evaluate(this.visProp.label.position)) {
1038
- case 'ulft':
1039
- x = ax;
1040
- y = ay;
1041
- break;
1042
- case 'llft':
1043
- x = ax;
1044
- y = by;
1045
- break;
1046
- case 'rt':
1047
- x = bx;
1048
- y = 0.5 * by;
1049
- break;
1050
- case 'lrt':
1051
- x = bx;
1052
- y = by;
1053
- break;
1054
- case 'urt':
1055
- x = bx;
1056
- y = ay;
1057
- break;
1058
- case 'top':
1059
- x = 0.5 * bx;
1060
- y = ay;
1061
- break;
1062
- case 'bot':
1063
- x = 0.5 * bx;
1064
- y = by;
1065
- break;
1066
- default:
1067
- // includes case 'lft'
1068
- x = ax;
1069
- y = 0.5 * by;
1038
+ case 'ulft':
1039
+ x = ax;
1040
+ y = ay;
1041
+ break;
1042
+ case 'llft':
1043
+ x = ax;
1044
+ y = by;
1045
+ break;
1046
+ case 'rt':
1047
+ x = bx;
1048
+ y = 0.5 * by;
1049
+ break;
1050
+ case 'lrt':
1051
+ x = bx;
1052
+ y = by;
1053
+ break;
1054
+ case 'urt':
1055
+ x = bx;
1056
+ y = ay;
1057
+ break;
1058
+ case 'top':
1059
+ x = 0.5 * bx;
1060
+ y = ay;
1061
+ break;
1062
+ case 'bot':
1063
+ x = 0.5 * bx;
1064
+ y = by;
1065
+ break;
1066
+ default:
1067
+ // includes case 'lft'
1068
+ x = ax;
1069
+ y = 0.5 * by;
1070
1070
  }
1071
1071
 
1072
1072
  c = new Coords(Const.COORDS_BY_SCREEN, [x, y], this.board, false);
@@ -1104,7 +1104,7 @@ define([
1104
1104
  return this;
1105
1105
  },
1106
1106
 
1107
- // already documented in GeometryElement
1107
+ // Already documented in GeometryElement
1108
1108
  bounds: function () {
1109
1109
  var minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity,
1110
1110
  l = this.points.length, i,
@@ -1113,15 +1113,15 @@ define([
1113
1113
  if (this.bezierDegree === 3) {
1114
1114
  // Add methods X(), Y()
1115
1115
  for (i = 0; i < l; i++) {
1116
- this.points[i].X = Type.bind(function() { return this.usrCoords[1]; }, this.points[i]);
1117
- this.points[i].Y = Type.bind(function() { return this.usrCoords[2]; }, this.points[i]);
1116
+ this.points[i].X = Type.bind(function () { return this.usrCoords[1]; }, this.points[i]);
1117
+ this.points[i].Y = Type.bind(function () { return this.usrCoords[2]; }, this.points[i]);
1118
1118
  }
1119
1119
  bezier = Numerics.bezier(this.points);
1120
1120
  up = bezier[3]();
1121
- minX = Numerics.fminbr(function(t) { return bezier[0](t); }, [0, up]);
1122
- maxX = Numerics.fminbr(function(t) { return -bezier[0](t); }, [0, up]);
1123
- minY = Numerics.fminbr(function(t) { return bezier[1](t); }, [0, up]);
1124
- maxY = Numerics.fminbr(function(t) { return -bezier[1](t); }, [0, up]);
1121
+ minX = Numerics.fminbr(function (t) { return bezier[0](t); }, [0, up]);
1122
+ maxX = Numerics.fminbr(function (t) { return -bezier[0](t); }, [0, up]);
1123
+ minY = Numerics.fminbr(function (t) { return bezier[1](t); }, [0, up]);
1124
+ maxY = Numerics.fminbr(function (t) { return -bezier[1](t); }, [0, up]);
1125
1125
 
1126
1126
  minX = bezier[0](minX);
1127
1127
  maxX = bezier[0](maxX);
@@ -1169,18 +1169,18 @@ define([
1169
1169
  * @param {Array} where Array containing the x and y coordinate of the target location.
1170
1170
  * @returns {JXG.Curve} Reference to itself.
1171
1171
  */
1172
- moveTo: function(where) {
1172
+ moveTo: function (where) {
1173
1173
  // TODO add animation
1174
1174
  var delta = [], p;
1175
1175
  if (this.points.length > 0 && !Type.evaluate(this.visProp.fixed)) {
1176
1176
  p = this.points[0];
1177
1177
  if (where.length === 3) {
1178
1178
  delta = [where[0] - p.usrCoords[0],
1179
- where[1] - p.usrCoords[1],
1180
- where[2] - p.usrCoords[2]];
1179
+ where[1] - p.usrCoords[1],
1180
+ where[2] - p.usrCoords[2]];
1181
1181
  } else {
1182
1182
  delta = [where[0] - p.usrCoords[1],
1183
- where[1] - p.usrCoords[2]];
1183
+ where[1] - p.usrCoords[2]];
1184
1184
  }
1185
1185
  this.setPosition(Const.COORDS_BY_USER, delta);
1186
1186
  }
@@ -1198,14 +1198,14 @@ define([
1198
1198
  * @returns {Array} [Boolean, curve]: Array contining 'true' if curve is result of a transformation,
1199
1199
  * and the source curve of the transformation.
1200
1200
  */
1201
- getTransformationSource: function() {
1201
+ getTransformationSource: function () {
1202
1202
  var isTransformed, curve_org;
1203
1203
  if (Type.exists(this._transformationSource)) {
1204
1204
  curve_org = this._transformationSource;
1205
1205
  if (curve_org.elementClass === Const.OBJECT_CLASS_CURVE //&&
1206
1206
  //Type.evaluate(curve_org.visProp.curvetype) !== 'plot'
1207
- ) {
1208
- isTransformed = true;
1207
+ ) {
1208
+ isTransformed = true;
1209
1209
  }
1210
1210
  }
1211
1211
  return [isTransformed, curve_org];
@@ -1380,10 +1380,10 @@ define([
1380
1380
  obj = board.select(parents[0], true);
1381
1381
  if (Type.isObject(obj) &&
1382
1382
  (obj.type === Const.OBJECT_TYPE_CURVE ||
1383
- obj.type === Const.OBJECT_TYPE_ANGLE ||
1384
- obj.type === Const.OBJECT_TYPE_ARC ||
1385
- obj.type === Const.OBJECT_TYPE_CONIC ||
1386
- obj.type === Const.OBJECT_TYPE_SECTOR) &&
1383
+ obj.type === Const.OBJECT_TYPE_ANGLE ||
1384
+ obj.type === Const.OBJECT_TYPE_ARC ||
1385
+ obj.type === Const.OBJECT_TYPE_CONIC ||
1386
+ obj.type === Const.OBJECT_TYPE_SECTOR) &&
1387
1387
  Type.isTransformationOrArray(parents[1])) {
1388
1388
 
1389
1389
  if (obj.type === Const.OBJECT_TYPE_SECTOR) {
@@ -1401,17 +1401,17 @@ define([
1401
1401
  attr = Type.copyAttributes(attr, board.options, 'curve');
1402
1402
 
1403
1403
  cu = new JXG.Curve(board, ['x', [], []], attr);
1404
- cu.updateDataArray = function() {
1405
- var i, le = obj.numberPoints;
1406
- this.bezierDegree = obj.bezierDegree;
1407
- this.dataX = [];
1408
- this.dataY = [];
1409
- for (i = 0; i < le; i++) {
1410
- this.dataX.push(obj.points[i].usrCoords[1]);
1411
- this.dataY.push(obj.points[i].usrCoords[2]);
1412
- }
1413
- return this;
1414
- };
1404
+ cu.updateDataArray = function () {
1405
+ var i, le = obj.numberPoints;
1406
+ this.bezierDegree = obj.bezierDegree;
1407
+ this.dataX = [];
1408
+ this.dataY = [];
1409
+ for (i = 0; i < le; i++) {
1410
+ this.dataX.push(obj.points[i].usrCoords[1]);
1411
+ this.dataY.push(obj.points[i].usrCoords[2]);
1412
+ }
1413
+ return this;
1414
+ };
1415
1415
  cu.addTransform(parents[1]);
1416
1416
  obj.addChild(cu);
1417
1417
  cu.setParents([obj]);
@@ -1560,7 +1560,7 @@ define([
1560
1560
  if (Type.isPoint(parents[i])) {
1561
1561
  x.push(parents[i].X());
1562
1562
  y.push(parents[i].Y());
1563
- // given as [[x1,y1], [x2, y2], ...]
1563
+ // given as [[x1,y1], [x2, y2], ...]
1564
1564
  } else if (Type.isArray(parents[i]) && parents[i].length === 2) {
1565
1565
  for (j = 0; j < parents.length; j++) {
1566
1566
  if (Type.isFunction(parents[j][0])) {
@@ -1591,12 +1591,12 @@ define([
1591
1591
  return Numerics.splineEval(t, x, y, D);
1592
1592
  },
1593
1593
  // minX()
1594
- function() {
1594
+ function () {
1595
1595
  return x[0];
1596
1596
  },
1597
1597
  //maxX()
1598
- function() {
1599
- return x[x.length -1];
1598
+ function () {
1599
+ return x[x.length - 1];
1600
1600
  }];
1601
1601
 
1602
1602
  };
@@ -1675,7 +1675,7 @@ define([
1675
1675
  * </script><pre>
1676
1676
  */
1677
1677
  JXG.createCardinalSpline = function (board, parents, attributes) {
1678
- var el,
1678
+ var el, getPointLike,
1679
1679
  points, tau, type,
1680
1680
  p, q, i, le,
1681
1681
  splineArr,
@@ -1723,7 +1723,7 @@ define([
1723
1723
  q.push(board.select(p[i]));
1724
1724
  } else if (Type.isPoint(p[i])) {
1725
1725
  q.push(p[i]);
1726
- // given as [[x0,y0], [x1, y2], ...]
1726
+ // given as [[x0,y0], [x1, y2], ...]
1727
1727
  } else if (Type.isArray(p[i]) && p[i].length === 2) {
1728
1728
  q[i] = [];
1729
1729
  if (Type.isFunction(p[i][0])) {
@@ -1747,22 +1747,27 @@ define([
1747
1747
  points = Type.providePoints(board, q, attributes, 'cardinalspline', ['points']);
1748
1748
  } else {
1749
1749
  points = [];
1750
+
1751
+ /**
1752
+ * @ignore
1753
+ */
1754
+ getPointLike = function (ii) {
1755
+ return {
1756
+ X: function () { return q[ii][0]; },
1757
+ Y: function () { return q[ii][1]; },
1758
+ Dist: function (p) {
1759
+ var dx = this.X() - p.X(),
1760
+ dy = this.Y() - p.Y();
1761
+ return Math.sqrt(dx * dx + dy * dy);
1762
+ }
1763
+ };
1764
+ };
1765
+
1750
1766
  for (i = 0; i < q.length; i++) {
1751
1767
  if (Type.isPoint(q[i])) {
1752
1768
  points.push(q[i]);
1753
1769
  } else {
1754
- points.push(
1755
- (function(ii) { return {
1756
- X: function() { return q[ii][0]; },
1757
- Y: function() { return q[ii][1]; },
1758
- Dist: function(p) {
1759
- var dx = this.X() - p.X(),
1760
- dy = this.Y() - p.Y();
1761
- return Math.sqrt(dx * dx + dy * dy);
1762
- }
1763
- };
1764
- })(i)
1765
- );
1770
+ points.push(getPointLike(i));
1766
1771
  }
1767
1772
  }
1768
1773
  }
@@ -1892,7 +1897,7 @@ define([
1892
1897
  *
1893
1898
  */
1894
1899
  JXG.createMetapostSpline = function (board, parents, attributes) {
1895
- var el,
1900
+ var el, getPointLike,
1896
1901
  points, controls,
1897
1902
  p, q, i, le,
1898
1903
  errStr = "\nPossible parent types: [points:array, controls:object";
@@ -1936,7 +1941,7 @@ define([
1936
1941
  q.push(board.select(p[i]));
1937
1942
  } else if (Type.isPoint(p[i])) {
1938
1943
  q.push(p[i]);
1939
- // given as [[x0,y0], [x1, y2], ...]
1944
+ // given as [[x0,y0], [x1, y2], ...]
1940
1945
  } else if (Type.isArray(p[i]) && p[i].length === 2) {
1941
1946
  q[i] = [];
1942
1947
  if (Type.isFunction(p[i][0])) {
@@ -1960,17 +1965,22 @@ define([
1960
1965
  points = Type.providePoints(board, q, attributes, 'metapostspline', ['points']);
1961
1966
  } else {
1962
1967
  points = [];
1968
+
1969
+ /**
1970
+ * @ignore
1971
+ */
1972
+ getPointLike = function (ii) {
1973
+ return {
1974
+ X: function () { return q[ii][0]; },
1975
+ Y: function () { return q[ii][1]; }
1976
+ };
1977
+ };
1978
+
1963
1979
  for (i = 0; i < q.length; i++) {
1964
1980
  if (Type.isPoint(q[i])) {
1965
1981
  points.push(q[i]);
1966
1982
  } else {
1967
- points.push(
1968
- (function(ii) { return {
1969
- X: function() { return q[ii][0]; },
1970
- Y: function() { return q[ii][1]; }
1971
- };
1972
- })(i)
1973
- );
1983
+ points.push(getPointLike);
1974
1984
  }
1975
1985
  }
1976
1986
  }
@@ -2117,6 +2127,9 @@ define([
2117
2127
  return this.sum;
2118
2128
  };
2119
2129
 
2130
+ /**
2131
+ * @ignore
2132
+ */
2120
2133
  c.updateDataArray = function () {
2121
2134
  var u = Numerics.riemann(f, n(), type(), this.minX(), this.maxX());
2122
2135
  this.dataX = u[0];
@@ -2183,7 +2196,10 @@ define([
2183
2196
  attr.curvetype = 'plot';
2184
2197
  c = board.create('curve', [[0], [0]], attr);
2185
2198
 
2186
- c.updateDataArray = function () {
2199
+ /**
2200
+ * @ignore
2201
+ */
2202
+ c.updateDataArray = function () {
2187
2203
  var i, step, t, el, pEl, x, y, from, savetrace,
2188
2204
  le = attr.numberpoints,
2189
2205
  savePos = glider.position,
@@ -2307,7 +2323,10 @@ define([
2307
2323
 
2308
2324
  attr = Type.copyAttributes(attributes, board.options, 'stepfunction');
2309
2325
  c = board.create('curve', parents, attr);
2310
- c.updateDataArray = function () {
2326
+ /**
2327
+ * @ignore
2328
+ */
2329
+ c.updateDataArray = function () {
2311
2330
  var i, j = 0,
2312
2331
  len = this.xterm.length;
2313
2332
 
@@ -2383,10 +2402,10 @@ define([
2383
2402
  dy = Numerics.D(curve.Y);
2384
2403
 
2385
2404
  c = board.create('curve', [
2386
- function(t) { return curve.X(t); },
2387
- function(t) { return dy(t) / dx(t); },
2388
- curve.minX(), curve.maxX()
2389
- ], attr);
2405
+ function (t) { return curve.X(t); },
2406
+ function (t) { return dy(t) / dx(t); },
2407
+ curve.minX(), curve.maxX()
2408
+ ], attr);
2390
2409
 
2391
2410
  c.setParents(curve);
2392
2411
 
@@ -2438,10 +2457,13 @@ define([
2438
2457
  }
2439
2458
 
2440
2459
  c = board.create('curve', [[], []], attributes);
2441
- c.updateDataArray = function() {
2442
- var a = JXG.Math.Clip.intersection(parents[0], parents[1], this.board);
2443
- this.dataX = a[0];
2444
- this.dataY = a[1];
2460
+ /**
2461
+ * @ignore
2462
+ */
2463
+ c.updateDataArray = function () {
2464
+ var a = JXG.Math.Clip.intersection(parents[0], parents[1], this.board);
2465
+ this.dataX = a[0];
2466
+ this.dataY = a[1];
2445
2467
  };
2446
2468
  return c;
2447
2469
  };
@@ -2480,7 +2502,7 @@ define([
2480
2502
  * </script><pre>
2481
2503
  *
2482
2504
  */
2483
- JXG.createCurveUnion = function (board, parents, attributes) {
2505
+ JXG.createCurveUnion = function (board, parents, attributes) {
2484
2506
  var c;
2485
2507
 
2486
2508
  if (parents.length !== 2) {
@@ -2489,10 +2511,13 @@ define([
2489
2511
  }
2490
2512
 
2491
2513
  c = board.create('curve', [[], []], attributes);
2492
- c.updateDataArray = function() {
2493
- var a = JXG.Math.Clip.union(parents[0], parents[1], this.board);
2494
- this.dataX = a[0];
2495
- this.dataY = a[1];
2514
+ /**
2515
+ * @ignore
2516
+ */
2517
+ c.updateDataArray = function () {
2518
+ var a = JXG.Math.Clip.union(parents[0], parents[1], this.board);
2519
+ this.dataX = a[0];
2520
+ this.dataY = a[1];
2496
2521
  };
2497
2522
  return c;
2498
2523
  };
@@ -2531,7 +2556,7 @@ define([
2531
2556
  * </script><pre>
2532
2557
  *
2533
2558
  */
2534
- JXG.createCurveDifference = function (board, parents, attributes) {
2559
+ JXG.createCurveDifference = function (board, parents, attributes) {
2535
2560
  var c;
2536
2561
 
2537
2562
  if (parents.length !== 2) {
@@ -2540,10 +2565,13 @@ define([
2540
2565
  }
2541
2566
 
2542
2567
  c = board.create('curve', [[], []], attributes);
2543
- c.updateDataArray = function() {
2544
- var a = JXG.Math.Clip.difference(parents[0], parents[1], this.board);
2545
- this.dataX = a[0];
2546
- this.dataY = a[1];
2568
+ /**
2569
+ * @ignore
2570
+ */
2571
+ c.updateDataArray = function () {
2572
+ var a = JXG.Math.Clip.difference(parents[0], parents[1], this.board);
2573
+ this.dataX = a[0];
2574
+ this.dataY = a[1];
2547
2575
  };
2548
2576
  return c;
2549
2577
  };
@@ -2552,6 +2580,169 @@ define([
2552
2580
  JXG.registerElement('curveintersection', JXG.createCurveIntersection);
2553
2581
  JXG.registerElement('curveunion', JXG.createCurveUnion);
2554
2582
 
2583
+ /**
2584
+ * @class Box plot curve. The direction of the box plot can be either vertical or horizontal which
2585
+ * is controlled by the attribute "dir".
2586
+ * @pseudo
2587
+ * @description
2588
+ * @name Boxplot
2589
+ * @param {Array} quantiles Array conatining at least five quantiles. The elements can be of type number, function or string.
2590
+ * @param {Number|Function} axis Axis position of the box plot
2591
+ * @param {Number|Function} width Width of the rectangle part of the box plot. The width of the first and 4th quantile
2592
+ * is relative to this width and can be controlled by the attribute "smallWidth".
2593
+ * @augments JXG.Curve
2594
+ * @constructor
2595
+ * @type JXG.Curve
2596
+ *
2597
+ * @example
2598
+ * var Q = [ -1, 2, 3, 3.5, 5 ];
2599
+ *
2600
+ * var b = board.create('boxplot', [Q, 2, 4], {strokeWidth: 3});
2601
+ *
2602
+ * </pre><div id="JXG13eb23a1-a641-41a2-be11-8e03e400a947" class="jxgbox" style="width: 300px; height: 300px;"></div>
2603
+ * <script type="text/javascript">
2604
+ * (function() {
2605
+ * var board = JXG.JSXGraph.initBoard('JXG13eb23a1-a641-41a2-be11-8e03e400a947',
2606
+ * {boundingbox: [-8, 8, 8,-8], axis: true, showcopyright: false, shownavigation: false});
2607
+ * var Q = [ -1, 2, 3, 3.5, 5 ];
2608
+ * var b = board.create('boxplot', [Q, 2, 4], {strokeWidth: 3});
2609
+ *
2610
+ * })();
2611
+ *
2612
+ * </script><pre>
2613
+ *
2614
+ * @example
2615
+ * var Q = [ -1, 2, 3, 3.5, 5 ];
2616
+ * var b = board.create('boxplot', [Q, 3, 4], {dir: 'horizontal', smallWidth: 0.25, color:'red'});
2617
+ *
2618
+ * </pre><div id="JXG0deb9cb2-84bc-470d-a6db-8be9a5694813" class="jxgbox" style="width: 300px; height: 300px;"></div>
2619
+ * <script type="text/javascript">
2620
+ * (function() {
2621
+ * var board = JXG.JSXGraph.initBoard('JXG0deb9cb2-84bc-470d-a6db-8be9a5694813',
2622
+ * {boundingbox: [-8, 8, 8,-8], axis: true, showcopyright: false, shownavigation: false});
2623
+ * var Q = [ -1, 2, 3, 3.5, 5 ];
2624
+ * var b = board.create('boxplot', [Q, 3, 4], {dir: 'horizontal', smallWidth: 0.25, color:'red'});
2625
+ *
2626
+ * })();
2627
+ *
2628
+ * </script><pre>
2629
+ *
2630
+ * @example
2631
+ * var data = [57, 57, 57, 58, 63, 66, 66, 67, 67, 68, 69, 70, 70, 70, 70, 72, 73, 75, 75, 76, 76, 78, 79, 81];
2632
+ * var Q = [];
2633
+ *
2634
+ * Q[0] = JXG.Math.Statistics.min(data);
2635
+ * Q = Q.concat(JXG.Math.Statistics.percentile(data, [25, 50, 75]));
2636
+ * Q[4] = JXG.Math.Statistics.max(data);
2637
+ *
2638
+ * var b = board.create('boxplot', [Q, 0, 3]);
2639
+ *
2640
+ * </pre><div id="JXGef079e76-ae99-41e4-af29-1d07d83bf85a" class="jxgbox" style="width: 300px; height: 300px;"></div>
2641
+ * <script type="text/javascript">
2642
+ * (function() {
2643
+ * var board = JXG.JSXGraph.initBoard('JXGef079e76-ae99-41e4-af29-1d07d83bf85a',
2644
+ * {boundingbox: [-5,90,5,30], axis: true, showcopyright: false, shownavigation: false});
2645
+ * var data = [57, 57, 57, 58, 63, 66, 66, 67, 67, 68, 69, 70, 70, 70, 70, 72, 73, 75, 75, 76, 76, 78, 79, 81];
2646
+ * var Q = [];
2647
+ *
2648
+ * Q[0] = JXG.Math.Statistics.min(data);
2649
+ * Q = Q.concat(JXG.Math.Statistics.percentile(data, [25, 50, 75]));
2650
+ * Q[4] = JXG.Math.Statistics.max(data);
2651
+ *
2652
+ * var b = board.create('boxplot', [Q, 0, 3]);
2653
+ *
2654
+ * })();
2655
+ *
2656
+ * </script><pre>
2657
+ *
2658
+ * @example
2659
+ * var mi = board.create('glider', [0, -1, board.defaultAxes.y]);
2660
+ * var ma = board.create('glider', [0, 5, board.defaultAxes.y]);
2661
+ * var Q = [function() { return mi.Y(); }, 2, 3, 3.5, function() { return ma.Y(); }];
2662
+ *
2663
+ * var b = board.create('boxplot', [Q, 0, 2]);
2664
+ *
2665
+ * </pre><div id="JXG3b3225da-52f0-42fe-8396-be9016bf289b" class="jxgbox" style="width: 300px; height: 300px;"></div>
2666
+ * <script type="text/javascript">
2667
+ * (function() {
2668
+ * var board = JXG.JSXGraph.initBoard('JXG3b3225da-52f0-42fe-8396-be9016bf289b',
2669
+ * {boundingbox: [-8, 8, 8,-8], axis: true, showcopyright: false, shownavigation: false});
2670
+ * var mi = board.create('glider', [0, -1, board.defaultAxes.y]);
2671
+ * var ma = board.create('glider', [0, 5, board.defaultAxes.y]);
2672
+ * var Q = [function() { return mi.Y(); }, 2, 3, 3.5, function() { return ma.Y(); }];
2673
+ *
2674
+ * var b = board.create('boxplot', [Q, 0, 2]);
2675
+ *
2676
+ * })();
2677
+ *
2678
+ * </script><pre>
2679
+ *
2680
+ */
2681
+ JXG.createBoxPlot = function (board, parents, attributes) {
2682
+ var box, i, len, w2,
2683
+ attr = Type.copyAttributes(attributes, board.options, 'boxplot');
2684
+
2685
+ if (parents.length !== 3) {
2686
+ throw new Error("JSXGraph: Can't create box plot with given parent'" +
2687
+ "\nPossible parent types: [array, number|function, number|function] containing quantiles, axis, width");
2688
+ }
2689
+ if (parents[0].length < 5) {
2690
+ throw new Error("JSXGraph: Can't create box plot with given parent[0]'" +
2691
+ "\nparent[0] has to conatin at least 5 quantiles.");
2692
+ }
2693
+ box = board.create('curve', [[],[]], attr);
2694
+
2695
+ len = parents[0].length; // Quantiles
2696
+ box.Q = [];
2697
+ for (i = 0; i < len; i++) {
2698
+ box.Q[i] = Type.createFunction(parents[0][i], board, null, true);
2699
+ }
2700
+ box.x = Type.createFunction(parents[1], board, null, true);
2701
+ box.w = Type.createFunction(parents[2], board, null, true);
2702
+
2703
+ box.updateDataArray = function() {
2704
+ var v1, v2, l1, l2, r1, r2, w2, dir, x;
2705
+
2706
+ w2 = Type.evaluate(this.visProp.smallwidth);
2707
+ dir = Type.evaluate(this.visProp.dir);
2708
+ x = this.x();
2709
+ l1 = x - this.w() * 0.5;
2710
+ l2 = x - this.w() * 0.5 * w2;
2711
+ r1 = x + this.w() * 0.5;
2712
+ r2 = x + this.w() * 0.5 * w2;
2713
+ v1 = [x, l2, r2, x, x, l1, l1, r1, r1, x, NaN, l1, r1, NaN, x, x, l2, r2, x];
2714
+ v2 = [this.Q[0](),
2715
+ this.Q[0](),
2716
+ this.Q[0](),
2717
+ this.Q[0](),
2718
+ this.Q[1](),
2719
+ this.Q[1](),
2720
+ this.Q[3](),
2721
+ this.Q[3](),
2722
+ this.Q[1](),
2723
+ this.Q[1](),
2724
+ NaN,
2725
+ this.Q[2](),
2726
+ this.Q[2](),
2727
+ NaN,
2728
+ this.Q[3](),
2729
+ this.Q[4](),
2730
+ this.Q[4](),
2731
+ this.Q[4](),
2732
+ this.Q[4]()];
2733
+ if (dir === 'vertical') {
2734
+ this.dataX = v1;
2735
+ this.dataY = v2;
2736
+ } else {
2737
+ this.dataX = v2;
2738
+ this.dataY = v1;
2739
+ }
2740
+ };
2741
+ return box;
2742
+ };
2743
+
2744
+ JXG.registerElement('boxplot', JXG.createBoxPlot);
2745
+
2555
2746
  return {
2556
2747
  Curve: JXG.Curve,
2557
2748
  createCardinalSpline: JXG.createCardinalSpline,