jsxgraph 1.4.1 → 1.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/base/ticks.js CHANGED
@@ -1016,12 +1016,13 @@ define([
1016
1016
  * @private
1017
1017
  */
1018
1018
  formatLabelText: function(value) {
1019
- var labelText = value.toString(),
1019
+ var labelText,
1020
1020
  digits,
1021
1021
  ev_s = Type.evaluate(this.visProp.scalesymbol);
1022
1022
 
1023
1023
  // if value is Number
1024
1024
  if (Type.isNumber(value)) {
1025
+ labelText = (Math.round(value * 1.e13) / 1.e13).toString();
1025
1026
  if (labelText.length > Type.evaluate(this.visProp.maxlabellength) ||
1026
1027
  labelText.indexOf('e') !== -1) {
1027
1028
 
@@ -1030,7 +1031,9 @@ define([
1030
1031
  // Use the deprecated attribute "precision"
1031
1032
  digits = Type.evaluate(this.visProp.precision);
1032
1033
  }
1033
- labelText = value.toPrecision(digits).toString();
1034
+
1035
+ //labelText = value.toPrecision(digits).toString();
1036
+ labelText = value.toExponential(digits).toString();
1034
1037
  }
1035
1038
 
1036
1039
  if (Type.evaluate(this.visProp.beautifulscientificticklabels)) {
@@ -1043,6 +1046,8 @@ define([
1043
1046
  // trim trailing .
1044
1047
  labelText = labelText.replace(/\.$/, '');
1045
1048
  }
1049
+ } else {
1050
+ labelText = value.toString();
1046
1051
  }
1047
1052
 
1048
1053
  if (ev_s.length > 0) {
@@ -1262,6 +1267,8 @@ define([
1262
1267
  attr.id = this.id + ld.i + 'Label' + this.labelCounter;
1263
1268
 
1264
1269
  label = Text.createText(this.board, [ld.x, ld.y, ld.t], attr);
1270
+ this.addChild(label);
1271
+ label.setParents(this);
1265
1272
  label.isDraggable = false;
1266
1273
  label.dump = false;
1267
1274
  this.labels.push(label);
@@ -592,9 +592,6 @@ define([
592
592
  b.addChild(t);
593
593
  }
594
594
 
595
-
596
-
597
-
598
595
  t.elType = 'midpoint';
599
596
  t.setParents([a.id, b.id]);
600
597
 
@@ -804,14 +801,21 @@ define([
804
801
  };
805
802
 
806
803
  /**
807
- * @class A parallel is a line through a given point with the same slope as a given line.
804
+ * @class A parallel is a line through a given point with the same slope as a given line or
805
+ * the line through two given point.
806
+ * <p>
807
+ * If original line is given as a JSXGraph line object, the resulting parallel line will be defined by the given point and an
808
+ * infinitely far away point (an ideal point). That means, the line can not be shortened to a segment.
809
+ * <p>
810
+ * If the original line is given as two points, the resulting parallel line can be shortened to a a segment.
808
811
  * @pseudo
809
812
  * @name Parallel
810
813
  * @augments Line
811
814
  * @constructor
812
815
  * @type JXG.Line
813
816
  * @throws {Error} If the element cannot be constructed with the given parent objects an exception is thrown.
814
- * @param {JXG.Line_JXG.Point} l,p The constructed line contains p and has the same slope as l.
817
+ * @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
818
+ * constructed line contains p and has the same slope as the line through p1 and p2.
815
819
  * @example
816
820
  * // Create a parallel
817
821
  * var p1 = board.create('point', [0.0, 2.0]);
@@ -829,22 +833,47 @@ define([
829
833
  * var plex1_p3 = plex1_board.create('point', [3.0, 3.0]);
830
834
  * var plex1_pl1 = plex1_board.create('parallel', [plex1_l1, plex1_p3]);
831
835
  * </script><pre>
836
+ * @example
837
+ * var p1, p2, p3, l1, pl1;
838
+ *
839
+ * p1 = board.create('point', [0.0, 2.0]);
840
+ * p2 = board.create('point', [2.0, 1.0]);
841
+ * l1 = board.create('line', [p1, p2]);
842
+ *
843
+ * p3 = board.create('point', [1.0, 3.0]);
844
+ * pl1 = board.create('parallel', [p1, p2, p3], {straightFirst: false, straightLast: false});
845
+ *
846
+ * </pre><div id="JXGd643305d-20c3-4a88-91f9-8d0c4448594f" class="jxgbox" style="width: 300px; height: 300px;"></div>
847
+ * <script type="text/javascript">
848
+ * (function() {
849
+ * var board = JXG.JSXGraph.initBoard('JXGd643305d-20c3-4a88-91f9-8d0c4448594f',
850
+ * {boundingbox: [-8, 8, 8,-8], axis: true, showcopyright: false, shownavigation: false});
851
+ * var p1, p2, p3, l1, pl1;
852
+ *
853
+ * p1 = board.create('point', [0.0, 2.0]);
854
+ * p2 = board.create('point', [2.0, 1.0]);
855
+ * l1 = board.create('line', [p1, p2]);
856
+ *
857
+ * p3 = board.create('point', [1.0, 3.0]);
858
+ * pl1 = board.create('parallel', [p1, p2, p3], {straightFirst: false, straightLast: false});
859
+ *
860
+ * })();
861
+ *
862
+ * </script><pre>
863
+ *
832
864
  */
833
865
  JXG.createParallel = function (board, parents, attributes) {
834
- var p, pp, pl, li, i, attr;
866
+ var p, pp, pl, li, i, attr, ty = 1;
835
867
 
836
868
  for (i = 0; i < parents.length; ++i) {
837
869
  parents[i] = board.select(parents[i]);
838
870
  }
839
871
  p = null;
840
872
  if (parents.length === 3) {
873
+ // Line / segment through point parents[2] which is parallel to line through parents[0] and parents[1]
841
874
  parents = Type.providePoints(board, parents, attributes, 'point');
842
- // line through point parents[2] which is parallel to line through parents[0] and parents[1]
843
875
  p = parents[2];
844
- /** @ignore */
845
- li = function () {
846
- return Mat.crossProduct(parents[0].coords.usrCoords, parents[1].coords.usrCoords);
847
- };
876
+ ty = 0;
848
877
  } else if (Type.isPointType(board, parents[0])) {
849
878
  // Parallel to line parents[1] through point parents[0]
850
879
  p = Type.providePoints(board, [parents[0]], attributes, 'point')[0];
@@ -866,11 +895,19 @@ define([
866
895
  }
867
896
 
868
897
  attr = Type.copyAttributes(attributes, board.options, 'parallel', 'point');
869
- pp = board.create('point', [
870
- function () {
871
- return Mat.crossProduct([1, 0, 0], li());
872
- }
873
- ], attr);
898
+ if (ty === 1) {
899
+ // Line is given by line element. The parallel line is
900
+ // constructed as line through an ideal point.
901
+ pp = board.create('point', [
902
+ function () {
903
+ return Mat.crossProduct([1, 0, 0], li());
904
+ }
905
+ ], attr);
906
+ } else {
907
+ // Line is given by two points. The parallel line is
908
+ // constructed as line through two finite point.
909
+ pp = board.create('parallelpoint', parents, attr);
910
+ }
874
911
  pp.isDraggable = true;
875
912
 
876
913
  attr = Type.copyAttributes(attributes, board.options, 'parallel');
@@ -904,31 +941,33 @@ define([
904
941
  };
905
942
 
906
943
  /**
907
- * @class An arrow parallel is a parallel segment with an arrow attached.
944
+ * @class An arrow parallel is a segment with an arrow attached which is parallel through a given segment, given by its defining two points,
945
+ * through a given point.
946
+ * <p>
908
947
  * @pseudo
909
948
  * @constructor
910
949
  * @name Arrowparallel
911
950
  * @type Parallel
912
951
  * @augments Parallel
913
952
  * @throws {Error} If the element cannot be constructed with the given parent objects an exception is thrown.
914
- * @param {JXG.Line_JXG.Point} l,p The constructed arrow contains p and has the same slope as l.
953
+ * @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.
915
954
  * @example
916
955
  * // Create a parallel
917
956
  * var p1 = board.create('point', [0.0, 2.0]);
918
957
  * var p2 = board.create('point', [2.0, 1.0]);
919
- * var l1 = board.create('line', [p1, p2]);
958
+ * var l1 = board.create('segment', [p1, p2]);
920
959
  *
921
960
  * var p3 = board.create('point', [3.0, 3.0]);
922
- * var pl1 = board.create('arrowparallel', [l1, p3]);
961
+ * var pl1 = board.create('arrowparallel', [p1, p2, p3]);
923
962
  * </pre><div class="jxgbox" id="JXGeeacdf99-036f-4e83-aeb6-f7388423e369" style="width: 400px; height: 400px;"></div>
924
963
  * <script type="text/javascript">
925
964
  * (function () {
926
965
  * var plex1_board = JXG.JSXGraph.initBoard('JXGeeacdf99-036f-4e83-aeb6-f7388423e369', {boundingbox: [-1, 9, 9, -1], axis: true, showcopyright: false, shownavigation: false});
927
966
  * var plex1_p1 = plex1_board.create('point', [0.0, 2.0]);
928
967
  * var plex1_p2 = plex1_board.create('point', [2.0, 1.0]);
929
- * var plex1_l1 = plex1_board.create('line', [plex1_p1, plex1_p2]);
968
+ * var plex1_l1 = plex1_board.create('segment', [plex1_p1, plex1_p2]);
930
969
  * var plex1_p3 = plex1_board.create('point', [3.0, 3.0]);
931
- * var plex1_pl1 = plex1_board.create('arrowparallel', [plex1_l1, plex1_p3]);
970
+ * var plex1_pl1 = plex1_board.create('arrowparallel', [plex1_p1, plex1_p2, plex1_p3]);
932
971
  * })();
933
972
  * </script><pre>
934
973
  */
@@ -1375,7 +1414,7 @@ define([
1375
1414
  };
1376
1415
 
1377
1416
  /**
1378
- * @class Bisector lines are similar to {@link Bisector} but takes two lines as parent elements. The resulting element is
1417
+ * @class Bisector lines are similar to {@link Bisector} but take two lines as parent elements. The resulting element is
1379
1418
  * a composition of two lines.
1380
1419
  * @pseudo
1381
1420
  * @constructor
@@ -463,6 +463,10 @@ define([
463
463
  p2.dump = false;
464
464
  l1.dump = false;
465
465
  l2.dump = false;
466
+ if (withText) {
467
+ t.dump = false;
468
+ }
469
+
466
470
 
467
471
  p3.elType = 'slider';
468
472
  p3.parents = parents;
@@ -480,6 +484,14 @@ define([
480
484
  p3.inherits.push(ti);
481
485
  }
482
486
 
487
+ p3.getParents = function() {
488
+ return [
489
+ this.point1.coords.usrCoords.slice(1),
490
+ this.point2.coords.usrCoords.slice(1),
491
+ [this._smin, this.position * (this._smax - this._smin) + this._smin, this._smax]
492
+ ];
493
+ };
494
+
483
495
  p3.baseline.on('up', function(evt) {
484
496
  var pos, c;
485
497
 
package/src/jsxgraph.js CHANGED
@@ -228,6 +228,7 @@ define([
228
228
  */
229
229
  _setARIA: function(container, attr) {
230
230
  var doc = attr.document || document,
231
+ doc_glob,
231
232
  node_jsx, newNode, parent,
232
233
  id_label, id_description;
233
234
 
@@ -236,18 +237,19 @@ define([
236
237
  }
237
238
 
238
239
  node_jsx = doc.getElementById(container);
240
+ doc_glob = node_jsx.ownerDocument; // This is the window.document element, needed below.
239
241
  parent = node_jsx.parentNode;
240
242
 
241
243
  id_label = container + '_ARIAlabel';
242
244
  id_description = container + '_ARIAdescription';
243
245
 
244
- newNode = doc.createElement('div');
246
+ newNode = doc_glob.createElement('div');
245
247
  newNode.innerHTML = attr.title;
246
248
  newNode.setAttribute('id', id_label);
247
249
  newNode.style.display = 'none';
248
250
  parent.insertBefore(newNode, node_jsx);
249
251
 
250
- newNode = doc.createElement('div');
252
+ newNode = doc_glob.createElement('div');
251
253
  newNode.innerHTML = attr.description;
252
254
  newNode.setAttribute('id', id_description);
253
255
  newNode.style.display = 'none';
@@ -273,12 +275,12 @@ define([
273
275
  }
274
276
 
275
277
  id = board.containerObj.getAttribute('aria-labelledby');
276
- node = document.getElementById(id);
278
+ node = doc.getElementById(id);
277
279
  if (node && node.parentNode) {
278
280
  node.parentNode.removeChild(node);
279
281
  }
280
282
  id = board.containerObj.getAttribute('aria-describedby');
281
- node = document.getElementById(id);
283
+ node = doc.getElementById(id);
282
284
  if (node && node.parentNode) {
283
285
  node.parentNode.removeChild(node);
284
286
  }
@@ -55,10 +55,9 @@ var JXG = {},
55
55
  //// ////
56
56
  //// Attention! Slows down the loading time! ////
57
57
  //////////////////////////////////////////////////////////////////////////
58
- var preventCachingFiles = true;
59
-
60
- // check and table are initialized at the end of the life
61
- var table,
58
+ var preventCachingFiles = true,
59
+ // check and table are initialized at the end of the life
60
+ table,
62
61
  waitlist = [],
63
62
  checkwaitlist = true,
64
63
  checkJXG = function () {
@@ -146,6 +145,9 @@ var JXG = {},
146
145
  ////////////////////////////////////////////////////////////////////////////////
147
146
 
148
147
  JXG.Load = (function () {
148
+ var requirePathLocation = 'href',
149
+ allowDocumentWrite = true;
150
+
149
151
  function createHTMLElement(tagName, attr) {
150
152
  var el = document.createElement(tagName), i,
151
153
  a_name, a_value, a_object;
@@ -162,14 +164,10 @@ var JXG = {},
162
164
  return el;
163
165
  }
164
166
 
165
- var allowDocumentWrite = true;
166
-
167
167
  window.onload = function () {
168
168
  allowDocumentWrite = false;
169
169
  };
170
170
 
171
- var requirePathLocation = 'href';
172
-
173
171
  return {
174
172
  requirePath: window.location.href,
175
173
 
@@ -298,7 +296,7 @@ var JXG = {},
298
296
  xhr.open('POST', url, true);
299
297
  xhr.send();
300
298
  }(file));
301
- },
299
+ }
302
300
  };
303
301
  })();
304
302
 
@@ -307,7 +305,7 @@ var JXG = {},
307
305
  ////////////////////////////////////////////////////////////////////////////////
308
306
 
309
307
  // Has to be a String for Makefile!
310
- JXG.Load.baseFiles = 'jxg,base/constants,utils/type,utils/xml,utils/env,utils/event,utils/expect,utils/color,math/probfuncs,math/math,math/ia,math/extrapolate,math/numerics,math/nlp,math/plot,math/metapost,math/statistics,math/symbolic,math/geometry,math/clip,math/poly,math/complex,renderer/abstract,renderer/no,reader/file,parser/geonext,base/board,options,jsxgraph,base/element,base/coordselement,base/coords,base/point,base/line,base/group,base/circle,element/conic,base/polygon,base/curve,element/arc,element/sector,base/composition,element/composition,base/text,base/image,element/slider,element/measure,base/chart,base/transformation,base/turtle,base/ticks,utils/zip,utils/base64,utils/uuid,utils/encoding,server/server,element/locus,parser/datasource,parser/ca,parser/jessiecode,utils/dump,renderer/svg,renderer/vml,renderer/canvas,renderer/no,element/comb,element/slopetriangle,math/qdt,element/checkbox,element/input,element/button,base/foreignobject';
308
+ JXG.Load.baseFiles = 'jxg,base/constants,utils/type,utils/xml,utils/env,utils/event,utils/expect,utils/color,math/probfuncs,math/math,math/ia,math/extrapolate,math/numerics,math/nlp,math/plot,math/metapost,math/statistics,math/symbolic,math/geometry,math/clip,math/poly,math/complex,renderer/abstract,renderer/no,reader/file,parser/geonext,base/board,options,jsxgraph,base/element,base/coordselement,base/coords,base/point,base/line,base/group,base/circle,element/conic,base/polygon,base/curve,element/arc,element/sector,base/composition,element/composition,base/text,base/image,element/slider,element/measure,base/chart,base/transformation,base/turtle,base/ticks,utils/zip,utils/base64,utils/uuid,utils/encoding,server/server,element/locus,parser/datasource,parser/ca,parser/jessiecode,utils/dump,renderer/svg,renderer/vml,renderer/canvas,renderer/no,element/comb,element/slopetriangle,math/qdt,element/checkbox,element/input,element/button,base/foreignobject,options3d,3d/threed,3d/view3d,3d/point3d,3d/curve3d,3d/surface3d,3d/linspace3d,3d/box3d';
311
309
  JXG.Load.setRequirePathToScriptFile('loadjsxgraph.js');
312
310
  JXG.Load.JSfiles(JXG.Load.baseFiles.split(','), preventCachingFiles);
313
311
  JXG.Load.baseFiles = null;
@@ -403,6 +401,14 @@ var JXG = {},
403
401
  'utils/type': checkJXG,
404
402
  'utils/uuid': makeCheck('Util'),
405
403
  'utils/xml': makeCheck('XML'),
406
- 'utils/zip': makeCheck('Util')
404
+ 'utils/zip': makeCheck('Util'),
405
+
406
+ '3d/threed': checkJXG,
407
+ '3d/view3d': checkJXG,
408
+ '3d/point3d': checkJXG,
409
+ '3d/curve3d': checkJXG,
410
+ '3d/surface3d': checkJXG,
411
+ '3d/linspace3d': checkJXG
412
+
407
413
  };
408
414
  }());
package/src/math/clip.js CHANGED
@@ -1888,7 +1888,6 @@ define([
1888
1888
 
1889
1889
  // Collect all points into clip array C
1890
1890
  C = this._getPath(clip, board);
1891
-
1892
1891
  len = C.length;
1893
1892
  if (len > 0 && Geometry.distance(C[0].coords.usrCoords, C[len - 1].coords.usrCoords, 3) < Mat.eps * Mat.eps) {
1894
1893
  C.pop();
@@ -1101,6 +1101,30 @@ define([
1101
1101
  return that.meetCurveLine(el1, el2, i, el1.board, alwaysintersect);
1102
1102
  };
1103
1103
 
1104
+ } else if (el1.type === Const.OBJECT_TYPE_POLYGON || el2.type === Const.OBJECT_TYPE_POLYGON) {
1105
+ // polygon - other
1106
+ // Uses the Greiner-Hormann clipping algorithm
1107
+ // Not implemented: polygon - point
1108
+
1109
+ if (el1.elementClass === Const.OBJECT_CLASS_LINE) {
1110
+ // line - path
1111
+ /** @ignore */
1112
+ func = function () {
1113
+ return that.meetPolygonLine(el2, el1, i, el1.board, alwaysintersect);
1114
+ };
1115
+ } else if (el2.elementClass === Const.OBJECT_CLASS_LINE) {
1116
+ // path - line
1117
+ func = function () {
1118
+ return that.meetPolygonLine(el1, el2, i, el1.board, alwaysintersect);
1119
+ };
1120
+ } else {
1121
+ // path - path
1122
+ /** @ignore */
1123
+ func = function () {
1124
+ return that.meetPathPath(el1, el2, i, el1.board);
1125
+ };
1126
+ }
1127
+
1104
1128
  } else if (el1.elementClass === Const.OBJECT_CLASS_LINE && el2.elementClass === Const.OBJECT_CLASS_LINE) {
1105
1129
  // line - line, lines may also be segments.
1106
1130
  /** @ignore */
@@ -1516,6 +1540,8 @@ define([
1516
1540
  * @param {JXG.Line} li Line
1517
1541
  * @param {Number} nr Will return the nr-th intersection point.
1518
1542
  * @param {JXG.Board} board
1543
+ * @param {Boolean} testSegment Test if intersection has to be inside of the segment or somewhere on the
1544
+ * line defined by the segment
1519
1545
  * @returns {JXG.Coords} Coords object containing the intersection.
1520
1546
  */
1521
1547
  meetCurveLineContinuous: function (cu, li, nr, board, testSegment) {
@@ -1580,7 +1606,6 @@ define([
1580
1606
  return (new Coords(Const.COORDS_BY_USER, [z, cu.X(t), cu.Y(t)], board));
1581
1607
  },
1582
1608
 
1583
-
1584
1609
  /**
1585
1610
  * Intersection of line and curve, discrete case.
1586
1611
  * Segments are treated as lines.
@@ -1767,6 +1792,87 @@ define([
1767
1792
  return [c, t, u];
1768
1793
  },
1769
1794
 
1795
+ /**
1796
+ * Find the n-th intersection point of two pathes, usually given by polygons. Uses parts of the
1797
+ * Greiner-Hormann algorithm in JXG.Math.Clip.
1798
+ *
1799
+ * @param {JXG.Circle|JXG.Curve|JXG.Polygon} path1
1800
+ * @param {JXG.Circle|JXG.Curve|JXG.Polygon} path2
1801
+ * @param {Number} n
1802
+ * @param {JXG.Board} board
1803
+ *
1804
+ * @returns {JXG.Coords} Intersection point. In case no intersection point is detected,
1805
+ * the ideal point [0,0,0] is returned.
1806
+ *
1807
+ */
1808
+ meetPathPath: function(path1, path2, nr, board) {
1809
+ var S, C, len, intersections;
1810
+
1811
+ S = JXG.Math.Clip._getPath(path1, board);
1812
+ len = S.length;
1813
+ if (len > 0 && this.distance(S[0].coords.usrCoords, S[len - 1].coords.usrCoords, 3) < Mat.eps) {
1814
+ S.pop();
1815
+ }
1816
+
1817
+ C = JXG.Math.Clip._getPath(path2, board);
1818
+ len = C.length;
1819
+ if (len > 0 && this.distance(C[0].coords.usrCoords, C[len - 1].coords.usrCoords, 3) < Mat.eps * Mat.eps) {
1820
+ C.pop();
1821
+ }
1822
+
1823
+ // Handle cases where at least one of the paths is empty
1824
+ if (nr < 0 || JXG.Math.Clip.isEmptyCase(S, C, 'intersection')) {
1825
+ return (new Coords(Const.COORDS_BY_USER, [0, 0, 0], board));
1826
+ }
1827
+
1828
+ JXG.Math.Clip.makeDoublyLinkedList(S);
1829
+ JXG.Math.Clip.makeDoublyLinkedList(C);
1830
+
1831
+ intersections = JXG.Math.Clip.findIntersections(S, C, board)[0];
1832
+ if (nr < intersections.length) {
1833
+ return intersections[nr].coords;
1834
+ }
1835
+ return (new Coords(Const.COORDS_BY_USER, [0, 0, 0], board));
1836
+ },
1837
+
1838
+ /**
1839
+ * Find the n-th intersection point between a polygon and a line.
1840
+ * @param {JXG.Polygon} path
1841
+ * @param {JXG.Line} line
1842
+ * @param {Number} nr
1843
+ * @param {JXG.Board} board
1844
+ * @param {Boolean} alwaysIntersect If false just the segment between the two defining points of the line are tested for intersection.
1845
+ *
1846
+ * @returns {JXG.Coords} Intersection point. In case no intersection point is detected,
1847
+ * the ideal point [0,0,0] is returned.
1848
+ */
1849
+ meetPolygonLine: function(path, line, nr, board, alwaysIntersect) {
1850
+ var i, res, border,
1851
+ crds = [0,0,0],
1852
+ len = path.borders.length,
1853
+ intersections = [];
1854
+
1855
+ for (i = 0; i < len; i++) {
1856
+ border = path.borders[i];
1857
+ res = this.meetSegmentSegment(
1858
+ border.point1.coords.usrCoords,
1859
+ border.point2.coords.usrCoords,
1860
+ line.point1.coords.usrCoords,
1861
+ line.point2.coords.usrCoords);
1862
+
1863
+ if (
1864
+ (!alwaysIntersect || (res[2] >= 0 && res[2] < 1)) &&
1865
+ res[1] >= 0 && res[1] < 1) {
1866
+ intersections.push(res[0]);
1867
+ }
1868
+ }
1869
+
1870
+ if (nr >= 0 && nr < intersections.length) {
1871
+ crds = intersections[nr];
1872
+ }
1873
+ return (new Coords(Const.COORDS_BY_USER, crds, board));
1874
+ },
1875
+
1770
1876
  /****************************************/
1771
1877
  /**** BEZIER CURVE ALGORITHMS ****/
1772
1878
  /****************************************/
@@ -2707,7 +2813,86 @@ define([
2707
2813
  };
2708
2814
 
2709
2815
  return [makeFct('X', 'cos'), makeFct('Y', 'sin'), 0, pi2];
2710
- }
2816
+ },
2817
+
2818
+
2819
+ meet3Planes: function (n1, d1, n2, d2, n3, d3) {
2820
+ var p = [0, 0, 0],
2821
+ n31, n12, n23, denom,
2822
+ i;
2823
+
2824
+ n31 = Mat.crossProduct(n3, n1);
2825
+ n12 = Mat.crossProduct(n1, n2);
2826
+ n23 = Mat.crossProduct(n2, n3);
2827
+ denom = Mat.innerProduct(n1, n23, 3);
2828
+ for (i = 0; i < 3; i++) {
2829
+ p[i] = (d1 * n23[i] + d2 * n31[i] + d3 * n12[i]) / denom;
2830
+ }
2831
+ return p;
2832
+ },
2833
+
2834
+
2835
+ meetPlanePlane: function (v11, v12, v21, v22) {
2836
+ var i, no1, no2,
2837
+ v = [0, 0, 0],
2838
+ w = [0, 0, 0];
2839
+
2840
+ for (i = 0; i < 3; i++) {
2841
+ v[i] = Type.evaluate(v11[i]);
2842
+ w[i] = Type.evaluate(v12[i]);
2843
+ }
2844
+ no1 = Mat.crossProduct(v, w);
2845
+
2846
+ for (i = 0; i < 3; i++) {
2847
+ v[i] = Type.evaluate(v21[i]);
2848
+ w[i] = Type.evaluate(v22[i]);
2849
+ }
2850
+ no2 = Mat.crossProduct(v, w);
2851
+
2852
+ return Mat.crossProduct(no1, no2);
2853
+ },
2854
+
2855
+ project3DTo3DPlane: function (point, normal, foot) {
2856
+ // TODO: homogeneous 3D coordinates
2857
+ var sol = [0, 0, 0],
2858
+ le, d1, d2, lbda;
2859
+
2860
+ foot = foot || [0, 0, 0];
2861
+
2862
+ le = Mat.norm(normal);
2863
+ d1 = Mat.innerProduct(point, normal, 3);
2864
+ d2 = Mat.innerProduct(foot, normal, 3);
2865
+ // (point - lbda * normal / le) * normal / le == foot * normal / le
2866
+ // => (point * normal - foot * normal) == lbda * le
2867
+ lbda = (d1 - d2) / le;
2868
+ sol = Mat.axpy(-lbda, normal, point);
2869
+
2870
+ return sol;
2871
+ },
2872
+
2873
+ getPlaneBounds: function (v1, v2, q, s, e) {
2874
+ var s1, s2, e1, e2, mat, rhs, sol;
2875
+
2876
+ if (v1[2] + v2[0] !== 0) {
2877
+ mat = [
2878
+ [v1[0], v2[0]],
2879
+ [v1[1], v2[1]]
2880
+ ];
2881
+ rhs = [s - q[0], s - q[1]];
2882
+
2883
+ sol = Numerics.Gauss(mat, rhs);
2884
+ s1 = sol[0];
2885
+ s2 = sol[1];
2886
+
2887
+ rhs = [e - q[0], e - q[1]];
2888
+ sol = Numerics.Gauss(mat, rhs);
2889
+ e1 = sol[0];
2890
+ e2 = sol[1];
2891
+ return [s1, e1, s2, e2];
2892
+ }
2893
+ return null;
2894
+ },
2895
+
2711
2896
  });
2712
2897
 
2713
2898
  return Mat.Geometry;
package/src/math/math.js CHANGED
@@ -466,6 +466,15 @@ define(['jxg', 'utils/type'], function (JXG, Type) {
466
466
  return Math.sqrt(sum);
467
467
  },
468
468
 
469
+ axpy: function (a, x, y) {
470
+ var i, le = x.length,
471
+ p = [];
472
+ for (i = 0; i < le; i++) {
473
+ p[i] = a * x[i] + y[i];
474
+ }
475
+ return p;
476
+ },
477
+
469
478
  /**
470
479
  * Compute the factorial of a positive integer. If a non-integer value
471
480
  * is given, the fraction will be ignored.
package/src/options.js CHANGED
@@ -783,6 +783,10 @@ define([
783
783
  * visible: false // Initial visibility. Should be set to false always
784
784
  * }
785
785
  * </pre>
786
+ * <p>
787
+ * Board events triggered by selection manipulation:
788
+ * 'startselecting', 'stopselecting', 'mousestartselecting', 'mousestopselecting',
789
+ * 'pointerstartselecting', 'pointerstopselecting', 'touchstartselecting', 'touchstopselecting'.
786
790
  *
787
791
  * @example
788
792
  * board.on('stopselecting', function(){
@@ -796,14 +800,10 @@ define([
796
800
  * });
797
801
  *
798
802
  * @name JXG.Board#selection
799
- * @see JXG.Board#startselecting
800
- * @see JXG.Board#stopselecting
801
- * @see JXG.Board#mousestartselecting
802
- * @see JXG.Board#pointerstartselecting
803
- * @see JXG.Board#touchstartselecting
804
- * @see JXG.Board#mousestopselecting
805
- * @see JXG.Board#pointerstopselecting
806
- * @see JXG.Board#touchstopselecting
803
+ *
804
+ * @see JXG.Board#startSelectionMode
805
+ * @see JXG.Board#stopSelectionMode
806
+ *
807
807
  * @type Object
808
808
  * @default
809
809
  */
@@ -1488,7 +1488,20 @@ define([
1488
1488
  */
1489
1489
  isLabel: false,
1490
1490
 
1491
-
1491
+ /**
1492
+ * Controls if an element can get the focus with the tab key.
1493
+ * See <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex">descriptiona at MDN</a>.
1494
+ * The additional value null completely disables focus of an element.
1495
+ * The value will be ignored if keyboard control of the board is not enabled or
1496
+ * the element is fixed or not visible.
1497
+ *
1498
+ * @name JXG.GeometryElement#tabindex
1499
+ * @type Number
1500
+ * @default 0
1501
+ * @see JXG.Board#keyboard
1502
+ * @see JXG.GeometryElement#fixed
1503
+ * @see JXG.GeometryElement#visible
1504
+ */
1492
1505
  tabindex: 0
1493
1506
 
1494
1507
  // close the meta tag
@@ -4688,6 +4701,7 @@ define([
4688
4701
  visible: 'inherit',
4689
4702
  fixed: true,
4690
4703
  scalable: false,
4704
+ tabindex: null,
4691
4705
  name: '',
4692
4706
  strokeWidth: 1,
4693
4707
  strokeColor: '#000000',
@@ -4737,6 +4751,7 @@ define([
4737
4751
  strokeWidth: 3,
4738
4752
  visible: 'inherit',
4739
4753
  fixed: true,
4754
+ tabindex: null,
4740
4755
  name: '',
4741
4756
  strokeColor: '#000000',
4742
4757
  highlightStrokeColor: '#888888'