jsxgraph 1.4.3 → 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.
@@ -842,7 +842,7 @@ define('base/constants',['jxg'], function (JXG) {
842
842
 
843
843
  var major = 1,
844
844
  minor = 4,
845
- patch = 3,
845
+ patch = 4,
846
846
  add = '', //'dev'
847
847
  version = major + '.' + minor + '.' + patch + (add ? '-' + add : ''),
848
848
  constants;
@@ -14737,6 +14737,30 @@ define('math/geometry',[
14737
14737
  return that.meetCurveLine(el1, el2, i, el1.board, alwaysintersect);
14738
14738
  };
14739
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
+
14740
14764
  } else if (el1.elementClass === Const.OBJECT_CLASS_LINE && el2.elementClass === Const.OBJECT_CLASS_LINE) {
14741
14765
  // line - line, lines may also be segments.
14742
14766
  /** @ignore */
@@ -15152,6 +15176,8 @@ define('math/geometry',[
15152
15176
  * @param {JXG.Line} li Line
15153
15177
  * @param {Number} nr Will return the nr-th intersection point.
15154
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
15155
15181
  * @returns {JXG.Coords} Coords object containing the intersection.
15156
15182
  */
15157
15183
  meetCurveLineContinuous: function (cu, li, nr, board, testSegment) {
@@ -15216,7 +15242,6 @@ define('math/geometry',[
15216
15242
  return (new Coords(Const.COORDS_BY_USER, [z, cu.X(t), cu.Y(t)], board));
15217
15243
  },
15218
15244
 
15219
-
15220
15245
  /**
15221
15246
  * Intersection of line and curve, discrete case.
15222
15247
  * Segments are treated as lines.
@@ -15403,6 +15428,87 @@ define('math/geometry',[
15403
15428
  return [c, t, u];
15404
15429
  },
15405
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
+
15406
15512
  /****************************************/
15407
15513
  /**** BEZIER CURVE ALGORITHMS ****/
15408
15514
  /****************************************/
@@ -23228,7 +23334,6 @@ define('math/clip',[
23228
23334
 
23229
23335
  // Collect all points into clip array C
23230
23336
  C = this._getPath(clip, board);
23231
-
23232
23337
  len = C.length;
23233
23338
  if (len > 0 && Geometry.distance(C[0].coords.usrCoords, C[len - 1].coords.usrCoords, 3) < Mat.eps * Mat.eps) {
23234
23339
  C.pop();
@@ -44255,8 +44360,12 @@ define('base/board',[
44255
44360
  */
44256
44361
  getCoordsTopLeftCorner: function () {
44257
44362
  var cPos, doc, crect,
44258
- docElement = this.document.documentElement || this.document.body.parentNode,
44259
- 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,
44260
44369
  container = this.containerObj,
44261
44370
  // viewport, content,
44262
44371
  zoom, o;
@@ -46779,7 +46888,7 @@ define('base/board',[
46779
46888
  }
46780
46889
 
46781
46890
  // If div is invisible - do nothing
46782
- if (w <= 0 || h <= 0) {
46891
+ if (w <= 0 || h <= 0 || Type.isNaN(w) || Type.isNaN(h)) {
46783
46892
  return;
46784
46893
  }
46785
46894
 
@@ -48185,12 +48294,12 @@ define('base/board',[
48185
48294
  this.inUpdate = true;
48186
48295
 
48187
48296
  if (this.attr.minimizereflow === 'all' && this.containerObj && this.renderer.type !== 'vml') {
48188
- storeActiveEl = document.activeElement; // Store focus element
48297
+ storeActiveEl = this.document.activeElement; // Store focus element
48189
48298
  insert = this.renderer.removeToInsertLater(this.containerObj);
48190
48299
  }
48191
48300
 
48192
48301
  if (this.attr.minimizereflow === 'svg' && this.renderer.type === 'svg') {
48193
- storeActiveEl = document.activeElement;
48302
+ storeActiveEl = this.document.activeElement;
48194
48303
  insert = this.renderer.removeToInsertLater(this.renderer.svgRoot);
48195
48304
  }
48196
48305
 
@@ -48813,7 +48922,7 @@ define('base/board',[
48813
48922
  o2 = o2.parentNode;
48814
48923
  while (o2 !== o) {
48815
48924
  this.cssTransMat = Mat.matMatMult(Env.getCSSTransformMatrix(o), this.cssTransMat);
48816
- o2 = o2.parentNode;
48925
+ o2 = o2.parentNode || o2.host;
48817
48926
  }
48818
48927
 
48819
48928
  o = o.offsetParent;
@@ -49383,7 +49492,7 @@ define('base/board',[
49383
49492
 
49384
49493
  id = id || this.container;
49385
49494
  this._fullscreen_inner_id = id;
49386
- inner_node = document.getElementById(id);
49495
+ inner_node = this.document.getElementById(id);
49387
49496
  wrap_id = 'fullscreenwrap_' + id;
49388
49497
 
49389
49498
  // Wrap a div around the JSXGraph div.
@@ -49429,16 +49538,16 @@ define('base/board',[
49429
49538
  return;
49430
49539
  }
49431
49540
 
49432
- document.fullscreenElement = document.fullscreenElement ||
49433
- document.webkitFullscreenElement ||
49434
- document.mozFullscreenElement ||
49435
- document.msFullscreenElement;
49541
+ this.document.fullscreenElement = this.document.fullscreenElement ||
49542
+ this.document.webkitFullscreenElement ||
49543
+ this.document.mozFullscreenElement ||
49544
+ this.document.msFullscreenElement;
49436
49545
 
49437
- inner_node = document.getElementById(inner_id);
49546
+ inner_node = this.document.getElementById(inner_id);
49438
49547
  // If full screen mode is started we have to remove CSS margin around the JSXGraph div.
49439
49548
  // Otherwise, the positioning of the fullscreen div will be false.
49440
49549
  // When leaving the fullscreen mode, the margin is put back in.
49441
- if (document.fullscreenElement) {
49550
+ if (this.document.fullscreenElement) {
49442
49551
  // Just entered fullscreen mode
49443
49552
 
49444
49553
  // Get the data computed in board.toFullscreen()
@@ -49450,7 +49559,7 @@ define('base/board',[
49450
49559
  // Further, the CSS margin has to be removed when in fullscreen mode,
49451
49560
  // and must be restored later.
49452
49561
  inner_node._cssFullscreenStore = {
49453
- id: document.fullscreenElement.id,
49562
+ id: this.document.fullscreenElement.id,
49454
49563
  isFullscreen: true,
49455
49564
  margin: inner_node.style.margin,
49456
49565
  width: inner_node.style.width,
@@ -49466,16 +49575,16 @@ define('base/board',[
49466
49575
  // of the JSXGraph div.
49467
49576
  Env.scaleJSXGraphDiv(document.fullscreenElement.id, inner_id, res.scale, res.vshift);
49468
49577
 
49469
- // Clear document.fullscreenElement, because Safari doesn't to it and
49578
+ // Clear this.document.fullscreenElement, because Safari doesn't to it and
49470
49579
  // when leaving full screen mode it is still set.
49471
- document.fullscreenElement = null;
49580
+ this.document.fullscreenElement = null;
49472
49581
 
49473
49582
  } else if (Type.exists(inner_node._cssFullscreenStore)) {
49474
49583
  // Just left the fullscreen mode
49475
49584
 
49476
49585
  // Remove the CSS rules added in Env.scaleJSXGraphDiv
49477
49586
  try {
49478
- document.styleSheets[document.styleSheets.length - 1].deleteRule(0);
49587
+ this.document.styleSheets[this.document.styleSheets.length - 1].deleteRule(0);
49479
49588
  } catch (err) {
49480
49589
  console.log('JSXGraph: Could not remove CSS rules for full screen mode');
49481
49590
  }
@@ -49483,7 +49592,6 @@ define('base/board',[
49483
49592
  inner_node._cssFullscreenStore.isFullscreen = false;
49484
49593
  inner_node.style.margin = inner_node._cssFullscreenStore.margin;
49485
49594
  inner_node.style.width = inner_node._cssFullscreenStore.width;
49486
-
49487
49595
  }
49488
49596
 
49489
49597
  this.updateCSSTransforms();
@@ -51393,10 +51501,11 @@ define('renderer/svg',[
51393
51501
  * setTimeout(function() { console.log('done'); }, 400);
51394
51502
  */
51395
51503
  dumpToCanvas: function (canvasId, w, h, ignoreTexts) {
51396
- var svg, tmpImg, cv, ctx;
51504
+ var svg, tmpImg, cv, ctx,
51505
+ doc = this.container.ownerDocument;
51397
51506
 
51398
51507
  // Prepare the canvas element
51399
- cv = document.getElementById(canvasId);
51508
+ cv = doc.getElementById(canvasId);
51400
51509
 
51401
51510
  // Clear the canvas
51402
51511
  /* eslint-disable no-self-assign */
@@ -51532,7 +51641,8 @@ define('renderer/svg',[
51532
51641
  } else {
51533
51642
  // Debug: use canvas element 'jxgbox_canvas' from jsxdev/dump.html
51534
51643
  id = 'jxgbox_canvas';
51535
- canvas = document.getElementById(id);
51644
+ // canvas = document.getElementById(id);
51645
+ canvas = doc.getElementById(id);
51536
51646
  }
51537
51647
 
51538
51648
  if (newImg) {
@@ -51552,7 +51662,8 @@ define('renderer/svg',[
51552
51662
  }
51553
51663
 
51554
51664
  // Hide navigation bar in board
51555
- zbar = document.getElementById(this.container.id + '_navigationbar');
51665
+ // zbar = document.getElementById(this.container.id + '_navigationbar');
51666
+ zbar = doc.getElementById(this.container.id + '_navigationbar');
51556
51667
  if (Type.exists(zbar)) {
51557
51668
  zbarDisplay = zbar.style.display;
51558
51669
  zbar.style.display = 'none';
@@ -55088,6 +55199,7 @@ define('jsxgraph',[
55088
55199
  */
55089
55200
  _setARIA: function(container, attr) {
55090
55201
  var doc = attr.document || document,
55202
+ doc_glob,
55091
55203
  node_jsx, newNode, parent,
55092
55204
  id_label, id_description;
55093
55205
 
@@ -55096,18 +55208,19 @@ define('jsxgraph',[
55096
55208
  }
55097
55209
 
55098
55210
  node_jsx = doc.getElementById(container);
55211
+ doc_glob = node_jsx.ownerDocument; // This is the window.document element, needed below.
55099
55212
  parent = node_jsx.parentNode;
55100
55213
 
55101
55214
  id_label = container + '_ARIAlabel';
55102
55215
  id_description = container + '_ARIAdescription';
55103
55216
 
55104
- newNode = doc.createElement('div');
55217
+ newNode = doc_glob.createElement('div');
55105
55218
  newNode.innerHTML = attr.title;
55106
55219
  newNode.setAttribute('id', id_label);
55107
55220
  newNode.style.display = 'none';
55108
55221
  parent.insertBefore(newNode, node_jsx);
55109
55222
 
55110
- newNode = doc.createElement('div');
55223
+ newNode = doc_glob.createElement('div');
55111
55224
  newNode.innerHTML = attr.description;
55112
55225
  newNode.setAttribute('id', id_description);
55113
55226
  newNode.style.display = 'none';
@@ -55133,12 +55246,12 @@ define('jsxgraph',[
55133
55246
  }
55134
55247
 
55135
55248
  id = board.containerObj.getAttribute('aria-labelledby');
55136
- node = document.getElementById(id);
55249
+ node = doc.getElementById(id);
55137
55250
  if (node && node.parentNode) {
55138
55251
  node.parentNode.removeChild(node);
55139
55252
  }
55140
55253
  id = board.containerObj.getAttribute('aria-describedby');
55141
- node = document.getElementById(id);
55254
+ node = doc.getElementById(id);
55142
55255
  if (node && node.parentNode) {
55143
55256
  node.parentNode.removeChild(node);
55144
55257
  }
@@ -68837,9 +68950,6 @@ define('element/composition',[
68837
68950
  b.addChild(t);
68838
68951
  }
68839
68952
 
68840
-
68841
-
68842
-
68843
68953
  t.elType = 'midpoint';
68844
68954
  t.setParents([a.id, b.id]);
68845
68955
 
@@ -69049,14 +69159,21 @@ define('element/composition',[
69049
69159
  };
69050
69160
 
69051
69161
  /**
69052
- * @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.
69053
69169
  * @pseudo
69054
69170
  * @name Parallel
69055
69171
  * @augments Line
69056
69172
  * @constructor
69057
69173
  * @type JXG.Line
69058
69174
  * @throws {Error} If the element cannot be constructed with the given parent objects an exception is thrown.
69059
- * @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.
69060
69177
  * @example
69061
69178
  * // Create a parallel
69062
69179
  * var p1 = board.create('point', [0.0, 2.0]);
@@ -69074,22 +69191,47 @@ define('element/composition',[
69074
69191
  * var plex1_p3 = plex1_board.create('point', [3.0, 3.0]);
69075
69192
  * var plex1_pl1 = plex1_board.create('parallel', [plex1_l1, plex1_p3]);
69076
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
+ *
69077
69222
  */
69078
69223
  JXG.createParallel = function (board, parents, attributes) {
69079
- var p, pp, pl, li, i, attr;
69224
+ var p, pp, pl, li, i, attr, ty = 1;
69080
69225
 
69081
69226
  for (i = 0; i < parents.length; ++i) {
69082
69227
  parents[i] = board.select(parents[i]);
69083
69228
  }
69084
69229
  p = null;
69085
69230
  if (parents.length === 3) {
69231
+ // Line / segment through point parents[2] which is parallel to line through parents[0] and parents[1]
69086
69232
  parents = Type.providePoints(board, parents, attributes, 'point');
69087
- // line through point parents[2] which is parallel to line through parents[0] and parents[1]
69088
69233
  p = parents[2];
69089
- /** @ignore */
69090
- li = function () {
69091
- return Mat.crossProduct(parents[0].coords.usrCoords, parents[1].coords.usrCoords);
69092
- };
69234
+ ty = 0;
69093
69235
  } else if (Type.isPointType(board, parents[0])) {
69094
69236
  // Parallel to line parents[1] through point parents[0]
69095
69237
  p = Type.providePoints(board, [parents[0]], attributes, 'point')[0];
@@ -69111,11 +69253,19 @@ define('element/composition',[
69111
69253
  }
69112
69254
 
69113
69255
  attr = Type.copyAttributes(attributes, board.options, 'parallel', 'point');
69114
- pp = board.create('point', [
69115
- function () {
69116
- return Mat.crossProduct([1, 0, 0], li());
69117
- }
69118
- ], 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
+ }
69119
69269
  pp.isDraggable = true;
69120
69270
 
69121
69271
  attr = Type.copyAttributes(attributes, board.options, 'parallel');
@@ -69149,31 +69299,33 @@ define('element/composition',[
69149
69299
  };
69150
69300
 
69151
69301
  /**
69152
- * @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>
69153
69305
  * @pseudo
69154
69306
  * @constructor
69155
69307
  * @name Arrowparallel
69156
69308
  * @type Parallel
69157
69309
  * @augments Parallel
69158
69310
  * @throws {Error} If the element cannot be constructed with the given parent objects an exception is thrown.
69159
- * @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.
69160
69312
  * @example
69161
69313
  * // Create a parallel
69162
69314
  * var p1 = board.create('point', [0.0, 2.0]);
69163
69315
  * var p2 = board.create('point', [2.0, 1.0]);
69164
- * var l1 = board.create('line', [p1, p2]);
69316
+ * var l1 = board.create('segment', [p1, p2]);
69165
69317
  *
69166
69318
  * var p3 = board.create('point', [3.0, 3.0]);
69167
- * var pl1 = board.create('arrowparallel', [l1, p3]);
69319
+ * var pl1 = board.create('arrowparallel', [p1, p2, p3]);
69168
69320
  * </pre><div class="jxgbox" id="JXGeeacdf99-036f-4e83-aeb6-f7388423e369" style="width: 400px; height: 400px;"></div>
69169
69321
  * <script type="text/javascript">
69170
69322
  * (function () {
69171
69323
  * var plex1_board = JXG.JSXGraph.initBoard('JXGeeacdf99-036f-4e83-aeb6-f7388423e369', {boundingbox: [-1, 9, 9, -1], axis: true, showcopyright: false, shownavigation: false});
69172
69324
  * var plex1_p1 = plex1_board.create('point', [0.0, 2.0]);
69173
69325
  * var plex1_p2 = plex1_board.create('point', [2.0, 1.0]);
69174
- * var plex1_l1 = plex1_board.create('line', [plex1_p1, plex1_p2]);
69326
+ * var plex1_l1 = plex1_board.create('segment', [plex1_p1, plex1_p2]);
69175
69327
  * var plex1_p3 = plex1_board.create('point', [3.0, 3.0]);
69176
- * 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]);
69177
69329
  * })();
69178
69330
  * </script><pre>
69179
69331
  */
@@ -80066,6 +80218,272 @@ define('element/button',[
80066
80218
  };
80067
80219
  });
80068
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
+
80069
80487
  /*
80070
80488
  Copyright 2008-2022
80071
80489
  Matthias Ehmann,
@@ -80470,11 +80888,81 @@ define('3d/view3d',['jxg', 'options', 'base/constants', 'utils/type', 'math/math
80470
80888
  });
80471
80889
 
80472
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>
80473
80965
  *
80474
- * @param {*} board
80475
- * @param {*} parents
80476
- * @param {*} attributes
80477
- * @returns
80478
80966
  */
80479
80967
  ThreeD.createView3D = function (board, parents, attributes) {
80480
80968
  var view, frame, attr,
@@ -80615,7 +81103,8 @@ define('3d/box3d',['jxg', 'utils/type', 'math/math', 'math/geometry', '3d/view3d
80615
81103
  rear = [0, 0, 0], // x, y, z
80616
81104
  front = [0, 0, 0], // x, y, z
80617
81105
  from, to,
80618
- vec1, vec2, range1, range2, na,
81106
+ vec1, vec2, range1, range2,
81107
+ na, na_parent,
80619
81108
  ticks_attr,
80620
81109
  axes = {};
80621
81110
 
@@ -80631,9 +81120,8 @@ define('3d/box3d',['jxg', 'utils/type', 'math/math', 'math/geometry', '3d/view3d
80631
81120
  }
80632
81121
  }
80633
81122
 
80634
- // Axes
81123
+ // Main 3D axes
80635
81124
  attr = Type.copyAttributes(attributes, board.options, 'axes3d');
80636
-
80637
81125
  pos = attr.axesposition;
80638
81126
  for (i = 0; i < directions.length; i++) {
80639
81127
  // Run through ['x', 'y', 'z']
@@ -80682,7 +81170,7 @@ define('3d/box3d',['jxg', 'utils/type', 'math/math', 'math/geometry', '3d/view3d
80682
81170
  name: '', visible: false, withLabel: false
80683
81171
  });
80684
81172
 
80685
- // Planes
81173
+ // Front and rear planes
80686
81174
  for (i = 0; i < directions.length; i++) {
80687
81175
  // Run through ['x', 'y', 'z']
80688
81176
  i1 = (i + 1) % 3;
@@ -80702,13 +81190,14 @@ define('3d/box3d',['jxg', 'utils/type', 'math/math', 'math/geometry', '3d/view3d
80702
81190
  range2 = [rear[i2], front[i2]];
80703
81191
  na = dir + 'Plane' + sides[j];
80704
81192
 
81193
+ attr = Type.copyAttributes(attributes, board.options, 'axes3d', na);
80705
81194
  axes[na] =
80706
- view.create('plane3d', [from, vec1, vec2, range1, range2], attr[na.toLowerCase()]);
81195
+ view.create('plane3d', [from, vec1, vec2, range1, range2], attr);
80707
81196
  axes[na].D3.elType = 'axisplane3d';
80708
81197
  }
80709
81198
  }
80710
81199
 
80711
- // Axes on planes
81200
+ // Axes on front and rear planes
80712
81201
  for (i = 0; i < directions.length; i++) {
80713
81202
  // Run through ['x', 'y', 'z']
80714
81203
  dir = directions[i];
@@ -80717,6 +81206,7 @@ define('3d/box3d',['jxg', 'utils/type', 'math/math', 'math/geometry', '3d/view3d
80717
81206
  i1 = (i + k) % 3;
80718
81207
  dir1 = directions[i1];
80719
81208
  na = dir + 'Plane' + sides[j] + dir1.toUpperCase() + 'Axis';
81209
+ na_parent = dir + 'Plane' + sides[j];
80720
81210
 
80721
81211
  from = [0, 0, 0];
80722
81212
  to = [0, 0, 0];
@@ -80725,11 +81215,13 @@ define('3d/box3d',['jxg', 'utils/type', 'math/math', 'math/geometry', '3d/view3d
80725
81215
  from[i1] = rear[i1];
80726
81216
  to[i1] = front[i1];
80727
81217
 
80728
- axes[na] = view.create('axis3d', [from, to], attr[na.toLowerCase()]);
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]);
80729
81222
  }
80730
81223
  }
80731
81224
  }
80732
- // axes.Y2Dxy = view.create('axis3d', [[0, sy, sz], [0, ey, sz]], attr);
80733
81225
 
80734
81226
  return axes;
80735
81227
  };
@@ -81534,6 +82026,68 @@ define('3d/point3d',['jxg', 'base/constants', 'math/math', 'math/geometry', 'uti
81534
82026
  define('3d/surface3d',['jxg', 'utils/type', '3d/view3d'
81535
82027
  ], function (JXG, Type, ThreeD) {
81536
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
+ */
81537
82091
  ThreeD.createParametricSurface = function (board, parents, attributes) {
81538
82092
  var view = parents[0],
81539
82093
  attr,
@@ -81557,9 +82111,11 @@ define('3d/surface3d',['jxg', 'utils/type', '3d/view3d'
81557
82111
  el.updateDataArray = function () {
81558
82112
  var steps_u = Type.evaluate(this.visProp.stepsu),
81559
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),
81560
82116
  res = view.getMesh(this.D3.X, this.D3.Y, this.D3.Z,
81561
- this.D3.range_u.concat([steps_u]),
81562
- this.D3.range_v.concat([steps_v]));
82117
+ r_u.concat([steps_u]),
82118
+ r_v.concat([steps_v]));
81563
82119
  this.dataX = res[0];
81564
82120
  this.dataY = res[1];
81565
82121
  };
@@ -81569,6 +82125,81 @@ define('3d/surface3d',['jxg', 'utils/type', '3d/view3d'
81569
82125
  };
81570
82126
  JXG.registerElement('parametricsurface3d', ThreeD.createParametricSurface);
81571
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
+ */
81572
82203
  ThreeD.createFunctiongraph = function (board, parents, attributes) {
81573
82204
  var view = parents[0],
81574
82205
  X = function(u, v) { return u; },
@@ -81582,6 +82213,7 @@ define('3d/surface3d',['jxg', 'utils/type', '3d/view3d'
81582
82213
  JXG.registerElement('functiongraph3d', ThreeD.createFunctiongraph);
81583
82214
 
81584
82215
  });
82216
+
81585
82217
  /*global define: true*/
81586
82218
  define('../build/core.deps.js',[
81587
82219
  'jxg',
@@ -81655,6 +82287,7 @@ define('../build/core.deps.js',[
81655
82287
  'element/input',
81656
82288
  'element/button',
81657
82289
  'base/foreignobject',
82290
+ 'options3d',
81658
82291
  '3d/box3d',
81659
82292
  '3d/curve3d',
81660
82293
  '3d/linspace3d',