commit 810728014395012b890a5be8c2bc45a814b8020c
parent eabdc55267e4cc3cfc887dd39eff4182ee5e97f7
Author: hrryt <harry@mayesfield.uk>
Date: Thu, 13 Aug 2026 17:29:51 +0100
Add angle graphing component
Diffstat:
2 files changed, 55 insertions(+), 0 deletions(-)
diff --git a/src/components/graphing/Angle.jsx b/src/components/graphing/Angle.jsx
@@ -0,0 +1,53 @@
+import Label from './Label.jsx';
+import { getColourClass } from '../../scripts/utils.js';
+
+function sum(arr) {
+ return arr.reduce((a, b) => a + b);
+}
+
+function sumVectors(arr) {
+ return arr.reduce((a, b) => a.map((ai, i) => ai + b[i]));
+}
+
+function scale(vector, factor) {
+ return vector.map(a => a * factor);
+}
+
+function normalise(vector, scaleFactor = 1) {
+ const length = Math.sqrt(sum(vector.map(a => a*a)));
+ return scale(vector, scaleFactor / length);
+}
+
+function getVector(start, end) {
+ return [end[0] - start[0], end[1] - start[1]];
+}
+
+function interpolate(start, end, along) {
+ return sumVectors([start, scale(getVector(start, end), along)]);
+}
+
+function interpolateDistance(start, end, distance) {
+ return sumVectors([start, normalise(getVector(start, end), distance)]);
+}
+
+function getArc(points, radius) {
+ const start = interpolateDistance(points[1], points[0], radius);
+ const end = interpolateDistance(points[1], points[2], radius);
+ return [start, end];
+}
+
+function getLabelPosition(points, start, end) {
+ const midpoint = interpolate(start, end, 0.5);
+ return interpolate(points[1], midpoint, 1.5);
+}
+
+export default function Angle({ points, radius = 0.5, label = null, colour = "auto" }) {
+ const [start, end] = getArc(points, radius);
+ if (label ) { const [labelX, labelY] = getLabelPosition(points, start, end); }
+ return (
+ <g>
+ <path d={`M ${start} A ${radius} ${radius} 0 0 1 ${end}`} class={getColourClass(colour)} />
+ {label && <Label x={labelX} y={labelY} colour={colour}>{label}</Label>}
+ </g>
+ );
+}
diff --git a/src/pages/Home.jsx b/src/pages/Home.jsx
@@ -3,6 +3,7 @@ import Graph from '../components/graphing/Graph.jsx';
import Quadratic from '../components/graphing/Quadratic.jsx';
import Cubic from '../components/graphing/Cubic.jsx';
import Polygon from '../components/graphing/Polygon.jsx';
+import Angle from '../components/graphing/Angle.jsx';
export default function Home() {
const viewBox = [-5, -4, 8, 8];
@@ -14,6 +15,7 @@ export default function Home() {
<Graph viewBox={viewBox}>
<Quadratic a={2} b={1} c={-3} colour="1" viewBox={viewBox} />
<Polygon points={[[1,2], [-1,1], [-4,3]]} label="P" colour="2" />
+ <Angle points={[[-4,3], [1,2], [-1,1]]} colour="2" />
<Cubic a={1} b={-3} c={3} d={-1} colour="3" viewBox={viewBox}/>
</Graph>
</div>