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
@@ -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,
@@ -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,
@@ -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,
@@ -495,6 +495,38 @@ define([
495
495
  return d;
496
496
  },
497
497
 
498
+ /**
499
+ * Affine ratio of three collinear points a, b, c: (c - a) / (b - a).
500
+ * If r > 1 or r < 0 then c is outside of the segment ab.
501
+ *
502
+ * @param {Array|JXG.Coords} a
503
+ * @param {Array|JXG.Coords} b
504
+ * @param {Array|JXG.Coords} c
505
+ * @returns {Number} affine ratio (c - a) / (b - a)
506
+ */
507
+ affineRatio: function(a, b, c) {
508
+ var r = 0.0, dx;
509
+
510
+ if (Type.exists(a.usrCoords)) {
511
+ a = a.usrCoords;
512
+ }
513
+ if (Type.exists(b.usrCoords)) {
514
+ b = b.usrCoords;
515
+ }
516
+ if (Type.exists(c.usrCoords)) {
517
+ c = c.usrCoords;
518
+ }
519
+
520
+ dx = b[1] - a[1];
521
+
522
+ if (Math.abs(dx) > Mat.eps) {
523
+ r = (c[1] - a[1]) / dx;
524
+ } else {
525
+ r = (c[2] - a[2]) / (b[2] - a[2]);
526
+ }
527
+ return r;
528
+ },
529
+
498
530
  /**
499
531
  * Sort vertices counter clockwise starting with the first point.
500
532
  *
@@ -1040,8 +1072,10 @@ define([
1040
1072
  (el2.type === Const.OBJECT_TYPE_ARC || el2.type === Const.OBJECT_TYPE_SECTOR)
1041
1073
  ) ? true : false;
1042
1074
 
1043
- if (el1.elementClass === Const.OBJECT_CLASS_CURVE &&
1044
- el2.elementClass === Const.OBJECT_CLASS_CURVE && !(el1_isArcType && el2_isArcType) ) {
1075
+ if ((el1.elementClass === Const.OBJECT_CLASS_CURVE || el2.elementClass === Const.OBJECT_CLASS_CURVE) &&
1076
+ (el1.elementClass === Const.OBJECT_CLASS_CURVE || el1.elementClass === Const.OBJECT_CLASS_CIRCLE) &&
1077
+ (el2.elementClass === Const.OBJECT_CLASS_CURVE || el2.elementClass === Const.OBJECT_CLASS_CIRCLE) /*&&
1078
+ !(el1_isArcType && el2_isArcType)*/ ) {
1045
1079
  // curve - curve
1046
1080
  // with the exception that both elements are arc types
1047
1081
  /** @ignore */
@@ -1049,10 +1083,17 @@ define([
1049
1083
  return that.meetCurveCurve(el1, el2, i, j, el1.board);
1050
1084
  };
1051
1085
 
1052
- } else if ((el1.elementClass === Const.OBJECT_CLASS_CURVE &&
1053
- !el1_isArcType && el2.elementClass === Const.OBJECT_CLASS_LINE) ||
1054
- (el2.elementClass === Const.OBJECT_CLASS_CURVE &&
1055
- !el2_isArcType && el1.elementClass === Const.OBJECT_CLASS_LINE)) {
1086
+ } else if ((
1087
+ el1.elementClass === Const.OBJECT_CLASS_CURVE &&
1088
+ !el1_isArcType &&
1089
+ el2.elementClass === Const.OBJECT_CLASS_LINE
1090
+ ) ||
1091
+ (
1092
+ el2.elementClass === Const.OBJECT_CLASS_CURVE &&
1093
+ !el2_isArcType &&
1094
+ el1.elementClass === Const.OBJECT_CLASS_LINE
1095
+ )
1096
+ ) {
1056
1097
  // curve - line (this includes intersections between conic sections and lines)
1057
1098
  // with the exception that the curve is of arc type
1058
1099
  /** @ignore */
@@ -1103,15 +1144,39 @@ define([
1103
1144
  /** @ignore */
1104
1145
  func = function () {
1105
1146
  var res = that.meet(el1.stdform, el2.stdform, i, el1.board),
1106
- has = true;
1147
+ has = true,
1148
+ first, last, r, dx;
1107
1149
 
1108
- if (!alwaysintersect && el1_isArcType) {
1150
+ if (alwaysintersect) {
1151
+ return res;
1152
+ }
1153
+ if (el1.elementClass === Const.OBJECT_CLASS_LINE) {
1154
+ first = Type.evaluate(el1.visProp.straightfirst);
1155
+ last = Type.evaluate(el1.visProp.straightlast);
1156
+ if (!first || !last) {
1157
+ r = that.affineRatio(el1.point1.coords, el1.point2.coords, res);
1158
+ if ( (!last && r > 1 + Mat.eps) || (!first && r < 0 - Mat.eps) ) {
1159
+ return (new Coords(JXG.COORDS_BY_USER, [0, NaN, NaN], el1.board));
1160
+ }
1161
+ }
1162
+ }
1163
+ if (el2.elementClass === Const.OBJECT_CLASS_LINE) {
1164
+ first = Type.evaluate(el2.visProp.straightfirst);
1165
+ last = Type.evaluate(el2.visProp.straightlast);
1166
+ if (!first || !last) {
1167
+ r = that.affineRatio(el2.point1.coords, el2.point2.coords, res);
1168
+ if ( (!last && r > 1 + Mat.eps) || (!first && r < 0 - Mat.eps) ) {
1169
+ return (new Coords(JXG.COORDS_BY_USER, [0, NaN, NaN], el1.board));
1170
+ }
1171
+ }
1172
+ }
1173
+ if (el1_isArcType) {
1109
1174
  has = that.coordsOnArc(el1, res);
1110
1175
  if (has && el2_isArcType) {
1111
1176
  has = that.coordsOnArc(el2, res);
1112
1177
  }
1113
1178
  if (!has) {
1114
- res = (new Coords(JXG.COORDS_BY_USER, [0, NaN, NaN], el1.board));
1179
+ return (new Coords(JXG.COORDS_BY_USER, [0, NaN, NaN], el1.board));
1115
1180
  }
1116
1181
  }
1117
1182
  return res;
@@ -1304,7 +1369,6 @@ define([
1304
1369
 
1305
1370
  return new Coords(Const.COORDS_BY_USER, [NaN, NaN], board);
1306
1371
  }
1307
-
1308
1372
  c = circ[0];
1309
1373
  b = circ.slice(1, 3);
1310
1374
  a = circ[3];
@@ -1396,7 +1460,7 @@ define([
1396
1460
  if (Type.exists(method) && method === 'newton') {
1397
1461
  co = Numerics.generalizedNewton(c1, c2, nr, t2ini);
1398
1462
  } else {
1399
- if (c1.bezierDegree === 3 && c2.bezierDegree === 3) {
1463
+ if (c1.bezierDegree === 3 || c2.bezierDegree === 3) {
1400
1464
  co = this.meetBezierCurveRedBlueSegments(c1, c2, nr);
1401
1465
  } else {
1402
1466
  co = this.meetCurveRedBlueSegments(c1, c2, nr);
@@ -1437,11 +1501,7 @@ define([
1437
1501
  li = el1;
1438
1502
  }
1439
1503
 
1440
- // if (Type.evaluate(cu.visProp.curvetype) === 'plot') {
1441
- v = this.meetCurveLineDiscrete(cu, li, nr, board, !alwaysIntersect);
1442
- // } else {
1443
- // v = this.meetCurveLineContinuous(cu, li, nr, board);
1444
- // }
1504
+ v = this.meetCurveLineDiscrete(cu, li, nr, board, !alwaysIntersect);
1445
1505
 
1446
1506
  return v;
1447
1507
  },
@@ -1520,80 +1580,6 @@ define([
1520
1580
  return (new Coords(Const.COORDS_BY_USER, [z, cu.X(t), cu.Y(t)], board));
1521
1581
  },
1522
1582
 
1523
- /**
1524
- * Intersection of line and curve, continuous case.
1525
- * Segments are treated as lines. Finding the nr-the intersection point
1526
- * works for nr=0,1 only.
1527
- *
1528
- * @private
1529
- * @deprecated
1530
- * @param {JXG.Curve} cu Curve
1531
- * @param {JXG.Line} li Line
1532
- * @param {Number} nr Will return the nr-th intersection point.
1533
- * @param {JXG.Board} board
1534
- *
1535
- * BUG: does not respect cu.minX() and cu.maxX()
1536
- */
1537
- meetCurveLineContinuousOld: function (cu, li, nr, board) {
1538
- var t, t2, i, func, z,
1539
- tnew, steps, delta, tstart, tend, cux, cuy,
1540
- eps = Mat.eps * 10;
1541
-
1542
- JXG.deprecated('Geometry.meetCurveLineContinuousOld()', 'Geometry.meetCurveLineContinuous()');
1543
- func = function (t) {
1544
- var v = li.stdform[0] + li.stdform[1] * cu.X(t) + li.stdform[2] * cu.Y(t);
1545
- return v * v;
1546
- };
1547
-
1548
- // Find some intersection point
1549
- if (this.meetCurveLineContinuous.t1memo) {
1550
- tstart = this.meetCurveLineContinuous.t1memo;
1551
- t = Numerics.root(func, tstart);
1552
- } else {
1553
- tstart = cu.minX();
1554
- tend = cu.maxX();
1555
- t = Numerics.root(func, [tstart, tend]);
1556
- }
1557
-
1558
- this.meetCurveLineContinuous.t1memo = t;
1559
- cux = cu.X(t);
1560
- cuy = cu.Y(t);
1561
-
1562
- // Find second intersection point
1563
- if (nr === 1) {
1564
- if (this.meetCurveLineContinuous.t2memo) {
1565
- tstart = this.meetCurveLineContinuous.t2memo;
1566
- }
1567
- t2 = Numerics.root(func, tstart);
1568
-
1569
- if (!(Math.abs(t2 - t) > 0.1 && Math.abs(cux - cu.X(t2)) > 0.1 && Math.abs(cuy - cu.Y(t2)) > 0.1)) {
1570
- steps = 20;
1571
- delta = (cu.maxX() - cu.minX()) / steps;
1572
- tnew = cu.minX();
1573
-
1574
- for (i = 0; i < steps; i++) {
1575
- t2 = Numerics.root(func, [tnew, tnew + delta]);
1576
-
1577
- if (Math.abs(func(t2)) <= eps && Math.abs(t2 - t) > 0.1 && Math.abs(cux - cu.X(t2)) > 0.1 && Math.abs(cuy - cu.Y(t2)) > 0.1) {
1578
- break;
1579
- }
1580
-
1581
- tnew += delta;
1582
- }
1583
- }
1584
- t = t2;
1585
- this.meetCurveLineContinuous.t2memo = t;
1586
- }
1587
-
1588
- // Is the point on the line?
1589
- if (Math.abs(func(t)) > eps) {
1590
- z = NaN;
1591
- } else {
1592
- z = 1.0;
1593
- }
1594
-
1595
- return (new Coords(Const.COORDS_BY_USER, [z, cu.X(t), cu.Y(t)], board));
1596
- },
1597
1583
 
1598
1584
  /**
1599
1585
  * Intersection of line and curve, discrete case.
@@ -1630,7 +1616,7 @@ define([
1630
1616
  }
1631
1617
 
1632
1618
  p2 = cu.points[0].usrCoords;
1633
- for (i = 1; i < len; i++) {
1619
+ for (i = 1; i < len; i += cu.bezierDegree) {
1634
1620
  p1 = p2.slice(0);
1635
1621
  p2 = cu.points[i].usrCoords;
1636
1622
  d = this.distance(p1, p2);
@@ -1647,8 +1633,6 @@ define([
1647
1633
  lip1.slice(1),
1648
1634
  lip2.slice(1)
1649
1635
  ], testSegment);
1650
-
1651
- i += 2;
1652
1636
  } else {
1653
1637
  res = [this.meetSegmentSegment(p1, p2, lip1, lip2)];
1654
1638
  }
@@ -1660,7 +1644,7 @@ define([
1660
1644
  /**
1661
1645
  * If the intersection point is not part of the segment,
1662
1646
  * this intersection point is set to non-existent.
1663
- * This prevents jumping of the intersection points.
1647
+ * This prevents jumping behavior of the intersection points.
1664
1648
  * But it may be discussed if it is the desired behavior.
1665
1649
  */
1666
1650
  if (testSegment &&
@@ -1739,32 +1723,46 @@ define([
1739
1723
  },
1740
1724
 
1741
1725
  /**
1742
- * Intersection of two segments.
1743
- * @param {Array} p1 First point of segment 1 using homogeneous coordinates [z,x,y]
1744
- * @param {Array} p2 Second point of segment 1 using homogeneous coordinates [z,x,y]
1745
- * @param {Array} q1 First point of segment 2 using homogeneous coordinates [z,x,y]
1746
- * @param {Array} q2 Second point of segment 2 using homogeneous coordinates [z,x,y]
1726
+ * (Virtual) Intersection of two segments.
1727
+ * @param {Array} p1 First point of segment 1 using normalized homogeneous coordinates [1,x,y]
1728
+ * @param {Array} p2 Second point or direction of segment 1 using normalized homogeneous coordinates [1,x,y] or point at infinity [0,x,y], respectively
1729
+ * @param {Array} q1 First point of segment 2 using normalized homogeneous coordinates [1,x,y]
1730
+ * @param {Array} q2 Second point or direction of segment 2 using normalized homogeneous coordinates [1,x,y] or point at infinity [0,x,y], respectively
1747
1731
  * @returns {Array} [Intersection point, t, u] The first entry contains the homogeneous coordinates
1748
- * of the intersection point. The second and third entry gives the position of the intersection between the
1749
- * two defining points. For example, the second entry t is defined by: intersection point = t*p1 + (1-t)*p2.
1732
+ * of the intersection point. The second and third entry give the position of the intersection with respect
1733
+ * to the definiting parameters. For example, the second entry t is defined by: intersection point = p1 + t * deltaP, where
1734
+ * deltaP = (p2 - p1) when both parameters are coordinates, and deltaP = p2 if p2 is a point at infinity.
1750
1735
  * If the two segments are collinear, [[0,0,0], Infinity, Infinity] is returned.
1751
1736
  **/
1752
1737
  meetSegmentSegment: function (p1, p2, q1, q2) {
1753
- var t, u, diff,
1738
+ var t, u, i, d,
1754
1739
  li1 = Mat.crossProduct(p1, p2),
1755
1740
  li2 = Mat.crossProduct(q1, q2),
1756
- c = Mat.crossProduct(li1, li2),
1757
- denom = c[0];
1741
+ c = Mat.crossProduct(li1, li2);
1758
1742
 
1759
- if (Math.abs(denom) < Mat.eps) {
1743
+ if (Math.abs(c[0]) < Mat.eps) {
1760
1744
  return [c, Infinity, Infinity];
1761
1745
  }
1762
1746
 
1763
- diff = [q1[1] - p1[1], q1[2] - p1[2]];
1747
+ // Normalize the intersection coordinates
1748
+ c[1] /= c[0];
1749
+ c[2] /= c[0];
1750
+ c[0] /= c[0];
1764
1751
 
1765
- // Because of speed issues, evalute the determinants directly
1766
- t = (diff[0] * (q2[2] - q1[2]) - diff[1] * (q2[1] - q1[1])) / denom;
1767
- u = (diff[0] * (p2[2] - p1[2]) - diff[1] * (p2[1] - p1[1])) / denom;
1752
+ // Now compute in principle:
1753
+ // t = dist(c - p1) / dist(p2 - p1) and
1754
+ // u = dist(c - q1) / dist(q2 - q1)
1755
+ // However: the points q1, q2, p1, p2 might be ideal points - or in general - the
1756
+ // coordinates might be not normalized.
1757
+ // Note that the z-coordinates of p2 and q2 are used to determine whether it should be interpreted
1758
+ // as a segment coordinate or a direction.
1759
+ i = (Math.abs(p2[1] - p2[0] * p1[1]) < Mat.eps) ? 2 : 1;
1760
+ d = p1[i] / p1[0];
1761
+ t = (c[i] - d) / ( (p2[0] !== 0) ? (p2[i] / p2[0] - d) : p2[i] );
1762
+
1763
+ i = (Math.abs(q2[1] - q2[0] * q1[1]) < Mat.eps) ? 2 : 1;
1764
+ d = q1[i] / q1[0];
1765
+ u = (c[i] - d) / ( (q2[0] !== 0) ? (q2[i] / q2[0] - d) : q2[i] );
1768
1766
 
1769
1767
  return [c, t, u];
1770
1768
  },
@@ -2004,40 +2002,71 @@ define([
2004
2002
  * @returns {Array} The homogeneous coordinates of the nr-th intersection point.
2005
2003
  */
2006
2004
  meetBezierCurveRedBlueSegments: function (red, blue, nr) {
2007
- var p, i, j,
2005
+ var p, i, j, k, po,
2008
2006
  redArr, blueArr,
2009
- bbr, bbb,
2010
- lenBlue = blue.numberPoints, //points.length,
2011
- lenRed = red.numberPoints, // points.length,
2007
+ bbr, bbb, intersections,
2008
+ startRed = 0,
2009
+ startBlue = 0,
2010
+ lenBlue = blue.numberPoints,
2011
+ lenRed = red.numberPoints,
2012
2012
  L = [];
2013
2013
 
2014
- if (lenBlue < 4 || lenRed < 4) {
2014
+ if (lenBlue < blue.bezierDegree + 1 || lenRed < red.bezierDegree + 1) {
2015
2015
  return [0, NaN, NaN];
2016
2016
  }
2017
+ lenBlue -= blue.bezierDegree;
2018
+ lenRed -= red.bezierDegree;
2017
2019
 
2018
- for (i = 0; i < lenRed - 3; i += 3) {
2020
+ // For sectors, we ignore the "legs"
2021
+ if (red.type === Const.OBJECT_TYPE_SECTOR) {
2022
+ startRed = 3;
2023
+ lenRed -= 3;
2024
+ }
2025
+ if (blue.type === Const.OBJECT_TYPE_SECTOR) {
2026
+ startBlue = 3;
2027
+ lenBlue -= 3;
2028
+ }
2029
+
2030
+ for (i = startRed; i < lenRed; i += red.bezierDegree) {
2019
2031
  p = red.points;
2020
2032
  redArr = [
2021
- [p[i].usrCoords[1], p[i].usrCoords[2]],
2022
- [p[i + 1].usrCoords[1], p[i + 1].usrCoords[2]],
2023
- [p[i + 2].usrCoords[1], p[i + 2].usrCoords[2]],
2024
- [p[i + 3].usrCoords[1], p[i + 3].usrCoords[2]]
2033
+ p[i].usrCoords.slice(1),
2034
+ p[i + 1].usrCoords.slice(1)
2025
2035
  ];
2036
+ if (red.bezierDegree === 3) {
2037
+ redArr[2] = p[i + 2].usrCoords.slice(1);
2038
+ redArr[3] = p[i + 3].usrCoords.slice(1);
2039
+ }
2026
2040
 
2027
2041
  bbr = this._bezierBbox(redArr);
2028
2042
 
2029
- for (j = 0; j < lenBlue - 3; j += 3) {
2043
+ for (j = startBlue; j < lenBlue; j += blue.bezierDegree) {
2030
2044
  p = blue.points;
2031
2045
  blueArr = [
2032
- [p[j].usrCoords[1], p[j].usrCoords[2]],
2033
- [p[j + 1].usrCoords[1], p[j + 1].usrCoords[2]],
2034
- [p[j + 2].usrCoords[1], p[j + 2].usrCoords[2]],
2035
- [p[j + 3].usrCoords[1], p[j + 3].usrCoords[2]]
2046
+ p[j].usrCoords.slice(1),
2047
+ p[j + 1].usrCoords.slice(1)
2036
2048
  ];
2049
+ if (blue.bezierDegree === 3) {
2050
+ blueArr[2] = p[j + 2].usrCoords.slice(1);
2051
+ blueArr[3] = p[j + 3].usrCoords.slice(1);
2052
+ }
2037
2053
 
2038
2054
  bbb = this._bezierBbox(blueArr);
2039
2055
  if (this._bezierOverlap(bbr, bbb)) {
2040
- L = L.concat(this.meetBeziersegmentBeziersegment(redArr, blueArr));
2056
+ intersections = this.meetBeziersegmentBeziersegment(redArr, blueArr);
2057
+ if (intersections.length === 0) {
2058
+ continue;
2059
+ }
2060
+ for (k = 0; k < intersections.length; k++) {
2061
+ po = intersections[k];
2062
+ if (po[1] < -Mat.eps ||
2063
+ po[1] > 1 + Mat.eps ||
2064
+ po[2] < -Mat.eps ||
2065
+ po[2] > 1 + Mat.eps) {
2066
+ continue;
2067
+ }
2068
+ L.push(po);
2069
+ }
2041
2070
  if (L.length > nr) {
2042
2071
  return L[nr][0];
2043
2072
  }