bezierjs icon indicating copy to clipboard operation
bezierjs copied to clipboard

`simple` does not behave correctly on edge case

Open hfutrell opened this issue 7 years ago • 0 comments

The simple function has a minor issue in edge cases where the start and end point normals are equal, such as when constructing a bezier curve for a straight line. The issue appears to arise due to limits of floating point.

The simple function has the following snippet to compute the angle between endpoint normals

      var n1 = this.normal(0);
      var n2 = this.normal(1);
      var s = n1.x*n2.x + n1.y*n2.y;
      if(this._3d) { s += n1.z*n2.z; }
      var angle = abs(acos(s));

The snippet is mathematically correct, but in practice when n1 = n2 the variable s is computed with finite precision and can fall just outside the domain of the acos function and cause it to return NaN. As an example If I construct a cubic bezier curve from the points (1,1), (2,2), (3,3) and (4,4) we have n1 = n2 and then we have s = 1.0000000000000002, and finally angle = NaN. All comparisons with NaN return false in javascript (and most other languages) and so the function incorrectly returns false.

I believe the issue is remedied if we simply clamp s to the interval [-1, 1] as one would never expect a dot product between unit vectors to be outside this range.

The issue can cause unnecessary splitting of straight lines in the reduce function.

hfutrell avatar Jan 04 '18 05:01 hfutrell