10
10
'use strict' ;
11
11
12
12
var BADNUM = require ( '../../constants/numerical' ) . BADNUM ;
13
- var segmentsIntersect = require ( '../../lib/geometry2d' ) . segmentsIntersect ;
13
+ var Lib = require ( '../../lib' ) ;
14
+ var segmentsIntersect = Lib . segmentsIntersect ;
15
+ var constrain = Lib . constrain ;
14
16
var constants = require ( './constants' ) ;
15
17
16
18
@@ -20,7 +22,8 @@ module.exports = function linePoints(d, opts) {
20
22
var simplify = opts . simplify ;
21
23
var connectGaps = opts . connectGaps ;
22
24
var baseTolerance = opts . baseTolerance ;
23
- var linear = opts . linear ;
25
+ var shape = opts . shape ;
26
+ var linear = shape === 'linear' ;
24
27
var segments = [ ] ;
25
28
var minTolerance = constants . minTolerance ;
26
29
var pts = new Array ( d . length ) ;
@@ -100,7 +103,10 @@ module.exports = function linePoints(d, opts) {
100
103
] ;
101
104
var xEdge , yEdge , lastXEdge , lastYEdge , lastFarPt , edgePt ;
102
105
103
- function getEdgeIntersections ( pt1 , pt2 ) {
106
+ // for linear line shape, edge intersections should be linearly interpolated
107
+ // spline uses this too, which isn't precisely correct but is actually pretty
108
+ // good, because Catmull-Rom weights far-away points less in creating the curvature
109
+ function getLinearEdgeIntersections ( pt1 , pt2 ) {
104
110
var out = [ ] ;
105
111
var ptCount = 0 ;
106
112
for ( var i = 0 ; i < 4 ; i ++ ) {
@@ -121,6 +127,70 @@ module.exports = function linePoints(d, opts) {
121
127
return out ;
122
128
}
123
129
130
+ function onlyConstrainedPoint ( pt ) {
131
+ if ( pt [ 0 ] < xEdge0 || pt [ 0 ] > xEdge1 || pt [ 1 ] < yEdge0 || pt [ 1 ] > yEdge1 ) {
132
+ return [ constrain ( pt [ 0 ] , xEdge0 , xEdge1 ) , constrain ( pt [ 1 ] , yEdge0 , yEdge1 ) ] ;
133
+ }
134
+ }
135
+
136
+ function sameEdge ( pt1 , pt2 ) {
137
+ if ( pt1 [ 0 ] === pt2 [ 0 ] && ( pt1 [ 0 ] === xEdge0 || pt1 [ 0 ] === xEdge1 ) ) return true ;
138
+ if ( pt1 [ 1 ] === pt2 [ 1 ] && ( pt1 [ 1 ] === yEdge0 || pt1 [ 1 ] === yEdge1 ) ) return true ;
139
+ }
140
+
141
+ // for line shapes hv and vh, movement in the two dimensions is decoupled,
142
+ // so all we need to do is constrain each dimension independently
143
+ function getHVEdgeIntersections ( pt1 , pt2 ) {
144
+ var out = [ ] ;
145
+ var ptInt1 = onlyConstrainedPoint ( pt1 ) ;
146
+ var ptInt2 = onlyConstrainedPoint ( pt2 ) ;
147
+ if ( ptInt1 && ptInt2 && sameEdge ( ptInt1 , ptInt2 ) ) return out ;
148
+
149
+ if ( ptInt1 ) out . push ( ptInt1 ) ;
150
+ if ( ptInt2 ) out . push ( ptInt2 ) ;
151
+ return out ;
152
+ }
153
+
154
+ // hvh and vhv we sometimes have to move one of the intersection points
155
+ // out BEYOND the clipping rect, by a maximum of a factor of 2, so that
156
+ // the midpoint line is drawn in the right place
157
+ function getABAEdgeIntersections ( dim , limit0 , limit1 ) {
158
+ return function ( pt1 , pt2 ) {
159
+ var ptInt1 = onlyConstrainedPoint ( pt1 ) ;
160
+ var ptInt2 = onlyConstrainedPoint ( pt2 ) ;
161
+
162
+ var out = [ ] ;
163
+ if ( ptInt1 && ptInt2 && sameEdge ( ptInt1 , ptInt2 ) ) return out ;
164
+
165
+ if ( ptInt1 ) out . push ( ptInt1 ) ;
166
+ if ( ptInt2 ) out . push ( ptInt2 ) ;
167
+
168
+ var midShift = 2 * Lib . constrain ( ( pt1 [ dim ] + pt2 [ dim ] ) / 2 , limit0 , limit1 ) -
169
+ ( ( ptInt1 || pt1 ) [ dim ] + ( ptInt2 || pt2 ) [ dim ] ) ;
170
+ if ( midShift ) {
171
+ var ptToAlter ;
172
+ if ( ptInt1 && ptInt2 ) {
173
+ ptToAlter = ( midShift > 0 === ptInt1 [ dim ] > ptInt2 [ dim ] ) ? ptInt1 : ptInt2 ;
174
+ }
175
+ else ptToAlter = ptInt1 || ptInt2 ;
176
+
177
+ ptToAlter [ dim ] += midShift ;
178
+ }
179
+
180
+ return out ;
181
+ } ;
182
+ }
183
+
184
+ var getEdgeIntersections ;
185
+ if ( shape === 'linear' || shape === 'spline' ) {
186
+ getEdgeIntersections = getLinearEdgeIntersections ;
187
+ }
188
+ else if ( shape === 'hv' || shape === 'vh' ) {
189
+ getEdgeIntersections = getHVEdgeIntersections ;
190
+ }
191
+ else if ( shape === 'hvh' ) getEdgeIntersections = getABAEdgeIntersections ( 0 , xEdge0 , xEdge1 ) ;
192
+ else if ( shape === 'vhv' ) getEdgeIntersections = getABAEdgeIntersections ( 1 , yEdge0 , yEdge1 ) ;
193
+
124
194
// a segment pt1->pt2 entirely outside the nearby region:
125
195
// find the corner it gets closest to touching
126
196
function getClosestCorner ( pt1 , pt2 ) {
0 commit comments