1010'use strict' ;
1111
1212var 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 ;
1416var constants = require ( './constants' ) ;
1517
1618
@@ -20,7 +22,8 @@ module.exports = function linePoints(d, opts) {
2022 var simplify = opts . simplify ;
2123 var connectGaps = opts . connectGaps ;
2224 var baseTolerance = opts . baseTolerance ;
23- var linear = opts . linear ;
25+ var shape = opts . shape ;
26+ var linear = shape === 'linear' ;
2427 var segments = [ ] ;
2528 var minTolerance = constants . minTolerance ;
2629 var pts = new Array ( d . length ) ;
@@ -100,7 +103,10 @@ module.exports = function linePoints(d, opts) {
100103 ] ;
101104 var xEdge , yEdge , lastXEdge , lastYEdge , lastFarPt , edgePt ;
102105
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 ) {
104110 var out = [ ] ;
105111 var ptCount = 0 ;
106112 for ( var i = 0 ; i < 4 ; i ++ ) {
@@ -121,6 +127,70 @@ module.exports = function linePoints(d, opts) {
121127 return out ;
122128 }
123129
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+
124194 // a segment pt1->pt2 entirely outside the nearby region:
125195 // find the corner it gets closest to touching
126196 function getClosestCorner ( pt1 , pt2 ) {
0 commit comments