index.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. import distance from "@turf/distance";
  2. import intersect from "@turf/intersect";
  3. import { polygon, featureCollection, } from "@turf/helpers";
  4. /**
  5. * Takes a bounding box and a cell depth and returns a set of triangular {@link Polygon|polygons} in a grid.
  6. *
  7. * @name triangleGrid
  8. * @param {Array<number>} bbox extent in [minX, minY, maxX, maxY] order
  9. * @param {number} cellSide dimension of each cell
  10. * @param {Object} [options={}] Optional parameters
  11. * @param {string} [options.units='kilometers'] used in calculating cellSide, can be degrees, radians, miles, or kilometers
  12. * @param {Feature<Polygon>} [options.mask] if passed a Polygon or MultiPolygon, the grid Points will be created only inside it
  13. * @param {Object} [options.properties={}] passed to each point of the grid
  14. * @returns {FeatureCollection<Polygon>} grid of polygons
  15. * @example
  16. * var bbox = [-95, 30 ,-85, 40];
  17. * var cellSide = 50;
  18. * var options = {units: 'miles'};
  19. *
  20. * var triangleGrid = turf.triangleGrid(bbox, cellSide, options);
  21. *
  22. * //addToMap
  23. * var addToMap = [triangleGrid];
  24. */
  25. function triangleGrid(bbox, cellSide, options) {
  26. if (options === void 0) { options = {}; }
  27. // Containers
  28. var results = [];
  29. // Input Validation is being handled by Typescript
  30. // if (cellSide === null || cellSide === undefined) throw new Error('cellSide is required');
  31. // if (!isNumber(cellSide)) throw new Error('cellSide is invalid');
  32. // if (!bbox) throw new Error('bbox is required');
  33. // if (!Array.isArray(bbox)) throw new Error('bbox must be array');
  34. // if (bbox.length !== 4) throw new Error('bbox must contain 4 numbers');
  35. // if (mask && ['Polygon', 'MultiPolygon'].indexOf(getType(mask)) === -1) throw new Error('options.mask must be a (Multi)Polygon');
  36. // Main
  37. var xFraction = cellSide / distance([bbox[0], bbox[1]], [bbox[2], bbox[1]], options);
  38. var cellWidth = xFraction * (bbox[2] - bbox[0]);
  39. var yFraction = cellSide / distance([bbox[0], bbox[1]], [bbox[0], bbox[3]], options);
  40. var cellHeight = yFraction * (bbox[3] - bbox[1]);
  41. var xi = 0;
  42. var currentX = bbox[0];
  43. while (currentX <= bbox[2]) {
  44. var yi = 0;
  45. var currentY = bbox[1];
  46. while (currentY <= bbox[3]) {
  47. var cellTriangle1 = null;
  48. var cellTriangle2 = null;
  49. if (xi % 2 === 0 && yi % 2 === 0) {
  50. cellTriangle1 = polygon([
  51. [
  52. [currentX, currentY],
  53. [currentX, currentY + cellHeight],
  54. [currentX + cellWidth, currentY],
  55. [currentX, currentY],
  56. ],
  57. ], options.properties);
  58. cellTriangle2 = polygon([
  59. [
  60. [currentX, currentY + cellHeight],
  61. [currentX + cellWidth, currentY + cellHeight],
  62. [currentX + cellWidth, currentY],
  63. [currentX, currentY + cellHeight],
  64. ],
  65. ], options.properties);
  66. }
  67. else if (xi % 2 === 0 && yi % 2 === 1) {
  68. cellTriangle1 = polygon([
  69. [
  70. [currentX, currentY],
  71. [currentX + cellWidth, currentY + cellHeight],
  72. [currentX + cellWidth, currentY],
  73. [currentX, currentY],
  74. ],
  75. ], options.properties);
  76. cellTriangle2 = polygon([
  77. [
  78. [currentX, currentY],
  79. [currentX, currentY + cellHeight],
  80. [currentX + cellWidth, currentY + cellHeight],
  81. [currentX, currentY],
  82. ],
  83. ], options.properties);
  84. }
  85. else if (yi % 2 === 0 && xi % 2 === 1) {
  86. cellTriangle1 = polygon([
  87. [
  88. [currentX, currentY],
  89. [currentX, currentY + cellHeight],
  90. [currentX + cellWidth, currentY + cellHeight],
  91. [currentX, currentY],
  92. ],
  93. ], options.properties);
  94. cellTriangle2 = polygon([
  95. [
  96. [currentX, currentY],
  97. [currentX + cellWidth, currentY + cellHeight],
  98. [currentX + cellWidth, currentY],
  99. [currentX, currentY],
  100. ],
  101. ], options.properties);
  102. }
  103. else if (yi % 2 === 1 && xi % 2 === 1) {
  104. cellTriangle1 = polygon([
  105. [
  106. [currentX, currentY],
  107. [currentX, currentY + cellHeight],
  108. [currentX + cellWidth, currentY],
  109. [currentX, currentY],
  110. ],
  111. ], options.properties);
  112. cellTriangle2 = polygon([
  113. [
  114. [currentX, currentY + cellHeight],
  115. [currentX + cellWidth, currentY + cellHeight],
  116. [currentX + cellWidth, currentY],
  117. [currentX, currentY + cellHeight],
  118. ],
  119. ], options.properties);
  120. }
  121. if (options.mask) {
  122. if (intersect(options.mask, cellTriangle1))
  123. results.push(cellTriangle1);
  124. if (intersect(options.mask, cellTriangle2))
  125. results.push(cellTriangle2);
  126. }
  127. else {
  128. results.push(cellTriangle1);
  129. results.push(cellTriangle2);
  130. }
  131. currentY += cellHeight;
  132. yi++;
  133. }
  134. xi++;
  135. currentX += cellWidth;
  136. }
  137. return featureCollection(results);
  138. }
  139. export default triangleGrid;