Skip to content

Commit 5ec2f5c

Browse files
Filmbostock
andauthored
fix arrow (#833)
* add test * remove arrows with a non-positive length fixes inset bug closes #832 * tweak test style * M for matrix Co-authored-by: Mike Bostock <[email protected]>
1 parent 6945a70 commit 5ec2f5c

File tree

4 files changed

+70
-2
lines changed

4 files changed

+70
-2
lines changed

src/marks/arrow.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,9 @@ export class Arrow extends Mark {
7676
// The start ⟨x1,y1⟩ and end ⟨x2,y2⟩ points may be inset, and the
7777
// ending line angle may be altered for inset swoopy arrows.
7878
let x1 = X1[i], y1 = Y1[i], x2 = X2[i], y2 = Y2[i];
79-
let lineAngle = Math.atan2(y2 - y1, x2 - x1);
8079
const lineLength = Math.hypot(x2 - x1, y2 - y1);
80+
if (lineLength <= insetStart + insetEnd) return null;
81+
let lineAngle = Math.atan2(y2 - y1, x2 - x1);
8182

8283
// We don’t allow the wing length to be too large relative to the
8384
// length of the arrow. (Plot.vector allows arbitrarily large
@@ -156,7 +157,7 @@ function pointPointCenter([ax, ay], [bx, by], r, sign) {
156157
function circleCircleIntersect([ax, ay, ar], [bx, by, br], sign) {
157158
const dx = bx - ax, dy = by - ay, d = Math.hypot(dx, dy);
158159
const x = (dx * dx + dy * dy - br * br + ar * ar) / (2 * d);
159-
const y = sign * Math.sign(ay) * Math.sqrt(ar * ar - x * x);
160+
const y = sign * Math.sqrt(ar * ar - x * x);
160161
return [ax + (dx * x + dy * y) / d, ay + (dy * x - dx * y) / d];
161162
}
162163

test/output/markovChain.svg

Lines changed: 34 additions & 0 deletions
Loading

test/plots/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ export {default as letterFrequencyLollipop} from "./letter-frequency-lollipop.js
8080
export {default as letterFrequencyWheel} from "./letter-frequency-wheel.js";
8181
export {default as likertSurvey} from "./likert-survey.js";
8282
export {default as logDegenerate} from "./log-degenerate.js";
83+
export {default as markovChain} from "./markov-chain.js";
8384
export {default as metroInequality} from "./metro-inequality.js";
8485
export {default as metroInequalityChange} from "./metro-inequality-change.js";
8586
export {default as metroUnemployment} from "./metro-unemployment.js";

test/plots/markov-chain.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import * as Plot from "@observablehq/plot";
2+
import * as d3 from "d3";
3+
4+
export default async function() {
5+
const matrix = [[0.3, 0.2, 0.5], [0.1, 0.7, 0.2], [0.1, 0.1, 0.8]];
6+
const centers = matrix.map((m, i) => d3.pointRadial((2 - i) * 2 * Math.PI / matrix.length, 100));
7+
const factors = matrix.flatMap((m, i) => m.map((value, j) => ({i, j, value})));
8+
return Plot.plot({
9+
width: 400,
10+
height: 380,
11+
inset: 60,
12+
axis: null,
13+
marks: [
14+
Plot.dot(centers, {r: 40}),
15+
Plot.arrow(factors, {
16+
x1: ({i}) => centers[i][0],
17+
y1: ({i}) => centers[i][1],
18+
x2: ({j}) => centers[j][0],
19+
y2: ({j}) => centers[j][1],
20+
strokeOpacity: "value",
21+
bend: true,
22+
inset: 55
23+
}),
24+
Plot.text(centers, {text: ["A", "B", "C"], dy: 55}),
25+
Plot.text(factors, {
26+
x: ({i, j}) => (centers[i][0] + centers[j][0]) / 2 + (centers[i][1] - centers[j][1]) * 0.16,
27+
y: ({i, j}) => (centers[i][1] + centers[j][1]) / 2 - (centers[i][0] - centers[j][0]) * 0.16,
28+
text: "value"
29+
})
30+
]
31+
});
32+
}

0 commit comments

Comments
 (0)