@@ -61,17 +61,44 @@ module.exports = function linePoints(d, opts) {
61
61
// turn one calcdata point into pixel coordinates
62
62
function getPt ( index ) {
63
63
var di = d [ index ] ;
64
+ if ( ! di ) return false ;
64
65
var x = xa . c2p ( di . x ) ;
65
66
var y = ya . c2p ( di . y ) ;
66
67
if ( x === BADNUM || y === BADNUM ) return di . intoCenter || false ;
67
68
return [ x , y ] ;
68
69
}
69
70
71
+ function crossesViewport ( xFrac0 , yFrac0 , xFrac1 , yFrac1 ) {
72
+ var dx = xFrac1 - xFrac0 ;
73
+ var dy = yFrac1 - yFrac0 ;
74
+ var dx0 = 0.5 - xFrac0 ;
75
+ var dy0 = 0.5 - yFrac0 ;
76
+ var norm2 = dx * dx + dy * dy ;
77
+ var dot = dx * dx0 + dy * dy0 ;
78
+ if ( dot > 0 && dot < norm2 ) {
79
+ var cross = dx0 * dy - dy0 * dx ;
80
+ if ( cross * cross < norm2 ) return true ;
81
+ }
82
+ }
83
+
84
+ var latestXFrac , latestYFrac ;
70
85
// if we're off-screen, increase tolerance over baseTolerance
71
- function getTolerance ( pt ) {
86
+ function getTolerance ( pt , nextPt ) {
72
87
var xFrac = pt [ 0 ] / xa . _length ;
73
88
var yFrac = pt [ 1 ] / ya . _length ;
74
- return ( 1 + constants . toleranceGrowth * Math . max ( 0 , - xFrac , xFrac - 1 , - yFrac , yFrac - 1 ) ) * baseTolerance ;
89
+ var offScreenFraction = Math . max ( 0 , - xFrac , xFrac - 1 , - yFrac , yFrac - 1 ) ;
90
+ if ( offScreenFraction && ( latestXFrac !== undefined ) &&
91
+ crossesViewport ( xFrac , yFrac , latestXFrac , latestYFrac )
92
+ ) {
93
+ offScreenFraction = 0 ;
94
+ }
95
+ if ( offScreenFraction && nextPt &&
96
+ crossesViewport ( xFrac , yFrac , nextPt [ 0 ] / xa . _length , nextPt [ 1 ] / ya . _length )
97
+ ) {
98
+ offScreenFraction = 0 ;
99
+ }
100
+
101
+ return ( 1 + constants . toleranceGrowth * offScreenFraction ) * baseTolerance ;
75
102
}
76
103
77
104
function ptDist ( pt1 , pt2 ) {
@@ -239,6 +266,8 @@ module.exports = function linePoints(d, opts) {
239
266
}
240
267
241
268
function addPt ( pt ) {
269
+ latestXFrac = pt [ 0 ] / xa . _length ;
270
+ latestYFrac = pt [ 1 ] / ya . _length ;
242
271
// Are we more than maxScreensAway off-screen any direction?
243
272
// if so, clip to this box, but in such a way that on-screen
244
273
// drawing is unchanged
@@ -333,9 +362,11 @@ module.exports = function linePoints(d, opts) {
333
362
continue ;
334
363
}
335
364
365
+ var nextPt = getPt ( i + 1 ) ;
366
+
336
367
clusterRefDist = ptDist ( clusterHighPt , clusterStartPt ) ;
337
368
338
- if ( clusterRefDist < getTolerance ( clusterHighPt ) * minTolerance ) continue ;
369
+ if ( clusterRefDist < getTolerance ( clusterHighPt , nextPt ) * minTolerance ) continue ;
339
370
340
371
clusterUnitVector = [
341
372
( clusterHighPt [ 0 ] - clusterStartPt [ 0 ] ) / clusterRefDist ,
@@ -350,7 +381,8 @@ module.exports = function linePoints(d, opts) {
350
381
351
382
// loop over one cluster of points that collapse onto one line
352
383
for ( i ++ ; i < d . length ; i ++ ) {
353
- thisPt = getPt ( i ) ;
384
+ thisPt = nextPt ;
385
+ nextPt = getPt ( i + 1 ) ;
354
386
if ( ! thisPt ) {
355
387
if ( connectGaps ) continue ;
356
388
else break ;
@@ -364,7 +396,7 @@ module.exports = function linePoints(d, opts) {
364
396
clusterMinDeviation = Math . min ( clusterMinDeviation , thisDeviation ) ;
365
397
clusterMaxDeviation = Math . max ( clusterMaxDeviation , thisDeviation ) ;
366
398
367
- if ( clusterMaxDeviation - clusterMinDeviation > getTolerance ( thisPt ) ) break ;
399
+ if ( clusterMaxDeviation - clusterMinDeviation > getTolerance ( thisPt , nextPt ) ) break ;
368
400
369
401
clusterEndPt = thisPt ;
370
402
thisVal = thisVector [ 0 ] * clusterUnitVector [ 0 ] + thisVector [ 1 ] * clusterUnitVector [ 1 ] ;
0 commit comments