jsxgraph 1.4.2 → 1.4.3

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 = 2,
845
+ patch = 3,
846
846
  add = '', //'dev'
847
847
  version = major + '.' + minor + '.' + patch + (add ? '-' + add : ''),
848
848
  constants;
@@ -2026,7 +2026,7 @@ define('utils/type',[
2026
2026
  }
2027
2027
 
2028
2028
  // options from attributes
2029
- o = attributes;
2029
+ o = (typeof attributes === 'object') ? attributes : {};
2030
2030
  isAvail = true;
2031
2031
  for (i = 3; i < len; i++) {
2032
2032
  if (this.exists(o[arguments[i]])) {
@@ -2332,7 +2332,7 @@ define('utils/type',[
2332
2332
  return html_sanitize(str, function () { return undefined; }, function (id) { return id; });
2333
2333
  }
2334
2334
 
2335
- if (str) {
2335
+ if (str && typeof str === 'string') {
2336
2336
  str = str.replace(/</g, '&lt;').replace(/>/g, '&gt;');
2337
2337
  }
2338
2338
 
@@ -3999,6 +3999,15 @@ define('math/math',['jxg', 'utils/type'], function (JXG, Type) {
3999
3999
  return Math.sqrt(sum);
4000
4000
  },
4001
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
+
4002
4011
  /**
4003
4012
  * Compute the factorial of a positive integer. If a non-integer value
4004
4013
  * is given, the fraction will be ignored.
@@ -16334,7 +16343,86 @@ define('math/geometry',[
16334
16343
  };
16335
16344
 
16336
16345
  return [makeFct('X', 'cos'), makeFct('Y', 'sin'), 0, pi2];
16337
- }
16346
+ },
16347
+
16348
+
16349
+ meet3Planes: function (n1, d1, n2, d2, n3, d3) {
16350
+ var p = [0, 0, 0],
16351
+ n31, n12, n23, denom,
16352
+ i;
16353
+
16354
+ n31 = Mat.crossProduct(n3, n1);
16355
+ n12 = Mat.crossProduct(n1, n2);
16356
+ n23 = Mat.crossProduct(n2, n3);
16357
+ denom = Mat.innerProduct(n1, n23, 3);
16358
+ for (i = 0; i < 3; i++) {
16359
+ p[i] = (d1 * n23[i] + d2 * n31[i] + d3 * n12[i]) / denom;
16360
+ }
16361
+ return p;
16362
+ },
16363
+
16364
+
16365
+ meetPlanePlane: function (v11, v12, v21, v22) {
16366
+ var i, no1, no2,
16367
+ v = [0, 0, 0],
16368
+ w = [0, 0, 0];
16369
+
16370
+ for (i = 0; i < 3; i++) {
16371
+ v[i] = Type.evaluate(v11[i]);
16372
+ w[i] = Type.evaluate(v12[i]);
16373
+ }
16374
+ no1 = Mat.crossProduct(v, w);
16375
+
16376
+ for (i = 0; i < 3; i++) {
16377
+ v[i] = Type.evaluate(v21[i]);
16378
+ w[i] = Type.evaluate(v22[i]);
16379
+ }
16380
+ no2 = Mat.crossProduct(v, w);
16381
+
16382
+ return Mat.crossProduct(no1, no2);
16383
+ },
16384
+
16385
+ project3DTo3DPlane: function (point, normal, foot) {
16386
+ // TODO: homogeneous 3D coordinates
16387
+ var sol = [0, 0, 0],
16388
+ le, d1, d2, lbda;
16389
+
16390
+ foot = foot || [0, 0, 0];
16391
+
16392
+ le = Mat.norm(normal);
16393
+ d1 = Mat.innerProduct(point, normal, 3);
16394
+ d2 = Mat.innerProduct(foot, normal, 3);
16395
+ // (point - lbda * normal / le) * normal / le == foot * normal / le
16396
+ // => (point * normal - foot * normal) == lbda * le
16397
+ lbda = (d1 - d2) / le;
16398
+ sol = Mat.axpy(-lbda, normal, point);
16399
+
16400
+ return sol;
16401
+ },
16402
+
16403
+ getPlaneBounds: function (v1, v2, q, s, e) {
16404
+ var s1, s2, e1, e2, mat, rhs, sol;
16405
+
16406
+ if (v1[2] + v2[0] !== 0) {
16407
+ mat = [
16408
+ [v1[0], v2[0]],
16409
+ [v1[1], v2[1]]
16410
+ ];
16411
+ rhs = [s - q[0], s - q[1]];
16412
+
16413
+ sol = Numerics.Gauss(mat, rhs);
16414
+ s1 = sol[0];
16415
+ s2 = sol[1];
16416
+
16417
+ rhs = [e - q[0], e - q[1]];
16418
+ sol = Numerics.Gauss(mat, rhs);
16419
+ e1 = sol[0];
16420
+ e2 = sol[1];
16421
+ return [s1, e1, s2, e2];
16422
+ }
16423
+ return null;
16424
+ },
16425
+
16338
16426
  });
16339
16427
 
16340
16428
  return Mat.Geometry;
@@ -25837,6 +25925,10 @@ define('options',[
25837
25925
  * visible: false // Initial visibility. Should be set to false always
25838
25926
  * }
25839
25927
  * </pre>
25928
+ * <p>
25929
+ * Board events triggered by selection manipulation:
25930
+ * 'startselecting', 'stopselecting', 'mousestartselecting', 'mousestopselecting',
25931
+ * 'pointerstartselecting', 'pointerstopselecting', 'touchstartselecting', 'touchstopselecting'.
25840
25932
  *
25841
25933
  * @example
25842
25934
  * board.on('stopselecting', function(){
@@ -25850,14 +25942,10 @@ define('options',[
25850
25942
  * });
25851
25943
  *
25852
25944
  * @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
25945
+ *
25946
+ * @see JXG.Board#startSelectionMode
25947
+ * @see JXG.Board#stopSelectionMode
25948
+ *
25861
25949
  * @type Object
25862
25950
  * @default
25863
25951
  */
@@ -35099,26 +35187,35 @@ define('base/element',[
35099
35187
  },
35100
35188
 
35101
35189
  /**
35102
- * Resolves property shortcuts like <tt>color</tt> and expands them, e.g. <tt>strokeColor</tt> and <tt>fillColor</tt>.
35103
- * Writes the expanded properties back to the given <tt>properties</tt>.
35104
- * @param {Object} properties
35105
- * @returns {Object} The given parameter with shortcuts expanded.
35190
+ * Resolves attribute shortcuts like <tt>color</tt> and expands them, e.g. <tt>strokeColor</tt> and <tt>fillColor</tt>.
35191
+ * Writes the expanded attributes back to the given <tt>attributes</tt>.
35192
+ * @param {Object} attributes object
35193
+ * @returns {Object} The given attributes object with shortcuts expanded.
35194
+ * @private
35106
35195
  */
35107
- resolveShortcuts: function (properties) {
35108
- var key, i;
35196
+ resolveShortcuts: function (attributes) {
35197
+ var key, i,
35198
+ j,
35199
+ subattr = ['traceattributes', 'traceAttributes'];
35109
35200
 
35110
35201
  for (key in Options.shortcuts) {
35111
35202
  if (Options.shortcuts.hasOwnProperty(key)) {
35112
- if (Type.exists(properties[key])) {
35113
- for (i = 0; i < Options.shortcuts[key].length; i++) {
35114
- if (!Type.exists(properties[Options.shortcuts[key][i]])) {
35115
- properties[Options.shortcuts[key][i]] = properties[key];
35203
+
35204
+ if (Type.exists(attributes[key])) {
35205
+ for (i = 0; i < Options.shortcuts[key].length; i++) {
35206
+ if (!Type.exists(attributes[Options.shortcuts[key][i]])) {
35207
+ attributes[Options.shortcuts[key][i]] = attributes[key];
35208
+ }
35209
+ }
35210
+ }
35211
+ for (j = 0; j < subattr.length; j++) {
35212
+ if (Type.isObject(attributes[subattr[j]])) {
35213
+ attributes[subattr[j]] = this.resolveShortcuts(attributes[subattr[j]]);
35214
+ }
35116
35215
  }
35117
35216
  }
35118
- }
35119
- }
35120
35217
  }
35121
- return properties;
35218
+ return attributes;
35122
35219
  },
35123
35220
 
35124
35221
  /**
@@ -36546,8 +36643,6 @@ define('base/coordselement',[
36546
36643
  * @private
36547
36644
  */
36548
36645
  updateCoords: function (fromParent) {
36549
- var i;
36550
-
36551
36646
  if (!this.needsUpdate) {
36552
36647
  return this;
36553
36648
  }
@@ -36674,7 +36769,6 @@ define('base/coordselement',[
36674
36769
  doRound = true;
36675
36770
  newPos = 0.0;
36676
36771
  } else {
36677
- //this.coords.setCoordinates(Const.COORDS_BY_USER, Geometry.projectPointToLine(this, slide, this.board).usrCoords, false);
36678
36772
  newCoords = Geometry.projectPointToLine(this, slide, this.board);
36679
36773
  p1c = p1c.usrCoords.slice(0);
36680
36774
  p2c = p2c.usrCoords.slice(0);
@@ -38181,7 +38275,7 @@ define('base/coordselement',[
38181
38275
  if (direction < 0) {
38182
38276
  alpha *= this.intervalCount / stepCount;
38183
38277
  } else {
38184
- alpha *= (stepCount - this.intervalCount);
38278
+ alpha *= (stepCount - this.intervalCount) / stepCount;
38185
38279
  }
38186
38280
  radius = this.slideObject.Radius();
38187
38281
 
@@ -45762,10 +45856,14 @@ define('base/board',[
45762
45856
  }
45763
45857
  }
45764
45858
 
45859
+ this.originMoveEnd();
45860
+ this.update();
45861
+
45765
45862
  // selection
45766
45863
  if (this.selectingMode) {
45767
45864
  this._stopSelecting(evt);
45768
45865
  this.triggerEventHandlers(['touchstopselecting', 'pointerstopselecting', 'stopselecting'], [evt]);
45866
+ this.stopSelectionMode();
45769
45867
  } else {
45770
45868
  for (i = this.downObjects.length - 1; i > -1; i--) {
45771
45869
  found = false;
@@ -45776,32 +45874,30 @@ define('base/board',[
45776
45874
  }
45777
45875
  if (!found) {
45778
45876
  this.downObjects[i].triggerEventHandlers(['touchend', 'up', 'pointerup', 'MSPointerUp'], [evt]);
45779
- this.downObjects[i].snapToGrid();
45780
- this.downObjects[i].snapToPoints();
45877
+ // this.downObjects[i].snapToGrid();
45878
+ // this.downObjects[i].snapToPoints();
45781
45879
  this.downObjects.splice(i, 1);
45782
45880
  }
45783
45881
  }
45784
45882
  }
45785
45883
 
45786
- // this._pointerRemoveTouches(evt);
45787
- // if (this._board_touches.length === 0) {
45788
- if (this.hasPointerUp) {
45789
- if (window.navigator.msPointerEnabled) { // IE10-
45790
- Env.removeEvent(this.document, 'MSPointerUp', this.pointerUpListener, this);
45791
- } else {
45792
- Env.removeEvent(this.document, 'pointerup', this.pointerUpListener, this);
45793
- Env.removeEvent(this.document, 'pointercancel', this.pointerUpListener, this);
45794
- }
45795
- this.hasPointerUp = false;
45884
+ if (this.hasPointerUp) {
45885
+ if (window.navigator.msPointerEnabled) { // IE10-
45886
+ Env.removeEvent(this.document, 'MSPointerUp', this.pointerUpListener, this);
45887
+ } else {
45888
+ Env.removeEvent(this.document, 'pointerup', this.pointerUpListener, this);
45889
+ Env.removeEvent(this.document, 'pointercancel', this.pointerUpListener, this);
45796
45890
  }
45891
+ this.hasPointerUp = false;
45892
+ }
45797
45893
 
45798
- // this.dehighlightAll();
45799
- // this.updateQuality = this.BOARD_QUALITY_HIGH;
45800
- // this.mode = this.BOARD_MODE_NONE;
45894
+ // this.dehighlightAll();
45895
+ // this.updateQuality = this.BOARD_QUALITY_HIGH;
45896
+ // this.mode = this.BOARD_MODE_NONE;
45897
+
45898
+ // this.originMoveEnd();
45899
+ // this.update();
45801
45900
 
45802
- this.originMoveEnd();
45803
- this.update();
45804
- // }
45805
45901
  // After one finger leaves the screen the gesture is stopped.
45806
45902
  this._pointerClearTouches();
45807
45903
  return true;
@@ -46144,6 +46240,7 @@ define('base/board',[
46144
46240
  if (this.selectingMode) {
46145
46241
  this._stopSelecting(evt);
46146
46242
  this.triggerEventHandlers(['touchstopselecting', 'stopselecting'], [evt]);
46243
+ this.stopSelectionMode();
46147
46244
  } else if (evtTouches && evtTouches.length > 0) {
46148
46245
  for (i = 0; i < this.touches.length; i++) {
46149
46246
  tmpTouches[i] = this.touches[i];
@@ -46235,8 +46332,8 @@ define('base/board',[
46235
46332
  }
46236
46333
  if (!found) {
46237
46334
  this.downObjects[i].triggerEventHandlers(['touchup', 'up'], [evt]);
46238
- this.downObjects[i].snapToGrid();
46239
- this.downObjects[i].snapToPoints();
46335
+ // this.downObjects[i].snapToGrid();
46336
+ // this.downObjects[i].snapToPoints();
46240
46337
  this.downObjects.splice(i, 1);
46241
46338
  }
46242
46339
  }
@@ -46399,11 +46496,11 @@ define('base/board',[
46399
46496
  // redraw with high precision
46400
46497
  this.updateQuality = this.BOARD_QUALITY_HIGH;
46401
46498
 
46402
- if (this.mouse && this.mouse.obj) {
46403
- // The parameter is needed for lines with snapToGrid enabled
46404
- this.mouse.obj.snapToGrid(this.mouse.targets[0]);
46405
- this.mouse.obj.snapToPoints();
46406
- }
46499
+ // if (this.mouse && this.mouse.obj) {
46500
+ // // The parameter is needed for lines with snapToGrid enabled
46501
+ // this.mouse.obj.snapToGrid(this.mouse.targets[0]);
46502
+ // this.mouse.obj.snapToPoints();
46503
+ // }
46407
46504
 
46408
46505
  this.originMoveEnd();
46409
46506
  this.dehighlightAll();
@@ -46413,6 +46510,7 @@ define('base/board',[
46413
46510
  if (this.selectingMode) {
46414
46511
  this._stopSelecting(evt);
46415
46512
  this.triggerEventHandlers(['mousestopselecting', 'stopselecting'], [evt]);
46513
+ this.stopSelectionMode();
46416
46514
  } else {
46417
46515
  for (i = 0; i < this.downObjects.length; i++) {
46418
46516
  this.downObjects[i].triggerEventHandlers(['mouseup', 'up'], [evt]);
@@ -46593,7 +46691,7 @@ define('base/board',[
46593
46691
 
46594
46692
  this.update();
46595
46693
 
46596
- if (done) {
46694
+ if (done && Type.exists(evt.preventDefault)) {
46597
46695
  evt.preventDefault();
46598
46696
  }
46599
46697
  return true;
@@ -57018,7 +57116,7 @@ define('base/line',[
57018
57116
  if (this.parents.length < 3) { // Line through two points
57019
57117
  this.point1.handleSnapToGrid(true, true);
57020
57118
  this.point2.handleSnapToGrid(true, true);
57021
- } else if (Type.exists(pos)) { // Free line
57119
+ } else if (Type.exists(pos)) { // Free line
57022
57120
  sX = Type.evaluate(this.visProp.snapsizex);
57023
57121
  sY = Type.evaluate(this.visProp.snapsizey);
57024
57122
 
@@ -61697,8 +61795,35 @@ define('base/polygon',[
61697
61795
 
61698
61796
  /**
61699
61797
  * Add more points to the polygon. The new points will be inserted at the end.
61700
- * @param {JXG.Point} p Arbitrary number of points
61798
+ * The attributes of new border segments are set to the same values
61799
+ * as those used when the polygon was created.
61800
+ * If new vertices are supplied by coordinates, the default attributes of polygon
61801
+ * vertices are taken as their attributes. Therefore, the visual attributes of
61802
+ * new vertices and borders may have to be adapted afterwards.
61803
+ * @param {JXG.Point} p Arbitrary number of points or coordinate arrays
61701
61804
  * @returns {JXG.Polygon} Reference to the polygon
61805
+ * @example
61806
+ * const board = JXG.JSXGraph.initBoard('jxgbox', {axis:true});
61807
+ * var pg = board.create('polygon', [[1,2], [3,4], [-3,1]], {hasInnerPoints: true});
61808
+ * var newPoint = board.create('point', [-1, -1]);
61809
+ * var newPoint2 = board.create('point', [-1, -2]);
61810
+ * pg.addPoints(newPoint, newPoint2, [1, -2]);
61811
+ *
61812
+ * </pre><div id="JXG70eb0fd2-d20f-4ba9-9ab6-0eac92aabfa5" class="jxgbox" style="width: 300px; height: 300px;"></div>
61813
+ * <script type="text/javascript">
61814
+ * (function() {
61815
+ * var board = JXG.JSXGraph.initBoard('JXG70eb0fd2-d20f-4ba9-9ab6-0eac92aabfa5',
61816
+ * {boundingbox: [-8, 8, 8,-8], axis: true, showcopyright: false, shownavigation: false});
61817
+ * const board = JXG.JSXGraph.initBoard('jxgbox', {axis:true});
61818
+ * var pg = board.create('polygon', [[1,2], [3,4], [-3,1]], {hasInnerPoints: true});
61819
+ * var newPoint = board.create('point', [-1, -1]);
61820
+ * var newPoint2 = board.create('point', [-1, -2]);
61821
+ * pg.addPoints(newPoint, newPoint2, [1, -2]);
61822
+ *
61823
+ * })();
61824
+ *
61825
+ * </script><pre>
61826
+ *
61702
61827
  */
61703
61828
  addPoints: function (p) {
61704
61829
  var args = Array.prototype.slice.call(arguments);
@@ -61707,44 +61832,72 @@ define('base/polygon',[
61707
61832
  },
61708
61833
 
61709
61834
  /**
61710
- * Adds more points to the vertex list of the polygon, starting with index <tt><i</tt>
61711
- * @param {Number} idx The position where the new vertices are inserted, starting with 0.
61712
- * @param {JXG.Point} p Arbitrary number of points to insert.
61835
+ * Insert points to the vertex list of the polygon after index <tt><idx</tt>.
61836
+ * The attributes of new border segments are set to the same values
61837
+ * as those used when the polygon was created.
61838
+ * If new vertices are supplied by coordinates, the default attributes of polygon
61839
+ * vertices are taken as their attributes. Therefore, the visual attributes of
61840
+ * new vertices and borders may have to be adapted afterwards.
61841
+ *
61842
+ * @param {Number} idx The position after which the new vertices are inserted.
61843
+ * Setting idx to -1 inserts the new points at the front, i.e. at position 0.
61844
+ * @param {JXG.Point} p Arbitrary number of points or coordinate arrays to insert.
61713
61845
  * @returns {JXG.Polygon} Reference to the polygon object
61846
+ *
61847
+ * @example
61848
+ * const board = JXG.JSXGraph.initBoard('jxgbox', {axis:true});
61849
+ * var pg = board.create('polygon', [[1,2], [3,4], [-3,1]], {hasInnerPoints: true});
61850
+ * var newPoint = board.create('point', [-1, -1]);
61851
+ * pg.insertPoints(0, newPoint, newPoint, [1, -2]);
61852
+ *
61853
+ * </pre><div id="JXG17b84b2a-a851-4e3f-824f-7f6a60f166ca" class="jxgbox" style="width: 300px; height: 300px;"></div>
61854
+ * <script type="text/javascript">
61855
+ * (function() {
61856
+ * var board = JXG.JSXGraph.initBoard('JXG17b84b2a-a851-4e3f-824f-7f6a60f166ca',
61857
+ * {boundingbox: [-8, 8, 8,-8], axis: true, showcopyright: false, shownavigation: false});
61858
+ * const board = JXG.JSXGraph.initBoard('jxgbox', {axis:true});
61859
+ * var pg = board.create('polygon', [[1,2], [3,4], [-3,1]], {hasInnerPoints: true});
61860
+ * var newPoint = board.create('point', [-1, -1]);
61861
+ * pg.insertPoints(0, newPoint, newPoint, [1, -2]);
61862
+ *
61863
+ * })();
61864
+ *
61865
+ * </script><pre>
61866
+ *
61714
61867
  */
61715
61868
  insertPoints: function (idx, p) {
61716
- var i, npoints = [], tmp;
61869
+ var i, le;
61717
61870
 
61718
61871
  if (arguments.length === 0) {
61719
61872
  return this;
61720
61873
  }
61721
61874
 
61722
61875
 
61723
- if (idx < 0 || idx > this.vertices.length - 2) {
61876
+ if (idx < -1 || idx > this.vertices.length - 2) {
61724
61877
  return this;
61725
61878
  }
61726
61879
 
61727
- for (i = 1; i < arguments.length; i++) {
61728
- if (Type.isPoint(arguments[i])) {
61729
- npoints.push(arguments[i]);
61730
- }
61880
+ le = arguments.length - 1;
61881
+ for (i = 1; i < le + 1; i++) {
61882
+ this.vertices.splice(idx + i, 0,
61883
+ Type.providePoints(this.board, [arguments[i]], {}, 'polygon', ['vertices'])[0]
61884
+ );
61885
+ }
61886
+ if (idx === -1) {
61887
+ this.vertices[this.vertices.length - 1] = this.vertices[0];
61731
61888
  }
61732
-
61733
- tmp = this.vertices.slice(0, idx + 1).concat(npoints);
61734
- this.vertices = tmp.concat(this.vertices.slice(idx + 1));
61735
-
61736
61889
  if (this.withLines) {
61737
- tmp = this.borders.slice(0, idx);
61738
- this.board.removeObject(this.borders[idx]);
61739
-
61740
- for (i = 0; i < npoints.length; i++) {
61741
- tmp.push(this.board.create('segment', [this.vertices[idx + i], this.vertices[idx + i + 1]], this.attr_line));
61890
+ if (idx < 0) {
61891
+ this.borders[this.borders.length - 1].point2 = this.vertices[this.vertices.length - 1];
61892
+ } else {
61893
+ this.borders[idx].point2 = this.vertices[idx + 1];
61894
+ }
61895
+ for (i = idx + 1; i < idx + 1 + le; i++) {
61896
+ this.borders.splice(i, 0,
61897
+ this.board.create('segment', [this.vertices[i], this.vertices[i + 1]], this.attr_line)
61898
+ );
61742
61899
  }
61743
-
61744
- tmp.push(this.board.create('segment', [this.vertices[idx + npoints.length], this.vertices[idx + npoints.length + 1]], this.attr_line));
61745
- this.borders = tmp.concat(this.borders.slice(idx + 1));
61746
61900
  }
61747
-
61748
61901
  this.board.update();
61749
61902
 
61750
61903
  return this;
@@ -61759,7 +61912,7 @@ define('base/polygon',[
61759
61912
  var i, j, idx, nvertices = [], nborders = [],
61760
61913
  nidx = [], partition = [];
61761
61914
 
61762
- // partition:
61915
+ // Partition:
61763
61916
  // in order to keep the borders which could be recycled, we have to partition
61764
61917
  // the set of removed points. I.e. if the points 1, 2, 5, 6, 7, 10 are removed,
61765
61918
  // the partitions are
@@ -61767,10 +61920,10 @@ define('base/polygon',[
61767
61920
  // this gives us the borders, that can be removed and the borders we have to create.
61768
61921
 
61769
61922
 
61770
- // remove the last vertex which is identical to the first
61923
+ // Remove the last vertex which is identical to the first
61771
61924
  this.vertices = this.vertices.slice(0, this.vertices.length - 1);
61772
61925
 
61773
- // collect all valid parameters as indices in nidx
61926
+ // Collect all valid parameters as indices in nidx
61774
61927
  for (i = 0; i < arguments.length; i++) {
61775
61928
  idx = arguments[i];
61776
61929
  if (Type.isPoint(idx)) {
@@ -61782,22 +61935,22 @@ define('base/polygon',[
61782
61935
  }
61783
61936
  }
61784
61937
 
61785
- // remove the polygon from each removed point's children
61938
+ // Remove the polygon from each removed point's children
61786
61939
  for (i = 0; i < nidx.length; i++) {
61787
61940
  this.vertices[nidx[i]].removeChild(this);
61788
61941
  }
61789
61942
 
61790
- // sort the elements to be eliminated
61943
+ // Sort the elements to be eliminated
61791
61944
  nidx = nidx.sort();
61792
61945
  nvertices = this.vertices.slice();
61793
61946
  nborders = this.borders.slice();
61794
61947
 
61795
- // initialize the partition
61948
+ // Initialize the partition
61796
61949
  if (this.withLines) {
61797
61950
  partition.push([nidx[nidx.length - 1]]);
61798
61951
  }
61799
61952
 
61800
- // run through all existing vertices and copy all remaining ones to nvertices
61953
+ // Run through all existing vertices and copy all remaining ones to nvertices,
61801
61954
  // compute the partition
61802
61955
  for (i = nidx.length - 1; i > -1; i--) {
61803
61956
  nvertices[nidx[i]] = -1;
@@ -61808,12 +61961,12 @@ define('base/polygon',[
61808
61961
  }
61809
61962
  }
61810
61963
 
61811
- // finalize the partition computation
61964
+ // Finalize the partition computation
61812
61965
  if (this.withLines) {
61813
61966
  partition[partition.length - 1][1] = nidx[0];
61814
61967
  }
61815
61968
 
61816
- // update vertices
61969
+ // Update vertices
61817
61970
  this.vertices = [];
61818
61971
  for (i = 0; i < nvertices.length; i++) {
61819
61972
  if (Type.isPoint(nvertices[i])) {
@@ -61824,7 +61977,7 @@ define('base/polygon',[
61824
61977
  this.vertices.push(this.vertices[0]);
61825
61978
  }
61826
61979
 
61827
- // delete obsolete and create missing borders
61980
+ // Delete obsolete and create missing borders
61828
61981
  if (this.withLines) {
61829
61982
  for (i = 0; i < partition.length; i++) {
61830
61983
  for (j = partition[i][1] - 1; j < partition[i][0] + 1; j++) {
@@ -69467,7 +69620,7 @@ define('element/composition',[
69467
69620
  };
69468
69621
 
69469
69622
  /**
69470
- * @class Bisector lines are similar to {@link Bisector} but takes two lines as parent elements. The resulting element is
69623
+ * @class Bisector lines are similar to {@link Bisector} but take two lines as parent elements. The resulting element is
69471
69624
  * a composition of two lines.
69472
69625
  * @pseudo
69473
69626
  * @constructor
@@ -72224,6 +72377,10 @@ define('element/slider',[
72224
72377
  p2.dump = false;
72225
72378
  l1.dump = false;
72226
72379
  l2.dump = false;
72380
+ if (withText) {
72381
+ t.dump = false;
72382
+ }
72383
+
72227
72384
 
72228
72385
  p3.elType = 'slider';
72229
72386
  p3.parents = parents;
@@ -72241,6 +72398,14 @@ define('element/slider',[
72241
72398
  p3.inherits.push(ti);
72242
72399
  }
72243
72400
 
72401
+ p3.getParents = function() {
72402
+ return [
72403
+ this.point1.coords.usrCoords.slice(1),
72404
+ this.point2.coords.usrCoords.slice(1),
72405
+ [this._smin, this.position * (this._smax - this._smin) + this._smin, this._smax]
72406
+ ];
72407
+ };
72408
+
72244
72409
  p3.baseline.on('up', function(evt) {
72245
72410
  var pos, c;
72246
72411
 
@@ -76214,6 +76379,8 @@ define('base/ticks',[
76214
76379
  attr.id = this.id + ld.i + 'Label' + this.labelCounter;
76215
76380
 
76216
76381
  label = Text.createText(this.board, [ld.x, ld.y, ld.t], attr);
76382
+ this.addChild(label);
76383
+ label.setParents(this);
76217
76384
  label.isDraggable = false;
76218
76385
  label.dump = false;
76219
76386
  this.labels.push(label);
@@ -79755,7 +79922,13 @@ define('element/button',[
79755
79922
  * an SVG foreignObject container.
79756
79923
  * <p>
79757
79924
  * Instead of board.create('foreignobject') the shortcut board.create('fo') may be used.
79758
- *
79925
+ *
79926
+ * <p style="background-color:#dddddd; padding:10px"><b>NOTE:</b> In Safari up to version 15, a foreignObject does not obey the layer structure
79927
+ * if it contains &lt;video&gt; or &lt;iframe&gt; tags, as well as elements which are
79928
+ * positioned with <tt>position:absolute|relative|fixed</tt>. In this case, the foreignobject will be
79929
+ * "above" the JSXGraph construction.
79930
+ * </p>
79931
+ *
79759
79932
  * @pseudo
79760
79933
  * @description
79761
79934
  * @name ForeignObject
@@ -79893,6 +80066,1522 @@ define('element/button',[
79893
80066
  };
79894
80067
  });
79895
80068
 
80069
+ /*
80070
+ Copyright 2008-2022
80071
+ Matthias Ehmann,
80072
+ Carsten Miller,
80073
+ Andreas Walter,
80074
+ Alfred Wassermann
80075
+
80076
+ This file is part of JSXGraph.
80077
+
80078
+ JSXGraph is free software dual licensed under the GNU LGPL or MIT License.
80079
+
80080
+ You can redistribute it and/or modify it under the terms of the
80081
+
80082
+ * GNU Lesser General Public License as published by
80083
+ the Free Software Foundation, either version 3 of the License, or
80084
+ (at your option) any later version
80085
+ OR
80086
+ * MIT License: https://github.com/jsxgraph/jsxgraph/blob/master/LICENSE.MIT
80087
+
80088
+ JSXGraph is distributed in the hope that it will be useful,
80089
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
80090
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
80091
+ GNU Lesser General Public License for more details.
80092
+
80093
+ You should have received a copy of the GNU Lesser General Public License and
80094
+ the MIT License along with JSXGraph. If not, see <http://www.gnu.org/licenses/>
80095
+ and <http://opensource.org/licenses/MIT/>.
80096
+ */
80097
+ /*global JXG:true, define: true*/
80098
+
80099
+ define('3d/threed',['jxg'
80100
+ ], function (JXG) {
80101
+ "use strict";
80102
+
80103
+ JXG.ThreeD = {};
80104
+
80105
+ return JXG.ThreeD;
80106
+ });
80107
+
80108
+ /*
80109
+ Copyright 2008-2022
80110
+ Matthias Ehmann,
80111
+ Carsten Miller,
80112
+ Andreas Walter,
80113
+ Alfred Wassermann
80114
+
80115
+ This file is part of JSXGraph.
80116
+
80117
+ JSXGraph is free software dual licensed under the GNU LGPL or MIT License.
80118
+
80119
+ You can redistribute it and/or modify it under the terms of the
80120
+
80121
+ * GNU Lesser General Public License as published by
80122
+ the Free Software Foundation, either version 3 of the License, or
80123
+ (at your option) any later version
80124
+ OR
80125
+ * MIT License: https://github.com/jsxgraph/jsxgraph/blob/master/LICENSE.MIT
80126
+
80127
+ JSXGraph is distributed in the hope that it will be useful,
80128
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
80129
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
80130
+ GNU Lesser General Public License for more details.
80131
+
80132
+ You should have received a copy of the GNU Lesser General Public License and
80133
+ the MIT License along with JSXGraph. If not, see <http://www.gnu.org/licenses/>
80134
+ and <http://opensource.org/licenses/MIT/>.
80135
+ */
80136
+ /*global JXG:true, define: true*/
80137
+
80138
+ define('3d/view3d',['jxg', 'options', 'base/constants', 'utils/type', 'math/math', 'base/element', '3d/threed',
80139
+ ], function (JXG, Options, Const, Type, Mat, GeometryElement, ThreeD) {
80140
+ "use strict";
80141
+
80142
+ ThreeD.View3D = function (board, parents, attributes) {
80143
+ var bbox3d, coords, size;
80144
+ this.constructor(board, attributes, Const.OBJECT_TYPE_VIEW3D, Const.OBJECT_CLASS_CURVE);
80145
+
80146
+ bbox3d = parents[2]; // [[x1, x2], [y1,y2], [z1,z2]]
80147
+ coords = parents[0]; // llft corner
80148
+ size = parents[1]; // [w, h]
80149
+
80150
+ /**
80151
+ * "Namespace" for all 3D handling
80152
+ */
80153
+ this.D3 = {};
80154
+
80155
+ /**
80156
+ * An associative array containing all geometric objects belonging to the view.
80157
+ * Key is the id of the object and value is a reference to the object.
80158
+ * @type Object
80159
+ */
80160
+ this.D3.objects = {};
80161
+
80162
+ /**
80163
+ * An array containing all geometric objects in this view in the order of construction.
80164
+ * @type Array
80165
+ */
80166
+ this.D3.objectsList = [];
80167
+
80168
+ /**
80169
+ * @type {Object} contains the axes of the view or null
80170
+ * @default null
80171
+ */
80172
+ this.D3.defaultAxes = null;
80173
+
80174
+ /**
80175
+ * 3D-to-2D transformation matrix
80176
+ * @type {Array} 3 x 4 mattrix
80177
+ */
80178
+ this.D3.matrix = [
80179
+ [1, 0, 0, 0],
80180
+ [0, 1, 0, 0],
80181
+ [0, 0, 1, 0]
80182
+ ];
80183
+
80184
+ // Bounding box (cube) [[x1, x2], [y1,y2], [z1,z2]]:
80185
+ this.D3.bbox3d = bbox3d;
80186
+ this.D3.coords = coords;
80187
+ this.D3.size = size;
80188
+
80189
+ /**
80190
+ * Distance of the view to the origin. In other words, its
80191
+ * the radius of the sphere where the camera sits.
80192
+ */
80193
+ this.D3.r = -1;
80194
+
80195
+ this.timeoutAzimuth = null;
80196
+
80197
+ this.id = this.board.setId(this, 'V');
80198
+ this.board.finalizeAdding(this);
80199
+ this.elType = 'view3d';
80200
+ this.methodMap = Type.deepCopy(this.methodMap, {
80201
+ });
80202
+ };
80203
+ ThreeD.View3D.prototype = new GeometryElement();
80204
+
80205
+ JXG.extend(ThreeD.View3D.prototype, /** @lends ThreeD.View3D.prototype */ {
80206
+ create: function (elementType, parents, attributes) {
80207
+ var prefix = [],
80208
+ is3D = false,
80209
+ el;
80210
+
80211
+ if (elementType.indexOf('3d') > 0) {
80212
+ is3D = true;
80213
+ prefix.push(this);
80214
+ }
80215
+ el = this.board.create(elementType, prefix.concat(parents), attributes);
80216
+ if (true || is3D) {
80217
+ this.add(el);
80218
+ }
80219
+ return el;
80220
+ },
80221
+
80222
+ add: function (el) {
80223
+ this.D3.objects[el.id] = el;
80224
+ this.D3.objectsList.push(el);
80225
+ },
80226
+
80227
+ /**
80228
+ * Update 3D-to-2D transformation matrix with the actual
80229
+ * elevation and azimuth angles.
80230
+ *
80231
+ * @private
80232
+ */
80233
+ update: function () {
80234
+ var D3 = this.D3,
80235
+ e, r, a, f, mat;
80236
+
80237
+ if (!Type.exists(D3.el_slide) ||
80238
+ !Type.exists(D3.az_slide) ||
80239
+ !this.needsUpdate) {
80240
+ return this;
80241
+ }
80242
+
80243
+ e = D3.el_slide.Value();
80244
+ r = D3.r;
80245
+ a = D3.az_slide.Value();
80246
+ f = r * Math.sin(e);
80247
+ mat = [[1, 0, 0,], [0, 1, 0], [0, 0, 1]];
80248
+
80249
+ D3.matrix = [
80250
+ [1, 0, 0, 0],
80251
+ [0, 1, 0, 0],
80252
+ [0, 0, 1, 0]
80253
+ ];
80254
+
80255
+ D3.matrix[1][1] = r * Math.cos(a);
80256
+ D3.matrix[1][2] = -r * Math.sin(a);
80257
+ D3.matrix[2][1] = f * Math.sin(a);
80258
+ D3.matrix[2][2] = f * Math.cos(a);
80259
+ D3.matrix[2][3] = Math.cos(e);
80260
+
80261
+ if (true) {
80262
+ mat[1][1] = D3.size[0] / (D3.bbox3d[0][1] - D3.bbox3d[0][0]); // w / d_x
80263
+ mat[2][2] = D3.size[1] / (D3.bbox3d[1][1] - D3.bbox3d[1][0]); // h / d_y
80264
+ mat[1][0] = D3.coords[0] - mat[1][1] * D3.bbox3d[0][0]; // llft_x
80265
+ mat[2][0] = D3.coords[1] - mat[2][2] * D3.bbox3d[1][0]; // llft_y
80266
+
80267
+ D3.matrix = Mat.matMatMult(mat, D3.matrix);
80268
+ }
80269
+
80270
+ return this;
80271
+ },
80272
+
80273
+ updateRenderer: function () {
80274
+ this.needsUpdate = false;
80275
+ return this;
80276
+ },
80277
+
80278
+ /**
80279
+ * Project 3D coordinates to 2D board coordinates
80280
+ * The 3D coordinates are provides as three numbers x, y, z or one array of length 3.
80281
+ *
80282
+ * @param {Number|Array} x
80283
+ * @param {[Number]} y
80284
+ * @param {[Number]} z
80285
+ * @returns {Array} Array of length 3 containing the projection on to the board
80286
+ * in homogeneous user coordinates.
80287
+ */
80288
+ project3DTo2D: function (x, y, z) {
80289
+ var vec;
80290
+ if (arguments.length === 3) {
80291
+ vec = [1, x, y, z];
80292
+ } else {
80293
+ // Argument is an array
80294
+ if (x.length === 3) {
80295
+ vec = [1].concat(x);
80296
+ } else {
80297
+ vec = x;
80298
+ }
80299
+ }
80300
+ return Mat.matVecMult(this.D3.matrix, vec);
80301
+ },
80302
+
80303
+ /**
80304
+ * Project a 2D coordinate to the plane through the origin
80305
+ * defined by its normal vector `normal`.
80306
+ *
80307
+ * @param {JXG.Point} point
80308
+ * @param {Array} normal
80309
+ * @returns Array of length 4 containing the projected
80310
+ * point in homogeneous coordinates.
80311
+ */
80312
+ project2DTo3DPlane: function (point, normal, foot) {
80313
+ var mat, rhs, d, le,
80314
+ n = normal.slice(1),
80315
+ sol = [1, 0, 0, 0];
80316
+
80317
+ foot = foot || [1, 0, 0, 0];
80318
+ le = Mat.norm(n, 3);
80319
+ d = Mat.innerProduct(foot.slice(1), n, 3) / le;
80320
+
80321
+ mat = this.D3.matrix.slice(0, 3); // True copy
80322
+ mat.push([0].concat(n));
80323
+
80324
+ // 2D coordinates of point:
80325
+ rhs = point.coords.usrCoords.concat([d]);
80326
+ try {
80327
+ // Prevent singularity in case elevation angle is zero
80328
+ if (mat[2][3] === 1.0) {
80329
+ mat[2][1] = mat[2][2] = Mat.eps * 0.001;
80330
+ }
80331
+ sol = Mat.Numerics.Gauss(mat, rhs);
80332
+ } catch (err) {
80333
+ sol = [0, NaN, NaN, NaN];
80334
+ }
80335
+
80336
+ return sol;
80337
+ },
80338
+
80339
+ project3DToCube: function (c3d) {
80340
+ var cube = this.D3.bbox3d;
80341
+ if (c3d[1] < cube[0][0]) { c3d[1] = cube[0][0]; }
80342
+ if (c3d[1] > cube[0][1]) { c3d[1] = cube[0][1]; }
80343
+ if (c3d[2] < cube[1][0]) { c3d[2] = cube[1][0]; }
80344
+ if (c3d[2] > cube[1][1]) { c3d[2] = cube[1][1]; }
80345
+ if (c3d[3] < cube[2][0]) { c3d[3] = cube[2][0]; }
80346
+ if (c3d[3] > cube[2][1]) { c3d[3] = cube[2][1]; }
80347
+
80348
+ return c3d;
80349
+ },
80350
+
80351
+ intersectionLineCube: function (p, d, r) {
80352
+ var rnew, i, r0, r1;
80353
+
80354
+ rnew = r;
80355
+ for (i = 0; i < 3; i++) {
80356
+ if (d[i] !== 0) {
80357
+ r0 = (this.D3.bbox3d[i][0] - p[i]) / d[i];
80358
+ r1 = (this.D3.bbox3d[i][1] - p[i]) / d[i];
80359
+ if (r < 0) {
80360
+ rnew = Math.max(rnew, Math.min(r0, r1));
80361
+ } else {
80362
+ rnew = Math.min(rnew, Math.max(r0, r1));
80363
+ }
80364
+ }
80365
+ }
80366
+ return rnew;
80367
+ },
80368
+
80369
+ isInCube: function (q) {
80370
+ return q[0] > this.D3.bbox3d[0][0] - Mat.eps && q[0] < this.D3.bbox3d[0][1] + Mat.eps &&
80371
+ q[1] > this.D3.bbox3d[1][0] - Mat.eps && q[1] < this.D3.bbox3d[1][1] + Mat.eps &&
80372
+ q[2] > this.D3.bbox3d[2][0] - Mat.eps && q[2] < this.D3.bbox3d[2][1] + Mat.eps;
80373
+ },
80374
+
80375
+ /**
80376
+ *
80377
+ * @param {*} plane1
80378
+ * @param {*} plane2
80379
+ * @param {*} d
80380
+ * @returns Array of length 2 containing the coordinates of the defining points of
80381
+ * of the intersection segment.
80382
+ */
80383
+ intersectionPlanePlane: function(plane1, plane2, d) {
80384
+ var ret = [[], []],
80385
+ p, dir, r, q;
80386
+
80387
+ d = d || plane2.D3.d;
80388
+
80389
+ p = Mat.Geometry.meet3Planes(plane1.D3.normal, plane1.D3.d, plane2.D3.normal, d,
80390
+ Mat.crossProduct(plane1.D3.normal, plane2.D3.normal), 0);
80391
+ dir = Mat.Geometry.meetPlanePlane(plane1.D3.dir1, plane1.D3.dir2, plane2.D3.dir1, plane2.D3.dir2);
80392
+ r = this.intersectionLineCube(p, dir, Infinity);
80393
+ q = Mat.axpy(r, dir, p);
80394
+ if (this.isInCube(q)) {
80395
+ ret[0] = q;
80396
+ }
80397
+ r = this.intersectionLineCube(p, dir, -Infinity);
80398
+ q = Mat.axpy(r, dir, p);
80399
+ if (this.isInCube(q) ) {
80400
+ ret[1] = q;
80401
+ }
80402
+ return ret;
80403
+ },
80404
+
80405
+ getMesh: function (X, Y, Z, interval_u, interval_v) {
80406
+ var i_u, i_v, u, v, c2d,
80407
+ delta_u, delta_v,
80408
+ p = [0, 0, 0],
80409
+ steps_u = interval_u[2],
80410
+ steps_v = interval_v[2],
80411
+
80412
+ dataX = [],
80413
+ dataY = [];
80414
+
80415
+ delta_u = (Type.evaluate(interval_u[1]) - Type.evaluate(interval_u[0])) / (steps_u);
80416
+ delta_v = (Type.evaluate(interval_v[1]) - Type.evaluate(interval_v[0])) / (steps_v);
80417
+
80418
+ for (i_u = 0; i_u <= steps_u; i_u++) {
80419
+ u = interval_u[0] + delta_u * i_u;
80420
+ for (i_v = 0; i_v <= steps_v; i_v++) {
80421
+ v = interval_v[0] + delta_v * i_v;
80422
+ p[0] = X(u, v);
80423
+ p[1] = Y(u, v);
80424
+ p[2] = Z(u, v);
80425
+ c2d = this.project3DTo2D(p);
80426
+ dataX.push(c2d[1]);
80427
+ dataY.push(c2d[2]);
80428
+ }
80429
+ dataX.push(NaN);
80430
+ dataY.push(NaN);
80431
+ }
80432
+
80433
+ for (i_v = 0; i_v <= steps_v; i_v++) {
80434
+ v = interval_v[0] + delta_v * i_v;
80435
+ for (i_u = 0; i_u <= steps_u; i_u++) {
80436
+ u = interval_u[0] + delta_u * i_u;
80437
+ p[0] = X(u, v);
80438
+ p[1] = Y(u, v);
80439
+ p[2] = Z(u, v);
80440
+ c2d = this.project3DTo2D(p);
80441
+ dataX.push(c2d[1]);
80442
+ dataY.push(c2d[2]);
80443
+ }
80444
+ dataX.push(NaN);
80445
+ dataY.push(NaN);
80446
+ }
80447
+
80448
+ return [dataX, dataY];
80449
+ },
80450
+
80451
+ animateAzimuth: function () {
80452
+ var s = this.D3.az_slide._smin,
80453
+ e = this.D3.az_slide._smax,
80454
+ sdiff = e - s,
80455
+ newVal = this.D3.az_slide.Value() + 0.1;
80456
+
80457
+ this.D3.az_slide.position = ((newVal - s) / sdiff);
80458
+ if (this.D3.az_slide.position > 1) {
80459
+ this.D3.az_slide.position = 0.0;
80460
+ }
80461
+ this.board.update();
80462
+
80463
+ this.timeoutAzimuth = setTimeout(function () { this.animateAzimuth(); }.bind(this), 200);
80464
+ },
80465
+
80466
+ stopAzimuth: function () {
80467
+ clearTimeout(this.timeoutAzimuth);
80468
+ this.timeoutAzimuth = null;
80469
+ }
80470
+ });
80471
+
80472
+ /**
80473
+ *
80474
+ * @param {*} board
80475
+ * @param {*} parents
80476
+ * @param {*} attributes
80477
+ * @returns
80478
+ */
80479
+ ThreeD.createView3D = function (board, parents, attributes) {
80480
+ var view, frame, attr,
80481
+ x, y, w, h,
80482
+ coords = parents[0], // llft corner
80483
+ size = parents[1]; // [w, h]
80484
+
80485
+ attr = Type.copyAttributes(attributes, board.options, 'view3d');
80486
+ view = new ThreeD.View3D(board, parents, attr);
80487
+ view.defaultAxes = view.create('axes3d', parents, attributes);
80488
+
80489
+ x = coords[0];
80490
+ y = coords[1];
80491
+ w = size[0];
80492
+ h = size[1];
80493
+
80494
+ /**
80495
+ * Frame around the view object
80496
+ */
80497
+ if (false) {
80498
+ frame = board.create('polygon', [
80499
+ [coords[0], coords[1] + size[1]], // ulft
80500
+ [coords[0], coords[1]], // llft
80501
+ [coords[0] + size[0], coords[1]], // lrt
80502
+ [coords[0] + size[0], coords[1] + size[1]], // urt
80503
+ ], {
80504
+ fillColor: 'none',
80505
+ highlightFillColor: 'none',
80506
+ highlight: false,
80507
+ vertices: {
80508
+ fixed: true,
80509
+ visible: false
80510
+ },
80511
+ borders: {
80512
+ strokeColor: 'black',
80513
+ highlight: false,
80514
+ strokeWidth: 0.5,
80515
+ dash: 4
80516
+ }
80517
+ });
80518
+ //view.add(frame);
80519
+ }
80520
+
80521
+ /**
80522
+ * Slider to adapt azimuth angle
80523
+ */
80524
+ view.D3.az_slide = board.create('slider', [[x - 1, y - 2], [x + w + 1, y - 2], [0, 1.0, 2 * Math.PI]], {
80525
+ style: 6, name: 'az',
80526
+ point1: { frozen: true },
80527
+ point2: { frozen: true }
80528
+ });
80529
+
80530
+ /**
80531
+ * Slider to adapt elevation angle
80532
+ */
80533
+ view.D3.el_slide = board.create('slider', [[x - 1, y], [x - 1, y + h], [0, 0.30, Math.PI / 2]], {
80534
+ style: 6, name: 'el',
80535
+ point1: { frozen: true },
80536
+ point2: { frozen: true }
80537
+ });
80538
+
80539
+ view.board.highlightInfobox = function (x, y, el) {
80540
+ var d;
80541
+
80542
+ if (Type.exists(el.D3)) {
80543
+ d = Type.evaluate(el.visProp.infoboxdigits);
80544
+ if (d === 'auto') {
80545
+ view.board.highlightCustomInfobox('(' +
80546
+ Type.autoDigits(el.D3.X()) + ' | ' +
80547
+ Type.autoDigits(el.D3.Y()) + ' | ' +
80548
+ Type.autoDigits(el.D3.Z()) + ')', el);
80549
+ } else {
80550
+ view.board.highlightCustomInfobox('(' +
80551
+ Type.toFixed(el.D3.X(), d) + ' | ' +
80552
+ Type.toFixed(el.D3.Y(), d) + ' | ' +
80553
+ Type.toFixed(el.D3.Z(), d) + ')', el);
80554
+ }
80555
+ } else {
80556
+ view.board.highlightCustomInfobox('(' + x + ', ' + y + ')', el);
80557
+ }
80558
+ };
80559
+
80560
+ return view;
80561
+ };
80562
+ JXG.registerElement('view3d', ThreeD.createView3D);
80563
+
80564
+ return ThreeD.View3D;
80565
+ });
80566
+
80567
+
80568
+ /*
80569
+ Copyright 2008-2022
80570
+ Matthias Ehmann,
80571
+ Carsten Miller,
80572
+ Andreas Walter,
80573
+ Alfred Wassermann
80574
+
80575
+ This file is part of JSXGraph.
80576
+
80577
+ JSXGraph is free software dual licensed under the GNU LGPL or MIT License.
80578
+
80579
+ You can redistribute it and/or modify it under the terms of the
80580
+
80581
+ * GNU Lesser General Public License as published by
80582
+ the Free Software Foundation, either version 3 of the License, or
80583
+ (at your option) any later version
80584
+ OR
80585
+ * MIT License: https://github.com/jsxgraph/jsxgraph/blob/master/LICENSE.MIT
80586
+
80587
+ JSXGraph is distributed in the hope that it will be useful,
80588
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
80589
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
80590
+ GNU Lesser General Public License for more details.
80591
+
80592
+ You should have received a copy of the GNU Lesser General Public License and
80593
+ the MIT License along with JSXGraph. If not, see <http://www.gnu.org/licenses/>
80594
+ and <http://opensource.org/licenses/MIT/>.
80595
+ */
80596
+ /*global JXG:true, define: true*/
80597
+
80598
+ /**
80599
+ * Create axes and rear and front walls of the
80600
+ * view3d bounding box bbox3d.
80601
+ */
80602
+ define('3d/box3d',['jxg', 'utils/type', 'math/math', 'math/geometry', '3d/view3d'
80603
+ ], function (JXG, Type, Mat, Geometry, ThreeD) {
80604
+ "use strict";
80605
+
80606
+ ThreeD.createAxes = function (board, parents, attributes) {
80607
+ var view = parents[0],
80608
+ i, j, k, i1, i2,
80609
+ attr,
80610
+ pos,
80611
+ directions = ['x', 'y', 'z'],
80612
+ suffixAxis = 'Axis',
80613
+ dir, dir1,
80614
+ sides = ['Rear', 'Front'],
80615
+ rear = [0, 0, 0], // x, y, z
80616
+ front = [0, 0, 0], // x, y, z
80617
+ from, to,
80618
+ vec1, vec2, range1, range2, na,
80619
+ ticks_attr,
80620
+ axes = {};
80621
+
80622
+ if (Type.exists(view.D3)) {
80623
+ for (i = 0; i < directions.length; i++) {
80624
+ rear[i] = view.D3.bbox3d[i][0];
80625
+ front[i] = view.D3.bbox3d[i][1];
80626
+ }
80627
+ } else {
80628
+ for (i = 0; i < directions.length; i++) {
80629
+ rear[i] = parents[1][i];
80630
+ front[i] = parents[2][1];
80631
+ }
80632
+ }
80633
+
80634
+ // Axes
80635
+ attr = Type.copyAttributes(attributes, board.options, 'axes3d');
80636
+
80637
+ pos = attr.axesposition;
80638
+ for (i = 0; i < directions.length; i++) {
80639
+ // Run through ['x', 'y', 'z']
80640
+ dir = directions[i];
80641
+ na = dir + suffixAxis;
80642
+
80643
+ if (pos === 'center') { // Axes centered
80644
+ from = [0, 0, 0];
80645
+ to = [0, 0, 0];
80646
+ to[i] = front[i];
80647
+ axes[na] = view.create('axis3d', [from, to], attr[na.toLowerCase()]);
80648
+ } else {
80649
+ na += 'Border'; // Axes bordered
80650
+ from = rear.slice();
80651
+ to = front.slice();
80652
+ if (i === 2) {
80653
+ from[1] = front[1];
80654
+ to[0] = rear[0];
80655
+ } else {
80656
+ from[i] = front[i];
80657
+ to[2] = rear[2];
80658
+ }
80659
+ to[i] = front[i];
80660
+ attr[na.toLowerCase()].lastArrow = false;
80661
+ axes[na] = view.create('axis3d', [from, to], attr[na.toLowerCase()]);
80662
+
80663
+ // TODO
80664
+ ticks_attr = {
80665
+ visible: true, // Für z-Ticks wird path nicht berechnet
80666
+ minorTicks: 0,
80667
+ tickEndings: [0, 1],
80668
+ drawLabels: false
80669
+ };
80670
+ if (i === 2) {
80671
+ ticks_attr.tickEndings = [1, 0];
80672
+ }
80673
+ axes[na + 'Ticks'] = view.create('ticks', [axes[na], 1], ticks_attr);
80674
+ }
80675
+ }
80676
+
80677
+ // Origin (2D point)
80678
+ axes.O = board.create('intersection', [
80679
+ axes[directions[0] + suffixAxis],
80680
+ axes[directions[1] + suffixAxis]
80681
+ ], {
80682
+ name: '', visible: false, withLabel: false
80683
+ });
80684
+
80685
+ // Planes
80686
+ for (i = 0; i < directions.length; i++) {
80687
+ // Run through ['x', 'y', 'z']
80688
+ i1 = (i + 1) % 3;
80689
+ i2 = (i + 2) % 3;
80690
+
80691
+ dir = directions[i];
80692
+ for (j = 0; j < sides.length; j++) {
80693
+ // Run through ['Rear', 'Front']
80694
+
80695
+ from = [0, 0, 0];
80696
+ from[i] = (j === 0) ? rear[i] : front[i];
80697
+ vec1 = [0, 0, 0];
80698
+ vec2 = [0, 0, 0];
80699
+ vec1[i1] = 1;
80700
+ vec2[i2] = 1;
80701
+ range1 = [rear[i1], front[i1]];
80702
+ range2 = [rear[i2], front[i2]];
80703
+ na = dir + 'Plane' + sides[j];
80704
+
80705
+ axes[na] =
80706
+ view.create('plane3d', [from, vec1, vec2, range1, range2], attr[na.toLowerCase()]);
80707
+ axes[na].D3.elType = 'axisplane3d';
80708
+ }
80709
+ }
80710
+
80711
+ // Axes on planes
80712
+ for (i = 0; i < directions.length; i++) {
80713
+ // Run through ['x', 'y', 'z']
80714
+ dir = directions[i];
80715
+ for (j = 0; j < sides.length; j++) {
80716
+ for (k = 1; k <= 2; k++) {
80717
+ i1 = (i + k) % 3;
80718
+ dir1 = directions[i1];
80719
+ na = dir + 'Plane' + sides[j] + dir1.toUpperCase() + 'Axis';
80720
+
80721
+ from = [0, 0, 0];
80722
+ to = [0, 0, 0];
80723
+ from[i] = to[i] = (j === 0) ? rear[i] : front[i];
80724
+
80725
+ from[i1] = rear[i1];
80726
+ to[i1] = front[i1];
80727
+
80728
+ axes[na] = view.create('axis3d', [from, to], attr[na.toLowerCase()]);
80729
+ }
80730
+ }
80731
+ }
80732
+ // axes.Y2Dxy = view.create('axis3d', [[0, sy, sz], [0, ey, sz]], attr);
80733
+
80734
+ return axes;
80735
+ };
80736
+ JXG.registerElement('axes3d', ThreeD.createAxes);
80737
+
80738
+ ThreeD.createAxis = function (board, parents, attributes) {
80739
+ var view = parents[0],
80740
+ attr,
80741
+ start = parents[1],
80742
+ end = parents[2],
80743
+ el_start, el_end, el;
80744
+
80745
+ // Use 2D points to create axis
80746
+ attr = Type.copyAttributes(attributes.point1, board.options, 'axis3d', 'point1');
80747
+ el_start = board.create('point', [
80748
+ (function (xx, yy, zz) {
80749
+ return function () { return view.project3DTo2D(xx, yy, zz)[1]; };
80750
+ })(start[0], start[1], start[2]),
80751
+ (function (xx, yy, zz) {
80752
+ return function () { return view.project3DTo2D(xx, yy, zz)[2]; };
80753
+ })(start[0], start[1], start[2])
80754
+ ], attr);
80755
+
80756
+ attr = Type.copyAttributes(attributes.point2, board.options, 'axis3d', 'point2');
80757
+ el_end = board.create('point', [
80758
+ (function (xx, yy, zz) {
80759
+ return function () { return view.project3DTo2D(xx, yy, zz)[1]; };
80760
+ })(end[0], end[1], end[2]),
80761
+ (function (xx, yy, zz) {
80762
+ return function () { return view.project3DTo2D(xx, yy, zz)[2]; };
80763
+ })(end[0], end[1], end[2])
80764
+ ], attr);
80765
+
80766
+ attr = Type.copyAttributes(attributes, board.options, 'axis3d');
80767
+ el = board.create('arrow', [el_start, el_end], attr);
80768
+
80769
+ return el;
80770
+ };
80771
+ JXG.registerElement('axis3d', ThreeD.createAxis);
80772
+
80773
+ ThreeD.createMesh = function (board, parents, attr) {
80774
+ var view = parents[0],
80775
+ point = parents[1],
80776
+ vec1 = parents[2],
80777
+ range1 = parents[3],
80778
+ vec2 = parents[4],
80779
+ range2 = parents[5],
80780
+ el;
80781
+
80782
+ el = board.create('curve', [[], []], attr);
80783
+ el.updateDataArray = function () {
80784
+ var s1 = range1[0],
80785
+ e1 = range1[1],
80786
+ s2 = range2[0],
80787
+ e2 = range2[1],
80788
+ l1, l2, res, i, sol,
80789
+ v1 = [0, 0, 0],
80790
+ v2 = [0, 0, 0],
80791
+ step = 1,
80792
+ q = [0, 0, 0];
80793
+
80794
+ this.dataX = [];
80795
+ this.dataY = [];
80796
+
80797
+ for (i = 0; i < 3; i++) {
80798
+ q[i] = Type.evaluate(point[i]);
80799
+ v1[i] = Type.evaluate(vec1[i]);
80800
+ v2[i] = Type.evaluate(vec2[i]);
80801
+ }
80802
+ l1 = JXG.Math.norm(v1, 3);
80803
+ l2 = JXG.Math.norm(v2, 3);
80804
+ for (i = 0; i < 3; i++) {
80805
+ v1[i] /= l1;
80806
+ v2[i] /= l2;
80807
+ }
80808
+ if (false) {
80809
+ sol = Mat.Geometry.getPlaneBounds(v1, v2, q, s1, e1);
80810
+ if (sol !== null) {
80811
+ s1 = sol[0];
80812
+ e1 = sol[1];
80813
+ s2 = sol[2];
80814
+ e2 = sol[3];
80815
+ }
80816
+ }
80817
+
80818
+ res = view.getMesh(
80819
+ function(u, v) { return q[0] + u * v1[0] + v * v2[0]; },
80820
+ function(u, v) { return q[1] + u * v1[1] + v * v2[1]; },
80821
+ function(u, v) { return q[2] + u * v1[2] + v * v2[2]; },
80822
+ [Math.ceil(s1), Math.floor(e1), (Math.ceil(e1) - Math.floor(s1)) / step],
80823
+ [Math.ceil(s2), Math.floor(e2), (Math.ceil(e2) - Math.floor(s2)) / step]);
80824
+ this.dataX = res[0];
80825
+ this.dataY = res[1];
80826
+ };
80827
+ return el;
80828
+ };
80829
+ JXG.registerElement('mesh3d', ThreeD.createMesh);
80830
+
80831
+ });
80832
+ /*
80833
+ Copyright 2008-2022
80834
+ Matthias Ehmann,
80835
+ Carsten Miller,
80836
+ Andreas Walter,
80837
+ Alfred Wassermann
80838
+
80839
+ This file is part of JSXGraph.
80840
+
80841
+ JSXGraph is free software dual licensed under the GNU LGPL or MIT License.
80842
+
80843
+ You can redistribute it and/or modify it under the terms of the
80844
+
80845
+ * GNU Lesser General Public License as published by
80846
+ the Free Software Foundation, either version 3 of the License, or
80847
+ (at your option) any later version
80848
+ OR
80849
+ * MIT License: https://github.com/jsxgraph/jsxgraph/blob/master/LICENSE.MIT
80850
+
80851
+ JSXGraph is distributed in the hope that it will be useful,
80852
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
80853
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
80854
+ GNU Lesser General Public License for more details.
80855
+
80856
+ You should have received a copy of the GNU Lesser General Public License and
80857
+ the MIT License along with JSXGraph. If not, see <http://www.gnu.org/licenses/>
80858
+ and <http://opensource.org/licenses/MIT/>.
80859
+ */
80860
+ /*global JXG:true, define: true*/
80861
+
80862
+ define('3d/curve3d',['jxg', 'utils/type', '3d/view3d'
80863
+ ], function (JXG, Type, ThreeD) {
80864
+ "use strict";
80865
+
80866
+ ThreeD.createCurve = function (board, parents, attr) {
80867
+ var view = parents[0],
80868
+ D3, el;
80869
+
80870
+ D3 = {
80871
+ elType: 'curve3D',
80872
+ X: parents[1],
80873
+ Y: parents[2],
80874
+ Z: parents[3],
80875
+ };
80876
+ D3.F = [D3.X, D3.Y, D3.Z];
80877
+
80878
+ el = board.create('curve', [[], []], attr);
80879
+ el.D3 = D3;
80880
+
80881
+ if (Type.isFunction(el.D3.X)) {
80882
+ // 3D curve given as t -> [X(t), Y(t), Z(t)]
80883
+
80884
+ el.D3.range = parents[4];
80885
+ el.updateDataArray = function () {
80886
+ var steps = Type.evaluate(this.visProp.numberpointshigh),
80887
+ s = Type.evaluate(this.D3.range[0]),
80888
+ e = Type.evaluate(this.D3.range[1]),
80889
+ delta = (e - s) / (steps - 1),
80890
+ c2d, t, i,
80891
+ p = [0, 0, 0];
80892
+
80893
+ this.dataX = [];
80894
+ this.dataY = [];
80895
+
80896
+ for (t = s; t <= e; t += delta) {
80897
+ for (i = 0; i < 3; i++) {
80898
+ p[i] = this.D3.F[i](t);
80899
+ }
80900
+ c2d = view.project3DTo2D(p);
80901
+ this.dataX.push(c2d[1]);
80902
+ this.dataY.push(c2d[2]);
80903
+ }
80904
+ };
80905
+ } else if (Type.isArray(el.D3.X)) {
80906
+ // 3D curve given as array of 3D points
80907
+
80908
+ el.updateDataArray = function () {
80909
+ var i,
80910
+ le = this.D3.X.length,
80911
+ c2d;
80912
+
80913
+ this.dataX = [];
80914
+ this.dataY = [];
80915
+
80916
+ for (i = 0; i < le; i++) {
80917
+ c2d = view.project3DTo2D([this.D3.X[i], this.D3.Y[i], this.D3.Z[i]]);
80918
+ this.dataX.push(c2d[1]);
80919
+ this.dataY.push(c2d[2]);
80920
+ }
80921
+ };
80922
+ }
80923
+
80924
+ return el;
80925
+ };
80926
+ JXG.registerElement('curve3d', ThreeD.createCurve);
80927
+
80928
+ });
80929
+ /*
80930
+ Copyright 2008-2022
80931
+ Matthias Ehmann,
80932
+ Carsten Miller,
80933
+ Andreas Walter,
80934
+ Alfred Wassermann
80935
+
80936
+ This file is part of JSXGraph.
80937
+
80938
+ JSXGraph is free software dual licensed under the GNU LGPL or MIT License.
80939
+
80940
+ You can redistribute it and/or modify it under the terms of the
80941
+
80942
+ * GNU Lesser General Public License as published by
80943
+ the Free Software Foundation, either version 3 of the License, or
80944
+ (at your option) any later version
80945
+ OR
80946
+ * MIT License: https://github.com/jsxgraph/jsxgraph/blob/master/LICENSE.MIT
80947
+
80948
+ JSXGraph is distributed in the hope that it will be useful,
80949
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
80950
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
80951
+ GNU Lesser General Public License for more details.
80952
+
80953
+ You should have received a copy of the GNU Lesser General Public License and
80954
+ the MIT License along with JSXGraph. If not, see <http://www.gnu.org/licenses/>
80955
+ and <http://opensource.org/licenses/MIT/>.
80956
+ */
80957
+ /*global JXG:true, define: true*/
80958
+
80959
+ /**
80960
+ * Create linear spaces of dimension at least one,
80961
+ * i.e. lines and planes.
80962
+ */
80963
+ define('3d/linspace3d',['jxg', 'utils/type', 'math/math', 'math/geometry', '3d/view3d'
80964
+ ], function (JXG, Type, Mat, Geometry, ThreeD) {
80965
+ "use strict";
80966
+
80967
+ /**
80968
+ * @class This element is used to provide a constructor for a 3D line.
80969
+ * @pseudo
80970
+ * @description There are two possibilities to create a Line3D object.
80971
+ * <p>
80972
+ * First: the line in 3D is defined by two points in 3D (Point3D).
80973
+ * The points can be either existing points or coordinate arrays of
80974
+ * the form [x, y, z].
80975
+ * <p>Second: the line in 3D is defined by a point (or coordinate array [x, y, z])
80976
+ * a direction given as array [x, y, z] and an optional range
80977
+ * given as array [s, e]. The default value for the range is [-Infinity, Infinity].
80978
+ * <p>
80979
+ * All numbers can also be provided as functions returning a number.
80980
+ *
80981
+ * @name Line3D
80982
+ * @augments JXG.Curve
80983
+ * @constructor
80984
+ * @type JXG.Curve
80985
+ * @throws {Exception} If the element cannot be constructed with the given parent
80986
+ * objects an exception is thrown.
80987
+ * @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
80988
+ * 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
80989
+ * line will determine the radius), or another {@link JXG.Circle}.
80990
+ *
80991
+ */
80992
+ ThreeD.createLine = function (board, parents, attributes) {
80993
+ var view = parents[0],
80994
+ attr, D3, point, point1, point2,
80995
+ el;
80996
+
80997
+ // Range
80998
+ D3 = {
80999
+ elType: 'line3d',
81000
+ range: parents[3] || [-Infinity, Infinity]
81001
+ };
81002
+
81003
+ // Point
81004
+ if (Type.isPoint(parents[1])) {
81005
+ point = parents[1];
81006
+ } else {
81007
+ point = view.create('point3d', parents[1], { visible: false, name: '', withLabel: false });
81008
+ }
81009
+ D3.point = point;
81010
+
81011
+ // Direction
81012
+ if (Type.isPoint(parents[2]) && Type.exists(parents[2].D3)) {
81013
+ // Line defined by two points
81014
+
81015
+ point1 = point;
81016
+ point2 = parents[2];
81017
+ D3.direction = function () {
81018
+ return [
81019
+ point2.D3.X() - point.D3.X(),
81020
+ point2.D3.Y() - point.D3.Y(),
81021
+ point2.D3.Z() - point.D3.Z()
81022
+ ];
81023
+ };
81024
+ D3.range = [0, 1];
81025
+ } else {
81026
+ // Line defined by point, direction and range
81027
+
81028
+ // Directions are handled as arrays of length 4,
81029
+ // i.e. with homogeneous coordinates.
81030
+ if (Type.isFunction(parents[2])) {
81031
+ D3.direction = parents[2];
81032
+ } else if (parents[2].length === 3) {
81033
+ D3.direction = [1].concat(parents[2]);
81034
+ } else if (parents[2].length === 4) {
81035
+ D3.direction = parents[2];
81036
+ } else {
81037
+ // Throw error
81038
+ }
81039
+
81040
+ // Direction given as array
81041
+ D3.getPointCoords = function (r) {
81042
+ var p = [],
81043
+ d = [],
81044
+ i;
81045
+
81046
+ p.push(point.D3.X());
81047
+ p.push(point.D3.Y());
81048
+ p.push(point.D3.Z());
81049
+
81050
+ if (Type.isFunction(D3.direction)) {
81051
+ d = D3.direction();
81052
+ } else {
81053
+ for (i = 1; i < 4; i++) {
81054
+ d.push(Type.evaluate(D3.direction[i]));
81055
+ }
81056
+ }
81057
+ if (Math.abs(r) === Infinity) {
81058
+ r = view.intersectionLineCube(p, d, r);
81059
+ }
81060
+ return [
81061
+ p[0] + d[0] * r,
81062
+ p[1] + d[1] * r,
81063
+ p[2] + d[2] * r
81064
+ ];
81065
+
81066
+ };
81067
+
81068
+ attr = Type.copyAttributes(attributes, board.options, 'line3d', 'point1');
81069
+ point1 = view.create('point3d', [
81070
+ function () {
81071
+ return D3.getPointCoords(Type.evaluate(D3.range[0]));
81072
+ }
81073
+ ], attr);
81074
+ attr = Type.copyAttributes(attributes, board.options, 'line3d', 'point2');
81075
+ point2 = view.create('point3d', [
81076
+ function () {
81077
+ return D3.getPointCoords(Type.evaluate(D3.range[1]));
81078
+ }
81079
+ ], attr);
81080
+ }
81081
+
81082
+ attr = Type.copyAttributes(attributes, board.options, 'line3d');
81083
+ el = view.create('segment', [point1, point2], attr);
81084
+ el.point1 = point1;
81085
+ el.point2 = point2;
81086
+ point1.addChild(el);
81087
+ point2.addChild(el);
81088
+ el.D3 = D3;
81089
+
81090
+ return el;
81091
+ };
81092
+ JXG.registerElement('line3d', ThreeD.createLine);
81093
+
81094
+ ThreeD.createPlane = function (board, parents, attributes) {
81095
+ var view = parents[0],
81096
+ attr, D3,
81097
+ point,
81098
+ vec1 = parents[2],
81099
+ vec2 = parents[3],
81100
+ el, grid, update;
81101
+
81102
+ // D3: {
81103
+ // point,
81104
+ // vec1,
81105
+ // vec2,
81106
+ // poin1,
81107
+ // point2,
81108
+ // normal array of len 3
81109
+ // d
81110
+ // }
81111
+ D3 = {
81112
+ elType: 'plane3d',
81113
+ dir1: [],
81114
+ dir2: [],
81115
+ range1: parents[4],
81116
+ range2: parents[5],
81117
+ vec1: vec1,
81118
+ vec2: vec2
81119
+ };
81120
+
81121
+ if (Type.isPoint(parents[1])) {
81122
+ point = parents[1];
81123
+ } else {
81124
+ point = view.create('point3d', parents[1], { visible: false, name: '', withLabel: false });
81125
+ }
81126
+ D3.point = point;
81127
+
81128
+ D3.updateNormal = function () {
81129
+ var i;
81130
+ for (i = 0; i < 3; i++) {
81131
+ D3.dir1[i] = Type.evaluate(D3.vec1[i]);
81132
+ D3.dir2[i] = Type.evaluate(D3.vec2[i]);
81133
+ }
81134
+ D3.normal = Mat.crossProduct(D3.dir1, D3.dir2);
81135
+ D3.d = Mat.innerProduct(D3.point.D3.coords.slice(1), D3.normal, 3);
81136
+ };
81137
+ D3.updateNormal();
81138
+
81139
+ attr = Type.copyAttributes(attributes, board.options, 'plane3d');
81140
+ el = board.create('curve', [[], []], attr);
81141
+ el.D3 = D3;
81142
+
81143
+ el.updateDataArray = function () {
81144
+ var s1, e1, s2, e2,
81145
+ c2d, l1, l2,
81146
+ planes = ['xPlaneRear', 'yPlaneRear', 'zPlaneRear'],
81147
+ points = [],
81148
+ v1 = [0, 0, 0],
81149
+ v2 = [0, 0, 0],
81150
+ q = [0, 0, 0],
81151
+ p = [0, 0, 0], d, i, j, a, b, first, pos, pos_akt;
81152
+
81153
+ this.dataX = [];
81154
+ this.dataY = [];
81155
+
81156
+ this.D3.updateNormal();
81157
+
81158
+ // Infinite plane
81159
+ if (this.D3.elType !== 'axisplane3d' && view.defaultAxes &&
81160
+ (!D3.range1 || !D3.range2)
81161
+ ) {
81162
+
81163
+ // Start with the rear plane.
81164
+ // Determine the intersections with the view bbox3d
81165
+ // For each face of the bbox3d we determine two points
81166
+ // which are the ends of the intersection line.
81167
+ // We start with the three rear planes.
81168
+ for (j = 0; j < planes.length; j++) {
81169
+ p = view.intersectionPlanePlane(this, view.defaultAxes[planes[j]]);
81170
+
81171
+ if (p[0].length === 3 && p[1].length === 3) {
81172
+ // This test is necessary to filter out intersection lines which are
81173
+ // identical to intersections of axis planes (they would occur twice).
81174
+ for (i = 0; i < points.length; i++) {
81175
+ if ((Geometry.distance(p[0], points[i][0], 3) < Mat.eps && Geometry.distance(p[1], points[i][1], 3) < Mat.eps) ||
81176
+ (Geometry.distance(p[0], points[i][1], 3) < Mat.eps && Geometry.distance(p[1], points[i][0], 3) < Mat.eps)) {
81177
+ break;
81178
+ }
81179
+ }
81180
+ if (i === points.length) {
81181
+ points.push(p.slice());
81182
+ }
81183
+ }
81184
+
81185
+ // Point on the front plane of the bbox3d
81186
+ p = [0, 0, 0];
81187
+ p[j] = view.D3.bbox3d[j][1];
81188
+
81189
+ // d is the rhs of the Hesse normal form of the front plane.
81190
+ d = Mat.innerProduct(p, view.defaultAxes[planes[j]].D3.normal, 3);
81191
+ p = view.intersectionPlanePlane(this, view.defaultAxes[planes[j]], d);
81192
+
81193
+ if (p[0].length === 3 && p[1].length === 3) {
81194
+ // Do the same test as above
81195
+ for (i = 0; i < points.length; i++) {
81196
+ if ((Geometry.distance(p[0], points[i][0], 3) < Mat.eps && Geometry.distance(p[1], points[i][1], 3) < Mat.eps) ||
81197
+ (Geometry.distance(p[0], points[i][1], 3) < Mat.eps && Geometry.distance(p[1], points[i][0], 3) < Mat.eps)) {
81198
+ break;
81199
+ }
81200
+ }
81201
+ if (i === points.length) {
81202
+ points.push(p.slice());
81203
+ }
81204
+ }
81205
+ }
81206
+
81207
+ // Concatenate the intersection points to a polygon.
81208
+ // If all wents well, each intersection should appear
81209
+ // twice in the list.
81210
+ first = 0;
81211
+ pos = first;
81212
+ i = 0;
81213
+ do {
81214
+ p = points[pos][i];
81215
+ if (p.length === 3) {
81216
+ c2d = view.project3DTo2D(p);
81217
+ this.dataX.push(c2d[1]);
81218
+ this.dataY.push(c2d[2]);
81219
+ }
81220
+ i = (i + 1) % 2;
81221
+ p = points[pos][i];
81222
+
81223
+ pos_akt = pos;
81224
+ for (j = 0; j < points.length; j++) {
81225
+ if (j !== pos && Geometry.distance(p, points[j][0]) < Mat.eps) {
81226
+ pos = j;
81227
+ i = 0;
81228
+ break;
81229
+ }
81230
+ if (j !== pos && Geometry.distance(p, points[j][1]) < Mat.eps) {
81231
+ pos = j;
81232
+ i = 1;
81233
+ break;
81234
+ }
81235
+ }
81236
+ if (pos === pos_akt) {
81237
+ console.log("Error: update plane3d: did not find next", pos);
81238
+ break;
81239
+ }
81240
+ } while (pos !== first);
81241
+ c2d = view.project3DTo2D(points[first][0]);
81242
+ this.dataX.push(c2d[1]);
81243
+ this.dataY.push(c2d[2]);
81244
+
81245
+ } else {
81246
+ // 3D bounded flat
81247
+ s1 = Type.evaluate(this.D3.range1[0]);
81248
+ e1 = Type.evaluate(this.D3.range1[1]);
81249
+ s2 = Type.evaluate(this.D3.range2[0]);
81250
+ e2 = Type.evaluate(this.D3.range2[1]);
81251
+
81252
+ q = this.D3.point.D3.coords.slice(1);
81253
+
81254
+ v1 = this.D3.dir1.slice();
81255
+ v2 = this.D3.dir2.slice();
81256
+ l1 = Mat.norm(v1, 3);
81257
+ l2 = Mat.norm(v2, 3);
81258
+ for (i = 0; i < 3; i++) {
81259
+ v1[i] /= l1;
81260
+ v2[i] /= l2;
81261
+ }
81262
+
81263
+ for (j = 0; j < 4; j++) {
81264
+ switch (j) {
81265
+ case 0: a = s1; b = s2; break;
81266
+ case 1: a = e1; b = s2; break;
81267
+ case 2: a = e1; b = e2; break;
81268
+ case 3: a = s1; b = e2;
81269
+ }
81270
+ for (i = 0; i < 3; i++) {
81271
+ p[i] = q[i] + a * v1[i] + b * v2[i];
81272
+ }
81273
+ c2d = view.project3DTo2D(p);
81274
+ this.dataX.push(c2d[1]);
81275
+ this.dataY.push(c2d[2]);
81276
+ }
81277
+ // Close the curve
81278
+ this.dataX.push(this.dataX[0]);
81279
+ this.dataY.push(this.dataY[0]);
81280
+ }
81281
+ };
81282
+
81283
+ attr = Type.copyAttributes(attributes.mesh3d, board.options, 'mesh3d');
81284
+
81285
+ if (D3.range1 && D3.range2) {
81286
+ grid = view.create('mesh3d', [point.D3.coords.slice(1), vec1, D3.range1, vec2, D3.range2], attr);
81287
+ el.grid = grid;
81288
+ el.inherits.push(grid);
81289
+ }
81290
+
81291
+ // update = el.update;
81292
+ // el.update = function () {
81293
+ // if (el.needsUpdate) {
81294
+ // update.apply(el);
81295
+ // }
81296
+ // return this;
81297
+ // };
81298
+
81299
+ return el;
81300
+ };
81301
+ JXG.registerElement('plane3d', ThreeD.createPlane);
81302
+
81303
+ });
81304
+ /*
81305
+ Copyright 2008-2022
81306
+ Matthias Ehmann,
81307
+ Carsten Miller,
81308
+ Andreas Walter,
81309
+ Alfred Wassermann
81310
+
81311
+ This file is part of JSXGraph.
81312
+
81313
+ JSXGraph is free software dual licensed under the GNU LGPL or MIT License.
81314
+
81315
+ You can redistribute it and/or modify it under the terms of the
81316
+
81317
+ * GNU Lesser General Public License as published by
81318
+ the Free Software Foundation, either version 3 of the License, or
81319
+ (at your option) any later version
81320
+ OR
81321
+ * MIT License: https://github.com/jsxgraph/jsxgraph/blob/master/LICENSE.MIT
81322
+
81323
+ JSXGraph is distributed in the hope that it will be useful,
81324
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
81325
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
81326
+ GNU Lesser General Public License for more details.
81327
+
81328
+ You should have received a copy of the GNU Lesser General Public License and
81329
+ the MIT License along with JSXGraph. If not, see <http://www.gnu.org/licenses/>
81330
+ and <http://opensource.org/licenses/MIT/>.
81331
+ */
81332
+ /*global JXG:true, define: true*/
81333
+
81334
+ define('3d/point3d',['jxg', 'base/constants', 'math/math', 'math/geometry', 'utils/type', '3d/view3d'
81335
+ ], function (JXG, Const, Mat, Geometry, Type, ThreeD) {
81336
+ "use strict";
81337
+
81338
+ /**
81339
+ * @class This element is used to provide a constructor for a 3D Point.
81340
+ * @pseudo
81341
+ * @description There are two possibilities to create a Line3D object.
81342
+ * <p>
81343
+ * First: the line in 3D is defined by two points in 3D (Point3D).
81344
+ * The points can be either existing points or coordinate arrays of
81345
+ * the form [x, y, z].
81346
+ * <p>Second: the line in 3D is defined by a point (or coordinate array [x, y, z])
81347
+ * a direction given as array [x, y, z] and an optional range
81348
+ * given as array [s, e]. The default value for the range is [-Infinity, Infinity].
81349
+ * <p>
81350
+ * All numbers can also be provided as functions returning a number.
81351
+ *
81352
+ * @name Point3D
81353
+ * @augments JXG.Point
81354
+ * @constructor
81355
+ * @type JXG.Point
81356
+ * @throws {Exception} If the element cannot be constructed with the given parent
81357
+ * objects an exception is thrown.
81358
+ * @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
81359
+ * 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
81360
+ * line will determine the radius), or another {@link JXG.Circle}.
81361
+ *
81362
+ */
81363
+ ThreeD.createPoint = function (board, parents, attributes) {
81364
+ var view = parents[0],
81365
+ attr, update2D, D3,
81366
+ i, c2d,
81367
+ el;
81368
+
81369
+ attr = Type.copyAttributes(attributes, board.options, 'point3d');
81370
+
81371
+ D3 = {
81372
+ elType: 'point3d',
81373
+ coords: [1, 0, 0, 0],
81374
+ X: function () { return this.coords[1]; },
81375
+ Y: function () { return this.coords[2]; },
81376
+ Z: function () { return this.coords[3]; }
81377
+ };
81378
+
81379
+ // If the last element of partents is a 3D object, the point is a glider
81380
+ // on that element.
81381
+ if (parents.length > 2 && Type.exists(parents[parents.length - 1].D3)) {
81382
+ D3.slide = parents.pop();
81383
+ } else {
81384
+ D3.slide = null;
81385
+ }
81386
+
81387
+ if (parents.length === 2) {
81388
+ D3.F = parents[1]; // (Array [x, y, z] | function) returning [x, y, z]
81389
+ D3.coords = [1].concat(Type.evaluate(D3.F));
81390
+ } else if (parents.length === 4) {
81391
+ D3.F = parents.slice(1); // 3 numbers | functions
81392
+ for (i = 0; i < 3; i++) {
81393
+ D3.coords[i + 1] = Type.evaluate(D3.F[i]);
81394
+ }
81395
+ } else {
81396
+ // Throw error
81397
+ }
81398
+
81399
+ /**
81400
+ * Update the 4D coords array
81401
+ * @returns Object
81402
+ */
81403
+ D3.updateCoords = function () {
81404
+ var res, i;
81405
+ if (Type.isFunction(this.F)) {
81406
+ res = Type.evaluate(this.F);
81407
+ this.coords = [1, res[0], res[1], res[2]];
81408
+ } else {
81409
+ this.coords[0] = 1;
81410
+ for (i = 0; i < 3; i++) {
81411
+ if (Type.isFunction(this.F[i])) {
81412
+ this.coords[i + 1] = Type.evaluate(this.F[i]);
81413
+ }
81414
+ }
81415
+ }
81416
+ return this;
81417
+ };
81418
+ D3.updateCoords();
81419
+
81420
+ c2d = view.project3DTo2D(D3.coords);
81421
+ el = board.create('point', c2d, attr);
81422
+ el.D3 = D3;
81423
+ el.D3.c2d = el.coords.usrCoords.slice(); // Copy of the coordinates to detect dragging
81424
+ update2D = el.update;
81425
+
81426
+ if (el.D3.slide) {
81427
+ el._minFunc = function (n, m, x, con) {
81428
+ var surface = el.D3.slide.D3,
81429
+ c3d = [1, surface.X(x[0], x[1]), surface.Y(x[0], x[1]), surface.Z(x[0], x[1])],
81430
+ c2d = view.project3DTo2D(c3d);
81431
+
81432
+ con[0] = el.X() - c2d[1];
81433
+ con[1] = el.Y() - c2d[2];
81434
+
81435
+ return con[0] * con[0] + con[1] * con[1];
81436
+ };
81437
+
81438
+ el.projectCoords2Surface = function () {
81439
+ var n = 2, // # of variables
81440
+ m = 2, // number of constraints
81441
+ x = [0, 0],
81442
+ // Various Cobyla constants, see Cobyla docs in Cobyja.js
81443
+ rhobeg = 5.0,
81444
+ rhoend = 1.0e-6,
81445
+ iprint = 0,
81446
+ maxfun = 200,
81447
+ surface = this.D3.slide.D3,
81448
+ r, c3d, c2d;
81449
+
81450
+ if (Type.exists(this.D3.params)) {
81451
+ x = this.D3.params.slice();
81452
+ }
81453
+ r = Mat.Nlp.FindMinimum(this._minFunc, n, m, x, rhobeg, rhoend, iprint, maxfun);
81454
+
81455
+ c3d = [1, surface.X(x[0], x[1]), surface.Y(x[0], x[1]), surface.Z(x[0], x[1])];
81456
+ c2d = view.project3DTo2D(c3d);
81457
+ this.D3.params = x;
81458
+ this.D3.coords = c3d;
81459
+ this.coords.setCoordinates(Const.COORDS_BY_USER, c2d);
81460
+ this.D3.c2d = c2d;
81461
+ };
81462
+ }
81463
+
81464
+ el.update = function (drag) {
81465
+ var c3d, foot;
81466
+ if (!this.needsUpdate) {
81467
+ return this;
81468
+ }
81469
+
81470
+ // Update is called in from two methods:
81471
+ // Once in setToPositionDirectly and
81472
+ // once in the subsequent board.update
81473
+ if (this.draggable() &&
81474
+ Geometry.distance(this.D3.c2d, this.coords.usrCoords) !== 0) {
81475
+
81476
+ if (this.D3.slide) {
81477
+ this.projectCoords2Surface();
81478
+ } else {
81479
+ // Drag the point in its xy plane
81480
+ foot = [1, 0, 0, this.D3.coords[3]];
81481
+ c3d = view.project2DTo3DPlane(el, [1, 0, 0, 1], foot);
81482
+ if (c3d[0] !== 0) {
81483
+ this.D3.coords = view.project3DToCube(c3d);
81484
+ }
81485
+ }
81486
+ } else {
81487
+ this.D3.updateCoords();
81488
+ // Update 2D point from its 3D view
81489
+ el.coords.setCoordinates(Const.COORDS_BY_USER,
81490
+ view.project3DTo2D([1, this.D3.X(), this.D3.Y(), this.D3.Z()])
81491
+ );
81492
+ }
81493
+ this.D3.c2d = el.coords.usrCoords.slice();
81494
+
81495
+ update2D.apply(this, [drag]);
81496
+ return this;
81497
+ };
81498
+
81499
+ return el;
81500
+ };
81501
+ JXG.registerElement('point3d', ThreeD.createPoint);
81502
+
81503
+ });
81504
+ /*
81505
+ Copyright 2008-2022
81506
+ Matthias Ehmann,
81507
+ Carsten Miller,
81508
+ Andreas Walter,
81509
+ Alfred Wassermann
81510
+
81511
+ This file is part of JSXGraph.
81512
+
81513
+ JSXGraph is free software dual licensed under the GNU LGPL or MIT License.
81514
+
81515
+ You can redistribute it and/or modify it under the terms of the
81516
+
81517
+ * GNU Lesser General Public License as published by
81518
+ the Free Software Foundation, either version 3 of the License, or
81519
+ (at your option) any later version
81520
+ OR
81521
+ * MIT License: https://github.com/jsxgraph/jsxgraph/blob/master/LICENSE.MIT
81522
+
81523
+ JSXGraph is distributed in the hope that it will be useful,
81524
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
81525
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
81526
+ GNU Lesser General Public License for more details.
81527
+
81528
+ You should have received a copy of the GNU Lesser General Public License and
81529
+ the MIT License along with JSXGraph. If not, see <http://www.gnu.org/licenses/>
81530
+ and <http://opensource.org/licenses/MIT/>.
81531
+ */
81532
+ /*global JXG:true, define: true*/
81533
+
81534
+ define('3d/surface3d',['jxg', 'utils/type', '3d/view3d'
81535
+ ], function (JXG, Type, ThreeD) {
81536
+ "use strict";
81537
+ ThreeD.createParametricSurface = function (board, parents, attributes) {
81538
+ var view = parents[0],
81539
+ attr,
81540
+ X = parents[1],
81541
+ Y = parents[2],
81542
+ Z = parents[3],
81543
+ range_u = parents[4],
81544
+ range_v = parents[5],
81545
+ D3, el;
81546
+
81547
+ D3 = {
81548
+ elType: 'surface3d',
81549
+ X: X,
81550
+ Y: Y,
81551
+ Z: Z,
81552
+ range_u: range_u,
81553
+ range_v: range_v
81554
+ };
81555
+ attr = Type.copyAttributes(attributes, board.options, 'surface3d');
81556
+ el = board.create('curve', [[], []], attr);
81557
+ el.updateDataArray = function () {
81558
+ var steps_u = Type.evaluate(this.visProp.stepsu),
81559
+ steps_v = Type.evaluate(this.visProp.stepsv),
81560
+ 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]));
81563
+ this.dataX = res[0];
81564
+ this.dataY = res[1];
81565
+ };
81566
+ el.D3 = D3;
81567
+
81568
+ return el;
81569
+ };
81570
+ JXG.registerElement('parametricsurface3d', ThreeD.createParametricSurface);
81571
+
81572
+ ThreeD.createFunctiongraph = function (board, parents, attributes) {
81573
+ var view = parents[0],
81574
+ X = function(u, v) { return u; },
81575
+ Y = function(u, v) { return v; },
81576
+ Z = parents[1],
81577
+ range_u = parents[2],
81578
+ range_v = parents[3];
81579
+
81580
+ return view.create('parametricsurface3d', [X, Y, Z, range_u, range_v], attributes);
81581
+ };
81582
+ JXG.registerElement('functiongraph3d', ThreeD.createFunctiongraph);
81583
+
81584
+ });
79896
81585
  /*global define: true*/
79897
81586
  define('../build/core.deps.js',[
79898
81587
  'jxg',
@@ -79965,7 +81654,14 @@ define('../build/core.deps.js',[
79965
81654
  'element/checkbox',
79966
81655
  'element/input',
79967
81656
  'element/button',
79968
- 'base/foreignobject'
81657
+ 'base/foreignobject',
81658
+ '3d/box3d',
81659
+ '3d/curve3d',
81660
+ '3d/linspace3d',
81661
+ '3d/point3d',
81662
+ '3d/surface3d',
81663
+ '3d/threed',
81664
+ '3d/view3d'
79969
81665
  ], function (JXG, Env) {
79970
81666
  "use strict";
79971
81667