Angle.js 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. import Orientation from './Orientation'
  2. export default class Angle {
  3. static toDegrees(radians) {
  4. return radians * 180 / Math.PI
  5. }
  6. static normalize(angle) {
  7. while (angle > Math.PI) angle -= Angle.PI_TIMES_2
  8. while (angle <= -Math.PI) angle += Angle.PI_TIMES_2
  9. return angle
  10. }
  11. static angle() {
  12. if (arguments.length === 1) {
  13. const p = arguments[0]
  14. return Math.atan2(p.y, p.x)
  15. } else if (arguments.length === 2) {
  16. const p0 = arguments[0], p1 = arguments[1]
  17. const dx = p1.x - p0.x
  18. const dy = p1.y - p0.y
  19. return Math.atan2(dy, dx)
  20. }
  21. }
  22. static isAcute(p0, p1, p2) {
  23. const dx0 = p0.x - p1.x
  24. const dy0 = p0.y - p1.y
  25. const dx1 = p2.x - p1.x
  26. const dy1 = p2.y - p1.y
  27. const dotprod = dx0 * dx1 + dy0 * dy1
  28. return dotprod > 0
  29. }
  30. static isObtuse(p0, p1, p2) {
  31. const dx0 = p0.x - p1.x
  32. const dy0 = p0.y - p1.y
  33. const dx1 = p2.x - p1.x
  34. const dy1 = p2.y - p1.y
  35. const dotprod = dx0 * dx1 + dy0 * dy1
  36. return dotprod < 0
  37. }
  38. static interiorAngle(p0, p1, p2) {
  39. const anglePrev = Angle.angle(p1, p0)
  40. const angleNext = Angle.angle(p1, p2)
  41. return Math.abs(angleNext - anglePrev)
  42. }
  43. static normalizePositive(angle) {
  44. if (angle < 0.0) {
  45. while (angle < 0.0) angle += Angle.PI_TIMES_2
  46. if (angle >= Angle.PI_TIMES_2) angle = 0.0
  47. } else {
  48. while (angle >= Angle.PI_TIMES_2) angle -= Angle.PI_TIMES_2
  49. if (angle < 0.0) angle = 0.0
  50. }
  51. return angle
  52. }
  53. static angleBetween(tip1, tail, tip2) {
  54. const a1 = Angle.angle(tail, tip1)
  55. const a2 = Angle.angle(tail, tip2)
  56. return Angle.diff(a1, a2)
  57. }
  58. static diff(ang1, ang2) {
  59. let delAngle = null
  60. if (ang1 < ang2)
  61. delAngle = ang2 - ang1
  62. else
  63. delAngle = ang1 - ang2
  64. if (delAngle > Math.PI)
  65. delAngle = 2 * Math.PI - delAngle
  66. return delAngle
  67. }
  68. static toRadians(angleDegrees) {
  69. return angleDegrees * Math.PI / 180.0
  70. }
  71. static getTurn(ang1, ang2) {
  72. const crossproduct = Math.sin(ang2 - ang1)
  73. if (crossproduct > 0)
  74. return Angle.COUNTERCLOCKWISE
  75. if (crossproduct < 0)
  76. return Angle.CLOCKWISE
  77. return Angle.NONE
  78. }
  79. static angleBetweenOriented(tip1, tail, tip2) {
  80. const a1 = Angle.angle(tail, tip1)
  81. const a2 = Angle.angle(tail, tip2)
  82. const angDel = a2 - a1
  83. if (angDel <= -Math.PI) return angDel + Angle.PI_TIMES_2
  84. if (angDel > Math.PI) return angDel - Angle.PI_TIMES_2
  85. return angDel
  86. }
  87. }
  88. Angle.PI_TIMES_2 = 2.0 * Math.PI
  89. Angle.PI_OVER_2 = Math.PI / 2.0
  90. Angle.PI_OVER_4 = Math.PI / 4.0
  91. Angle.COUNTERCLOCKWISE = Orientation.COUNTERCLOCKWISE
  92. Angle.CLOCKWISE = Orientation.CLOCKWISE
  93. Angle.NONE = Orientation.COLLINEAR