line.ts 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. import { pointCenter, pointFrom, pointRotateRads } from "./point";
  2. import type { GlobalPoint, Line, LocalPoint, Radians } from "./types";
  3. /**
  4. * Create a line from two points.
  5. *
  6. * @param points The two points lying on the line
  7. * @returns The line on which the points lie
  8. */
  9. export function line<P extends GlobalPoint | LocalPoint>(a: P, b: P): Line<P> {
  10. return [a, b] as Line<P>;
  11. }
  12. /**
  13. * Convenient point creation from an array of two points.
  14. *
  15. * @param param0 The array with the two points to convert to a line
  16. * @returns The created line
  17. */
  18. export function lineFromPointPair<P extends GlobalPoint | LocalPoint>([a, b]: [
  19. P,
  20. P,
  21. ]): Line<P> {
  22. return line(a, b);
  23. }
  24. /**
  25. * TODO
  26. *
  27. * @param pointArray
  28. * @returns
  29. */
  30. export function lineFromPointArray<P extends GlobalPoint | LocalPoint>(
  31. pointArray: P[],
  32. ): Line<P> | undefined {
  33. return pointArray.length === 2
  34. ? line<P>(pointArray[0], pointArray[1])
  35. : undefined;
  36. }
  37. /**
  38. * Return the coordinates resulting from rotating the given line about an
  39. * origin by an angle in degrees note that when the origin is not given,
  40. * the midpoint of the given line is used as the origin
  41. *
  42. * @param l
  43. * @param angle
  44. * @param origin
  45. * @returns
  46. */
  47. export const lineRotate = <Point extends LocalPoint | GlobalPoint>(
  48. l: Line<Point>,
  49. angle: Radians,
  50. origin?: Point,
  51. ): Line<Point> => {
  52. return line(
  53. pointRotateRads(l[0], origin || pointCenter(l[0], l[1]), angle),
  54. pointRotateRads(l[1], origin || pointCenter(l[0], l[1]), angle),
  55. );
  56. };
  57. /**
  58. * Determines the intersection point (unless the lines are parallel) of two
  59. * lines
  60. *
  61. * @param a
  62. * @param b
  63. * @returns
  64. */
  65. export const linesIntersectAt = <Point extends GlobalPoint | LocalPoint>(
  66. a: Line<Point>,
  67. b: Line<Point>,
  68. ): Point | null => {
  69. const A1 = a[1][1] - a[0][1];
  70. const B1 = a[0][0] - a[1][0];
  71. const A2 = b[1][1] - b[0][1];
  72. const B2 = b[0][0] - b[1][0];
  73. const D = A1 * B2 - A2 * B1;
  74. if (D !== 0) {
  75. const C1 = A1 * a[0][0] + B1 * a[0][1];
  76. const C2 = A2 * b[0][0] + B2 * b[0][1];
  77. return pointFrom<Point>((C1 * B2 - C2 * B1) / D, (A1 * C2 - A2 * C1) / D);
  78. }
  79. return null;
  80. };