jsxgraph 1.3.0 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/README.md +2 -2
  2. package/distrib/README.md +2 -2
  3. package/distrib/geogebra.min.js +3 -3
  4. package/distrib/geonext.min.js +3 -3
  5. package/distrib/index.d.ts +651 -448
  6. package/distrib/intergeo.min.js +3 -3
  7. package/distrib/jsxgraph.css +4 -13
  8. package/distrib/jsxgraphcore.js +9 -25
  9. package/distrib/jsxgraphsrc.js +28203 -25234
  10. package/distrib/sketch.min.js +3 -3
  11. package/package.json +11 -22
  12. package/src/base/board.js +674 -469
  13. package/src/base/chart.js +1 -1
  14. package/src/base/circle.js +23 -1
  15. package/src/base/composition.js +1 -1
  16. package/src/base/constants.js +32 -11
  17. package/src/base/coords.js +4 -4
  18. package/src/base/coordselement.js +51 -24
  19. package/src/base/curve.js +308 -117
  20. package/src/base/element.js +79 -50
  21. package/src/base/foreignobject.js +463 -0
  22. package/src/base/group.js +2 -2
  23. package/src/base/image.js +12 -15
  24. package/src/base/line.js +108 -21
  25. package/src/base/point.js +24 -28
  26. package/src/base/polygon.js +75 -18
  27. package/src/base/text.js +116 -63
  28. package/src/base/ticks.js +29 -11
  29. package/src/base/transformation.js +1 -1
  30. package/src/base/turtle.js +1 -1
  31. package/src/element/arc.js +1 -1
  32. package/src/element/button.js +29 -2
  33. package/src/element/checkbox.js +31 -1
  34. package/src/element/comb.js +5 -2
  35. package/src/element/composition.js +127 -19
  36. package/src/element/conic.js +46 -5
  37. package/src/element/input.js +32 -1
  38. package/src/element/locus.js +2 -2
  39. package/src/element/measure.js +9 -4
  40. package/src/element/sector.js +46 -12
  41. package/src/element/slider.js +17 -12
  42. package/src/element/slopetriangle.js +1 -1
  43. package/src/jsxgraph.js +28 -9
  44. package/src/jxg.js +4 -3
  45. package/src/loadjsxgraph.js +3 -2
  46. package/src/math/bst.js +1 -1
  47. package/src/math/clip.js +550 -345
  48. package/src/math/complex.js +1 -1
  49. package/src/math/extrapolate.js +1 -1
  50. package/src/math/geometry.js +155 -126
  51. package/src/math/ia.js +290 -21
  52. package/src/math/math.js +30 -1
  53. package/src/math/metapost.js +1 -1
  54. package/src/math/nlp.js +25 -5
  55. package/src/math/numerics.js +183 -4
  56. package/src/math/plot.js +4 -4
  57. package/src/math/poly.js +1 -1
  58. package/src/math/probfuncs.js +2 -1
  59. package/src/math/qdt.js +68 -62
  60. package/src/math/statistics.js +58 -7
  61. package/src/math/symbolic.js +1 -1
  62. package/src/options.js +377 -114
  63. package/src/parser/ca.js +1297 -1291
  64. package/src/parser/datasource.js +1 -1
  65. package/src/parser/geonext.js +6 -6
  66. package/src/parser/jessiecode.js +275 -79
  67. package/src/parser/jessiescript.js +1 -1
  68. package/src/reader/cinderella.js +1 -1
  69. package/src/reader/file.js +1 -1
  70. package/src/reader/geogebra.js +1 -1
  71. package/src/reader/geonext.js +1 -1
  72. package/src/reader/graph.js +1 -1
  73. package/src/reader/intergeo.js +1 -1
  74. package/src/reader/sketch.js +21 -13
  75. package/src/renderer/abstract.js +21 -6
  76. package/src/renderer/canvas.js +22 -15
  77. package/src/renderer/no.js +11 -4
  78. package/src/renderer/svg.js +76 -53
  79. package/src/renderer/vml.js +36 -32
  80. package/src/server/server.js +1 -1
  81. package/src/utils/base64.js +2 -2
  82. package/src/utils/color.js +148 -3
  83. package/src/utils/dump.js +21 -15
  84. package/src/utils/env.js +63 -104
  85. package/src/utils/event.js +1 -1
  86. package/src/utils/expect.js +1 -1
  87. package/src/utils/type.js +30 -19
  88. package/src/utils/xml.js +1 -1
  89. package/src/utils/zip.js +1 -1
  90. package/CHANGELOG.md +0 -1281
package/src/base/image.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*
2
- Copyright 2008-2021
2
+ Copyright 2008-2022
3
3
  Matthias Ehmann,
4
4
  Michael Gerhaeuser,
5
5
  Carsten Miller,
@@ -39,7 +39,6 @@
39
39
  base/coords
40
40
  base/element
41
41
  math/math
42
- math/statistics
43
42
  utils/type
44
43
  */
45
44
 
@@ -55,8 +54,6 @@ define([
55
54
 
56
55
  /**
57
56
  * Construct and handle images
58
- * The coordinates can be relative to the coordinates of an element
59
- * given in {@link JXG.Options#text.anchor}.
60
57
  *
61
58
  * The image can be supplied as an URL or an base64 encoded inline image
62
59
  * like "data:image/png;base64, /9j/4AAQSkZJRgA..." or a function returning
@@ -66,8 +63,8 @@ define([
66
63
  * type {@link Image} instead.
67
64
  * @augments JXG.GeometryElement
68
65
  * @augments JXG.CoordsElement
69
- * @param {string|JXG.Board} board The board the new text is drawn on.
70
- * @param {Array} coordinates An array with the user coordinates of the text.
66
+ * @param {string|JXG.Board} board The board the new image is drawn on.
67
+ * @param {Array} coordinates An array with the user coordinates of the image.
71
68
  * @param {Object} attributes An object containing visual and - optionally - a name and an id.
72
69
  * @param {string|function} url An URL string or a function returning an URL string.
73
70
  * @param {Array} size Array containing width and height of the image in user coordinates.
@@ -85,13 +82,13 @@ define([
85
82
 
86
83
  /**
87
84
  * Array of length two containing [width, height] of the image in pixel.
88
- * @type {array}
85
+ * @type array
89
86
  */
90
87
  this.size = [Math.abs(this.usrSize[0] * board.unitX), Math.abs(this.usrSize[1] * board.unitY)];
91
88
 
92
89
  /**
93
90
  * 'href' of the image. This might be an URL, but also a data-uri is allowed.
94
- * @type {string}
91
+ * @type string
95
92
  */
96
93
  this.url = url;
97
94
 
@@ -269,7 +266,7 @@ define([
269
266
  return this;
270
267
  },
271
268
 
272
- // documented in element.js
269
+ // Documented in element.js
273
270
  getParents: function () {
274
271
  var p = [this.url, [this.Z(), this.X(), this.Y()], this.usrSize];
275
272
 
@@ -291,7 +288,7 @@ define([
291
288
  * @returns {JXG.GeometryElement} A reference to the element
292
289
  *
293
290
  * @example
294
- * var im = board.create('image', ['http://jsxgraph.uni-bayreuth.de/distrib/images/uccellino.jpg',
291
+ * var im = board.create('image', ['https://jsxgraph.org/distrib/images/uccellino.jpg',
295
292
  * [-3,-2], [3,3]]);
296
293
  * im.setSize(4, 4);
297
294
  * board.update();
@@ -301,7 +298,7 @@ define([
301
298
  * (function() {
302
299
  * var board = JXG.JSXGraph.initBoard('JXG8411e60c-f009-11e5-b1bf-901b0e1b8723',
303
300
  * {boundingbox: [-8, 8, 8,-8], axis: true, showcopyright: false, shownavigation: false});
304
- * var im = board.create('image', ['http://jsxgraph.uni-bayreuth.de/distrib/images/uccellino.jpg', [-3,-2], [3,3]]);
301
+ * var im = board.create('image', ['https://jsxgraph.org/distrib/images/uccellino.jpg', [-3,-2], [3,3]]);
305
302
  * //im.setSize(4, 4);
306
303
  * //board.update();
307
304
  *
@@ -311,7 +308,7 @@ define([
311
308
  *
312
309
  * @example
313
310
  * var p0 = board.create('point', [-3, -2]),
314
- * im = board.create('image', ['http://jsxgraph.uni-bayreuth.de/distrib/images/uccellino.jpg',
311
+ * im = board.create('image', ['https://jsxgraph.org/distrib/images/uccellino.jpg',
315
312
  * [function(){ return p0.X(); }, function(){ return p0.Y(); }],
316
313
  * [3,3]]),
317
314
  * p1 = board.create('point', [1, 2]);
@@ -325,7 +322,7 @@ define([
325
322
  * var board = JXG.JSXGraph.initBoard('JXG4ce706c0-f00a-11e5-b1bf-901b0e1b8723',
326
323
  * {boundingbox: [-8, 8, 8,-8], axis: true, showcopyright: false, shownavigation: false});
327
324
  * var p0 = board.create('point', [-3, -2]),
328
- * im = board.create('image', ['http://jsxgraph.uni-bayreuth.de/distrib/images/uccellino.jpg',
325
+ * im = board.create('image', ['https://jsxgraph.org/distrib/images/uccellino.jpg',
329
326
  * [function(){ return p0.X(); }, function(){ return p0.Y(); }],
330
327
  * [3,3]]),
331
328
  * p1 = board.create('point', [1, 2]);
@@ -382,12 +379,12 @@ define([
382
379
  * <p>
383
380
  * The array size defines the image's width and height in user coordinates.
384
381
  * @example
385
- * var im = board.create('image', ['http://jsxgraph.uni-bayreuth.de/jsxgraph/distrib/images/uccellino.jpg', [-3,-2], [3,3]]);
382
+ * var im = board.create('image', ['https://jsxgraph.org/jsxgraph/distrib/images/uccellino.jpg', [-3,-2], [3,3]]);
386
383
  *
387
384
  * </pre><div class="jxgbox" id="JXG9850cda0-7ea0-4750-981c-68bacf9cca57" style="width: 400px; height: 400px;"></div>
388
385
  * <script type="text/javascript">
389
386
  * var image_board = JXG.JSXGraph.initBoard('JXG9850cda0-7ea0-4750-981c-68bacf9cca57', {boundingbox: [-4, 4, 4, -4], axis: true, showcopyright: false, shownavigation: false});
390
- * var image_im = image_board.create('image', ['http://jsxgraph.uni-bayreuth.de/distrib/images/uccellino.jpg', [-3,-2],[3,3]]);
387
+ * var image_im = image_board.create('image', ['https://jsxgraph.org/distrib/images/uccellino.jpg', [-3,-2],[3,3]]);
391
388
  * </script><pre>
392
389
  */
393
390
  JXG.createImage = function (board, parents, attributes) {
package/src/base/line.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*
2
- Copyright 2008-2021
2
+ Copyright 2008-2022
3
3
  Matthias Ehmann,
4
4
  Michael Gerhaeuser,
5
5
  Carsten Miller,
@@ -1466,14 +1466,36 @@ define([
1466
1466
  // this is required for the geogebra reader to display a slope
1467
1467
  tangent.glider = p;
1468
1468
  } else { // curveType 'plot'
1469
- // equation of the line segment: 0 = y*(x1-x2) + x*(y2-y1) + y1*x2-x1*y2
1469
+ // In case of bezierDegree == 1:
1470
+ // Find two points p1, p2 enclosing the glider.
1471
+ // Then the equation of the line segment is: 0 = y*(x1-x2) + x*(y2-y1) + y1*x2-x1*y2,
1472
+ // which is the cross product of p1 and p2.
1473
+ //
1474
+ // In case of bezieDegree === 3:
1475
+ // The slope dy / dx of the tangent is determined. Then the
1476
+ // tangent is computed as cross product between
1477
+ // the glider p and [1, p.X() + dx, p.Y() + dy]
1478
+ //
1470
1479
  tangent = board.create('line', [
1471
1480
  function () {
1472
1481
  var i = Math.floor(p.position),
1473
- p1, p2;
1482
+ p1, p2, t, A, B, C, D, dx, dy, d;
1474
1483
 
1475
- if (i === c.numberPoints - 1) {
1476
- i--;
1484
+ if (c.bezierDegree === 1) {
1485
+ if (i === c.numberPoints - 1) {
1486
+ i--;
1487
+ }
1488
+ } else if (c.bezierDegree === 3) {
1489
+ // i is start of the Bezier segment
1490
+ // t is the position in the Bezier segment
1491
+ i = Math.floor(p.position * (c.numberPoints - 1) / 3) * 3;
1492
+ t = (p.position * (c.numberPoints - 1) - i) / 3;
1493
+ if (i >= c.numberPoints - 1) {
1494
+ i = c.numberPoints - 4;
1495
+ t = 1;
1496
+ }
1497
+ } else {
1498
+ return 0;
1477
1499
  }
1478
1500
 
1479
1501
  if (i < 0) {
@@ -1482,17 +1504,43 @@ define([
1482
1504
 
1483
1505
  // The curve points are transformed (if there is a transformation)
1484
1506
  // c.X(i) is not transformed.
1485
- p1 = c.points[i].usrCoords;
1486
- p2 = c.points[i + 1].usrCoords;
1487
- return p1[2] * p2[1] - p1[1] * p2[2];
1488
- //return c.Y(i) * c.X(i + 1) - c.X(i) * c.Y(i + 1);
1507
+ if (c.bezierDegree === 1) {
1508
+ p1 = c.points[i].usrCoords;
1509
+ p2 = c.points[i + 1].usrCoords;
1510
+ } else {
1511
+ A = c.points[i].usrCoords;
1512
+ B = c.points[i + 1].usrCoords;
1513
+ C = c.points[i + 2].usrCoords;
1514
+ D = c.points[i + 3].usrCoords;
1515
+ dx = (1 - t) * (1 - t) * (B[1] - A[1]) + 2 * (1 - t) * t * (C[1] - B[1]) + t * t * (D[1]- C[1]);
1516
+ dy = (1 - t) * (1 - t) * (B[2] - A[2]) + 2 * (1 - t) * t * (C[2] - B[2]) + t * t * (D[2]- C[2]);
1517
+ d = Math.sqrt(dx * dx + dy * dy);
1518
+ dx /= d;
1519
+ dy /= d;
1520
+ p1 = p.coords.usrCoords;
1521
+ p2 = [1, p1[1] + dx, p1[2] + dy];
1522
+ }
1523
+ return p1[2] * p2[1] - p1[1] * p2[2];
1489
1524
  },
1490
1525
  function () {
1491
1526
  var i = Math.floor(p.position),
1492
- p1, p2;
1527
+ p1, p2, t, A, B, C, D, dx, dy, d;
1493
1528
 
1494
- if (i === c.numberPoints - 1) {
1495
- i--;
1529
+ if (c.bezierDegree === 1) {
1530
+ if (i === c.numberPoints - 1) {
1531
+ i--;
1532
+ }
1533
+ } else if (c.bezierDegree === 3) {
1534
+ // i is start of the Bezier segment
1535
+ // t is the position in the Bezier segment
1536
+ i = Math.floor(p.position * (c.numberPoints - 1) / 3) * 3;
1537
+ t = (p.position * (c.numberPoints - 1) - i) / 3;
1538
+ if (i >= c.numberPoints - 1) {
1539
+ i = c.numberPoints - 4;
1540
+ t = 1;
1541
+ }
1542
+ } else {
1543
+ return 0;
1496
1544
  }
1497
1545
 
1498
1546
  if (i < 0) {
@@ -1501,17 +1549,43 @@ define([
1501
1549
 
1502
1550
  // The curve points are transformed (if there is a transformation)
1503
1551
  // c.X(i) is not transformed.
1504
- p1 = c.points[i].usrCoords;
1505
- p2 = c.points[i + 1].usrCoords;
1552
+ if (c.bezierDegree === 1) {
1553
+ p1 = c.points[i].usrCoords;
1554
+ p2 = c.points[i + 1].usrCoords;
1555
+ } else {
1556
+ A = c.points[i].usrCoords;
1557
+ B = c.points[i + 1].usrCoords;
1558
+ C = c.points[i + 2].usrCoords;
1559
+ D = c.points[i + 3].usrCoords;
1560
+ dx = (1 - t) * (1 - t) * (B[1] - A[1]) + 2 * (1 - t) * t * (C[1] - B[1]) + t * t * (D[1]- C[1]);
1561
+ dy = (1 - t) * (1 - t) * (B[2] - A[2]) + 2 * (1 - t) * t * (C[2] - B[2]) + t * t * (D[2]- C[2]);
1562
+ d = Math.sqrt(dx * dx + dy * dy);
1563
+ dx /= d;
1564
+ dy /= d;
1565
+ p1 = p.coords.usrCoords;
1566
+ p2 = [1, p1[1] + dx, p1[2] + dy];
1567
+ }
1506
1568
  return p2[2] - p1[2];
1507
- // return c.Y(i + 1) - c.Y(i);
1508
1569
  },
1509
1570
  function () {
1510
1571
  var i = Math.floor(p.position),
1511
- p1, p2;
1572
+ p1, p2, t, A, B, C, D, dx, dy, d;
1512
1573
 
1513
- if (i === c.numberPoints - 1) {
1514
- i--;
1574
+ if (c.bezierDegree === 1) {
1575
+ if (i === c.numberPoints - 1) {
1576
+ i--;
1577
+ }
1578
+ } else if (c.bezierDegree === 3) {
1579
+ // i is start of the Bezier segment
1580
+ // t is the position in the Bezier segment
1581
+ i = Math.floor(p.position * (c.numberPoints - 1) / 3) * 3;
1582
+ t = (p.position * (c.numberPoints - 1) - i) / 3;
1583
+ if (i >= c.numberPoints - 1) {
1584
+ i = c.numberPoints - 4;
1585
+ t = 1;
1586
+ }
1587
+ } else {
1588
+ return 0;
1515
1589
  }
1516
1590
 
1517
1591
  if (i < 0) {
@@ -1520,10 +1594,23 @@ define([
1520
1594
 
1521
1595
  // The curve points are transformed (if there is a transformation)
1522
1596
  // c.X(i) is not transformed.
1523
- p1 = c.points[i].usrCoords;
1524
- p2 = c.points[i + 1].usrCoords;
1597
+ if (c.bezierDegree === 1) {
1598
+ p1 = c.points[i].usrCoords;
1599
+ p2 = c.points[i + 1].usrCoords;
1600
+ } else {
1601
+ A = c.points[i].usrCoords;
1602
+ B = c.points[i + 1].usrCoords;
1603
+ C = c.points[i + 2].usrCoords;
1604
+ D = c.points[i + 3].usrCoords;
1605
+ dx = (1 - t) * (1 - t) * (B[1] - A[1]) + 2 * (1 - t) * t * (C[1] - B[1]) + t * t * (D[1]- C[1]);
1606
+ dy = (1 - t) * (1 - t) * (B[2] - A[2]) + 2 * (1 - t) * t * (C[2] - B[2]) + t * t * (D[2]- C[2]);
1607
+ d = Math.sqrt(dx * dx + dy * dy);
1608
+ dx /= d;
1609
+ dy /= d;
1610
+ p1 = p.coords.usrCoords;
1611
+ p2 = [1, p1[1] + dx, p1[2] + dy];
1612
+ }
1525
1613
  return p1[1] - p2[1];
1526
- // return c.X(i) - c.X(i + 1);
1527
1614
  }], attributes);
1528
1615
 
1529
1616
  p.addChild(tangent);
package/src/base/point.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*
2
- Copyright 2008-2021
2
+ Copyright 2008-2022
3
3
  Matthias Ehmann,
4
4
  Michael Gerhaeuser,
5
5
  Carsten Miller,
@@ -156,7 +156,7 @@ define([
156
156
  * @returns {JXG.CoordsElement} Reference to this object.
157
157
  */
158
158
  updateTransform: function (fromParent) {
159
- var c, i, invMat;
159
+ var c, i;
160
160
 
161
161
  if (this.transformations.length === 0 || this.baseElement === null) {
162
162
  return this;
@@ -167,21 +167,9 @@ define([
167
167
  c = this.transformations[0].apply(this.baseElement, 'self');
168
168
  this.coords.setCoordinates(Const.COORDS_BY_USER, c);
169
169
  } else {
170
- // Case of board.create('point',[baseElement, transform]);
171
-
172
- if (!fromParent) {
173
- // The element has been dragged, now we transform the baseElement
174
- if (this.draggable() && this.baseElement.draggable()) {
175
- this.transformations[0].update();
176
- invMat = Mat.inverse(this.transformations[0].matrix);
177
- c = Mat.matVecMult(invMat, this.coords.usrCoords);
178
- this.baseElement.coords.setCoordinates(Const.COORDS_BY_USER, c);
179
- }
180
- } else {
181
- c = this.transformations[0].apply(this.baseElement);
182
- this.coords.setCoordinates(Const.COORDS_BY_USER, c);
183
- }
170
+ c = this.transformations[0].apply(this.baseElement);
184
171
  }
172
+ this.coords.setCoordinates(Const.COORDS_BY_USER, c);
185
173
 
186
174
  for (i = 1; i < this.transformations.length; i++) {
187
175
  this.coords.setCoordinates(Const.COORDS_BY_USER, this.transformations[i].apply(this));
@@ -339,7 +327,7 @@ define([
339
327
  * 'point on curve = ' + point.isOn(curve) + '<br>' +
340
328
  * 'point on polygon = ' + point.isOn(pol) + '<br>';
341
329
  * }]);
342
- *
330
+ *
343
331
  * </pre><div id="JXG6c7d7404-758a-44eb-802c-e9644b9fab71" class="jxgbox" style="width: 300px; height: 300px;"></div>
344
332
  * <script type="text/javascript">
345
333
  * (function() {
@@ -351,25 +339,25 @@ define([
351
339
  * var po = board.create('point', [-1, 0], {color: 'blue'});
352
340
  * var curve = board.create('functiongraph', ['sin(x)'], {strokeColor: 'blue'});
353
341
  * var pol = board.create('polygon', [[2,2], [4,2], [4,3]], {strokeColor: 'blue'});
354
- *
342
+ *
355
343
  * var point = board.create('point', [-1, 1], {
356
- * attractors: [line, seg, circ, po, curve, pol],
344
+ * attractors: [line, seg, circ, po, curve, pol],
357
345
  * attractorDistance: 0.2
358
346
  * });
359
- *
347
+ *
360
348
  * var txt = board.create('text', [-4, 3, function() {
361
- * return 'point on line: ' + point.isOn(line) + '<br>' +
349
+ * return 'point on line: ' + point.isOn(line) + '<br>' +
362
350
  * 'point on seg: ' + point.isOn(seg) + '<br>' +
363
351
  * 'point on circ = ' + point.isOn(circ) + '<br>' +
364
352
  * 'point on point = ' + point.isOn(po) + '<br>' +
365
353
  * 'point on curve = ' + point.isOn(curve) + '<br>' +
366
354
  * 'point on polygon = ' + point.isOn(pol) + '<br>';
367
355
  * }]);
368
- *
356
+ *
369
357
  * })();
370
- *
358
+ *
371
359
  * </script><pre>
372
- *
360
+ *
373
361
  */
374
362
  isOn: function(el, tol) {
375
363
  var arr, crds;
@@ -381,24 +369,32 @@ define([
381
369
  } else if (el.elementClass === Const.OBJECT_CLASS_LINE) {
382
370
  if (el.elType === 'segment' && !Type.evaluate(this.visProp.alwaysintersect)) {
383
371
  arr = JXG.Math.Geometry.projectCoordsToSegment(
384
- this.coords.usrCoords,
372
+ this.coords.usrCoords,
385
373
  el.point1.coords.usrCoords,
386
374
  el.point2.coords.usrCoords);
387
375
  if (arr[1] >= 0 && arr[1] <= 1 &&
388
376
  Geometry.distPointLine(this.coords.usrCoords, el.stdform) < tol) {
389
- return true;
377
+ return true;
390
378
  } else {
391
- return false;
379
+ return false;
392
380
  }
393
381
  } else {
394
382
  return Geometry.distPointLine(this.coords.usrCoords, el.stdform) < tol;
395
383
  }
396
384
  } else if (el.elementClass === Const.OBJECT_CLASS_CIRCLE) {
385
+ if (Type.evaluate(el.visProp.hasinnerpoints)) {
386
+ return this.Dist(el.center) < el.Radius() + tol;
387
+ }
397
388
  return Math.abs(this.Dist(el.center) - el.Radius()) < tol;
398
389
  } else if (el.elementClass === Const.OBJECT_CLASS_CURVE) {
399
390
  crds = Geometry.projectPointToCurve(this, el, this.board)[0];
400
391
  return Geometry.distance(this.coords.usrCoords, crds.usrCoords, 3) < tol;
401
392
  } else if (el.type === Const.OBJECT_TYPE_POLYGON) {
393
+ if (Type.evaluate(el.visProp.hasinnerpoints)) {
394
+ if (el.pnpoly(this.coords.usrCoords[1], this.coords.usrCoords[2], JXG.COORDS_BY_USER)) {
395
+ return true;
396
+ }
397
+ }
402
398
  arr = Geometry.projectCoordsToPolygon(this.coords.usrCoords, el);
403
399
  return Geometry.distance(this.coords.usrCoords, arr, 3) < tol;
404
400
  } else if (el.type === Const.OBJECT_TYPE_TURTLE) {
@@ -410,7 +406,7 @@ define([
410
406
  return false;
411
407
  },
412
408
 
413
- // already documented in GeometryElement
409
+ // Already documented in GeometryElement
414
410
  cloneToBackground: function () {
415
411
  var copy = {};
416
412
 
@@ -1,5 +1,5 @@
1
1
  /*
2
- Copyright 2008-2021
2
+ Copyright 2008-2022
3
3
  Matthias Ehmann,
4
4
  Michael Gerhaeuser,
5
5
  Carsten Miller,
@@ -163,6 +163,72 @@ define([
163
163
  JXG.Polygon.prototype = new GeometryElement();
164
164
 
165
165
  JXG.extend(JXG.Polygon.prototype, /** @lends JXG.Polygon.prototype */ {
166
+
167
+ /**
168
+ * Decides if a point (x,y) is inside of the polygon.
169
+ * Implements W. Randolf Franklin's pnpoly method.
170
+ *
171
+ * See <a href="https://wrf.ecse.rpi.edu/Research/Short_Notes/pnpoly.html">https://wrf.ecse.rpi.edu/Research/Short_Notes/pnpoly.html</a>.
172
+ *
173
+ * @param {Number} x_in x-coordinate (screen or user coordinates)
174
+ * @param {Number} y_in y-coordinate (screen or user coordinates)
175
+ * @param {Number} coord_type (Optional) the type of coordinates used here.
176
+ * Possible values are <b>JXG.COORDS_BY_USER</b> and <b>JXG.COORDS_BY_SCREEN</b>.
177
+ * Default value is JXG.COORDS_BY_SCREEN
178
+ *
179
+ * @returns {Boolean} if (x,y) is inside of the polygon.
180
+ * @example
181
+ * var pol = board.create('polygon', [[-1,2], [2,2], [-1,4]]);
182
+ * var p = board.create('point', [4, 3]);
183
+ * var txt = board.create('text', [-1, 0.5, function() {
184
+ * return 'Point A is inside of the polygon = ' +
185
+ * pol.pnpoly(p.X(), p.Y(), JXG.COORDS_BY_USER);
186
+ * }]);
187
+ *
188
+ * </pre><div id="JXG7f96aec7-4e3d-4ffc-a3f5-d3f967b6691c" class="jxgbox" style="width: 300px; height: 300px;"></div>
189
+ * <script type="text/javascript">
190
+ * (function() {
191
+ * var board = JXG.JSXGraph.initBoard('JXG7f96aec7-4e3d-4ffc-a3f5-d3f967b6691c',
192
+ * {boundingbox: [-2, 5, 5,-2], axis: true, showcopyright: false, shownavigation: false});
193
+ * var pol = board.create('polygon', [[-1,2], [2,2], [-1,4]]);
194
+ * var p = board.create('point', [4, 3]);
195
+ * var txt = board.create('text', [-1, 0.5, function() {
196
+ * return 'Point A is inside of the polygon = ' + pol.pnpoly(p.X(), p.Y(), JXG.COORDS_BY_USER);
197
+ * }]);
198
+ *
199
+ * })();
200
+ *
201
+ * </script><pre>
202
+ *
203
+ */
204
+ pnpoly: function(x_in, y_in, coord_type) {
205
+ var i, j, len,
206
+ x, y, crds,
207
+ v = this.vertices,
208
+ isIn = false;
209
+
210
+ if (coord_type === Const.COORDS_BY_USER) {
211
+ crds = new Coords(Const.COORDS_BY_USER, [x_in, y_in], this.board);
212
+ x = crds.scrCoords[1];
213
+ y = crds.scrCoords[2];
214
+ } else {
215
+ x = x_in;
216
+ y = y_in;
217
+ }
218
+
219
+ len = this.vertices.length;
220
+ for (i = 0, j = len - 2; i < len - 1; j = i++) {
221
+ if (((v[i].coords.scrCoords[2] > y) !== (v[j].coords.scrCoords[2] > y)) &&
222
+ (x < (v[j].coords.scrCoords[1] - v[i].coords.scrCoords[1]) *
223
+ (y - v[i].coords.scrCoords[2]) / (v[j].coords.scrCoords[2] - v[i].coords.scrCoords[2]) + v[i].coords.scrCoords[1])
224
+ ) {
225
+ isIn = !isIn;
226
+ }
227
+ }
228
+
229
+ return isIn;
230
+ },
231
+
166
232
  /**
167
233
  * Checks whether (x,y) is near the polygon.
168
234
  * @param {Number} x Coordinate in x direction, screen coordinates.
@@ -170,22 +236,11 @@ define([
170
236
  * @returns {Boolean} Returns true, if (x,y) is inside or at the boundary the polygon, otherwise false.
171
237
  */
172
238
  hasPoint: function (x, y) {
173
-
174
- var i, j, len, c = false;
239
+ var i, len;
175
240
 
176
241
  if (Type.evaluate(this.visProp.hasinnerpoints)) {
177
242
  // All points of the polygon trigger hasPoint: inner and boundary points
178
- len = this.vertices.length;
179
- // W. Randolf Franklin's pnpoly method,
180
- // see https://wrf.ecse.rpi.edu/Research/Short_Notes/pnpoly.html
181
- for (i = 0, j = len - 2; i < len - 1; j = i++) {
182
- if (((this.vertices[i].coords.scrCoords[2] > y) !== (this.vertices[j].coords.scrCoords[2] > y)) &&
183
- (x < (this.vertices[j].coords.scrCoords[1] - this.vertices[i].coords.scrCoords[1]) * (y - this.vertices[i].coords.scrCoords[2]) /
184
- (this.vertices[j].coords.scrCoords[2] - this.vertices[i].coords.scrCoords[2]) + this.vertices[i].coords.scrCoords[1])) {
185
- c = !c;
186
- }
187
- }
188
- if (c) {
243
+ if (this.pnpoly(x, y)) {
189
244
  return true;
190
245
  }
191
246
  }
@@ -197,12 +252,11 @@ define([
197
252
  len = this.borders.length;
198
253
  for (i = 0; i < len; i++) {
199
254
  if (this.borders[i].hasPoint(x, y)) {
200
- c = true;
201
- break;
255
+ return true;
202
256
  }
203
257
  }
204
258
 
205
- return c;
259
+ return false;
206
260
  },
207
261
 
208
262
  /**
@@ -461,7 +515,7 @@ define([
461
515
  return box;
462
516
  },
463
517
 
464
- // already documented in GeometryElement
518
+ // Already documented in GeometryElement
465
519
  bounds: function () {
466
520
  return this.boundingBox();
467
521
  },
@@ -469,6 +523,8 @@ define([
469
523
  /**
470
524
  * This method removes the SVG or VML nodes of the lines and the filled area from the renderer, to remove
471
525
  * the object completely you should use {@link JXG.Board#removeObject}.
526
+ *
527
+ * @private
472
528
  */
473
529
  remove: function () {
474
530
  var i;
@@ -483,6 +539,7 @@ define([
483
539
  /**
484
540
  * Finds the index to a given point reference.
485
541
  * @param {JXG.Point} p Reference to an element of type {@link JXG.Point}
542
+ * @returns {Number} Index of the point or -1.
486
543
  */
487
544
  findPoint: function (p) {
488
545
  var i;