@@ -21,7 +21,7 @@ export class Arrow extends Mark {
21
21
y2,
22
22
bend = 0 ,
23
23
headAngle = 60 ,
24
- headLength = 8 ,
24
+ headLength = 8 , // Disable the arrow with headLength = 0; or, use Plot.link.
25
25
inset = 0 ,
26
26
insetStart = inset ,
27
27
insetEnd = inset
@@ -71,6 +71,8 @@ export class Arrow extends Mark {
71
71
. join ( "path" )
72
72
. call ( applyDirectStyles , this )
73
73
. attr ( "d" , i => {
74
+ // The start ⟨x1,y1⟩ and end ⟨x2,y2⟩ points may be inset, and the
75
+ // ending line angle may be altered for inset swoopy arrows.
74
76
let x1 = X1 [ i ] , y1 = Y1 [ i ] , x2 = X2 [ i ] , y2 = Y2 [ i ] ;
75
77
let lineAngle = Math . atan2 ( y2 - y1 , x2 - x1 ) ;
76
78
const lineLength = Math . hypot ( x2 - x1 , y2 - y1 ) ;
@@ -98,7 +100,7 @@ export class Arrow extends Mark {
98
100
}
99
101
// For the end inset, rotate the arrowhead so that it aligns
100
102
// with the truncated end of the arrow. Since the arrow is a
101
- // segment of the circle centered at < cx,cy> , we can compute
103
+ // segment of the circle centered at ⟨ cx,cy⟩ , we can compute
102
104
// the angular difference to the new endpoint.
103
105
if ( insetEnd ) {
104
106
const [ x , y ] = circleCircleIntersect ( [ cx , cy , r ] , [ x2 , y2 , insetEnd ] , sign * Math . sign ( insetEnd ) ) ;
@@ -135,13 +137,21 @@ export class Arrow extends Mark {
135
137
}
136
138
}
137
139
138
- function pointPointCenter ( [ ax , ay ] , [ bx , by ] , r , sign = 1 ) {
140
+ // Returns the center of a circle that goes through the two given points ⟨ax,ay⟩
141
+ // and ⟨bx,by⟩ and has radius r. There are two such points; use the sign +1 or
142
+ // -1 to chose between them. Returns [NaN, NaN] if r is too small.
143
+ function pointPointCenter ( [ ax , ay ] , [ bx , by ] , r , sign ) {
139
144
const dx = bx - ax , dy = by - ay , d = Math . hypot ( dx , dy ) ;
140
145
const k = sign * Math . sqrt ( r * r - d * d / 4 ) / d ;
141
146
return [ ( ax + bx ) / 2 - dy * k , ( ay + by ) / 2 + dx * k ] ;
142
147
}
143
148
144
- function circleCircleIntersect ( [ ax , ay , ar ] , [ bx , by , br ] , sign = 1 ) {
149
+ // Given two circles, one centered at ⟨ax,ay⟩ with radius ar, and the other
150
+ // centered at ⟨bx,by⟩ with radius br, returns a point at which the two circles
151
+ // intersect. There are typically two such points; use the sign +1 or -1 to
152
+ // chose between them. Returns [NaN, NaN] if there is no intersection.
153
+ // https://mathworld.wolfram.com/Circle-CircleIntersection.html
154
+ function circleCircleIntersect ( [ ax , ay , ar ] , [ bx , by , br ] , sign ) {
145
155
const dx = bx - ax , dy = by - ay , d = Math . hypot ( dx , dy ) ;
146
156
const x = ( dx * dx + dy * dy - br * br + ar * ar ) / ( 2 * d ) ;
147
157
const y = sign * Math . sign ( ay ) * Math . sqrt ( ar * ar - x * x ) ;
0 commit comments