-
Notifications
You must be signed in to change notification settings - Fork 354
/
Copy pathangles.ts
70 lines (61 loc) · 2.54 KB
/
angles.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// This file contains helper functions for working with angles.
import {clockwise} from "./geometry";
import type {Coord} from "@khanacademy/perseus-core";
export function convertDegreesToRadians(degrees: number): number {
return (degrees / 180) * Math.PI;
}
// Returns a value between -180 and 180, inclusive. The angle is measured
// between the positive x-axis and the given vector.
export function calculateAngleInDegrees([x, y]: Coord): number {
return (Math.atan2(y, x) * 180) / Math.PI;
}
// Converts polar coordinates to cartesian. The th(eta) parameter is in degrees.
export function polar(r: number | Coord, th: number): Coord {
if (typeof r === "number") {
r = [r, r];
}
th = (th * Math.PI) / 180;
return [r[0] * Math.cos(th), r[1] * Math.sin(th)];
}
// This function calculates the angle between two points and an optional vertex.
// If the vertex is not provided, the angle is measured between the two points.
// This does not account for reflex angles or clockwise position.
export const getAngleFromVertex = (point: Coord, vertex: Coord): number => {
const x = point[0] - vertex[0];
const y = point[1] - vertex[1];
if (!x && !y) {
return 0;
}
return (180 + (Math.atan2(-y, -x) * 180) / Math.PI + 360) % 360;
};
// This function calculates the clockwise angle between three points,
// and is used to generate the labels and equation strings of the
// current angle for the interactive graph.
export const getClockwiseAngle = (
coords: [Coord, Coord, Coord],
allowReflexAngles: boolean = false,
): number => {
const coordsCopy = [...coords];
// The coords are saved as [point1, vertex, point2] in the interactive graph
const areClockwise = clockwise([
coordsCopy[0],
coordsCopy[2],
coordsCopy[1],
]);
// We may need to reverse the coordinates if we allow
// reflex angles and the points are not in clockwise order.
const shouldReverseCoords = !areClockwise || allowReflexAngles;
// Reverse the coordinates accordingly to ensure the angle is calculated correctly
const clockwiseCoords = shouldReverseCoords
? coordsCopy.reverse()
: coordsCopy;
// Calculate the angles between the two points and get the difference
// between the two angles to get the clockwise angle.
const startAngle = getAngleFromVertex(
clockwiseCoords[0],
clockwiseCoords[1],
);
const endAngle = getAngleFromVertex(clockwiseCoords[2], clockwiseCoords[1]);
const angle = (startAngle + 360 - endAngle) % 360;
return angle;
};