index.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import { getCoord, getCoords } from "@turf/invariant";
  2. /**
  3. * Returns true if a point is on a line. Accepts a optional parameter to ignore the
  4. * start and end vertices of the linestring.
  5. *
  6. * @name booleanPointOnLine
  7. * @param {Coord} pt GeoJSON Point
  8. * @param {Feature<LineString>} line GeoJSON LineString
  9. * @param {Object} [options={}] Optional parameters
  10. * @param {boolean} [options.ignoreEndVertices=false] whether to ignore the start and end vertices.
  11. * @param {number} [options.epsilon] Fractional number to compare with the cross product result. Useful for dealing with floating points such as lng/lat points
  12. * @returns {boolean} true/false
  13. * @example
  14. * var pt = turf.point([0, 0]);
  15. * var line = turf.lineString([[-1, -1],[1, 1],[1.5, 2.2]]);
  16. * var isPointOnLine = turf.booleanPointOnLine(pt, line);
  17. * //=true
  18. */
  19. function booleanPointOnLine(pt, line, options) {
  20. if (options === void 0) { options = {}; }
  21. // Normalize inputs
  22. var ptCoords = getCoord(pt);
  23. var lineCoords = getCoords(line);
  24. // Main
  25. for (var i = 0; i < lineCoords.length - 1; i++) {
  26. var ignoreBoundary = false;
  27. if (options.ignoreEndVertices) {
  28. if (i === 0) {
  29. ignoreBoundary = "start";
  30. }
  31. if (i === lineCoords.length - 2) {
  32. ignoreBoundary = "end";
  33. }
  34. if (i === 0 && i + 1 === lineCoords.length - 1) {
  35. ignoreBoundary = "both";
  36. }
  37. }
  38. if (isPointOnLineSegment(lineCoords[i], lineCoords[i + 1], ptCoords, ignoreBoundary, typeof options.epsilon === "undefined" ? null : options.epsilon)) {
  39. return true;
  40. }
  41. }
  42. return false;
  43. }
  44. // See http://stackoverflow.com/a/4833823/1979085
  45. // See https://stackoverflow.com/a/328122/1048847
  46. /**
  47. * @private
  48. * @param {Position} lineSegmentStart coord pair of start of line
  49. * @param {Position} lineSegmentEnd coord pair of end of line
  50. * @param {Position} pt coord pair of point to check
  51. * @param {boolean|string} excludeBoundary whether the point is allowed to fall on the line ends.
  52. * @param {number} epsilon Fractional number to compare with the cross product result. Useful for dealing with floating points such as lng/lat points
  53. * If true which end to ignore.
  54. * @returns {boolean} true/false
  55. */
  56. function isPointOnLineSegment(lineSegmentStart, lineSegmentEnd, pt, excludeBoundary, epsilon) {
  57. var x = pt[0];
  58. var y = pt[1];
  59. var x1 = lineSegmentStart[0];
  60. var y1 = lineSegmentStart[1];
  61. var x2 = lineSegmentEnd[0];
  62. var y2 = lineSegmentEnd[1];
  63. var dxc = pt[0] - x1;
  64. var dyc = pt[1] - y1;
  65. var dxl = x2 - x1;
  66. var dyl = y2 - y1;
  67. var cross = dxc * dyl - dyc * dxl;
  68. if (epsilon !== null) {
  69. if (Math.abs(cross) > epsilon) {
  70. return false;
  71. }
  72. }
  73. else if (cross !== 0) {
  74. return false;
  75. }
  76. if (!excludeBoundary) {
  77. if (Math.abs(dxl) >= Math.abs(dyl)) {
  78. return dxl > 0 ? x1 <= x && x <= x2 : x2 <= x && x <= x1;
  79. }
  80. return dyl > 0 ? y1 <= y && y <= y2 : y2 <= y && y <= y1;
  81. }
  82. else if (excludeBoundary === "start") {
  83. if (Math.abs(dxl) >= Math.abs(dyl)) {
  84. return dxl > 0 ? x1 < x && x <= x2 : x2 <= x && x < x1;
  85. }
  86. return dyl > 0 ? y1 < y && y <= y2 : y2 <= y && y < y1;
  87. }
  88. else if (excludeBoundary === "end") {
  89. if (Math.abs(dxl) >= Math.abs(dyl)) {
  90. return dxl > 0 ? x1 <= x && x < x2 : x2 < x && x <= x1;
  91. }
  92. return dyl > 0 ? y1 <= y && y < y2 : y2 < y && y <= y1;
  93. }
  94. else if (excludeBoundary === "both") {
  95. if (Math.abs(dxl) >= Math.abs(dyl)) {
  96. return dxl > 0 ? x1 < x && x < x2 : x2 < x && x < x1;
  97. }
  98. return dyl > 0 ? y1 < y && y < y2 : y2 < y && y < y1;
  99. }
  100. return false;
  101. }
  102. export default booleanPointOnLine;