jsxgraph 1.4.1 → 1.4.4

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.
@@ -6,7 +6,7 @@
6
6
  } else {
7
7
  root.returnExports = factory();
8
8
  }
9
- }(this, function () {
9
+ }(typeof self !== 'undefined' ? self : this, function () {
10
10
  /**
11
11
  * @license almond 0.3.3 Copyright jQuery Foundation and other contributors.
12
12
  * Released under MIT license, http://github.com/requirejs/almond/LICENSE
@@ -842,7 +842,7 @@ define('base/constants',['jxg'], function (JXG) {
842
842
 
843
843
  var major = 1,
844
844
  minor = 4,
845
- patch = 1,
845
+ patch = 4,
846
846
  add = '', //'dev'
847
847
  version = major + '.' + minor + '.' + patch + (add ? '-' + add : ''),
848
848
  constants;
@@ -911,6 +911,7 @@ define('base/constants',['jxg'], function (JXG) {
911
911
  OBJECT_TYPE_BUTTON: 29,
912
912
  OBJECT_TYPE_TRANSFORMATION: 30,
913
913
  OBJECT_TYPE_FOREIGNOBJECT: 31,
914
+ OBJECT_TYPE_VIEW3D: 32,
914
915
 
915
916
  // IMPORTANT:
916
917
  // ----------
@@ -2025,7 +2026,7 @@ define('utils/type',[
2025
2026
  }
2026
2027
 
2027
2028
  // options from attributes
2028
- o = attributes;
2029
+ o = (typeof attributes === 'object') ? attributes : {};
2029
2030
  isAvail = true;
2030
2031
  for (i = 3; i < len; i++) {
2031
2032
  if (this.exists(o[arguments[i]])) {
@@ -2331,7 +2332,7 @@ define('utils/type',[
2331
2332
  return html_sanitize(str, function () { return undefined; }, function (id) { return id; });
2332
2333
  }
2333
2334
 
2334
- if (str) {
2335
+ if (str && typeof str === 'string') {
2335
2336
  str = str.replace(/</g, '&lt;').replace(/>/g, '&gt;');
2336
2337
  }
2337
2338
 
@@ -3998,6 +3999,15 @@ define('math/math',['jxg', 'utils/type'], function (JXG, Type) {
3998
3999
  return Math.sqrt(sum);
3999
4000
  },
4000
4001
 
4002
+ axpy: function (a, x, y) {
4003
+ var i, le = x.length,
4004
+ p = [];
4005
+ for (i = 0; i < le; i++) {
4006
+ p[i] = a * x[i] + y[i];
4007
+ }
4008
+ return p;
4009
+ },
4010
+
4001
4011
  /**
4002
4012
  * Compute the factorial of a positive integer. If a non-integer value
4003
4013
  * is given, the fraction will be ignored.
@@ -14727,6 +14737,30 @@ define('math/geometry',[
14727
14737
  return that.meetCurveLine(el1, el2, i, el1.board, alwaysintersect);
14728
14738
  };
14729
14739
 
14740
+ } else if (el1.type === Const.OBJECT_TYPE_POLYGON || el2.type === Const.OBJECT_TYPE_POLYGON) {
14741
+ // polygon - other
14742
+ // Uses the Greiner-Hormann clipping algorithm
14743
+ // Not implemented: polygon - point
14744
+
14745
+ if (el1.elementClass === Const.OBJECT_CLASS_LINE) {
14746
+ // line - path
14747
+ /** @ignore */
14748
+ func = function () {
14749
+ return that.meetPolygonLine(el2, el1, i, el1.board, alwaysintersect);
14750
+ };
14751
+ } else if (el2.elementClass === Const.OBJECT_CLASS_LINE) {
14752
+ // path - line
14753
+ func = function () {
14754
+ return that.meetPolygonLine(el1, el2, i, el1.board, alwaysintersect);
14755
+ };
14756
+ } else {
14757
+ // path - path
14758
+ /** @ignore */
14759
+ func = function () {
14760
+ return that.meetPathPath(el1, el2, i, el1.board);
14761
+ };
14762
+ }
14763
+
14730
14764
  } else if (el1.elementClass === Const.OBJECT_CLASS_LINE && el2.elementClass === Const.OBJECT_CLASS_LINE) {
14731
14765
  // line - line, lines may also be segments.
14732
14766
  /** @ignore */
@@ -15142,6 +15176,8 @@ define('math/geometry',[
15142
15176
  * @param {JXG.Line} li Line
15143
15177
  * @param {Number} nr Will return the nr-th intersection point.
15144
15178
  * @param {JXG.Board} board
15179
+ * @param {Boolean} testSegment Test if intersection has to be inside of the segment or somewhere on the
15180
+ * line defined by the segment
15145
15181
  * @returns {JXG.Coords} Coords object containing the intersection.
15146
15182
  */
15147
15183
  meetCurveLineContinuous: function (cu, li, nr, board, testSegment) {
@@ -15206,7 +15242,6 @@ define('math/geometry',[
15206
15242
  return (new Coords(Const.COORDS_BY_USER, [z, cu.X(t), cu.Y(t)], board));
15207
15243
  },
15208
15244
 
15209
-
15210
15245
  /**
15211
15246
  * Intersection of line and curve, discrete case.
15212
15247
  * Segments are treated as lines.
@@ -15393,6 +15428,87 @@ define('math/geometry',[
15393
15428
  return [c, t, u];
15394
15429
  },
15395
15430
 
15431
+ /**
15432
+ * Find the n-th intersection point of two pathes, usually given by polygons. Uses parts of the
15433
+ * Greiner-Hormann algorithm in JXG.Math.Clip.
15434
+ *
15435
+ * @param {JXG.Circle|JXG.Curve|JXG.Polygon} path1
15436
+ * @param {JXG.Circle|JXG.Curve|JXG.Polygon} path2
15437
+ * @param {Number} n
15438
+ * @param {JXG.Board} board
15439
+ *
15440
+ * @returns {JXG.Coords} Intersection point. In case no intersection point is detected,
15441
+ * the ideal point [0,0,0] is returned.
15442
+ *
15443
+ */
15444
+ meetPathPath: function(path1, path2, nr, board) {
15445
+ var S, C, len, intersections;
15446
+
15447
+ S = JXG.Math.Clip._getPath(path1, board);
15448
+ len = S.length;
15449
+ if (len > 0 && this.distance(S[0].coords.usrCoords, S[len - 1].coords.usrCoords, 3) < Mat.eps) {
15450
+ S.pop();
15451
+ }
15452
+
15453
+ C = JXG.Math.Clip._getPath(path2, board);
15454
+ len = C.length;
15455
+ if (len > 0 && this.distance(C[0].coords.usrCoords, C[len - 1].coords.usrCoords, 3) < Mat.eps * Mat.eps) {
15456
+ C.pop();
15457
+ }
15458
+
15459
+ // Handle cases where at least one of the paths is empty
15460
+ if (nr < 0 || JXG.Math.Clip.isEmptyCase(S, C, 'intersection')) {
15461
+ return (new Coords(Const.COORDS_BY_USER, [0, 0, 0], board));
15462
+ }
15463
+
15464
+ JXG.Math.Clip.makeDoublyLinkedList(S);
15465
+ JXG.Math.Clip.makeDoublyLinkedList(C);
15466
+
15467
+ intersections = JXG.Math.Clip.findIntersections(S, C, board)[0];
15468
+ if (nr < intersections.length) {
15469
+ return intersections[nr].coords;
15470
+ }
15471
+ return (new Coords(Const.COORDS_BY_USER, [0, 0, 0], board));
15472
+ },
15473
+
15474
+ /**
15475
+ * Find the n-th intersection point between a polygon and a line.
15476
+ * @param {JXG.Polygon} path
15477
+ * @param {JXG.Line} line
15478
+ * @param {Number} nr
15479
+ * @param {JXG.Board} board
15480
+ * @param {Boolean} alwaysIntersect If false just the segment between the two defining points of the line are tested for intersection.
15481
+ *
15482
+ * @returns {JXG.Coords} Intersection point. In case no intersection point is detected,
15483
+ * the ideal point [0,0,0] is returned.
15484
+ */
15485
+ meetPolygonLine: function(path, line, nr, board, alwaysIntersect) {
15486
+ var i, res, border,
15487
+ crds = [0,0,0],
15488
+ len = path.borders.length,
15489
+ intersections = [];
15490
+
15491
+ for (i = 0; i < len; i++) {
15492
+ border = path.borders[i];
15493
+ res = this.meetSegmentSegment(
15494
+ border.point1.coords.usrCoords,
15495
+ border.point2.coords.usrCoords,
15496
+ line.point1.coords.usrCoords,
15497
+ line.point2.coords.usrCoords);
15498
+
15499
+ if (
15500
+ (!alwaysIntersect || (res[2] >= 0 && res[2] < 1)) &&
15501
+ res[1] >= 0 && res[1] < 1) {
15502
+ intersections.push(res[0]);
15503
+ }
15504
+ }
15505
+
15506
+ if (nr >= 0 && nr < intersections.length) {
15507
+ crds = intersections[nr];
15508
+ }
15509
+ return (new Coords(Const.COORDS_BY_USER, crds, board));
15510
+ },
15511
+
15396
15512
  /****************************************/
15397
15513
  /**** BEZIER CURVE ALGORITHMS ****/
15398
15514
  /****************************************/
@@ -16333,7 +16449,86 @@ define('math/geometry',[
16333
16449
  };
16334
16450
 
16335
16451
  return [makeFct('X', 'cos'), makeFct('Y', 'sin'), 0, pi2];
16336
- }
16452
+ },
16453
+
16454
+
16455
+ meet3Planes: function (n1, d1, n2, d2, n3, d3) {
16456
+ var p = [0, 0, 0],
16457
+ n31, n12, n23, denom,
16458
+ i;
16459
+
16460
+ n31 = Mat.crossProduct(n3, n1);
16461
+ n12 = Mat.crossProduct(n1, n2);
16462
+ n23 = Mat.crossProduct(n2, n3);
16463
+ denom = Mat.innerProduct(n1, n23, 3);
16464
+ for (i = 0; i < 3; i++) {
16465
+ p[i] = (d1 * n23[i] + d2 * n31[i] + d3 * n12[i]) / denom;
16466
+ }
16467
+ return p;
16468
+ },
16469
+
16470
+
16471
+ meetPlanePlane: function (v11, v12, v21, v22) {
16472
+ var i, no1, no2,
16473
+ v = [0, 0, 0],
16474
+ w = [0, 0, 0];
16475
+
16476
+ for (i = 0; i < 3; i++) {
16477
+ v[i] = Type.evaluate(v11[i]);
16478
+ w[i] = Type.evaluate(v12[i]);
16479
+ }
16480
+ no1 = Mat.crossProduct(v, w);
16481
+
16482
+ for (i = 0; i < 3; i++) {
16483
+ v[i] = Type.evaluate(v21[i]);
16484
+ w[i] = Type.evaluate(v22[i]);
16485
+ }
16486
+ no2 = Mat.crossProduct(v, w);
16487
+
16488
+ return Mat.crossProduct(no1, no2);
16489
+ },
16490
+
16491
+ project3DTo3DPlane: function (point, normal, foot) {
16492
+ // TODO: homogeneous 3D coordinates
16493
+ var sol = [0, 0, 0],
16494
+ le, d1, d2, lbda;
16495
+
16496
+ foot = foot || [0, 0, 0];
16497
+
16498
+ le = Mat.norm(normal);
16499
+ d1 = Mat.innerProduct(point, normal, 3);
16500
+ d2 = Mat.innerProduct(foot, normal, 3);
16501
+ // (point - lbda * normal / le) * normal / le == foot * normal / le
16502
+ // => (point * normal - foot * normal) == lbda * le
16503
+ lbda = (d1 - d2) / le;
16504
+ sol = Mat.axpy(-lbda, normal, point);
16505
+
16506
+ return sol;
16507
+ },
16508
+
16509
+ getPlaneBounds: function (v1, v2, q, s, e) {
16510
+ var s1, s2, e1, e2, mat, rhs, sol;
16511
+
16512
+ if (v1[2] + v2[0] !== 0) {
16513
+ mat = [
16514
+ [v1[0], v2[0]],
16515
+ [v1[1], v2[1]]
16516
+ ];
16517
+ rhs = [s - q[0], s - q[1]];
16518
+
16519
+ sol = Numerics.Gauss(mat, rhs);
16520
+ s1 = sol[0];
16521
+ s2 = sol[1];
16522
+
16523
+ rhs = [e - q[0], e - q[1]];
16524
+ sol = Numerics.Gauss(mat, rhs);
16525
+ e1 = sol[0];
16526
+ e2 = sol[1];
16527
+ return [s1, e1, s2, e2];
16528
+ }
16529
+ return null;
16530
+ },
16531
+
16337
16532
  });
16338
16533
 
16339
16534
  return Mat.Geometry;
@@ -23139,7 +23334,6 @@ define('math/clip',[
23139
23334
 
23140
23335
  // Collect all points into clip array C
23141
23336
  C = this._getPath(clip, board);
23142
-
23143
23337
  len = C.length;
23144
23338
  if (len > 0 && Geometry.distance(C[0].coords.usrCoords, C[len - 1].coords.usrCoords, 3) < Mat.eps * Mat.eps) {
23145
23339
  C.pop();
@@ -25020,8 +25214,7 @@ define('utils/color',['jxg', 'utils/type', 'math/math'],
25020
25214
  green: '#009E73', // bluishgreen
25021
25215
  purple: '#CC79A7', // reddishpurple
25022
25216
  white: '#ffffff'
25023
- },
25024
-
25217
+ }
25025
25218
  });
25026
25219
 
25027
25220
  /**
@@ -25837,6 +26030,10 @@ define('options',[
25837
26030
  * visible: false // Initial visibility. Should be set to false always
25838
26031
  * }
25839
26032
  * </pre>
26033
+ * <p>
26034
+ * Board events triggered by selection manipulation:
26035
+ * 'startselecting', 'stopselecting', 'mousestartselecting', 'mousestopselecting',
26036
+ * 'pointerstartselecting', 'pointerstopselecting', 'touchstartselecting', 'touchstopselecting'.
25840
26037
  *
25841
26038
  * @example
25842
26039
  * board.on('stopselecting', function(){
@@ -25850,14 +26047,10 @@ define('options',[
25850
26047
  * });
25851
26048
  *
25852
26049
  * @name JXG.Board#selection
25853
- * @see JXG.Board#startselecting
25854
- * @see JXG.Board#stopselecting
25855
- * @see JXG.Board#mousestartselecting
25856
- * @see JXG.Board#pointerstartselecting
25857
- * @see JXG.Board#touchstartselecting
25858
- * @see JXG.Board#mousestopselecting
25859
- * @see JXG.Board#pointerstopselecting
25860
- * @see JXG.Board#touchstopselecting
26050
+ *
26051
+ * @see JXG.Board#startSelectionMode
26052
+ * @see JXG.Board#stopSelectionMode
26053
+ *
25861
26054
  * @type Object
25862
26055
  * @default
25863
26056
  */
@@ -26542,7 +26735,20 @@ define('options',[
26542
26735
  */
26543
26736
  isLabel: false,
26544
26737
 
26545
-
26738
+ /**
26739
+ * Controls if an element can get the focus with the tab key.
26740
+ * See <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex">descriptiona at MDN</a>.
26741
+ * The additional value null completely disables focus of an element.
26742
+ * The value will be ignored if keyboard control of the board is not enabled or
26743
+ * the element is fixed or not visible.
26744
+ *
26745
+ * @name JXG.GeometryElement#tabindex
26746
+ * @type Number
26747
+ * @default 0
26748
+ * @see JXG.Board#keyboard
26749
+ * @see JXG.GeometryElement#fixed
26750
+ * @see JXG.GeometryElement#visible
26751
+ */
26546
26752
  tabindex: 0
26547
26753
 
26548
26754
  // close the meta tag
@@ -29742,6 +29948,7 @@ define('options',[
29742
29948
  visible: 'inherit',
29743
29949
  fixed: true,
29744
29950
  scalable: false,
29951
+ tabindex: null,
29745
29952
  name: '',
29746
29953
  strokeWidth: 1,
29747
29954
  strokeColor: '#000000',
@@ -29791,6 +29998,7 @@ define('options',[
29791
29998
  strokeWidth: 3,
29792
29999
  visible: 'inherit',
29793
30000
  fixed: true,
30001
+ tabindex: null,
29794
30002
  name: '',
29795
30003
  strokeColor: '#000000',
29796
30004
  highlightStrokeColor: '#888888'
@@ -32720,8 +32928,11 @@ define('renderer/abstract',[
32720
32928
 
32721
32929
  setTabindex: function(element) {
32722
32930
  var val;
32723
- if (Type.exists(element.rendNode)) {
32931
+ if (element.board.attr.keyboard.enabled && Type.exists(element.rendNode)) {
32724
32932
  val = Type.evaluate(element.visProp.tabindex);
32933
+ if (!element.visPropCalc.visible || Type.evaluate(element.visProp.fixed)) {
32934
+ val = null;
32935
+ }
32725
32936
  if (val !== element.visPropOld.tabindex) {
32726
32937
  element.rendNode.setAttribute('tabindex', val);
32727
32938
  element.visPropOld.tabindex = val;
@@ -34253,7 +34464,7 @@ define('base/element',[
34253
34464
 
34254
34465
  /**
34255
34466
  * Inherits contains the subelements, which may have an attribute
34256
- * (in partuclar the attribute "visible") having value 'inherit'.
34467
+ * (in particular the attribute "visible") having value 'inherit'.
34257
34468
  * @type Object
34258
34469
  */
34259
34470
  this.inherits = [];
@@ -35081,26 +35292,35 @@ define('base/element',[
35081
35292
  },
35082
35293
 
35083
35294
  /**
35084
- * Resolves property shortcuts like <tt>color</tt> and expands them, e.g. <tt>strokeColor</tt> and <tt>fillColor</tt>.
35085
- * Writes the expanded properties back to the given <tt>properties</tt>.
35086
- * @param {Object} properties
35087
- * @returns {Object} The given parameter with shortcuts expanded.
35295
+ * Resolves attribute shortcuts like <tt>color</tt> and expands them, e.g. <tt>strokeColor</tt> and <tt>fillColor</tt>.
35296
+ * Writes the expanded attributes back to the given <tt>attributes</tt>.
35297
+ * @param {Object} attributes object
35298
+ * @returns {Object} The given attributes object with shortcuts expanded.
35299
+ * @private
35088
35300
  */
35089
- resolveShortcuts: function (properties) {
35090
- var key, i;
35301
+ resolveShortcuts: function (attributes) {
35302
+ var key, i,
35303
+ j,
35304
+ subattr = ['traceattributes', 'traceAttributes'];
35091
35305
 
35092
35306
  for (key in Options.shortcuts) {
35093
35307
  if (Options.shortcuts.hasOwnProperty(key)) {
35094
- if (Type.exists(properties[key])) {
35095
- for (i = 0; i < Options.shortcuts[key].length; i++) {
35096
- if (!Type.exists(properties[Options.shortcuts[key][i]])) {
35097
- properties[Options.shortcuts[key][i]] = properties[key];
35308
+
35309
+ if (Type.exists(attributes[key])) {
35310
+ for (i = 0; i < Options.shortcuts[key].length; i++) {
35311
+ if (!Type.exists(attributes[Options.shortcuts[key][i]])) {
35312
+ attributes[Options.shortcuts[key][i]] = attributes[key];
35313
+ }
35314
+ }
35315
+ }
35316
+ for (j = 0; j < subattr.length; j++) {
35317
+ if (Type.isObject(attributes[subattr[j]])) {
35318
+ attributes[subattr[j]] = this.resolveShortcuts(attributes[subattr[j]]);
35319
+ }
35098
35320
  }
35099
35321
  }
35100
- }
35101
- }
35102
35322
  }
35103
- return properties;
35323
+ return attributes;
35104
35324
  },
35105
35325
 
35106
35326
  /**
@@ -36528,8 +36748,6 @@ define('base/coordselement',[
36528
36748
  * @private
36529
36749
  */
36530
36750
  updateCoords: function (fromParent) {
36531
- var i;
36532
-
36533
36751
  if (!this.needsUpdate) {
36534
36752
  return this;
36535
36753
  }
@@ -36656,7 +36874,6 @@ define('base/coordselement',[
36656
36874
  doRound = true;
36657
36875
  newPos = 0.0;
36658
36876
  } else {
36659
- //this.coords.setCoordinates(Const.COORDS_BY_USER, Geometry.projectPointToLine(this, slide, this.board).usrCoords, false);
36660
36877
  newCoords = Geometry.projectPointToLine(this, slide, this.board);
36661
36878
  p1c = p1c.usrCoords.slice(0);
36662
36879
  p2c = p2c.usrCoords.slice(0);
@@ -38163,7 +38380,7 @@ define('base/coordselement',[
38163
38380
  if (direction < 0) {
38164
38381
  alpha *= this.intervalCount / stepCount;
38165
38382
  } else {
38166
- alpha *= (stepCount - this.intervalCount);
38383
+ alpha *= (stepCount - this.intervalCount) / stepCount;
38167
38384
  }
38168
38385
  radius = this.slideObject.Radius();
38169
38386
 
@@ -39664,6 +39881,12 @@ define('parser/jessiecode',[
39664
39881
  */
39665
39882
  this.builtIn = this.defineBuiltIn();
39666
39883
 
39884
+ /**
39885
+ * List of all possible operands in JessieCode (except of JSXGraph objects).
39886
+ * @type Object
39887
+ */
39888
+ this.operands = this.getPossibleOperands();
39889
+
39667
39890
  /**
39668
39891
  * The board which currently is used to create and look up elements.
39669
39892
  * @type JXG.Board
@@ -41956,6 +42179,103 @@ define('parser/jessiecode',[
41956
42179
  return builtIn;
41957
42180
  },
41958
42181
 
42182
+ /**
42183
+ * Returns information about the possible functions and constants.
42184
+ * @returns {Object}
42185
+ */
42186
+ getPossibleOperands: function () {
42187
+ var FORBIDDEN = ['E'],
42188
+ jessiecode = this.defineBuiltIn(),
42189
+ math = Math,
42190
+ jc, ma, merge,
42191
+ i, j, p, len, e,
42192
+ funcs, funcsJC, consts, operands,
42193
+ sort, pack;
42194
+
42195
+ sort = function (a, b) {
42196
+ return a.toLowerCase().localeCompare(b.toLowerCase());
42197
+ };
42198
+
42199
+ pack = function (name, origin) {
42200
+ var that = null;
42201
+
42202
+ if (origin === 'jc') that = jessiecode[name];
42203
+ else if (origin === 'Math') that = math[name];
42204
+ else return;
42205
+
42206
+ if (FORBIDDEN.includes(name)) {
42207
+ return;
42208
+ } else if (JXG.isFunction(that)) {
42209
+ return {
42210
+ name: name,
42211
+ type: 'function',
42212
+ numParams: that.length,
42213
+ origin: origin,
42214
+ };
42215
+ } else if (JXG.isNumber(that)) {
42216
+ return {
42217
+ name: name,
42218
+ type: 'constant',
42219
+ value: that,
42220
+ origin: origin,
42221
+ };
42222
+ } else if (that !== undefined) {
42223
+ console.error('undefined type', that);
42224
+ }
42225
+ };
42226
+
42227
+ jc = Object.getOwnPropertyNames(jessiecode).sort(sort);
42228
+ ma = Object.getOwnPropertyNames(math).sort(sort);
42229
+ merge = [];
42230
+ i = 0;
42231
+ j = 0;
42232
+
42233
+ while (i < jc.length || j < ma.length) {
42234
+ if (jc[i] === ma[j]) {
42235
+ p = pack(ma[j], 'Math');
42236
+ if (JXG.exists(p)) merge.push(p);
42237
+ i++;
42238
+ j++;
42239
+ } else if (!JXG.exists(ma[j]) || jc[i].toLowerCase().localeCompare(ma[j].toLowerCase()) < 0) {
42240
+ p = pack(jc[i], 'jc');
42241
+ if (JXG.exists(p)) merge.push(p);
42242
+ i++;
42243
+ } else {
42244
+ p = pack(ma[j], 'Math');
42245
+ if (JXG.exists(p)) merge.push(p);
42246
+ j++;
42247
+ }
42248
+ }
42249
+
42250
+ funcs = [];
42251
+ funcsJC = [];
42252
+ consts = [];
42253
+ operands = {};
42254
+ len = merge.length;
42255
+ for (i = 0; i < len; i++) {
42256
+ e = merge[i];
42257
+ switch (e.type) {
42258
+ case 'function':
42259
+ funcs.push(e.name);
42260
+ if (e.origin === 'jc')
42261
+ funcsJC.push(e.name);
42262
+ break;
42263
+ case 'constant':
42264
+ consts.push(e.name);
42265
+ break;
42266
+ }
42267
+ operands[e.name] = e;
42268
+ }
42269
+
42270
+ return {
42271
+ all: operands,
42272
+ list: merge,
42273
+ functions: funcs,
42274
+ functions_jessiecode: funcsJC,
42275
+ constants: consts,
42276
+ };
42277
+ },
42278
+
41959
42279
  /**
41960
42280
  * Output a debugging message. Uses debug console, if available. Otherwise an HTML element with the
41961
42281
  * id "debug" and an innerHTML property is used.
@@ -44040,8 +44360,12 @@ define('base/board',[
44040
44360
  */
44041
44361
  getCoordsTopLeftCorner: function () {
44042
44362
  var cPos, doc, crect,
44043
- docElement = this.document.documentElement || this.document.body.parentNode,
44044
- docBody = this.document.body,
44363
+ // In ownerDoc we need the "real" document object.
44364
+ // The first version is used in the case of shadowDom,
44365
+ // the second case in the "normal" case.
44366
+ ownerDoc = this.document.ownerDocument || this.document,
44367
+ docElement = ownerDoc.documentElement || this.document.body.parentNode,
44368
+ docBody = ownerDoc.body,
44045
44369
  container = this.containerObj,
44046
44370
  // viewport, content,
44047
44371
  zoom, o;
@@ -44888,7 +45212,7 @@ define('base/board',[
44888
45212
  },
44889
45213
 
44890
45214
  addKeyboardEventHandlers: function() {
44891
- if (!this.hasKeyboardHandlers && Env.isBrowser) {
45215
+ if (this.attr.keyboard.enabled && !this.hasKeyboardHandlers && Env.isBrowser) {
44892
45216
  Env.addEvent(this.containerObj, 'keydown', this.keyDownListener, this);
44893
45217
  Env.addEvent(this.containerObj, 'focusin', this.keyFocusInListener, this);
44894
45218
  Env.addEvent(this.containerObj, 'focusout', this.keyFocusOutListener, this);
@@ -45641,10 +45965,14 @@ define('base/board',[
45641
45965
  }
45642
45966
  }
45643
45967
 
45968
+ this.originMoveEnd();
45969
+ this.update();
45970
+
45644
45971
  // selection
45645
45972
  if (this.selectingMode) {
45646
45973
  this._stopSelecting(evt);
45647
45974
  this.triggerEventHandlers(['touchstopselecting', 'pointerstopselecting', 'stopselecting'], [evt]);
45975
+ this.stopSelectionMode();
45648
45976
  } else {
45649
45977
  for (i = this.downObjects.length - 1; i > -1; i--) {
45650
45978
  found = false;
@@ -45655,32 +45983,30 @@ define('base/board',[
45655
45983
  }
45656
45984
  if (!found) {
45657
45985
  this.downObjects[i].triggerEventHandlers(['touchend', 'up', 'pointerup', 'MSPointerUp'], [evt]);
45658
- this.downObjects[i].snapToGrid();
45659
- this.downObjects[i].snapToPoints();
45986
+ // this.downObjects[i].snapToGrid();
45987
+ // this.downObjects[i].snapToPoints();
45660
45988
  this.downObjects.splice(i, 1);
45661
45989
  }
45662
45990
  }
45663
45991
  }
45664
45992
 
45665
- // this._pointerRemoveTouches(evt);
45666
- // if (this._board_touches.length === 0) {
45667
- if (this.hasPointerUp) {
45668
- if (window.navigator.msPointerEnabled) { // IE10-
45669
- Env.removeEvent(this.document, 'MSPointerUp', this.pointerUpListener, this);
45670
- } else {
45671
- Env.removeEvent(this.document, 'pointerup', this.pointerUpListener, this);
45672
- Env.removeEvent(this.document, 'pointercancel', this.pointerUpListener, this);
45673
- }
45674
- this.hasPointerUp = false;
45993
+ if (this.hasPointerUp) {
45994
+ if (window.navigator.msPointerEnabled) { // IE10-
45995
+ Env.removeEvent(this.document, 'MSPointerUp', this.pointerUpListener, this);
45996
+ } else {
45997
+ Env.removeEvent(this.document, 'pointerup', this.pointerUpListener, this);
45998
+ Env.removeEvent(this.document, 'pointercancel', this.pointerUpListener, this);
45675
45999
  }
46000
+ this.hasPointerUp = false;
46001
+ }
45676
46002
 
45677
- // this.dehighlightAll();
45678
- // this.updateQuality = this.BOARD_QUALITY_HIGH;
45679
- // this.mode = this.BOARD_MODE_NONE;
46003
+ // this.dehighlightAll();
46004
+ // this.updateQuality = this.BOARD_QUALITY_HIGH;
46005
+ // this.mode = this.BOARD_MODE_NONE;
46006
+
46007
+ // this.originMoveEnd();
46008
+ // this.update();
45680
46009
 
45681
- this.originMoveEnd();
45682
- this.update();
45683
- // }
45684
46010
  // After one finger leaves the screen the gesture is stopped.
45685
46011
  this._pointerClearTouches();
45686
46012
  return true;
@@ -45815,7 +46141,7 @@ define('base/board',[
45815
46141
  obj.type === Const.OBJECT_TYPE_TICKS ||
45816
46142
  obj.type === Const.OBJECT_TYPE_IMAGE) {
45817
46143
  // It's a point, so it's single touch, so we just push it to our touches
45818
- targets = [obj];
46144
+ targets = [target];
45819
46145
 
45820
46146
  // For the UNDO/REDO of object moves
45821
46147
  this.saveStartPos(obj, targets[0]);
@@ -46023,6 +46349,7 @@ define('base/board',[
46023
46349
  if (this.selectingMode) {
46024
46350
  this._stopSelecting(evt);
46025
46351
  this.triggerEventHandlers(['touchstopselecting', 'stopselecting'], [evt]);
46352
+ this.stopSelectionMode();
46026
46353
  } else if (evtTouches && evtTouches.length > 0) {
46027
46354
  for (i = 0; i < this.touches.length; i++) {
46028
46355
  tmpTouches[i] = this.touches[i];
@@ -46114,8 +46441,8 @@ define('base/board',[
46114
46441
  }
46115
46442
  if (!found) {
46116
46443
  this.downObjects[i].triggerEventHandlers(['touchup', 'up'], [evt]);
46117
- this.downObjects[i].snapToGrid();
46118
- this.downObjects[i].snapToPoints();
46444
+ // this.downObjects[i].snapToGrid();
46445
+ // this.downObjects[i].snapToPoints();
46119
46446
  this.downObjects.splice(i, 1);
46120
46447
  }
46121
46448
  }
@@ -46278,11 +46605,11 @@ define('base/board',[
46278
46605
  // redraw with high precision
46279
46606
  this.updateQuality = this.BOARD_QUALITY_HIGH;
46280
46607
 
46281
- if (this.mouse && this.mouse.obj) {
46282
- // The parameter is needed for lines with snapToGrid enabled
46283
- this.mouse.obj.snapToGrid(this.mouse.targets[0]);
46284
- this.mouse.obj.snapToPoints();
46285
- }
46608
+ // if (this.mouse && this.mouse.obj) {
46609
+ // // The parameter is needed for lines with snapToGrid enabled
46610
+ // this.mouse.obj.snapToGrid(this.mouse.targets[0]);
46611
+ // this.mouse.obj.snapToPoints();
46612
+ // }
46286
46613
 
46287
46614
  this.originMoveEnd();
46288
46615
  this.dehighlightAll();
@@ -46292,6 +46619,7 @@ define('base/board',[
46292
46619
  if (this.selectingMode) {
46293
46620
  this._stopSelecting(evt);
46294
46621
  this.triggerEventHandlers(['mousestopselecting', 'stopselecting'], [evt]);
46622
+ this.stopSelectionMode();
46295
46623
  } else {
46296
46624
  for (i = 0; i < this.downObjects.length; i++) {
46297
46625
  this.downObjects[i].triggerEventHandlers(['mouseup', 'up'], [evt]);
@@ -46360,6 +46688,7 @@ define('base/board',[
46360
46688
  dx = Type.evaluate(this.attr.keyboard.dx) / this.unitX,
46361
46689
  dy = Type.evaluate(this.attr.keyboard.dy) / this.unitY,
46362
46690
  doZoom = false,
46691
+ done = true,
46363
46692
  dir, actPos;
46364
46693
 
46365
46694
  if (!this.attr.keyboard.enabled || id_node === '') {
@@ -46388,6 +46717,8 @@ define('base/board',[
46388
46717
  this.clickLeftArrow();
46389
46718
  } else if (evt.keyCode === 39) { // right
46390
46719
  this.clickRightArrow();
46720
+ } else {
46721
+ done = false;
46391
46722
  }
46392
46723
  } else {
46393
46724
  // Adapt dx, dy to snapToGrid and attractToGrid
@@ -46440,7 +46771,10 @@ define('base/board',[
46440
46771
  this.zoomOut();
46441
46772
  } else if (doZoom && evt.key === 'o') { // o
46442
46773
  this.zoom100();
46774
+ } else {
46775
+ done = false;
46443
46776
  }
46777
+
46444
46778
  if (dir && el.isDraggable &&
46445
46779
  el.visPropCalc.visible &&
46446
46780
  ((this.geonextCompatibilityMode &&
@@ -46466,6 +46800,9 @@ define('base/board',[
46466
46800
 
46467
46801
  this.update();
46468
46802
 
46803
+ if (done && Type.exists(evt.preventDefault)) {
46804
+ evt.preventDefault();
46805
+ }
46469
46806
  return true;
46470
46807
  },
46471
46808
 
@@ -46551,7 +46888,7 @@ define('base/board',[
46551
46888
  }
46552
46889
 
46553
46890
  // If div is invisible - do nothing
46554
- if (w <= 0 || h <= 0) {
46891
+ if (w <= 0 || h <= 0 || Type.isNaN(w) || Type.isNaN(h)) {
46555
46892
  return;
46556
46893
  }
46557
46894
 
@@ -47957,12 +48294,12 @@ define('base/board',[
47957
48294
  this.inUpdate = true;
47958
48295
 
47959
48296
  if (this.attr.minimizereflow === 'all' && this.containerObj && this.renderer.type !== 'vml') {
47960
- storeActiveEl = document.activeElement; // Store focus element
48297
+ storeActiveEl = this.document.activeElement; // Store focus element
47961
48298
  insert = this.renderer.removeToInsertLater(this.containerObj);
47962
48299
  }
47963
48300
 
47964
48301
  if (this.attr.minimizereflow === 'svg' && this.renderer.type === 'svg') {
47965
- storeActiveEl = document.activeElement;
48302
+ storeActiveEl = this.document.activeElement;
47966
48303
  insert = this.renderer.removeToInsertLater(this.renderer.svgRoot);
47967
48304
  }
47968
48305
 
@@ -48064,6 +48401,7 @@ define('base/board',[
48064
48401
  for (i = 0; i < parents.length; i++) {
48065
48402
  if (Type.isString(parents[i]) &&
48066
48403
  !(elementType === 'text' && i === 2) &&
48404
+ !(elementType === 'solidofrevolution3d' && i === 2) &&
48067
48405
  !((elementType === 'input' || elementType === 'checkbox' || elementType === 'button') &&
48068
48406
  (i === 2 || i === 3)) &&
48069
48407
  !(elementType === 'curve' && i > 0) // Allow curve plots with jessiecode
@@ -48584,7 +48922,7 @@ define('base/board',[
48584
48922
  o2 = o2.parentNode;
48585
48923
  while (o2 !== o) {
48586
48924
  this.cssTransMat = Mat.matMatMult(Env.getCSSTransformMatrix(o), this.cssTransMat);
48587
- o2 = o2.parentNode;
48925
+ o2 = o2.parentNode || o2.host;
48588
48926
  }
48589
48927
 
48590
48928
  o = o.offsetParent;
@@ -49154,7 +49492,7 @@ define('base/board',[
49154
49492
 
49155
49493
  id = id || this.container;
49156
49494
  this._fullscreen_inner_id = id;
49157
- inner_node = document.getElementById(id);
49495
+ inner_node = this.document.getElementById(id);
49158
49496
  wrap_id = 'fullscreenwrap_' + id;
49159
49497
 
49160
49498
  // Wrap a div around the JSXGraph div.
@@ -49200,16 +49538,16 @@ define('base/board',[
49200
49538
  return;
49201
49539
  }
49202
49540
 
49203
- document.fullscreenElement = document.fullscreenElement ||
49204
- document.webkitFullscreenElement ||
49205
- document.mozFullscreenElement ||
49206
- document.msFullscreenElement;
49541
+ this.document.fullscreenElement = this.document.fullscreenElement ||
49542
+ this.document.webkitFullscreenElement ||
49543
+ this.document.mozFullscreenElement ||
49544
+ this.document.msFullscreenElement;
49207
49545
 
49208
- inner_node = document.getElementById(inner_id);
49546
+ inner_node = this.document.getElementById(inner_id);
49209
49547
  // If full screen mode is started we have to remove CSS margin around the JSXGraph div.
49210
49548
  // Otherwise, the positioning of the fullscreen div will be false.
49211
49549
  // When leaving the fullscreen mode, the margin is put back in.
49212
- if (document.fullscreenElement) {
49550
+ if (this.document.fullscreenElement) {
49213
49551
  // Just entered fullscreen mode
49214
49552
 
49215
49553
  // Get the data computed in board.toFullscreen()
@@ -49221,7 +49559,7 @@ define('base/board',[
49221
49559
  // Further, the CSS margin has to be removed when in fullscreen mode,
49222
49560
  // and must be restored later.
49223
49561
  inner_node._cssFullscreenStore = {
49224
- id: document.fullscreenElement.id,
49562
+ id: this.document.fullscreenElement.id,
49225
49563
  isFullscreen: true,
49226
49564
  margin: inner_node.style.margin,
49227
49565
  width: inner_node.style.width,
@@ -49237,16 +49575,16 @@ define('base/board',[
49237
49575
  // of the JSXGraph div.
49238
49576
  Env.scaleJSXGraphDiv(document.fullscreenElement.id, inner_id, res.scale, res.vshift);
49239
49577
 
49240
- // Clear document.fullscreenElement, because Safari doesn't to it and
49578
+ // Clear this.document.fullscreenElement, because Safari doesn't to it and
49241
49579
  // when leaving full screen mode it is still set.
49242
- document.fullscreenElement = null;
49580
+ this.document.fullscreenElement = null;
49243
49581
 
49244
49582
  } else if (Type.exists(inner_node._cssFullscreenStore)) {
49245
49583
  // Just left the fullscreen mode
49246
49584
 
49247
49585
  // Remove the CSS rules added in Env.scaleJSXGraphDiv
49248
49586
  try {
49249
- document.styleSheets[document.styleSheets.length - 1].deleteRule(0);
49587
+ this.document.styleSheets[this.document.styleSheets.length - 1].deleteRule(0);
49250
49588
  } catch (err) {
49251
49589
  console.log('JSXGraph: Could not remove CSS rules for full screen mode');
49252
49590
  }
@@ -49254,7 +49592,6 @@ define('base/board',[
49254
49592
  inner_node._cssFullscreenStore.isFullscreen = false;
49255
49593
  inner_node.style.margin = inner_node._cssFullscreenStore.margin;
49256
49594
  inner_node.style.width = inner_node._cssFullscreenStore.width;
49257
-
49258
49595
  }
49259
49596
 
49260
49597
  this.updateCSSTransforms();
@@ -51164,10 +51501,11 @@ define('renderer/svg',[
51164
51501
  * setTimeout(function() { console.log('done'); }, 400);
51165
51502
  */
51166
51503
  dumpToCanvas: function (canvasId, w, h, ignoreTexts) {
51167
- var svg, tmpImg, cv, ctx;
51504
+ var svg, tmpImg, cv, ctx,
51505
+ doc = this.container.ownerDocument;
51168
51506
 
51169
51507
  // Prepare the canvas element
51170
- cv = document.getElementById(canvasId);
51508
+ cv = doc.getElementById(canvasId);
51171
51509
 
51172
51510
  // Clear the canvas
51173
51511
  /* eslint-disable no-self-assign */
@@ -51303,7 +51641,8 @@ define('renderer/svg',[
51303
51641
  } else {
51304
51642
  // Debug: use canvas element 'jxgbox_canvas' from jsxdev/dump.html
51305
51643
  id = 'jxgbox_canvas';
51306
- canvas = document.getElementById(id);
51644
+ // canvas = document.getElementById(id);
51645
+ canvas = doc.getElementById(id);
51307
51646
  }
51308
51647
 
51309
51648
  if (newImg) {
@@ -51323,7 +51662,8 @@ define('renderer/svg',[
51323
51662
  }
51324
51663
 
51325
51664
  // Hide navigation bar in board
51326
- zbar = document.getElementById(this.container.id + '_navigationbar');
51665
+ // zbar = document.getElementById(this.container.id + '_navigationbar');
51666
+ zbar = doc.getElementById(this.container.id + '_navigationbar');
51327
51667
  if (Type.exists(zbar)) {
51328
51668
  zbarDisplay = zbar.style.display;
51329
51669
  zbar.style.display = 'none';
@@ -54859,6 +55199,7 @@ define('jsxgraph',[
54859
55199
  */
54860
55200
  _setARIA: function(container, attr) {
54861
55201
  var doc = attr.document || document,
55202
+ doc_glob,
54862
55203
  node_jsx, newNode, parent,
54863
55204
  id_label, id_description;
54864
55205
 
@@ -54867,18 +55208,19 @@ define('jsxgraph',[
54867
55208
  }
54868
55209
 
54869
55210
  node_jsx = doc.getElementById(container);
55211
+ doc_glob = node_jsx.ownerDocument; // This is the window.document element, needed below.
54870
55212
  parent = node_jsx.parentNode;
54871
55213
 
54872
55214
  id_label = container + '_ARIAlabel';
54873
55215
  id_description = container + '_ARIAdescription';
54874
55216
 
54875
- newNode = doc.createElement('div');
55217
+ newNode = doc_glob.createElement('div');
54876
55218
  newNode.innerHTML = attr.title;
54877
55219
  newNode.setAttribute('id', id_label);
54878
55220
  newNode.style.display = 'none';
54879
55221
  parent.insertBefore(newNode, node_jsx);
54880
55222
 
54881
- newNode = doc.createElement('div');
55223
+ newNode = doc_glob.createElement('div');
54882
55224
  newNode.innerHTML = attr.description;
54883
55225
  newNode.setAttribute('id', id_description);
54884
55226
  newNode.style.display = 'none';
@@ -54904,12 +55246,12 @@ define('jsxgraph',[
54904
55246
  }
54905
55247
 
54906
55248
  id = board.containerObj.getAttribute('aria-labelledby');
54907
- node = document.getElementById(id);
55249
+ node = doc.getElementById(id);
54908
55250
  if (node && node.parentNode) {
54909
55251
  node.parentNode.removeChild(node);
54910
55252
  }
54911
55253
  id = board.containerObj.getAttribute('aria-describedby');
54912
- node = document.getElementById(id);
55254
+ node = doc.getElementById(id);
54913
55255
  if (node && node.parentNode) {
54914
55256
  node.parentNode.removeChild(node);
54915
55257
  }
@@ -55395,6 +55737,7 @@ define('base/point',[
55395
55737
  this.board.renderer.drawPoint(this);
55396
55738
  this.board.finalizeAdding(this);
55397
55739
 
55740
+ this.createGradient();
55398
55741
  this.createLabel();
55399
55742
 
55400
55743
  };
@@ -56886,7 +57229,7 @@ define('base/line',[
56886
57229
  if (this.parents.length < 3) { // Line through two points
56887
57230
  this.point1.handleSnapToGrid(true, true);
56888
57231
  this.point2.handleSnapToGrid(true, true);
56889
- } else if (Type.exists(pos)) { // Free line
57232
+ } else if (Type.exists(pos)) { // Free line
56890
57233
  sX = Type.evaluate(this.visProp.snapsizex);
56891
57234
  sY = Type.evaluate(this.visProp.snapsizey);
56892
57235
 
@@ -61565,8 +61908,35 @@ define('base/polygon',[
61565
61908
 
61566
61909
  /**
61567
61910
  * Add more points to the polygon. The new points will be inserted at the end.
61568
- * @param {JXG.Point} p Arbitrary number of points
61911
+ * The attributes of new border segments are set to the same values
61912
+ * as those used when the polygon was created.
61913
+ * If new vertices are supplied by coordinates, the default attributes of polygon
61914
+ * vertices are taken as their attributes. Therefore, the visual attributes of
61915
+ * new vertices and borders may have to be adapted afterwards.
61916
+ * @param {JXG.Point} p Arbitrary number of points or coordinate arrays
61569
61917
  * @returns {JXG.Polygon} Reference to the polygon
61918
+ * @example
61919
+ * const board = JXG.JSXGraph.initBoard('jxgbox', {axis:true});
61920
+ * var pg = board.create('polygon', [[1,2], [3,4], [-3,1]], {hasInnerPoints: true});
61921
+ * var newPoint = board.create('point', [-1, -1]);
61922
+ * var newPoint2 = board.create('point', [-1, -2]);
61923
+ * pg.addPoints(newPoint, newPoint2, [1, -2]);
61924
+ *
61925
+ * </pre><div id="JXG70eb0fd2-d20f-4ba9-9ab6-0eac92aabfa5" class="jxgbox" style="width: 300px; height: 300px;"></div>
61926
+ * <script type="text/javascript">
61927
+ * (function() {
61928
+ * var board = JXG.JSXGraph.initBoard('JXG70eb0fd2-d20f-4ba9-9ab6-0eac92aabfa5',
61929
+ * {boundingbox: [-8, 8, 8,-8], axis: true, showcopyright: false, shownavigation: false});
61930
+ * const board = JXG.JSXGraph.initBoard('jxgbox', {axis:true});
61931
+ * var pg = board.create('polygon', [[1,2], [3,4], [-3,1]], {hasInnerPoints: true});
61932
+ * var newPoint = board.create('point', [-1, -1]);
61933
+ * var newPoint2 = board.create('point', [-1, -2]);
61934
+ * pg.addPoints(newPoint, newPoint2, [1, -2]);
61935
+ *
61936
+ * })();
61937
+ *
61938
+ * </script><pre>
61939
+ *
61570
61940
  */
61571
61941
  addPoints: function (p) {
61572
61942
  var args = Array.prototype.slice.call(arguments);
@@ -61575,44 +61945,72 @@ define('base/polygon',[
61575
61945
  },
61576
61946
 
61577
61947
  /**
61578
- * Adds more points to the vertex list of the polygon, starting with index <tt><i</tt>
61579
- * @param {Number} idx The position where the new vertices are inserted, starting with 0.
61580
- * @param {JXG.Point} p Arbitrary number of points to insert.
61948
+ * Insert points to the vertex list of the polygon after index <tt><idx</tt>.
61949
+ * The attributes of new border segments are set to the same values
61950
+ * as those used when the polygon was created.
61951
+ * If new vertices are supplied by coordinates, the default attributes of polygon
61952
+ * vertices are taken as their attributes. Therefore, the visual attributes of
61953
+ * new vertices and borders may have to be adapted afterwards.
61954
+ *
61955
+ * @param {Number} idx The position after which the new vertices are inserted.
61956
+ * Setting idx to -1 inserts the new points at the front, i.e. at position 0.
61957
+ * @param {JXG.Point} p Arbitrary number of points or coordinate arrays to insert.
61581
61958
  * @returns {JXG.Polygon} Reference to the polygon object
61959
+ *
61960
+ * @example
61961
+ * const board = JXG.JSXGraph.initBoard('jxgbox', {axis:true});
61962
+ * var pg = board.create('polygon', [[1,2], [3,4], [-3,1]], {hasInnerPoints: true});
61963
+ * var newPoint = board.create('point', [-1, -1]);
61964
+ * pg.insertPoints(0, newPoint, newPoint, [1, -2]);
61965
+ *
61966
+ * </pre><div id="JXG17b84b2a-a851-4e3f-824f-7f6a60f166ca" class="jxgbox" style="width: 300px; height: 300px;"></div>
61967
+ * <script type="text/javascript">
61968
+ * (function() {
61969
+ * var board = JXG.JSXGraph.initBoard('JXG17b84b2a-a851-4e3f-824f-7f6a60f166ca',
61970
+ * {boundingbox: [-8, 8, 8,-8], axis: true, showcopyright: false, shownavigation: false});
61971
+ * const board = JXG.JSXGraph.initBoard('jxgbox', {axis:true});
61972
+ * var pg = board.create('polygon', [[1,2], [3,4], [-3,1]], {hasInnerPoints: true});
61973
+ * var newPoint = board.create('point', [-1, -1]);
61974
+ * pg.insertPoints(0, newPoint, newPoint, [1, -2]);
61975
+ *
61976
+ * })();
61977
+ *
61978
+ * </script><pre>
61979
+ *
61582
61980
  */
61583
61981
  insertPoints: function (idx, p) {
61584
- var i, npoints = [], tmp;
61982
+ var i, le;
61585
61983
 
61586
61984
  if (arguments.length === 0) {
61587
61985
  return this;
61588
61986
  }
61589
61987
 
61590
61988
 
61591
- if (idx < 0 || idx > this.vertices.length - 2) {
61989
+ if (idx < -1 || idx > this.vertices.length - 2) {
61592
61990
  return this;
61593
61991
  }
61594
61992
 
61595
- for (i = 1; i < arguments.length; i++) {
61596
- if (Type.isPoint(arguments[i])) {
61597
- npoints.push(arguments[i]);
61598
- }
61993
+ le = arguments.length - 1;
61994
+ for (i = 1; i < le + 1; i++) {
61995
+ this.vertices.splice(idx + i, 0,
61996
+ Type.providePoints(this.board, [arguments[i]], {}, 'polygon', ['vertices'])[0]
61997
+ );
61998
+ }
61999
+ if (idx === -1) {
62000
+ this.vertices[this.vertices.length - 1] = this.vertices[0];
61599
62001
  }
61600
-
61601
- tmp = this.vertices.slice(0, idx + 1).concat(npoints);
61602
- this.vertices = tmp.concat(this.vertices.slice(idx + 1));
61603
-
61604
62002
  if (this.withLines) {
61605
- tmp = this.borders.slice(0, idx);
61606
- this.board.removeObject(this.borders[idx]);
61607
-
61608
- for (i = 0; i < npoints.length; i++) {
61609
- tmp.push(this.board.create('segment', [this.vertices[idx + i], this.vertices[idx + i + 1]], this.attr_line));
62003
+ if (idx < 0) {
62004
+ this.borders[this.borders.length - 1].point2 = this.vertices[this.vertices.length - 1];
62005
+ } else {
62006
+ this.borders[idx].point2 = this.vertices[idx + 1];
62007
+ }
62008
+ for (i = idx + 1; i < idx + 1 + le; i++) {
62009
+ this.borders.splice(i, 0,
62010
+ this.board.create('segment', [this.vertices[i], this.vertices[i + 1]], this.attr_line)
62011
+ );
61610
62012
  }
61611
-
61612
- tmp.push(this.board.create('segment', [this.vertices[idx + npoints.length], this.vertices[idx + npoints.length + 1]], this.attr_line));
61613
- this.borders = tmp.concat(this.borders.slice(idx + 1));
61614
62013
  }
61615
-
61616
62014
  this.board.update();
61617
62015
 
61618
62016
  return this;
@@ -61627,7 +62025,7 @@ define('base/polygon',[
61627
62025
  var i, j, idx, nvertices = [], nborders = [],
61628
62026
  nidx = [], partition = [];
61629
62027
 
61630
- // partition:
62028
+ // Partition:
61631
62029
  // in order to keep the borders which could be recycled, we have to partition
61632
62030
  // the set of removed points. I.e. if the points 1, 2, 5, 6, 7, 10 are removed,
61633
62031
  // the partitions are
@@ -61635,10 +62033,10 @@ define('base/polygon',[
61635
62033
  // this gives us the borders, that can be removed and the borders we have to create.
61636
62034
 
61637
62035
 
61638
- // remove the last vertex which is identical to the first
62036
+ // Remove the last vertex which is identical to the first
61639
62037
  this.vertices = this.vertices.slice(0, this.vertices.length - 1);
61640
62038
 
61641
- // collect all valid parameters as indices in nidx
62039
+ // Collect all valid parameters as indices in nidx
61642
62040
  for (i = 0; i < arguments.length; i++) {
61643
62041
  idx = arguments[i];
61644
62042
  if (Type.isPoint(idx)) {
@@ -61650,22 +62048,22 @@ define('base/polygon',[
61650
62048
  }
61651
62049
  }
61652
62050
 
61653
- // remove the polygon from each removed point's children
62051
+ // Remove the polygon from each removed point's children
61654
62052
  for (i = 0; i < nidx.length; i++) {
61655
62053
  this.vertices[nidx[i]].removeChild(this);
61656
62054
  }
61657
62055
 
61658
- // sort the elements to be eliminated
62056
+ // Sort the elements to be eliminated
61659
62057
  nidx = nidx.sort();
61660
62058
  nvertices = this.vertices.slice();
61661
62059
  nborders = this.borders.slice();
61662
62060
 
61663
- // initialize the partition
62061
+ // Initialize the partition
61664
62062
  if (this.withLines) {
61665
62063
  partition.push([nidx[nidx.length - 1]]);
61666
62064
  }
61667
62065
 
61668
- // run through all existing vertices and copy all remaining ones to nvertices
62066
+ // Run through all existing vertices and copy all remaining ones to nvertices,
61669
62067
  // compute the partition
61670
62068
  for (i = nidx.length - 1; i > -1; i--) {
61671
62069
  nvertices[nidx[i]] = -1;
@@ -61676,12 +62074,12 @@ define('base/polygon',[
61676
62074
  }
61677
62075
  }
61678
62076
 
61679
- // finalize the partition computation
62077
+ // Finalize the partition computation
61680
62078
  if (this.withLines) {
61681
62079
  partition[partition.length - 1][1] = nidx[0];
61682
62080
  }
61683
62081
 
61684
- // update vertices
62082
+ // Update vertices
61685
62083
  this.vertices = [];
61686
62084
  for (i = 0; i < nvertices.length; i++) {
61687
62085
  if (Type.isPoint(nvertices[i])) {
@@ -61692,7 +62090,7 @@ define('base/polygon',[
61692
62090
  this.vertices.push(this.vertices[0]);
61693
62091
  }
61694
62092
 
61695
- // delete obsolete and create missing borders
62093
+ // Delete obsolete and create missing borders
61696
62094
  if (this.withLines) {
61697
62095
  for (i = 0; i < partition.length; i++) {
61698
62096
  for (j = partition[i][1] - 1; j < partition[i][0] + 1; j++) {
@@ -68552,9 +68950,6 @@ define('element/composition',[
68552
68950
  b.addChild(t);
68553
68951
  }
68554
68952
 
68555
-
68556
-
68557
-
68558
68953
  t.elType = 'midpoint';
68559
68954
  t.setParents([a.id, b.id]);
68560
68955
 
@@ -68764,14 +69159,21 @@ define('element/composition',[
68764
69159
  };
68765
69160
 
68766
69161
  /**
68767
- * @class A parallel is a line through a given point with the same slope as a given line.
69162
+ * @class A parallel is a line through a given point with the same slope as a given line or
69163
+ * the line through two given point.
69164
+ * <p>
69165
+ * If original line is given as a JSXGraph line object, the resulting parallel line will be defined by the given point and an
69166
+ * infinitely far away point (an ideal point). That means, the line can not be shortened to a segment.
69167
+ * <p>
69168
+ * If the original line is given as two points, the resulting parallel line can be shortened to a a segment.
68768
69169
  * @pseudo
68769
69170
  * @name Parallel
68770
69171
  * @augments Line
68771
69172
  * @constructor
68772
69173
  * @type JXG.Line
68773
69174
  * @throws {Error} If the element cannot be constructed with the given parent objects an exception is thrown.
68774
- * @param {JXG.Line_JXG.Point} l,p The constructed line contains p and has the same slope as l.
69175
+ * @param {JXG.Line_JXG.Point} l,p The constructed line contains p and has the same slope as l. Alternative parameters are p1, p2, p: The
69176
+ * constructed line contains p and has the same slope as the line through p1 and p2.
68775
69177
  * @example
68776
69178
  * // Create a parallel
68777
69179
  * var p1 = board.create('point', [0.0, 2.0]);
@@ -68789,22 +69191,47 @@ define('element/composition',[
68789
69191
  * var plex1_p3 = plex1_board.create('point', [3.0, 3.0]);
68790
69192
  * var plex1_pl1 = plex1_board.create('parallel', [plex1_l1, plex1_p3]);
68791
69193
  * </script><pre>
69194
+ * @example
69195
+ * var p1, p2, p3, l1, pl1;
69196
+ *
69197
+ * p1 = board.create('point', [0.0, 2.0]);
69198
+ * p2 = board.create('point', [2.0, 1.0]);
69199
+ * l1 = board.create('line', [p1, p2]);
69200
+ *
69201
+ * p3 = board.create('point', [1.0, 3.0]);
69202
+ * pl1 = board.create('parallel', [p1, p2, p3], {straightFirst: false, straightLast: false});
69203
+ *
69204
+ * </pre><div id="JXGd643305d-20c3-4a88-91f9-8d0c4448594f" class="jxgbox" style="width: 300px; height: 300px;"></div>
69205
+ * <script type="text/javascript">
69206
+ * (function() {
69207
+ * var board = JXG.JSXGraph.initBoard('JXGd643305d-20c3-4a88-91f9-8d0c4448594f',
69208
+ * {boundingbox: [-8, 8, 8,-8], axis: true, showcopyright: false, shownavigation: false});
69209
+ * var p1, p2, p3, l1, pl1;
69210
+ *
69211
+ * p1 = board.create('point', [0.0, 2.0]);
69212
+ * p2 = board.create('point', [2.0, 1.0]);
69213
+ * l1 = board.create('line', [p1, p2]);
69214
+ *
69215
+ * p3 = board.create('point', [1.0, 3.0]);
69216
+ * pl1 = board.create('parallel', [p1, p2, p3], {straightFirst: false, straightLast: false});
69217
+ *
69218
+ * })();
69219
+ *
69220
+ * </script><pre>
69221
+ *
68792
69222
  */
68793
69223
  JXG.createParallel = function (board, parents, attributes) {
68794
- var p, pp, pl, li, i, attr;
69224
+ var p, pp, pl, li, i, attr, ty = 1;
68795
69225
 
68796
69226
  for (i = 0; i < parents.length; ++i) {
68797
69227
  parents[i] = board.select(parents[i]);
68798
69228
  }
68799
69229
  p = null;
68800
69230
  if (parents.length === 3) {
69231
+ // Line / segment through point parents[2] which is parallel to line through parents[0] and parents[1]
68801
69232
  parents = Type.providePoints(board, parents, attributes, 'point');
68802
- // line through point parents[2] which is parallel to line through parents[0] and parents[1]
68803
69233
  p = parents[2];
68804
- /** @ignore */
68805
- li = function () {
68806
- return Mat.crossProduct(parents[0].coords.usrCoords, parents[1].coords.usrCoords);
68807
- };
69234
+ ty = 0;
68808
69235
  } else if (Type.isPointType(board, parents[0])) {
68809
69236
  // Parallel to line parents[1] through point parents[0]
68810
69237
  p = Type.providePoints(board, [parents[0]], attributes, 'point')[0];
@@ -68826,11 +69253,19 @@ define('element/composition',[
68826
69253
  }
68827
69254
 
68828
69255
  attr = Type.copyAttributes(attributes, board.options, 'parallel', 'point');
68829
- pp = board.create('point', [
68830
- function () {
68831
- return Mat.crossProduct([1, 0, 0], li());
68832
- }
68833
- ], attr);
69256
+ if (ty === 1) {
69257
+ // Line is given by line element. The parallel line is
69258
+ // constructed as line through an ideal point.
69259
+ pp = board.create('point', [
69260
+ function () {
69261
+ return Mat.crossProduct([1, 0, 0], li());
69262
+ }
69263
+ ], attr);
69264
+ } else {
69265
+ // Line is given by two points. The parallel line is
69266
+ // constructed as line through two finite point.
69267
+ pp = board.create('parallelpoint', parents, attr);
69268
+ }
68834
69269
  pp.isDraggable = true;
68835
69270
 
68836
69271
  attr = Type.copyAttributes(attributes, board.options, 'parallel');
@@ -68864,31 +69299,33 @@ define('element/composition',[
68864
69299
  };
68865
69300
 
68866
69301
  /**
68867
- * @class An arrow parallel is a parallel segment with an arrow attached.
69302
+ * @class An arrow parallel is a segment with an arrow attached which is parallel through a given segment, given by its defining two points,
69303
+ * through a given point.
69304
+ * <p>
68868
69305
  * @pseudo
68869
69306
  * @constructor
68870
69307
  * @name Arrowparallel
68871
69308
  * @type Parallel
68872
69309
  * @augments Parallel
68873
69310
  * @throws {Error} If the element cannot be constructed with the given parent objects an exception is thrown.
68874
- * @param {JXG.Line_JXG.Point} l,p The constructed arrow contains p and has the same slope as l.
69311
+ * @param JXG.Point_JXG.Point_JXG.Point} p1, p2,p3 The constructed arrow contains p3 and has the same slope as the line through p1 and p2.
68875
69312
  * @example
68876
69313
  * // Create a parallel
68877
69314
  * var p1 = board.create('point', [0.0, 2.0]);
68878
69315
  * var p2 = board.create('point', [2.0, 1.0]);
68879
- * var l1 = board.create('line', [p1, p2]);
69316
+ * var l1 = board.create('segment', [p1, p2]);
68880
69317
  *
68881
69318
  * var p3 = board.create('point', [3.0, 3.0]);
68882
- * var pl1 = board.create('arrowparallel', [l1, p3]);
69319
+ * var pl1 = board.create('arrowparallel', [p1, p2, p3]);
68883
69320
  * </pre><div class="jxgbox" id="JXGeeacdf99-036f-4e83-aeb6-f7388423e369" style="width: 400px; height: 400px;"></div>
68884
69321
  * <script type="text/javascript">
68885
69322
  * (function () {
68886
69323
  * var plex1_board = JXG.JSXGraph.initBoard('JXGeeacdf99-036f-4e83-aeb6-f7388423e369', {boundingbox: [-1, 9, 9, -1], axis: true, showcopyright: false, shownavigation: false});
68887
69324
  * var plex1_p1 = plex1_board.create('point', [0.0, 2.0]);
68888
69325
  * var plex1_p2 = plex1_board.create('point', [2.0, 1.0]);
68889
- * var plex1_l1 = plex1_board.create('line', [plex1_p1, plex1_p2]);
69326
+ * var plex1_l1 = plex1_board.create('segment', [plex1_p1, plex1_p2]);
68890
69327
  * var plex1_p3 = plex1_board.create('point', [3.0, 3.0]);
68891
- * var plex1_pl1 = plex1_board.create('arrowparallel', [plex1_l1, plex1_p3]);
69328
+ * var plex1_pl1 = plex1_board.create('arrowparallel', [plex1_p1, plex1_p2, plex1_p3]);
68892
69329
  * })();
68893
69330
  * </script><pre>
68894
69331
  */
@@ -69335,7 +69772,7 @@ define('element/composition',[
69335
69772
  };
69336
69773
 
69337
69774
  /**
69338
- * @class Bisector lines are similar to {@link Bisector} but takes two lines as parent elements. The resulting element is
69775
+ * @class Bisector lines are similar to {@link Bisector} but take two lines as parent elements. The resulting element is
69339
69776
  * a composition of two lines.
69340
69777
  * @pseudo
69341
69778
  * @constructor
@@ -72092,6 +72529,10 @@ define('element/slider',[
72092
72529
  p2.dump = false;
72093
72530
  l1.dump = false;
72094
72531
  l2.dump = false;
72532
+ if (withText) {
72533
+ t.dump = false;
72534
+ }
72535
+
72095
72536
 
72096
72537
  p3.elType = 'slider';
72097
72538
  p3.parents = parents;
@@ -72109,6 +72550,14 @@ define('element/slider',[
72109
72550
  p3.inherits.push(ti);
72110
72551
  }
72111
72552
 
72553
+ p3.getParents = function() {
72554
+ return [
72555
+ this.point1.coords.usrCoords.slice(1),
72556
+ this.point2.coords.usrCoords.slice(1),
72557
+ [this._smin, this.position * (this._smax - this._smin) + this._smin, this._smax]
72558
+ ];
72559
+ };
72560
+
72112
72561
  p3.baseline.on('up', function(evt) {
72113
72562
  var pos, c;
72114
72563
 
@@ -75831,12 +76280,13 @@ define('base/ticks',[
75831
76280
  * @private
75832
76281
  */
75833
76282
  formatLabelText: function(value) {
75834
- var labelText = value.toString(),
76283
+ var labelText,
75835
76284
  digits,
75836
76285
  ev_s = Type.evaluate(this.visProp.scalesymbol);
75837
76286
 
75838
76287
  // if value is Number
75839
76288
  if (Type.isNumber(value)) {
76289
+ labelText = (Math.round(value * 1.e13) / 1.e13).toString();
75840
76290
  if (labelText.length > Type.evaluate(this.visProp.maxlabellength) ||
75841
76291
  labelText.indexOf('e') !== -1) {
75842
76292
 
@@ -75845,7 +76295,9 @@ define('base/ticks',[
75845
76295
  // Use the deprecated attribute "precision"
75846
76296
  digits = Type.evaluate(this.visProp.precision);
75847
76297
  }
75848
- labelText = value.toPrecision(digits).toString();
76298
+
76299
+ //labelText = value.toPrecision(digits).toString();
76300
+ labelText = value.toExponential(digits).toString();
75849
76301
  }
75850
76302
 
75851
76303
  if (Type.evaluate(this.visProp.beautifulscientificticklabels)) {
@@ -75858,6 +76310,8 @@ define('base/ticks',[
75858
76310
  // trim trailing .
75859
76311
  labelText = labelText.replace(/\.$/, '');
75860
76312
  }
76313
+ } else {
76314
+ labelText = value.toString();
75861
76315
  }
75862
76316
 
75863
76317
  if (ev_s.length > 0) {
@@ -76077,6 +76531,8 @@ define('base/ticks',[
76077
76531
  attr.id = this.id + ld.i + 'Label' + this.labelCounter;
76078
76532
 
76079
76533
  label = Text.createText(this.board, [ld.x, ld.y, ld.t], attr);
76534
+ this.addChild(label);
76535
+ label.setParents(this);
76080
76536
  label.isDraggable = false;
76081
76537
  label.dump = false;
76082
76538
  this.labels.push(label);
@@ -79618,7 +80074,13 @@ define('element/button',[
79618
80074
  * an SVG foreignObject container.
79619
80075
  * <p>
79620
80076
  * Instead of board.create('foreignobject') the shortcut board.create('fo') may be used.
79621
- *
80077
+ *
80078
+ * <p style="background-color:#dddddd; padding:10px"><b>NOTE:</b> In Safari up to version 15, a foreignObject does not obey the layer structure
80079
+ * if it contains &lt;video&gt; or &lt;iframe&gt; tags, as well as elements which are
80080
+ * positioned with <tt>position:absolute|relative|fixed</tt>. In this case, the foreignobject will be
80081
+ * "above" the JSXGraph construction.
80082
+ * </p>
80083
+ *
79622
80084
  * @pseudo
79623
80085
  * @description
79624
80086
  * @name ForeignObject
@@ -79756,6 +80218,2002 @@ define('element/button',[
79756
80218
  };
79757
80219
  });
79758
80220
 
80221
+ /*global JXG:true, define: true*/
80222
+
80223
+ define('options3d',[
80224
+ 'jxg', 'options'
80225
+ ], function (JXG, Options) {
80226
+
80227
+ "use strict";
80228
+
80229
+ JXG.extend(Options, {
80230
+
80231
+ infobox: {
80232
+ strokeColor: 'black'
80233
+ },
80234
+
80235
+ axes3d: {
80236
+ /**#@+
80237
+ * @visprop
80238
+ */
80239
+
80240
+ /**
80241
+ * Position of the main axes in a View3D element. Possible values are
80242
+ * 'center' and 'border'.
80243
+ *
80244
+ * @type String
80245
+ * @name View3D#axesPosition
80246
+ * @default 'center'
80247
+ */
80248
+ axesPosition: 'center', // Possible values: 'center', otherwise: border
80249
+
80250
+ // Main axes
80251
+
80252
+ /**
80253
+ * Attributes of the 3D x-axis.
80254
+ *
80255
+ * @type Line3D
80256
+ * @name View3D#xAxis
80257
+ */
80258
+ xAxis: { visible: true, point2: {name: 'x'}},
80259
+
80260
+ /**
80261
+ * Attributes of the 3D y-axis.
80262
+ *
80263
+ * @type Line3D
80264
+ * @name View3D#yAxis
80265
+ */
80266
+ yAxis: { visible: true, point2: {name: 'y'}},
80267
+
80268
+ /**
80269
+ * Attributes of the 3D z-axis.
80270
+ *
80271
+ * @type Line3D
80272
+ * @name View3D#zAxis
80273
+ */
80274
+ zAxis: { visible: true, point2: {name: 'z'}},
80275
+
80276
+ // Planes
80277
+ /**
80278
+ * Attributes of the 3D plane orthogonal to the x-axis at the "rear" of the cube.
80279
+ * @type Plane3D
80280
+ * @name View3D#xPlaneRear
80281
+ */
80282
+ xPlaneRear: { visible: true, layer: 0, mesh3d: { layer: 1 } },
80283
+ /**
80284
+ * Attributes of the 3D plane orthogonal to the y-axis at the "rear" of the cube.
80285
+ * @type Plane3D
80286
+ * @name View3D#yPlaneRear
80287
+ */
80288
+ yPlaneRear: { visible: true, layer: 0, mesh3d: { layer: 1 } },
80289
+ /**
80290
+ * Attributes of the 3D plane orthogonal to the z-axis at the "rear" of the cube.
80291
+ * @type Plane3D
80292
+ * @name View3D#zPlaneRear
80293
+ */
80294
+ zPlaneRear: { visible: true, layer: 0, mesh3d: { layer: 1 } },
80295
+
80296
+ /**
80297
+ * Attributes of the 3D plane orthogonal to the x-axis at the "front" of the cube.
80298
+ * @type Plane3D
80299
+ * @name View3D#xPlaneFront
80300
+ */
80301
+ xPlaneFront: { visible: false, layer: 0, mesh3d: { layer: 1 } },
80302
+ /**
80303
+ * Attributes of the 3D plane orthogonal to the y-axis at the "front" of the cube.
80304
+ * @type Plane3D
80305
+ * @name View3D#yPlaneFront
80306
+ */
80307
+ yPlaneFront: { visible: false, layer: 0, mesh3d: { layer: 1 } },
80308
+ /**
80309
+ * Attributes of the 3D plane orthogonal to the z-axis at the "front" of the cube.
80310
+ * @type Plane3D
80311
+ * @name View3D#zPlaneFront
80312
+ */
80313
+ zPlaneFront: { visible: false, layer: 0, mesh3d: { layer: 1 } },
80314
+
80315
+ // Axes on the planes
80316
+ /**
80317
+ * Attributes of the 3D y-axis on the 3D plane orthogonal to the x-axis at the "rear" of the cube.
80318
+ * @type Plane3D
80319
+ * @name View3D#xPlaneRearYAxis
80320
+ */
80321
+ xPlaneRearYAxis: {visible: 'inherit', strokeColor: '#888888', strokeWidth: 1},
80322
+ /**
80323
+ * Attributes of the 3D z-axis on the 3D plane orthogonal to the x-axis at the "rear" of the cube.
80324
+ * @type Plane3D
80325
+ * @name View3D#xPlaneRearZAxis
80326
+ */
80327
+ xPlaneRearZAxis: {visible: 'inherit', strokeColor: '#888888', strokeWidth: 1},
80328
+ /**
80329
+ * Attributes of the 3D y-axis on the 3D plane orthogonal to the x-axis at the "front" of the cube.
80330
+ * @type Plane3D
80331
+ * @name View3D#xPlaneFrontYAxis
80332
+ */
80333
+ xPlaneFrontYAxis: {visible: 'inherit', strokeColor: '#888888', strokeWidth: 1},
80334
+ /**
80335
+ * Attributes of the 3D z-axis on the 3D plane orthogonal to the x-axis at the "front" of the cube.
80336
+ * @type Plane3D
80337
+ * @name View3D#xPlaneFrontZAxis
80338
+ */
80339
+ xPlaneFrontZAxis: {visible: 'inherit', strokeColor: '#888888', strokeWidth: 1},
80340
+
80341
+ /**
80342
+ * Attributes of the 3D x-axis on the 3D plane orthogonal to the y-axis at the "rear" of the cube.
80343
+ * @type Plane3D
80344
+ * @name View3D#yPlaneRearXAxis
80345
+ */
80346
+ yPlaneRearXAxis: {visible: 'inherit', strokeColor: '#888888', strokeWidth: 1},
80347
+ /**
80348
+ * Attributes of the 3D z-axis on the 3D plane orthogonal to the y-axis at the "rear" of the cube.
80349
+ * @type Plane3D
80350
+ * @name View3D#yPlaneRearZAxis
80351
+ */
80352
+ yPlaneRearZAxis: {visible: 'inherit', strokeColor: '#888888', strokeWidth: 1},
80353
+ /**
80354
+ * Attributes of the 3D x-axis on the 3D plane orthogonal to the y-axis at the "front" of the cube.
80355
+ * @type Plane3D
80356
+ * @name View3D#yPlaneFrontXAxis
80357
+ */
80358
+ yPlaneFrontXAxis: {visible: 'inherit', strokeColor: '#888888', strokeWidth: 1},
80359
+ /**
80360
+ * Attributes of the 3D z-axis on the 3D plane orthogonal to the y-axis at the "front" of the cube.
80361
+ * @type Plane3D
80362
+ * @name View3D#yPlaneFrontZAxis
80363
+ */
80364
+ yPlaneFrontZAxis: {visible: 'inherit', strokeColor: '#888888', strokeWidth: 1},
80365
+
80366
+ /**
80367
+ * Attributes of the 3D x-axis on the 3D plane orthogonal to the z-axis at the "rear" of the cube.
80368
+ * @type Plane3D
80369
+ * @name View3D#zPlaneRearXAxis
80370
+ */
80371
+ zPlaneRearXAxis: {visible: 'inherit', strokeColor: '#888888', strokeWidth: 1},
80372
+ /**
80373
+ * Attributes of the 3D y-axis on the 3D plane orthogonal to the z-axis at the "rear" of the cube.
80374
+ * @type Plane3D
80375
+ * @name View3D#zPlaneRearYAxis
80376
+ */
80377
+ zPlaneRearYAxis: {visible: 'inherit', strokeColor: '#888888', strokeWidth: 1},
80378
+ /**
80379
+ * Attributes of the 3D x-axis on the 3D plane orthogonal to the z-axis at the "front" of the cube.
80380
+ * @type Plane3D
80381
+ * @name View3D#zPlaneFrontXAxis
80382
+ */
80383
+ zPlaneFrontXAxis: {visible: 'inherit', strokeColor: '#888888', strokeWidth: 1},
80384
+ /**
80385
+ * Attributes of the 3D y-axis on the 3D plane orthogonal to the z-axis at the "front" of the cube.
80386
+ * @type Plane3D
80387
+ * @name View3D#zPlaneFrontYAxis
80388
+ */
80389
+ zPlaneFrontYAxis: {visible: 'inherit', strokeColor: '#888888', strokeWidth: 1}
80390
+
80391
+ /**#@-*/
80392
+ },
80393
+
80394
+ axis3d: {
80395
+ highlight: false,
80396
+ strokecolor: 'black',
80397
+ strokeWidth: 1,
80398
+ tabindex: null,
80399
+
80400
+ point1: { visible: false, name: '' },
80401
+ point2: { visible: false, name: '', label: { visible: true } }
80402
+ },
80403
+
80404
+ mesh3d: {
80405
+ strokeWidth: 1,
80406
+ strokeColor: '#9a9a9a',
80407
+ strokeOpacity: 0.6,
80408
+ highlight: false,
80409
+ fillColor: '#9a9a9a',
80410
+ fillOpacity: 0.1,
80411
+ tabindex: null,
80412
+
80413
+ visible: 'inherit'
80414
+ },
80415
+
80416
+ line3d: {
80417
+ strokeWidth: 1,
80418
+ strokeColor: 'black',
80419
+ fixed: true,
80420
+ tabindex: null,
80421
+
80422
+ gradient: 'linear',
80423
+ gradientSecondColor: '#ffffff',
80424
+
80425
+ point1: {visible: false, name: ''},
80426
+ point2: {visible: false, name: ''}
80427
+ },
80428
+
80429
+ plane3d: {
80430
+ strokeWidth: 0,
80431
+ strokeColor: 'black',
80432
+ strokeOpacity: 1,
80433
+ highlight: false,
80434
+ tabindex: null,
80435
+
80436
+ gradient: 'linear',
80437
+ gradientSecondColor: '#ffffff',
80438
+ gradientAngle: Math.PI,
80439
+ fillColor: '#a7a7a7',
80440
+ fillOpacity: 0.6
80441
+ },
80442
+
80443
+ point3d: {
80444
+ strokeWidth: 0,
80445
+ gradient: 'radial',
80446
+ gradientSecondColor: '#555555',
80447
+ fillColor: 'yellow',
80448
+ highlightStrokeColor: '#555555'
80449
+ },
80450
+
80451
+ surface3d: {
80452
+ /**#@+
80453
+ * @visprop
80454
+ */
80455
+
80456
+ highlight: false,
80457
+ tabindex: -1,
80458
+ strokeWidth: 1,
80459
+
80460
+ /**
80461
+ * Number of intervals the mesh is divided into in direction of parameter u.
80462
+ * @type Number
80463
+ * @name Surface3D#stepsU
80464
+ */
80465
+ stepsU: 30,
80466
+
80467
+ /**
80468
+ * Number of intervals the mesh is divided into in direction of parameter v.
80469
+ * @type Number
80470
+ * @name Surface3D#stepsV
80471
+ */
80472
+ stepsV: 30
80473
+
80474
+ /**#@-*/
80475
+ },
80476
+
80477
+ view3d: {
80478
+ needsRegularUpdate: true
80479
+ }
80480
+
80481
+ });
80482
+
80483
+ return JXG.Options;
80484
+ });
80485
+
80486
+
80487
+ /*
80488
+ Copyright 2008-2022
80489
+ Matthias Ehmann,
80490
+ Carsten Miller,
80491
+ Andreas Walter,
80492
+ Alfred Wassermann
80493
+
80494
+ This file is part of JSXGraph.
80495
+
80496
+ JSXGraph is free software dual licensed under the GNU LGPL or MIT License.
80497
+
80498
+ You can redistribute it and/or modify it under the terms of the
80499
+
80500
+ * GNU Lesser General Public License as published by
80501
+ the Free Software Foundation, either version 3 of the License, or
80502
+ (at your option) any later version
80503
+ OR
80504
+ * MIT License: https://github.com/jsxgraph/jsxgraph/blob/master/LICENSE.MIT
80505
+
80506
+ JSXGraph is distributed in the hope that it will be useful,
80507
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
80508
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
80509
+ GNU Lesser General Public License for more details.
80510
+
80511
+ You should have received a copy of the GNU Lesser General Public License and
80512
+ the MIT License along with JSXGraph. If not, see <http://www.gnu.org/licenses/>
80513
+ and <http://opensource.org/licenses/MIT/>.
80514
+ */
80515
+ /*global JXG:true, define: true*/
80516
+
80517
+ define('3d/threed',['jxg'
80518
+ ], function (JXG) {
80519
+ "use strict";
80520
+
80521
+ JXG.ThreeD = {};
80522
+
80523
+ return JXG.ThreeD;
80524
+ });
80525
+
80526
+ /*
80527
+ Copyright 2008-2022
80528
+ Matthias Ehmann,
80529
+ Carsten Miller,
80530
+ Andreas Walter,
80531
+ Alfred Wassermann
80532
+
80533
+ This file is part of JSXGraph.
80534
+
80535
+ JSXGraph is free software dual licensed under the GNU LGPL or MIT License.
80536
+
80537
+ You can redistribute it and/or modify it under the terms of the
80538
+
80539
+ * GNU Lesser General Public License as published by
80540
+ the Free Software Foundation, either version 3 of the License, or
80541
+ (at your option) any later version
80542
+ OR
80543
+ * MIT License: https://github.com/jsxgraph/jsxgraph/blob/master/LICENSE.MIT
80544
+
80545
+ JSXGraph is distributed in the hope that it will be useful,
80546
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
80547
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
80548
+ GNU Lesser General Public License for more details.
80549
+
80550
+ You should have received a copy of the GNU Lesser General Public License and
80551
+ the MIT License along with JSXGraph. If not, see <http://www.gnu.org/licenses/>
80552
+ and <http://opensource.org/licenses/MIT/>.
80553
+ */
80554
+ /*global JXG:true, define: true*/
80555
+
80556
+ define('3d/view3d',['jxg', 'options', 'base/constants', 'utils/type', 'math/math', 'base/element', '3d/threed',
80557
+ ], function (JXG, Options, Const, Type, Mat, GeometryElement, ThreeD) {
80558
+ "use strict";
80559
+
80560
+ ThreeD.View3D = function (board, parents, attributes) {
80561
+ var bbox3d, coords, size;
80562
+ this.constructor(board, attributes, Const.OBJECT_TYPE_VIEW3D, Const.OBJECT_CLASS_CURVE);
80563
+
80564
+ bbox3d = parents[2]; // [[x1, x2], [y1,y2], [z1,z2]]
80565
+ coords = parents[0]; // llft corner
80566
+ size = parents[1]; // [w, h]
80567
+
80568
+ /**
80569
+ * "Namespace" for all 3D handling
80570
+ */
80571
+ this.D3 = {};
80572
+
80573
+ /**
80574
+ * An associative array containing all geometric objects belonging to the view.
80575
+ * Key is the id of the object and value is a reference to the object.
80576
+ * @type Object
80577
+ */
80578
+ this.D3.objects = {};
80579
+
80580
+ /**
80581
+ * An array containing all geometric objects in this view in the order of construction.
80582
+ * @type Array
80583
+ */
80584
+ this.D3.objectsList = [];
80585
+
80586
+ /**
80587
+ * @type {Object} contains the axes of the view or null
80588
+ * @default null
80589
+ */
80590
+ this.D3.defaultAxes = null;
80591
+
80592
+ /**
80593
+ * 3D-to-2D transformation matrix
80594
+ * @type {Array} 3 x 4 mattrix
80595
+ */
80596
+ this.D3.matrix = [
80597
+ [1, 0, 0, 0],
80598
+ [0, 1, 0, 0],
80599
+ [0, 0, 1, 0]
80600
+ ];
80601
+
80602
+ // Bounding box (cube) [[x1, x2], [y1,y2], [z1,z2]]:
80603
+ this.D3.bbox3d = bbox3d;
80604
+ this.D3.coords = coords;
80605
+ this.D3.size = size;
80606
+
80607
+ /**
80608
+ * Distance of the view to the origin. In other words, its
80609
+ * the radius of the sphere where the camera sits.
80610
+ */
80611
+ this.D3.r = -1;
80612
+
80613
+ this.timeoutAzimuth = null;
80614
+
80615
+ this.id = this.board.setId(this, 'V');
80616
+ this.board.finalizeAdding(this);
80617
+ this.elType = 'view3d';
80618
+ this.methodMap = Type.deepCopy(this.methodMap, {
80619
+ });
80620
+ };
80621
+ ThreeD.View3D.prototype = new GeometryElement();
80622
+
80623
+ JXG.extend(ThreeD.View3D.prototype, /** @lends ThreeD.View3D.prototype */ {
80624
+ create: function (elementType, parents, attributes) {
80625
+ var prefix = [],
80626
+ is3D = false,
80627
+ el;
80628
+
80629
+ if (elementType.indexOf('3d') > 0) {
80630
+ is3D = true;
80631
+ prefix.push(this);
80632
+ }
80633
+ el = this.board.create(elementType, prefix.concat(parents), attributes);
80634
+ if (true || is3D) {
80635
+ this.add(el);
80636
+ }
80637
+ return el;
80638
+ },
80639
+
80640
+ add: function (el) {
80641
+ this.D3.objects[el.id] = el;
80642
+ this.D3.objectsList.push(el);
80643
+ },
80644
+
80645
+ /**
80646
+ * Update 3D-to-2D transformation matrix with the actual
80647
+ * elevation and azimuth angles.
80648
+ *
80649
+ * @private
80650
+ */
80651
+ update: function () {
80652
+ var D3 = this.D3,
80653
+ e, r, a, f, mat;
80654
+
80655
+ if (!Type.exists(D3.el_slide) ||
80656
+ !Type.exists(D3.az_slide) ||
80657
+ !this.needsUpdate) {
80658
+ return this;
80659
+ }
80660
+
80661
+ e = D3.el_slide.Value();
80662
+ r = D3.r;
80663
+ a = D3.az_slide.Value();
80664
+ f = r * Math.sin(e);
80665
+ mat = [[1, 0, 0,], [0, 1, 0], [0, 0, 1]];
80666
+
80667
+ D3.matrix = [
80668
+ [1, 0, 0, 0],
80669
+ [0, 1, 0, 0],
80670
+ [0, 0, 1, 0]
80671
+ ];
80672
+
80673
+ D3.matrix[1][1] = r * Math.cos(a);
80674
+ D3.matrix[1][2] = -r * Math.sin(a);
80675
+ D3.matrix[2][1] = f * Math.sin(a);
80676
+ D3.matrix[2][2] = f * Math.cos(a);
80677
+ D3.matrix[2][3] = Math.cos(e);
80678
+
80679
+ if (true) {
80680
+ mat[1][1] = D3.size[0] / (D3.bbox3d[0][1] - D3.bbox3d[0][0]); // w / d_x
80681
+ mat[2][2] = D3.size[1] / (D3.bbox3d[1][1] - D3.bbox3d[1][0]); // h / d_y
80682
+ mat[1][0] = D3.coords[0] - mat[1][1] * D3.bbox3d[0][0]; // llft_x
80683
+ mat[2][0] = D3.coords[1] - mat[2][2] * D3.bbox3d[1][0]; // llft_y
80684
+
80685
+ D3.matrix = Mat.matMatMult(mat, D3.matrix);
80686
+ }
80687
+
80688
+ return this;
80689
+ },
80690
+
80691
+ updateRenderer: function () {
80692
+ this.needsUpdate = false;
80693
+ return this;
80694
+ },
80695
+
80696
+ /**
80697
+ * Project 3D coordinates to 2D board coordinates
80698
+ * The 3D coordinates are provides as three numbers x, y, z or one array of length 3.
80699
+ *
80700
+ * @param {Number|Array} x
80701
+ * @param {[Number]} y
80702
+ * @param {[Number]} z
80703
+ * @returns {Array} Array of length 3 containing the projection on to the board
80704
+ * in homogeneous user coordinates.
80705
+ */
80706
+ project3DTo2D: function (x, y, z) {
80707
+ var vec;
80708
+ if (arguments.length === 3) {
80709
+ vec = [1, x, y, z];
80710
+ } else {
80711
+ // Argument is an array
80712
+ if (x.length === 3) {
80713
+ vec = [1].concat(x);
80714
+ } else {
80715
+ vec = x;
80716
+ }
80717
+ }
80718
+ return Mat.matVecMult(this.D3.matrix, vec);
80719
+ },
80720
+
80721
+ /**
80722
+ * Project a 2D coordinate to the plane through the origin
80723
+ * defined by its normal vector `normal`.
80724
+ *
80725
+ * @param {JXG.Point} point
80726
+ * @param {Array} normal
80727
+ * @returns Array of length 4 containing the projected
80728
+ * point in homogeneous coordinates.
80729
+ */
80730
+ project2DTo3DPlane: function (point, normal, foot) {
80731
+ var mat, rhs, d, le,
80732
+ n = normal.slice(1),
80733
+ sol = [1, 0, 0, 0];
80734
+
80735
+ foot = foot || [1, 0, 0, 0];
80736
+ le = Mat.norm(n, 3);
80737
+ d = Mat.innerProduct(foot.slice(1), n, 3) / le;
80738
+
80739
+ mat = this.D3.matrix.slice(0, 3); // True copy
80740
+ mat.push([0].concat(n));
80741
+
80742
+ // 2D coordinates of point:
80743
+ rhs = point.coords.usrCoords.concat([d]);
80744
+ try {
80745
+ // Prevent singularity in case elevation angle is zero
80746
+ if (mat[2][3] === 1.0) {
80747
+ mat[2][1] = mat[2][2] = Mat.eps * 0.001;
80748
+ }
80749
+ sol = Mat.Numerics.Gauss(mat, rhs);
80750
+ } catch (err) {
80751
+ sol = [0, NaN, NaN, NaN];
80752
+ }
80753
+
80754
+ return sol;
80755
+ },
80756
+
80757
+ project3DToCube: function (c3d) {
80758
+ var cube = this.D3.bbox3d;
80759
+ if (c3d[1] < cube[0][0]) { c3d[1] = cube[0][0]; }
80760
+ if (c3d[1] > cube[0][1]) { c3d[1] = cube[0][1]; }
80761
+ if (c3d[2] < cube[1][0]) { c3d[2] = cube[1][0]; }
80762
+ if (c3d[2] > cube[1][1]) { c3d[2] = cube[1][1]; }
80763
+ if (c3d[3] < cube[2][0]) { c3d[3] = cube[2][0]; }
80764
+ if (c3d[3] > cube[2][1]) { c3d[3] = cube[2][1]; }
80765
+
80766
+ return c3d;
80767
+ },
80768
+
80769
+ intersectionLineCube: function (p, d, r) {
80770
+ var rnew, i, r0, r1;
80771
+
80772
+ rnew = r;
80773
+ for (i = 0; i < 3; i++) {
80774
+ if (d[i] !== 0) {
80775
+ r0 = (this.D3.bbox3d[i][0] - p[i]) / d[i];
80776
+ r1 = (this.D3.bbox3d[i][1] - p[i]) / d[i];
80777
+ if (r < 0) {
80778
+ rnew = Math.max(rnew, Math.min(r0, r1));
80779
+ } else {
80780
+ rnew = Math.min(rnew, Math.max(r0, r1));
80781
+ }
80782
+ }
80783
+ }
80784
+ return rnew;
80785
+ },
80786
+
80787
+ isInCube: function (q) {
80788
+ return q[0] > this.D3.bbox3d[0][0] - Mat.eps && q[0] < this.D3.bbox3d[0][1] + Mat.eps &&
80789
+ q[1] > this.D3.bbox3d[1][0] - Mat.eps && q[1] < this.D3.bbox3d[1][1] + Mat.eps &&
80790
+ q[2] > this.D3.bbox3d[2][0] - Mat.eps && q[2] < this.D3.bbox3d[2][1] + Mat.eps;
80791
+ },
80792
+
80793
+ /**
80794
+ *
80795
+ * @param {*} plane1
80796
+ * @param {*} plane2
80797
+ * @param {*} d
80798
+ * @returns Array of length 2 containing the coordinates of the defining points of
80799
+ * of the intersection segment.
80800
+ */
80801
+ intersectionPlanePlane: function(plane1, plane2, d) {
80802
+ var ret = [[], []],
80803
+ p, dir, r, q;
80804
+
80805
+ d = d || plane2.D3.d;
80806
+
80807
+ p = Mat.Geometry.meet3Planes(plane1.D3.normal, plane1.D3.d, plane2.D3.normal, d,
80808
+ Mat.crossProduct(plane1.D3.normal, plane2.D3.normal), 0);
80809
+ dir = Mat.Geometry.meetPlanePlane(plane1.D3.dir1, plane1.D3.dir2, plane2.D3.dir1, plane2.D3.dir2);
80810
+ r = this.intersectionLineCube(p, dir, Infinity);
80811
+ q = Mat.axpy(r, dir, p);
80812
+ if (this.isInCube(q)) {
80813
+ ret[0] = q;
80814
+ }
80815
+ r = this.intersectionLineCube(p, dir, -Infinity);
80816
+ q = Mat.axpy(r, dir, p);
80817
+ if (this.isInCube(q) ) {
80818
+ ret[1] = q;
80819
+ }
80820
+ return ret;
80821
+ },
80822
+
80823
+ getMesh: function (X, Y, Z, interval_u, interval_v) {
80824
+ var i_u, i_v, u, v, c2d,
80825
+ delta_u, delta_v,
80826
+ p = [0, 0, 0],
80827
+ steps_u = interval_u[2],
80828
+ steps_v = interval_v[2],
80829
+
80830
+ dataX = [],
80831
+ dataY = [];
80832
+
80833
+ delta_u = (Type.evaluate(interval_u[1]) - Type.evaluate(interval_u[0])) / (steps_u);
80834
+ delta_v = (Type.evaluate(interval_v[1]) - Type.evaluate(interval_v[0])) / (steps_v);
80835
+
80836
+ for (i_u = 0; i_u <= steps_u; i_u++) {
80837
+ u = interval_u[0] + delta_u * i_u;
80838
+ for (i_v = 0; i_v <= steps_v; i_v++) {
80839
+ v = interval_v[0] + delta_v * i_v;
80840
+ p[0] = X(u, v);
80841
+ p[1] = Y(u, v);
80842
+ p[2] = Z(u, v);
80843
+ c2d = this.project3DTo2D(p);
80844
+ dataX.push(c2d[1]);
80845
+ dataY.push(c2d[2]);
80846
+ }
80847
+ dataX.push(NaN);
80848
+ dataY.push(NaN);
80849
+ }
80850
+
80851
+ for (i_v = 0; i_v <= steps_v; i_v++) {
80852
+ v = interval_v[0] + delta_v * i_v;
80853
+ for (i_u = 0; i_u <= steps_u; i_u++) {
80854
+ u = interval_u[0] + delta_u * i_u;
80855
+ p[0] = X(u, v);
80856
+ p[1] = Y(u, v);
80857
+ p[2] = Z(u, v);
80858
+ c2d = this.project3DTo2D(p);
80859
+ dataX.push(c2d[1]);
80860
+ dataY.push(c2d[2]);
80861
+ }
80862
+ dataX.push(NaN);
80863
+ dataY.push(NaN);
80864
+ }
80865
+
80866
+ return [dataX, dataY];
80867
+ },
80868
+
80869
+ animateAzimuth: function () {
80870
+ var s = this.D3.az_slide._smin,
80871
+ e = this.D3.az_slide._smax,
80872
+ sdiff = e - s,
80873
+ newVal = this.D3.az_slide.Value() + 0.1;
80874
+
80875
+ this.D3.az_slide.position = ((newVal - s) / sdiff);
80876
+ if (this.D3.az_slide.position > 1) {
80877
+ this.D3.az_slide.position = 0.0;
80878
+ }
80879
+ this.board.update();
80880
+
80881
+ this.timeoutAzimuth = setTimeout(function () { this.animateAzimuth(); }.bind(this), 200);
80882
+ },
80883
+
80884
+ stopAzimuth: function () {
80885
+ clearTimeout(this.timeoutAzimuth);
80886
+ this.timeoutAzimuth = null;
80887
+ }
80888
+ });
80889
+
80890
+ /**
80891
+ * @class This element creates a 3D view.
80892
+ * @pseudo
80893
+ * @description A View3D element provides the container and the methods to create and display 3D elements.
80894
+ * It is contained in a JSXGraph board.
80895
+ * @name View3D
80896
+ * @augments JXG.View3D
80897
+ * @constructor
80898
+ * @type Object
80899
+ * @throws {Exception} If the element cannot be constructed with the given parent objects an exception is thrown.
80900
+ * @param {Array_Array_Array} lower,dim,cube Here, lower is an array of the form [x, y] and
80901
+ * dim is an array of the form [w, h].
80902
+ * The arrays [x, y] and [w, h] define the 2D frame into which the 3D cube is
80903
+ * (roughly) projected.
80904
+ * cube is an array of the form [[x1, x2], [y1, y2], [z1, z2]]
80905
+ * which determines the coordinate ranges of the 3D cube.
80906
+ *
80907
+ * @example
80908
+ * var bound = [-5, 5];
80909
+ * var view = board.create('view3d',
80910
+ * [[-6, -3],
80911
+ * [8, 8],
80912
+ * [bound, bound, bound]],
80913
+ * {
80914
+ * // Main axes
80915
+ * axesPosition: 'center',
80916
+ * xAxis: { strokeColor: 'blue', strokeWidth: 3},
80917
+ *
80918
+ * // Planes
80919
+ * xPlaneRear: { fillColor: 'yellow', mesh3d: {visible: false}},
80920
+ * yPlaneFront: { visible: true, fillColor: 'blue'},
80921
+ *
80922
+ * // Axes on planes
80923
+ * xPlaneRearYAxis: {strokeColor: 'red'},
80924
+ * xPlaneRearZAxis: {strokeColor: 'red'},
80925
+ *
80926
+ * yPlaneFrontXAxis: {strokeColor: 'blue'},
80927
+ * yPlaneFrontZAxis: {strokeColor: 'blue'},
80928
+ *
80929
+ * zPlaneFrontXAxis: {visible: false},
80930
+ * zPlaneFrontYAxis: {visible: false}
80931
+ * });
80932
+ *
80933
+ * </pre><div id="JXGdd06d90e-be5d-4531-8f0b-65fc30b1a7c7" class="jxgbox" style="width: 500px; height: 500px;"></div>
80934
+ * <script type="text/javascript">
80935
+ * (function() {
80936
+ * var board = JXG.JSXGraph.initBoard('JXGdd06d90e-be5d-4531-8f0b-65fc30b1a7c7',
80937
+ * {boundingbox: [-8, 8, 8,-8], axis: false, showcopyright: false, shownavigation: false});
80938
+ * var bound = [-5, 5];
80939
+ * var view = board.create('view3d',
80940
+ * [[-6, -3], [8, 8],
80941
+ * [bound, bound, bound]],
80942
+ * {
80943
+ * // Main axes
80944
+ * axesPosition: 'center',
80945
+ * xAxis: { strokeColor: 'blue', strokeWidth: 3},
80946
+ *
80947
+ * // Planes
80948
+ * xPlaneRear: { fillColor: 'yellow', mesh3d: {visible: false}},
80949
+ * yPlaneFront: { visible: true, fillColor: 'blue'},
80950
+ *
80951
+ * // Axes on planes
80952
+ * xPlaneRearYAxis: {strokeColor: 'red'},
80953
+ * xPlaneRearZAxis: {strokeColor: 'red'},
80954
+ *
80955
+ * yPlaneFrontXAxis: {strokeColor: 'blue'},
80956
+ * yPlaneFrontZAxis: {strokeColor: 'blue'},
80957
+ *
80958
+ * zPlaneFrontXAxis: {visible: false},
80959
+ * zPlaneFrontYAxis: {visible: false}
80960
+ * });
80961
+ *
80962
+ * })();
80963
+ *
80964
+ * </script><pre>
80965
+ *
80966
+ */
80967
+ ThreeD.createView3D = function (board, parents, attributes) {
80968
+ var view, frame, attr,
80969
+ x, y, w, h,
80970
+ coords = parents[0], // llft corner
80971
+ size = parents[1]; // [w, h]
80972
+
80973
+ attr = Type.copyAttributes(attributes, board.options, 'view3d');
80974
+ view = new ThreeD.View3D(board, parents, attr);
80975
+ view.defaultAxes = view.create('axes3d', parents, attributes);
80976
+
80977
+ x = coords[0];
80978
+ y = coords[1];
80979
+ w = size[0];
80980
+ h = size[1];
80981
+
80982
+ /**
80983
+ * Frame around the view object
80984
+ */
80985
+ if (false) {
80986
+ frame = board.create('polygon', [
80987
+ [coords[0], coords[1] + size[1]], // ulft
80988
+ [coords[0], coords[1]], // llft
80989
+ [coords[0] + size[0], coords[1]], // lrt
80990
+ [coords[0] + size[0], coords[1] + size[1]], // urt
80991
+ ], {
80992
+ fillColor: 'none',
80993
+ highlightFillColor: 'none',
80994
+ highlight: false,
80995
+ vertices: {
80996
+ fixed: true,
80997
+ visible: false
80998
+ },
80999
+ borders: {
81000
+ strokeColor: 'black',
81001
+ highlight: false,
81002
+ strokeWidth: 0.5,
81003
+ dash: 4
81004
+ }
81005
+ });
81006
+ //view.add(frame);
81007
+ }
81008
+
81009
+ /**
81010
+ * Slider to adapt azimuth angle
81011
+ */
81012
+ view.D3.az_slide = board.create('slider', [[x - 1, y - 2], [x + w + 1, y - 2], [0, 1.0, 2 * Math.PI]], {
81013
+ style: 6, name: 'az',
81014
+ point1: { frozen: true },
81015
+ point2: { frozen: true }
81016
+ });
81017
+
81018
+ /**
81019
+ * Slider to adapt elevation angle
81020
+ */
81021
+ view.D3.el_slide = board.create('slider', [[x - 1, y], [x - 1, y + h], [0, 0.30, Math.PI / 2]], {
81022
+ style: 6, name: 'el',
81023
+ point1: { frozen: true },
81024
+ point2: { frozen: true }
81025
+ });
81026
+
81027
+ view.board.highlightInfobox = function (x, y, el) {
81028
+ var d;
81029
+
81030
+ if (Type.exists(el.D3)) {
81031
+ d = Type.evaluate(el.visProp.infoboxdigits);
81032
+ if (d === 'auto') {
81033
+ view.board.highlightCustomInfobox('(' +
81034
+ Type.autoDigits(el.D3.X()) + ' | ' +
81035
+ Type.autoDigits(el.D3.Y()) + ' | ' +
81036
+ Type.autoDigits(el.D3.Z()) + ')', el);
81037
+ } else {
81038
+ view.board.highlightCustomInfobox('(' +
81039
+ Type.toFixed(el.D3.X(), d) + ' | ' +
81040
+ Type.toFixed(el.D3.Y(), d) + ' | ' +
81041
+ Type.toFixed(el.D3.Z(), d) + ')', el);
81042
+ }
81043
+ } else {
81044
+ view.board.highlightCustomInfobox('(' + x + ', ' + y + ')', el);
81045
+ }
81046
+ };
81047
+
81048
+ return view;
81049
+ };
81050
+ JXG.registerElement('view3d', ThreeD.createView3D);
81051
+
81052
+ return ThreeD.View3D;
81053
+ });
81054
+
81055
+
81056
+ /*
81057
+ Copyright 2008-2022
81058
+ Matthias Ehmann,
81059
+ Carsten Miller,
81060
+ Andreas Walter,
81061
+ Alfred Wassermann
81062
+
81063
+ This file is part of JSXGraph.
81064
+
81065
+ JSXGraph is free software dual licensed under the GNU LGPL or MIT License.
81066
+
81067
+ You can redistribute it and/or modify it under the terms of the
81068
+
81069
+ * GNU Lesser General Public License as published by
81070
+ the Free Software Foundation, either version 3 of the License, or
81071
+ (at your option) any later version
81072
+ OR
81073
+ * MIT License: https://github.com/jsxgraph/jsxgraph/blob/master/LICENSE.MIT
81074
+
81075
+ JSXGraph is distributed in the hope that it will be useful,
81076
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
81077
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
81078
+ GNU Lesser General Public License for more details.
81079
+
81080
+ You should have received a copy of the GNU Lesser General Public License and
81081
+ the MIT License along with JSXGraph. If not, see <http://www.gnu.org/licenses/>
81082
+ and <http://opensource.org/licenses/MIT/>.
81083
+ */
81084
+ /*global JXG:true, define: true*/
81085
+
81086
+ /**
81087
+ * Create axes and rear and front walls of the
81088
+ * view3d bounding box bbox3d.
81089
+ */
81090
+ define('3d/box3d',['jxg', 'utils/type', 'math/math', 'math/geometry', '3d/view3d'
81091
+ ], function (JXG, Type, Mat, Geometry, ThreeD) {
81092
+ "use strict";
81093
+
81094
+ ThreeD.createAxes = function (board, parents, attributes) {
81095
+ var view = parents[0],
81096
+ i, j, k, i1, i2,
81097
+ attr,
81098
+ pos,
81099
+ directions = ['x', 'y', 'z'],
81100
+ suffixAxis = 'Axis',
81101
+ dir, dir1,
81102
+ sides = ['Rear', 'Front'],
81103
+ rear = [0, 0, 0], // x, y, z
81104
+ front = [0, 0, 0], // x, y, z
81105
+ from, to,
81106
+ vec1, vec2, range1, range2,
81107
+ na, na_parent,
81108
+ ticks_attr,
81109
+ axes = {};
81110
+
81111
+ if (Type.exists(view.D3)) {
81112
+ for (i = 0; i < directions.length; i++) {
81113
+ rear[i] = view.D3.bbox3d[i][0];
81114
+ front[i] = view.D3.bbox3d[i][1];
81115
+ }
81116
+ } else {
81117
+ for (i = 0; i < directions.length; i++) {
81118
+ rear[i] = parents[1][i];
81119
+ front[i] = parents[2][1];
81120
+ }
81121
+ }
81122
+
81123
+ // Main 3D axes
81124
+ attr = Type.copyAttributes(attributes, board.options, 'axes3d');
81125
+ pos = attr.axesposition;
81126
+ for (i = 0; i < directions.length; i++) {
81127
+ // Run through ['x', 'y', 'z']
81128
+ dir = directions[i];
81129
+ na = dir + suffixAxis;
81130
+
81131
+ if (pos === 'center') { // Axes centered
81132
+ from = [0, 0, 0];
81133
+ to = [0, 0, 0];
81134
+ to[i] = front[i];
81135
+ axes[na] = view.create('axis3d', [from, to], attr[na.toLowerCase()]);
81136
+ } else {
81137
+ na += 'Border'; // Axes bordered
81138
+ from = rear.slice();
81139
+ to = front.slice();
81140
+ if (i === 2) {
81141
+ from[1] = front[1];
81142
+ to[0] = rear[0];
81143
+ } else {
81144
+ from[i] = front[i];
81145
+ to[2] = rear[2];
81146
+ }
81147
+ to[i] = front[i];
81148
+ attr[na.toLowerCase()].lastArrow = false;
81149
+ axes[na] = view.create('axis3d', [from, to], attr[na.toLowerCase()]);
81150
+
81151
+ // TODO
81152
+ ticks_attr = {
81153
+ visible: true, // Für z-Ticks wird path nicht berechnet
81154
+ minorTicks: 0,
81155
+ tickEndings: [0, 1],
81156
+ drawLabels: false
81157
+ };
81158
+ if (i === 2) {
81159
+ ticks_attr.tickEndings = [1, 0];
81160
+ }
81161
+ axes[na + 'Ticks'] = view.create('ticks', [axes[na], 1], ticks_attr);
81162
+ }
81163
+ }
81164
+
81165
+ // Origin (2D point)
81166
+ axes.O = board.create('intersection', [
81167
+ axes[directions[0] + suffixAxis],
81168
+ axes[directions[1] + suffixAxis]
81169
+ ], {
81170
+ name: '', visible: false, withLabel: false
81171
+ });
81172
+
81173
+ // Front and rear planes
81174
+ for (i = 0; i < directions.length; i++) {
81175
+ // Run through ['x', 'y', 'z']
81176
+ i1 = (i + 1) % 3;
81177
+ i2 = (i + 2) % 3;
81178
+
81179
+ dir = directions[i];
81180
+ for (j = 0; j < sides.length; j++) {
81181
+ // Run through ['Rear', 'Front']
81182
+
81183
+ from = [0, 0, 0];
81184
+ from[i] = (j === 0) ? rear[i] : front[i];
81185
+ vec1 = [0, 0, 0];
81186
+ vec2 = [0, 0, 0];
81187
+ vec1[i1] = 1;
81188
+ vec2[i2] = 1;
81189
+ range1 = [rear[i1], front[i1]];
81190
+ range2 = [rear[i2], front[i2]];
81191
+ na = dir + 'Plane' + sides[j];
81192
+
81193
+ attr = Type.copyAttributes(attributes, board.options, 'axes3d', na);
81194
+ axes[na] =
81195
+ view.create('plane3d', [from, vec1, vec2, range1, range2], attr);
81196
+ axes[na].D3.elType = 'axisplane3d';
81197
+ }
81198
+ }
81199
+
81200
+ // Axes on front and rear planes
81201
+ for (i = 0; i < directions.length; i++) {
81202
+ // Run through ['x', 'y', 'z']
81203
+ dir = directions[i];
81204
+ for (j = 0; j < sides.length; j++) {
81205
+ for (k = 1; k <= 2; k++) {
81206
+ i1 = (i + k) % 3;
81207
+ dir1 = directions[i1];
81208
+ na = dir + 'Plane' + sides[j] + dir1.toUpperCase() + 'Axis';
81209
+ na_parent = dir + 'Plane' + sides[j];
81210
+
81211
+ from = [0, 0, 0];
81212
+ to = [0, 0, 0];
81213
+ from[i] = to[i] = (j === 0) ? rear[i] : front[i];
81214
+
81215
+ from[i1] = rear[i1];
81216
+ to[i1] = front[i1];
81217
+
81218
+ attr = Type.copyAttributes(attributes, board.options, 'axes3d', na);
81219
+ axes[na] = view.create('axis3d', [from, to], attr);
81220
+ axes[na_parent].addChild(axes[na]);
81221
+ axes[na_parent].inherits.push(axes[na]);
81222
+ }
81223
+ }
81224
+ }
81225
+
81226
+ return axes;
81227
+ };
81228
+ JXG.registerElement('axes3d', ThreeD.createAxes);
81229
+
81230
+ ThreeD.createAxis = function (board, parents, attributes) {
81231
+ var view = parents[0],
81232
+ attr,
81233
+ start = parents[1],
81234
+ end = parents[2],
81235
+ el_start, el_end, el;
81236
+
81237
+ // Use 2D points to create axis
81238
+ attr = Type.copyAttributes(attributes.point1, board.options, 'axis3d', 'point1');
81239
+ el_start = board.create('point', [
81240
+ (function (xx, yy, zz) {
81241
+ return function () { return view.project3DTo2D(xx, yy, zz)[1]; };
81242
+ })(start[0], start[1], start[2]),
81243
+ (function (xx, yy, zz) {
81244
+ return function () { return view.project3DTo2D(xx, yy, zz)[2]; };
81245
+ })(start[0], start[1], start[2])
81246
+ ], attr);
81247
+
81248
+ attr = Type.copyAttributes(attributes.point2, board.options, 'axis3d', 'point2');
81249
+ el_end = board.create('point', [
81250
+ (function (xx, yy, zz) {
81251
+ return function () { return view.project3DTo2D(xx, yy, zz)[1]; };
81252
+ })(end[0], end[1], end[2]),
81253
+ (function (xx, yy, zz) {
81254
+ return function () { return view.project3DTo2D(xx, yy, zz)[2]; };
81255
+ })(end[0], end[1], end[2])
81256
+ ], attr);
81257
+
81258
+ attr = Type.copyAttributes(attributes, board.options, 'axis3d');
81259
+ el = board.create('arrow', [el_start, el_end], attr);
81260
+
81261
+ return el;
81262
+ };
81263
+ JXG.registerElement('axis3d', ThreeD.createAxis);
81264
+
81265
+ ThreeD.createMesh = function (board, parents, attr) {
81266
+ var view = parents[0],
81267
+ point = parents[1],
81268
+ vec1 = parents[2],
81269
+ range1 = parents[3],
81270
+ vec2 = parents[4],
81271
+ range2 = parents[5],
81272
+ el;
81273
+
81274
+ el = board.create('curve', [[], []], attr);
81275
+ el.updateDataArray = function () {
81276
+ var s1 = range1[0],
81277
+ e1 = range1[1],
81278
+ s2 = range2[0],
81279
+ e2 = range2[1],
81280
+ l1, l2, res, i, sol,
81281
+ v1 = [0, 0, 0],
81282
+ v2 = [0, 0, 0],
81283
+ step = 1,
81284
+ q = [0, 0, 0];
81285
+
81286
+ this.dataX = [];
81287
+ this.dataY = [];
81288
+
81289
+ for (i = 0; i < 3; i++) {
81290
+ q[i] = Type.evaluate(point[i]);
81291
+ v1[i] = Type.evaluate(vec1[i]);
81292
+ v2[i] = Type.evaluate(vec2[i]);
81293
+ }
81294
+ l1 = JXG.Math.norm(v1, 3);
81295
+ l2 = JXG.Math.norm(v2, 3);
81296
+ for (i = 0; i < 3; i++) {
81297
+ v1[i] /= l1;
81298
+ v2[i] /= l2;
81299
+ }
81300
+ if (false) {
81301
+ sol = Mat.Geometry.getPlaneBounds(v1, v2, q, s1, e1);
81302
+ if (sol !== null) {
81303
+ s1 = sol[0];
81304
+ e1 = sol[1];
81305
+ s2 = sol[2];
81306
+ e2 = sol[3];
81307
+ }
81308
+ }
81309
+
81310
+ res = view.getMesh(
81311
+ function(u, v) { return q[0] + u * v1[0] + v * v2[0]; },
81312
+ function(u, v) { return q[1] + u * v1[1] + v * v2[1]; },
81313
+ function(u, v) { return q[2] + u * v1[2] + v * v2[2]; },
81314
+ [Math.ceil(s1), Math.floor(e1), (Math.ceil(e1) - Math.floor(s1)) / step],
81315
+ [Math.ceil(s2), Math.floor(e2), (Math.ceil(e2) - Math.floor(s2)) / step]);
81316
+ this.dataX = res[0];
81317
+ this.dataY = res[1];
81318
+ };
81319
+ return el;
81320
+ };
81321
+ JXG.registerElement('mesh3d', ThreeD.createMesh);
81322
+
81323
+ });
81324
+ /*
81325
+ Copyright 2008-2022
81326
+ Matthias Ehmann,
81327
+ Carsten Miller,
81328
+ Andreas Walter,
81329
+ Alfred Wassermann
81330
+
81331
+ This file is part of JSXGraph.
81332
+
81333
+ JSXGraph is free software dual licensed under the GNU LGPL or MIT License.
81334
+
81335
+ You can redistribute it and/or modify it under the terms of the
81336
+
81337
+ * GNU Lesser General Public License as published by
81338
+ the Free Software Foundation, either version 3 of the License, or
81339
+ (at your option) any later version
81340
+ OR
81341
+ * MIT License: https://github.com/jsxgraph/jsxgraph/blob/master/LICENSE.MIT
81342
+
81343
+ JSXGraph is distributed in the hope that it will be useful,
81344
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
81345
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
81346
+ GNU Lesser General Public License for more details.
81347
+
81348
+ You should have received a copy of the GNU Lesser General Public License and
81349
+ the MIT License along with JSXGraph. If not, see <http://www.gnu.org/licenses/>
81350
+ and <http://opensource.org/licenses/MIT/>.
81351
+ */
81352
+ /*global JXG:true, define: true*/
81353
+
81354
+ define('3d/curve3d',['jxg', 'utils/type', '3d/view3d'
81355
+ ], function (JXG, Type, ThreeD) {
81356
+ "use strict";
81357
+
81358
+ ThreeD.createCurve = function (board, parents, attr) {
81359
+ var view = parents[0],
81360
+ D3, el;
81361
+
81362
+ D3 = {
81363
+ elType: 'curve3D',
81364
+ X: parents[1],
81365
+ Y: parents[2],
81366
+ Z: parents[3],
81367
+ };
81368
+ D3.F = [D3.X, D3.Y, D3.Z];
81369
+
81370
+ el = board.create('curve', [[], []], attr);
81371
+ el.D3 = D3;
81372
+
81373
+ if (Type.isFunction(el.D3.X)) {
81374
+ // 3D curve given as t -> [X(t), Y(t), Z(t)]
81375
+
81376
+ el.D3.range = parents[4];
81377
+ el.updateDataArray = function () {
81378
+ var steps = Type.evaluate(this.visProp.numberpointshigh),
81379
+ s = Type.evaluate(this.D3.range[0]),
81380
+ e = Type.evaluate(this.D3.range[1]),
81381
+ delta = (e - s) / (steps - 1),
81382
+ c2d, t, i,
81383
+ p = [0, 0, 0];
81384
+
81385
+ this.dataX = [];
81386
+ this.dataY = [];
81387
+
81388
+ for (t = s; t <= e; t += delta) {
81389
+ for (i = 0; i < 3; i++) {
81390
+ p[i] = this.D3.F[i](t);
81391
+ }
81392
+ c2d = view.project3DTo2D(p);
81393
+ this.dataX.push(c2d[1]);
81394
+ this.dataY.push(c2d[2]);
81395
+ }
81396
+ };
81397
+ } else if (Type.isArray(el.D3.X)) {
81398
+ // 3D curve given as array of 3D points
81399
+
81400
+ el.updateDataArray = function () {
81401
+ var i,
81402
+ le = this.D3.X.length,
81403
+ c2d;
81404
+
81405
+ this.dataX = [];
81406
+ this.dataY = [];
81407
+
81408
+ for (i = 0; i < le; i++) {
81409
+ c2d = view.project3DTo2D([this.D3.X[i], this.D3.Y[i], this.D3.Z[i]]);
81410
+ this.dataX.push(c2d[1]);
81411
+ this.dataY.push(c2d[2]);
81412
+ }
81413
+ };
81414
+ }
81415
+
81416
+ return el;
81417
+ };
81418
+ JXG.registerElement('curve3d', ThreeD.createCurve);
81419
+
81420
+ });
81421
+ /*
81422
+ Copyright 2008-2022
81423
+ Matthias Ehmann,
81424
+ Carsten Miller,
81425
+ Andreas Walter,
81426
+ Alfred Wassermann
81427
+
81428
+ This file is part of JSXGraph.
81429
+
81430
+ JSXGraph is free software dual licensed under the GNU LGPL or MIT License.
81431
+
81432
+ You can redistribute it and/or modify it under the terms of the
81433
+
81434
+ * GNU Lesser General Public License as published by
81435
+ the Free Software Foundation, either version 3 of the License, or
81436
+ (at your option) any later version
81437
+ OR
81438
+ * MIT License: https://github.com/jsxgraph/jsxgraph/blob/master/LICENSE.MIT
81439
+
81440
+ JSXGraph is distributed in the hope that it will be useful,
81441
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
81442
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
81443
+ GNU Lesser General Public License for more details.
81444
+
81445
+ You should have received a copy of the GNU Lesser General Public License and
81446
+ the MIT License along with JSXGraph. If not, see <http://www.gnu.org/licenses/>
81447
+ and <http://opensource.org/licenses/MIT/>.
81448
+ */
81449
+ /*global JXG:true, define: true*/
81450
+
81451
+ /**
81452
+ * Create linear spaces of dimension at least one,
81453
+ * i.e. lines and planes.
81454
+ */
81455
+ define('3d/linspace3d',['jxg', 'utils/type', 'math/math', 'math/geometry', '3d/view3d'
81456
+ ], function (JXG, Type, Mat, Geometry, ThreeD) {
81457
+ "use strict";
81458
+
81459
+ /**
81460
+ * @class This element is used to provide a constructor for a 3D line.
81461
+ * @pseudo
81462
+ * @description There are two possibilities to create a Line3D object.
81463
+ * <p>
81464
+ * First: the line in 3D is defined by two points in 3D (Point3D).
81465
+ * The points can be either existing points or coordinate arrays of
81466
+ * the form [x, y, z].
81467
+ * <p>Second: the line in 3D is defined by a point (or coordinate array [x, y, z])
81468
+ * a direction given as array [x, y, z] and an optional range
81469
+ * given as array [s, e]. The default value for the range is [-Infinity, Infinity].
81470
+ * <p>
81471
+ * All numbers can also be provided as functions returning a number.
81472
+ *
81473
+ * @name Line3D
81474
+ * @augments JXG.Curve
81475
+ * @constructor
81476
+ * @type JXG.Curve
81477
+ * @throws {Exception} If the element cannot be constructed with the given parent
81478
+ * objects an exception is thrown.
81479
+ * @param {JXG.Point_number,JXG.Point,JXG.Line,JXG.Circle} center,radius The center must be given as a {@link JXG.Point}, see {@link JXG.providePoints}, but the radius can be given
81480
+ * as a number (which will create a circle with a fixed radius), another {@link JXG.Point}, a {@link JXG.Line} (the distance of start and end point of the
81481
+ * line will determine the radius), or another {@link JXG.Circle}.
81482
+ *
81483
+ */
81484
+ ThreeD.createLine = function (board, parents, attributes) {
81485
+ var view = parents[0],
81486
+ attr, D3, point, point1, point2,
81487
+ el;
81488
+
81489
+ // Range
81490
+ D3 = {
81491
+ elType: 'line3d',
81492
+ range: parents[3] || [-Infinity, Infinity]
81493
+ };
81494
+
81495
+ // Point
81496
+ if (Type.isPoint(parents[1])) {
81497
+ point = parents[1];
81498
+ } else {
81499
+ point = view.create('point3d', parents[1], { visible: false, name: '', withLabel: false });
81500
+ }
81501
+ D3.point = point;
81502
+
81503
+ // Direction
81504
+ if (Type.isPoint(parents[2]) && Type.exists(parents[2].D3)) {
81505
+ // Line defined by two points
81506
+
81507
+ point1 = point;
81508
+ point2 = parents[2];
81509
+ D3.direction = function () {
81510
+ return [
81511
+ point2.D3.X() - point.D3.X(),
81512
+ point2.D3.Y() - point.D3.Y(),
81513
+ point2.D3.Z() - point.D3.Z()
81514
+ ];
81515
+ };
81516
+ D3.range = [0, 1];
81517
+ } else {
81518
+ // Line defined by point, direction and range
81519
+
81520
+ // Directions are handled as arrays of length 4,
81521
+ // i.e. with homogeneous coordinates.
81522
+ if (Type.isFunction(parents[2])) {
81523
+ D3.direction = parents[2];
81524
+ } else if (parents[2].length === 3) {
81525
+ D3.direction = [1].concat(parents[2]);
81526
+ } else if (parents[2].length === 4) {
81527
+ D3.direction = parents[2];
81528
+ } else {
81529
+ // Throw error
81530
+ }
81531
+
81532
+ // Direction given as array
81533
+ D3.getPointCoords = function (r) {
81534
+ var p = [],
81535
+ d = [],
81536
+ i;
81537
+
81538
+ p.push(point.D3.X());
81539
+ p.push(point.D3.Y());
81540
+ p.push(point.D3.Z());
81541
+
81542
+ if (Type.isFunction(D3.direction)) {
81543
+ d = D3.direction();
81544
+ } else {
81545
+ for (i = 1; i < 4; i++) {
81546
+ d.push(Type.evaluate(D3.direction[i]));
81547
+ }
81548
+ }
81549
+ if (Math.abs(r) === Infinity) {
81550
+ r = view.intersectionLineCube(p, d, r);
81551
+ }
81552
+ return [
81553
+ p[0] + d[0] * r,
81554
+ p[1] + d[1] * r,
81555
+ p[2] + d[2] * r
81556
+ ];
81557
+
81558
+ };
81559
+
81560
+ attr = Type.copyAttributes(attributes, board.options, 'line3d', 'point1');
81561
+ point1 = view.create('point3d', [
81562
+ function () {
81563
+ return D3.getPointCoords(Type.evaluate(D3.range[0]));
81564
+ }
81565
+ ], attr);
81566
+ attr = Type.copyAttributes(attributes, board.options, 'line3d', 'point2');
81567
+ point2 = view.create('point3d', [
81568
+ function () {
81569
+ return D3.getPointCoords(Type.evaluate(D3.range[1]));
81570
+ }
81571
+ ], attr);
81572
+ }
81573
+
81574
+ attr = Type.copyAttributes(attributes, board.options, 'line3d');
81575
+ el = view.create('segment', [point1, point2], attr);
81576
+ el.point1 = point1;
81577
+ el.point2 = point2;
81578
+ point1.addChild(el);
81579
+ point2.addChild(el);
81580
+ el.D3 = D3;
81581
+
81582
+ return el;
81583
+ };
81584
+ JXG.registerElement('line3d', ThreeD.createLine);
81585
+
81586
+ ThreeD.createPlane = function (board, parents, attributes) {
81587
+ var view = parents[0],
81588
+ attr, D3,
81589
+ point,
81590
+ vec1 = parents[2],
81591
+ vec2 = parents[3],
81592
+ el, grid, update;
81593
+
81594
+ // D3: {
81595
+ // point,
81596
+ // vec1,
81597
+ // vec2,
81598
+ // poin1,
81599
+ // point2,
81600
+ // normal array of len 3
81601
+ // d
81602
+ // }
81603
+ D3 = {
81604
+ elType: 'plane3d',
81605
+ dir1: [],
81606
+ dir2: [],
81607
+ range1: parents[4],
81608
+ range2: parents[5],
81609
+ vec1: vec1,
81610
+ vec2: vec2
81611
+ };
81612
+
81613
+ if (Type.isPoint(parents[1])) {
81614
+ point = parents[1];
81615
+ } else {
81616
+ point = view.create('point3d', parents[1], { visible: false, name: '', withLabel: false });
81617
+ }
81618
+ D3.point = point;
81619
+
81620
+ D3.updateNormal = function () {
81621
+ var i;
81622
+ for (i = 0; i < 3; i++) {
81623
+ D3.dir1[i] = Type.evaluate(D3.vec1[i]);
81624
+ D3.dir2[i] = Type.evaluate(D3.vec2[i]);
81625
+ }
81626
+ D3.normal = Mat.crossProduct(D3.dir1, D3.dir2);
81627
+ D3.d = Mat.innerProduct(D3.point.D3.coords.slice(1), D3.normal, 3);
81628
+ };
81629
+ D3.updateNormal();
81630
+
81631
+ attr = Type.copyAttributes(attributes, board.options, 'plane3d');
81632
+ el = board.create('curve', [[], []], attr);
81633
+ el.D3 = D3;
81634
+
81635
+ el.updateDataArray = function () {
81636
+ var s1, e1, s2, e2,
81637
+ c2d, l1, l2,
81638
+ planes = ['xPlaneRear', 'yPlaneRear', 'zPlaneRear'],
81639
+ points = [],
81640
+ v1 = [0, 0, 0],
81641
+ v2 = [0, 0, 0],
81642
+ q = [0, 0, 0],
81643
+ p = [0, 0, 0], d, i, j, a, b, first, pos, pos_akt;
81644
+
81645
+ this.dataX = [];
81646
+ this.dataY = [];
81647
+
81648
+ this.D3.updateNormal();
81649
+
81650
+ // Infinite plane
81651
+ if (this.D3.elType !== 'axisplane3d' && view.defaultAxes &&
81652
+ (!D3.range1 || !D3.range2)
81653
+ ) {
81654
+
81655
+ // Start with the rear plane.
81656
+ // Determine the intersections with the view bbox3d
81657
+ // For each face of the bbox3d we determine two points
81658
+ // which are the ends of the intersection line.
81659
+ // We start with the three rear planes.
81660
+ for (j = 0; j < planes.length; j++) {
81661
+ p = view.intersectionPlanePlane(this, view.defaultAxes[planes[j]]);
81662
+
81663
+ if (p[0].length === 3 && p[1].length === 3) {
81664
+ // This test is necessary to filter out intersection lines which are
81665
+ // identical to intersections of axis planes (they would occur twice).
81666
+ for (i = 0; i < points.length; i++) {
81667
+ if ((Geometry.distance(p[0], points[i][0], 3) < Mat.eps && Geometry.distance(p[1], points[i][1], 3) < Mat.eps) ||
81668
+ (Geometry.distance(p[0], points[i][1], 3) < Mat.eps && Geometry.distance(p[1], points[i][0], 3) < Mat.eps)) {
81669
+ break;
81670
+ }
81671
+ }
81672
+ if (i === points.length) {
81673
+ points.push(p.slice());
81674
+ }
81675
+ }
81676
+
81677
+ // Point on the front plane of the bbox3d
81678
+ p = [0, 0, 0];
81679
+ p[j] = view.D3.bbox3d[j][1];
81680
+
81681
+ // d is the rhs of the Hesse normal form of the front plane.
81682
+ d = Mat.innerProduct(p, view.defaultAxes[planes[j]].D3.normal, 3);
81683
+ p = view.intersectionPlanePlane(this, view.defaultAxes[planes[j]], d);
81684
+
81685
+ if (p[0].length === 3 && p[1].length === 3) {
81686
+ // Do the same test as above
81687
+ for (i = 0; i < points.length; i++) {
81688
+ if ((Geometry.distance(p[0], points[i][0], 3) < Mat.eps && Geometry.distance(p[1], points[i][1], 3) < Mat.eps) ||
81689
+ (Geometry.distance(p[0], points[i][1], 3) < Mat.eps && Geometry.distance(p[1], points[i][0], 3) < Mat.eps)) {
81690
+ break;
81691
+ }
81692
+ }
81693
+ if (i === points.length) {
81694
+ points.push(p.slice());
81695
+ }
81696
+ }
81697
+ }
81698
+
81699
+ // Concatenate the intersection points to a polygon.
81700
+ // If all wents well, each intersection should appear
81701
+ // twice in the list.
81702
+ first = 0;
81703
+ pos = first;
81704
+ i = 0;
81705
+ do {
81706
+ p = points[pos][i];
81707
+ if (p.length === 3) {
81708
+ c2d = view.project3DTo2D(p);
81709
+ this.dataX.push(c2d[1]);
81710
+ this.dataY.push(c2d[2]);
81711
+ }
81712
+ i = (i + 1) % 2;
81713
+ p = points[pos][i];
81714
+
81715
+ pos_akt = pos;
81716
+ for (j = 0; j < points.length; j++) {
81717
+ if (j !== pos && Geometry.distance(p, points[j][0]) < Mat.eps) {
81718
+ pos = j;
81719
+ i = 0;
81720
+ break;
81721
+ }
81722
+ if (j !== pos && Geometry.distance(p, points[j][1]) < Mat.eps) {
81723
+ pos = j;
81724
+ i = 1;
81725
+ break;
81726
+ }
81727
+ }
81728
+ if (pos === pos_akt) {
81729
+ console.log("Error: update plane3d: did not find next", pos);
81730
+ break;
81731
+ }
81732
+ } while (pos !== first);
81733
+ c2d = view.project3DTo2D(points[first][0]);
81734
+ this.dataX.push(c2d[1]);
81735
+ this.dataY.push(c2d[2]);
81736
+
81737
+ } else {
81738
+ // 3D bounded flat
81739
+ s1 = Type.evaluate(this.D3.range1[0]);
81740
+ e1 = Type.evaluate(this.D3.range1[1]);
81741
+ s2 = Type.evaluate(this.D3.range2[0]);
81742
+ e2 = Type.evaluate(this.D3.range2[1]);
81743
+
81744
+ q = this.D3.point.D3.coords.slice(1);
81745
+
81746
+ v1 = this.D3.dir1.slice();
81747
+ v2 = this.D3.dir2.slice();
81748
+ l1 = Mat.norm(v1, 3);
81749
+ l2 = Mat.norm(v2, 3);
81750
+ for (i = 0; i < 3; i++) {
81751
+ v1[i] /= l1;
81752
+ v2[i] /= l2;
81753
+ }
81754
+
81755
+ for (j = 0; j < 4; j++) {
81756
+ switch (j) {
81757
+ case 0: a = s1; b = s2; break;
81758
+ case 1: a = e1; b = s2; break;
81759
+ case 2: a = e1; b = e2; break;
81760
+ case 3: a = s1; b = e2;
81761
+ }
81762
+ for (i = 0; i < 3; i++) {
81763
+ p[i] = q[i] + a * v1[i] + b * v2[i];
81764
+ }
81765
+ c2d = view.project3DTo2D(p);
81766
+ this.dataX.push(c2d[1]);
81767
+ this.dataY.push(c2d[2]);
81768
+ }
81769
+ // Close the curve
81770
+ this.dataX.push(this.dataX[0]);
81771
+ this.dataY.push(this.dataY[0]);
81772
+ }
81773
+ };
81774
+
81775
+ attr = Type.copyAttributes(attributes.mesh3d, board.options, 'mesh3d');
81776
+
81777
+ if (D3.range1 && D3.range2) {
81778
+ grid = view.create('mesh3d', [point.D3.coords.slice(1), vec1, D3.range1, vec2, D3.range2], attr);
81779
+ el.grid = grid;
81780
+ el.inherits.push(grid);
81781
+ }
81782
+
81783
+ // update = el.update;
81784
+ // el.update = function () {
81785
+ // if (el.needsUpdate) {
81786
+ // update.apply(el);
81787
+ // }
81788
+ // return this;
81789
+ // };
81790
+
81791
+ return el;
81792
+ };
81793
+ JXG.registerElement('plane3d', ThreeD.createPlane);
81794
+
81795
+ });
81796
+ /*
81797
+ Copyright 2008-2022
81798
+ Matthias Ehmann,
81799
+ Carsten Miller,
81800
+ Andreas Walter,
81801
+ Alfred Wassermann
81802
+
81803
+ This file is part of JSXGraph.
81804
+
81805
+ JSXGraph is free software dual licensed under the GNU LGPL or MIT License.
81806
+
81807
+ You can redistribute it and/or modify it under the terms of the
81808
+
81809
+ * GNU Lesser General Public License as published by
81810
+ the Free Software Foundation, either version 3 of the License, or
81811
+ (at your option) any later version
81812
+ OR
81813
+ * MIT License: https://github.com/jsxgraph/jsxgraph/blob/master/LICENSE.MIT
81814
+
81815
+ JSXGraph is distributed in the hope that it will be useful,
81816
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
81817
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
81818
+ GNU Lesser General Public License for more details.
81819
+
81820
+ You should have received a copy of the GNU Lesser General Public License and
81821
+ the MIT License along with JSXGraph. If not, see <http://www.gnu.org/licenses/>
81822
+ and <http://opensource.org/licenses/MIT/>.
81823
+ */
81824
+ /*global JXG:true, define: true*/
81825
+
81826
+ define('3d/point3d',['jxg', 'base/constants', 'math/math', 'math/geometry', 'utils/type', '3d/view3d'
81827
+ ], function (JXG, Const, Mat, Geometry, Type, ThreeD) {
81828
+ "use strict";
81829
+
81830
+ /**
81831
+ * @class This element is used to provide a constructor for a 3D Point.
81832
+ * @pseudo
81833
+ * @description There are two possibilities to create a Line3D object.
81834
+ * <p>
81835
+ * First: the line in 3D is defined by two points in 3D (Point3D).
81836
+ * The points can be either existing points or coordinate arrays of
81837
+ * the form [x, y, z].
81838
+ * <p>Second: the line in 3D is defined by a point (or coordinate array [x, y, z])
81839
+ * a direction given as array [x, y, z] and an optional range
81840
+ * given as array [s, e]. The default value for the range is [-Infinity, Infinity].
81841
+ * <p>
81842
+ * All numbers can also be provided as functions returning a number.
81843
+ *
81844
+ * @name Point3D
81845
+ * @augments JXG.Point
81846
+ * @constructor
81847
+ * @type JXG.Point
81848
+ * @throws {Exception} If the element cannot be constructed with the given parent
81849
+ * objects an exception is thrown.
81850
+ * @param {JXG.Point_number,JXG.Point,JXG.Line,JXG.Circle} center,radius The center must be given as a {@link JXG.Point}, see {@link JXG.providePoints}, but the radius can be given
81851
+ * as a number (which will create a circle with a fixed radius), another {@link JXG.Point}, a {@link JXG.Line} (the distance of start and end point of the
81852
+ * line will determine the radius), or another {@link JXG.Circle}.
81853
+ *
81854
+ */
81855
+ ThreeD.createPoint = function (board, parents, attributes) {
81856
+ var view = parents[0],
81857
+ attr, update2D, D3,
81858
+ i, c2d,
81859
+ el;
81860
+
81861
+ attr = Type.copyAttributes(attributes, board.options, 'point3d');
81862
+
81863
+ D3 = {
81864
+ elType: 'point3d',
81865
+ coords: [1, 0, 0, 0],
81866
+ X: function () { return this.coords[1]; },
81867
+ Y: function () { return this.coords[2]; },
81868
+ Z: function () { return this.coords[3]; }
81869
+ };
81870
+
81871
+ // If the last element of partents is a 3D object, the point is a glider
81872
+ // on that element.
81873
+ if (parents.length > 2 && Type.exists(parents[parents.length - 1].D3)) {
81874
+ D3.slide = parents.pop();
81875
+ } else {
81876
+ D3.slide = null;
81877
+ }
81878
+
81879
+ if (parents.length === 2) {
81880
+ D3.F = parents[1]; // (Array [x, y, z] | function) returning [x, y, z]
81881
+ D3.coords = [1].concat(Type.evaluate(D3.F));
81882
+ } else if (parents.length === 4) {
81883
+ D3.F = parents.slice(1); // 3 numbers | functions
81884
+ for (i = 0; i < 3; i++) {
81885
+ D3.coords[i + 1] = Type.evaluate(D3.F[i]);
81886
+ }
81887
+ } else {
81888
+ // Throw error
81889
+ }
81890
+
81891
+ /**
81892
+ * Update the 4D coords array
81893
+ * @returns Object
81894
+ */
81895
+ D3.updateCoords = function () {
81896
+ var res, i;
81897
+ if (Type.isFunction(this.F)) {
81898
+ res = Type.evaluate(this.F);
81899
+ this.coords = [1, res[0], res[1], res[2]];
81900
+ } else {
81901
+ this.coords[0] = 1;
81902
+ for (i = 0; i < 3; i++) {
81903
+ if (Type.isFunction(this.F[i])) {
81904
+ this.coords[i + 1] = Type.evaluate(this.F[i]);
81905
+ }
81906
+ }
81907
+ }
81908
+ return this;
81909
+ };
81910
+ D3.updateCoords();
81911
+
81912
+ c2d = view.project3DTo2D(D3.coords);
81913
+ el = board.create('point', c2d, attr);
81914
+ el.D3 = D3;
81915
+ el.D3.c2d = el.coords.usrCoords.slice(); // Copy of the coordinates to detect dragging
81916
+ update2D = el.update;
81917
+
81918
+ if (el.D3.slide) {
81919
+ el._minFunc = function (n, m, x, con) {
81920
+ var surface = el.D3.slide.D3,
81921
+ c3d = [1, surface.X(x[0], x[1]), surface.Y(x[0], x[1]), surface.Z(x[0], x[1])],
81922
+ c2d = view.project3DTo2D(c3d);
81923
+
81924
+ con[0] = el.X() - c2d[1];
81925
+ con[1] = el.Y() - c2d[2];
81926
+
81927
+ return con[0] * con[0] + con[1] * con[1];
81928
+ };
81929
+
81930
+ el.projectCoords2Surface = function () {
81931
+ var n = 2, // # of variables
81932
+ m = 2, // number of constraints
81933
+ x = [0, 0],
81934
+ // Various Cobyla constants, see Cobyla docs in Cobyja.js
81935
+ rhobeg = 5.0,
81936
+ rhoend = 1.0e-6,
81937
+ iprint = 0,
81938
+ maxfun = 200,
81939
+ surface = this.D3.slide.D3,
81940
+ r, c3d, c2d;
81941
+
81942
+ if (Type.exists(this.D3.params)) {
81943
+ x = this.D3.params.slice();
81944
+ }
81945
+ r = Mat.Nlp.FindMinimum(this._minFunc, n, m, x, rhobeg, rhoend, iprint, maxfun);
81946
+
81947
+ c3d = [1, surface.X(x[0], x[1]), surface.Y(x[0], x[1]), surface.Z(x[0], x[1])];
81948
+ c2d = view.project3DTo2D(c3d);
81949
+ this.D3.params = x;
81950
+ this.D3.coords = c3d;
81951
+ this.coords.setCoordinates(Const.COORDS_BY_USER, c2d);
81952
+ this.D3.c2d = c2d;
81953
+ };
81954
+ }
81955
+
81956
+ el.update = function (drag) {
81957
+ var c3d, foot;
81958
+ if (!this.needsUpdate) {
81959
+ return this;
81960
+ }
81961
+
81962
+ // Update is called in from two methods:
81963
+ // Once in setToPositionDirectly and
81964
+ // once in the subsequent board.update
81965
+ if (this.draggable() &&
81966
+ Geometry.distance(this.D3.c2d, this.coords.usrCoords) !== 0) {
81967
+
81968
+ if (this.D3.slide) {
81969
+ this.projectCoords2Surface();
81970
+ } else {
81971
+ // Drag the point in its xy plane
81972
+ foot = [1, 0, 0, this.D3.coords[3]];
81973
+ c3d = view.project2DTo3DPlane(el, [1, 0, 0, 1], foot);
81974
+ if (c3d[0] !== 0) {
81975
+ this.D3.coords = view.project3DToCube(c3d);
81976
+ }
81977
+ }
81978
+ } else {
81979
+ this.D3.updateCoords();
81980
+ // Update 2D point from its 3D view
81981
+ el.coords.setCoordinates(Const.COORDS_BY_USER,
81982
+ view.project3DTo2D([1, this.D3.X(), this.D3.Y(), this.D3.Z()])
81983
+ );
81984
+ }
81985
+ this.D3.c2d = el.coords.usrCoords.slice();
81986
+
81987
+ update2D.apply(this, [drag]);
81988
+ return this;
81989
+ };
81990
+
81991
+ return el;
81992
+ };
81993
+ JXG.registerElement('point3d', ThreeD.createPoint);
81994
+
81995
+ });
81996
+ /*
81997
+ Copyright 2008-2022
81998
+ Matthias Ehmann,
81999
+ Carsten Miller,
82000
+ Andreas Walter,
82001
+ Alfred Wassermann
82002
+
82003
+ This file is part of JSXGraph.
82004
+
82005
+ JSXGraph is free software dual licensed under the GNU LGPL or MIT License.
82006
+
82007
+ You can redistribute it and/or modify it under the terms of the
82008
+
82009
+ * GNU Lesser General Public License as published by
82010
+ the Free Software Foundation, either version 3 of the License, or
82011
+ (at your option) any later version
82012
+ OR
82013
+ * MIT License: https://github.com/jsxgraph/jsxgraph/blob/master/LICENSE.MIT
82014
+
82015
+ JSXGraph is distributed in the hope that it will be useful,
82016
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
82017
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
82018
+ GNU Lesser General Public License for more details.
82019
+
82020
+ You should have received a copy of the GNU Lesser General Public License and
82021
+ the MIT License along with JSXGraph. If not, see <http://www.gnu.org/licenses/>
82022
+ and <http://opensource.org/licenses/MIT/>.
82023
+ */
82024
+ /*global JXG:true, define: true*/
82025
+
82026
+ define('3d/surface3d',['jxg', 'utils/type', '3d/view3d'
82027
+ ], function (JXG, Type, ThreeD) {
82028
+ "use strict";
82029
+
82030
+
82031
+ /**
82032
+ * @class This element creates a 3D parametric surface.
82033
+ * @pseudo
82034
+ * @description A 3D parametric surface is defined by a function
82035
+ * <i>F: R<sup>2</sup> &rarr; R<sup>3</sup></i>.
82036
+ *
82037
+ * @name ParametricSurface3D
82038
+ * @augments Curve
82039
+ * @constructor
82040
+ * @type Object
82041
+ * @throws {Exception} If the element cannot be constructed with the given parent objects an exception is thrown.
82042
+ * @param {Function_Function_Function_Array_Array} F<sub>X</sub>,F<sub>Y</sub>,F<sub>Z</sub>,rangeX,rangeY
82043
+ * F<sub>X</sub>(u,v), F<sub>Y</sub>(u,v), F<sub>Z</sub>(u,v) are functions returning a number, rangeU is the array containing
82044
+ * lower and upper bound for the range of parameter u, rangeV is the array containing
82045
+ * lower and upper bound for the range of parameter v. rangeU and rangeV may also be functions returning an array of length two.
82046
+ * @example
82047
+ * var view = board.create('view3d',
82048
+ * [[-6, -3], [8, 8],
82049
+ * [[-5, 5], [-5, 5], [-5, 5]]]);
82050
+ *
82051
+ * // Sphere
82052
+ * var c = view.create('parametricsurface3d', [
82053
+ * (u, v) => 2 * Math.sin(u) * Math.cos(v),
82054
+ * (u, v) => 2 * Math.sin(u) * Math.sin(v),
82055
+ * (u, v) => 2 * Math.cos(u),
82056
+ * [0, 2 * Math.PI],
82057
+ * [0, Math.PI]
82058
+ * ], {
82059
+ * strokeColor: '#ff0000',
82060
+ * stepsU: 30,
82061
+ * stepsV: 30
82062
+ * });
82063
+ *
82064
+ * </pre><div id="JXG52da0ecc-1ba9-4d41-850c-36e5120025a5" class="jxgbox" style="width: 500px; height: 500px;"></div>
82065
+ * <script type="text/javascript">
82066
+ * (function() {
82067
+ * var board = JXG.JSXGraph.initBoard('JXG52da0ecc-1ba9-4d41-850c-36e5120025a5',
82068
+ * {boundingbox: [-8, 8, 8,-8], axis: false, showcopyright: false, shownavigation: false});
82069
+ * var view = board.create('view3d',
82070
+ * [[-6, -3], [8, 8],
82071
+ * [[-5, 5], [-5, 5], [-5, 5]]]);
82072
+ *
82073
+ * // Sphere
82074
+ * var c = view.create('parametricsurface3d', [
82075
+ * (u, v) => 2 * Math.sin(u) * Math.cos(v),
82076
+ * (u, v) => 2 * Math.sin(u) * Math.sin(v),
82077
+ * (u, v) => 2 * Math.cos(u),
82078
+ * [0, 2 * Math.PI],
82079
+ * [0, Math.PI]
82080
+ * ], {
82081
+ * strokeColor: '#ff0000',
82082
+ * stepsU: 20,
82083
+ * stepsV: 20
82084
+ * });
82085
+ *
82086
+ * })();
82087
+ *
82088
+ * </script><pre>
82089
+ *
82090
+ */
82091
+ ThreeD.createParametricSurface = function (board, parents, attributes) {
82092
+ var view = parents[0],
82093
+ attr,
82094
+ X = parents[1],
82095
+ Y = parents[2],
82096
+ Z = parents[3],
82097
+ range_u = parents[4],
82098
+ range_v = parents[5],
82099
+ D3, el;
82100
+
82101
+ D3 = {
82102
+ elType: 'surface3d',
82103
+ X: X,
82104
+ Y: Y,
82105
+ Z: Z,
82106
+ range_u: range_u,
82107
+ range_v: range_v
82108
+ };
82109
+ attr = Type.copyAttributes(attributes, board.options, 'surface3d');
82110
+ el = board.create('curve', [[], []], attr);
82111
+ el.updateDataArray = function () {
82112
+ var steps_u = Type.evaluate(this.visProp.stepsu),
82113
+ steps_v = Type.evaluate(this.visProp.stepsv),
82114
+ r_u = Type.evaluate(this.D3.range_u), // Type.evaluate(range_u),
82115
+ r_v = Type.evaluate(this.D3.range_v), // Type.evaluate(range_v),
82116
+ res = view.getMesh(this.D3.X, this.D3.Y, this.D3.Z,
82117
+ r_u.concat([steps_u]),
82118
+ r_v.concat([steps_v]));
82119
+ this.dataX = res[0];
82120
+ this.dataY = res[1];
82121
+ };
82122
+ el.D3 = D3;
82123
+
82124
+ return el;
82125
+ };
82126
+ JXG.registerElement('parametricsurface3d', ThreeD.createParametricSurface);
82127
+
82128
+ /**
82129
+ * @class This element creates a 3D function graph.
82130
+ * @pseudo
82131
+ * @description A 3D function graph is defined by a function
82132
+ * <i>F: R<sup>2</sup> &rarr; R</i>.
82133
+ *
82134
+ * @name Functiongraph3D
82135
+ * @augments ParametricSurface3D
82136
+ * @constructor
82137
+ * @type Object
82138
+ * @throws {Exception} If the element cannot be constructed with the given parent objects an exception is thrown.
82139
+ * @param {Function_Array_Array} F,rangeX,rangeY F(x,y) is a function returning a number, rangeX is the array containing
82140
+ * lower and upper bound for the range of x, rangeY is the array containing
82141
+ * lower and upper bound for the range of y.
82142
+ * @example
82143
+ * var box = [-5, 5];
82144
+ * var view = board.create('view3d',
82145
+ * [
82146
+ * [-6, -3], [8, 8],
82147
+ * [box, box, box]
82148
+ * ],
82149
+ * {
82150
+ * xPlaneRear: {visible: false},
82151
+ * yPlaneRear: {visible: false},
82152
+ * });
82153
+ *
82154
+ * // Function F to be plotted
82155
+ * var F = (x, y) => Math.sin(x * y / 4);
82156
+ *
82157
+ * // 3D surface
82158
+ * var c = view.create('functiongraph3d', [
82159
+ * F,
82160
+ * box, // () => [-s.Value()*5, s.Value() * 5],
82161
+ * box, // () => [-s.Value()*5, s.Value() * 5],
82162
+ * ], {
82163
+ * strokeWidth: 0.5,
82164
+ * stepsU: 70,
82165
+ * stepsV: 70
82166
+ * });
82167
+ *
82168
+ * </pre><div id="JXG87646dd4-9fe5-4c21-8734-089abc612515" class="jxgbox" style="width: 500px; height: 500px;"></div>
82169
+ * <script type="text/javascript">
82170
+ * (function() {
82171
+ * var board = JXG.JSXGraph.initBoard('JXG87646dd4-9fe5-4c21-8734-089abc612515',
82172
+ * {boundingbox: [-8, 8, 8,-8], axis: false, showcopyright: false, shownavigation: false});
82173
+ * var box = [-5, 5];
82174
+ * var view = board.create('view3d',
82175
+ * [
82176
+ * [-6, -3], [8, 8],
82177
+ * [box, box, box]
82178
+ * ],
82179
+ * {
82180
+ * xPlaneRear: {visible: false},
82181
+ * yPlaneRear: {visible: false},
82182
+ * });
82183
+ *
82184
+ * // Function F to be plotted
82185
+ * var F = (x, y) => Math.sin(x * y / 4);
82186
+ *
82187
+ * // 3D surface
82188
+ * var c = view.create('functiongraph3d', [
82189
+ * F,
82190
+ * box, // () => [-s.Value()*5, s.Value() * 5],
82191
+ * box, // () => [-s.Value()*5, s.Value() * 5],
82192
+ * ], {
82193
+ * strokeWidth: 0.5,
82194
+ * stepsU: 70,
82195
+ * stepsV: 70
82196
+ * });
82197
+ *
82198
+ * })();
82199
+ *
82200
+ * </script><pre>
82201
+ *
82202
+ */
82203
+ ThreeD.createFunctiongraph = function (board, parents, attributes) {
82204
+ var view = parents[0],
82205
+ X = function(u, v) { return u; },
82206
+ Y = function(u, v) { return v; },
82207
+ Z = parents[1],
82208
+ range_u = parents[2],
82209
+ range_v = parents[3];
82210
+
82211
+ return view.create('parametricsurface3d', [X, Y, Z, range_u, range_v], attributes);
82212
+ };
82213
+ JXG.registerElement('functiongraph3d', ThreeD.createFunctiongraph);
82214
+
82215
+ });
82216
+
79759
82217
  /*global define: true*/
79760
82218
  define('../build/core.deps.js',[
79761
82219
  'jxg',
@@ -79828,7 +82286,15 @@ define('../build/core.deps.js',[
79828
82286
  'element/checkbox',
79829
82287
  'element/input',
79830
82288
  'element/button',
79831
- 'base/foreignobject'
82289
+ 'base/foreignobject',
82290
+ 'options3d',
82291
+ '3d/box3d',
82292
+ '3d/curve3d',
82293
+ '3d/linspace3d',
82294
+ '3d/point3d',
82295
+ '3d/surface3d',
82296
+ '3d/threed',
82297
+ '3d/view3d'
79832
82298
  ], function (JXG, Env) {
79833
82299
  "use strict";
79834
82300