index.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. // index.ts
  2. import { getCoords, getType } from "@turf/invariant";
  3. import { point, featureCollection } from "@turf/helpers";
  4. import { bbox as calcBbox } from "@turf/bbox";
  5. import { explode } from "@turf/explode";
  6. import { nearestPoint } from "@turf/nearest-point";
  7. function polygonTangents(pt, polygon) {
  8. const pointCoords = getCoords(pt);
  9. const polyCoords = getCoords(polygon);
  10. let rtan = [];
  11. let ltan = [];
  12. let eprev;
  13. const bbox = calcBbox(polygon);
  14. let nearestPtIndex = 0;
  15. let nearest = null;
  16. if (pointCoords[0] > bbox[0] && pointCoords[0] < bbox[2] && pointCoords[1] > bbox[1] && pointCoords[1] < bbox[3]) {
  17. nearest = nearestPoint(pt, explode(polygon));
  18. nearestPtIndex = nearest.properties.featureIndex;
  19. }
  20. const type = getType(polygon);
  21. switch (type) {
  22. case "Polygon":
  23. rtan = polyCoords[0][nearestPtIndex];
  24. ltan = polyCoords[0][0];
  25. if (nearest !== null) {
  26. if (nearest.geometry.coordinates[1] < pointCoords[1])
  27. ltan = polyCoords[0][nearestPtIndex];
  28. }
  29. eprev = isLeft(
  30. polyCoords[0][0],
  31. polyCoords[0][polyCoords[0].length - 1],
  32. pointCoords
  33. );
  34. [rtan, ltan] = processPolygon(
  35. polyCoords[0],
  36. pointCoords,
  37. eprev,
  38. rtan,
  39. ltan
  40. );
  41. break;
  42. case "MultiPolygon":
  43. var closestFeature = 0;
  44. var closestVertex = 0;
  45. var verticesCounted = 0;
  46. for (var i = 0; i < polyCoords[0].length; i++) {
  47. closestFeature = i;
  48. var verticeFound = false;
  49. for (var i2 = 0; i2 < polyCoords[0][i].length; i2++) {
  50. closestVertex = i2;
  51. if (verticesCounted === nearestPtIndex) {
  52. verticeFound = true;
  53. break;
  54. }
  55. verticesCounted++;
  56. }
  57. if (verticeFound) break;
  58. }
  59. rtan = polyCoords[0][closestFeature][closestVertex];
  60. ltan = polyCoords[0][closestFeature][closestVertex];
  61. eprev = isLeft(
  62. polyCoords[0][0][0],
  63. polyCoords[0][0][polyCoords[0][0].length - 1],
  64. pointCoords
  65. );
  66. polyCoords.forEach(function(ring) {
  67. [rtan, ltan] = processPolygon(ring[0], pointCoords, eprev, rtan, ltan);
  68. });
  69. break;
  70. }
  71. return featureCollection([point(rtan), point(ltan)]);
  72. }
  73. function processPolygon(polygonCoords, ptCoords, eprev, rtan, ltan) {
  74. for (let i = 0; i < polygonCoords.length; i++) {
  75. const currentCoords = polygonCoords[i];
  76. let nextCoordPair = polygonCoords[i + 1];
  77. if (i === polygonCoords.length - 1) {
  78. nextCoordPair = polygonCoords[0];
  79. }
  80. const enext = isLeft(currentCoords, nextCoordPair, ptCoords);
  81. if (eprev <= 0 && enext > 0) {
  82. if (!isBelow(ptCoords, currentCoords, rtan)) {
  83. rtan = currentCoords;
  84. }
  85. } else if (eprev > 0 && enext <= 0) {
  86. if (!isAbove(ptCoords, currentCoords, ltan)) {
  87. ltan = currentCoords;
  88. }
  89. }
  90. eprev = enext;
  91. }
  92. return [rtan, ltan];
  93. }
  94. function isAbove(point1, point2, point3) {
  95. return isLeft(point1, point2, point3) > 0;
  96. }
  97. function isBelow(point1, point2, point3) {
  98. return isLeft(point1, point2, point3) < 0;
  99. }
  100. function isLeft(point1, point2, point3) {
  101. return (point2[0] - point1[0]) * (point3[1] - point1[1]) - (point3[0] - point1[0]) * (point2[1] - point1[1]);
  102. }
  103. var turf_polygon_tangents_default = polygonTangents;
  104. export {
  105. turf_polygon_tangents_default as default,
  106. polygonTangents
  107. };
  108. //# sourceMappingURL=index.js.map