-
Notifications
You must be signed in to change notification settings - Fork 953
/
Copy pathindex.ts
106 lines (99 loc) · 3.52 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import { booleanIntersects as intersect } from "@turf/boolean-intersects";
import {
BBox,
Feature,
FeatureCollection,
MultiPolygon,
Polygon,
GeoJsonProperties,
} from "geojson";
import {
convertLength,
featureCollection,
polygon,
Units,
} from "@turf/helpers";
/**
* Creates a grid of rectangular polygons with width and height consistent in degrees
*
* @function
* @param {BBox} bbox extent of grid in [minX, minY, maxX, maxY] order. If the grid does not fill the bbox perfectly, it is centered.
* @param {number} cellWidth width of each cell, in units
* @param {number} cellHeight height of each cell, in units
* @param {Object} [options={}] Optional parameters
* @param {Units} [options.units='kilometers'] the units of the cell width and height value.
* Supports all valid Turf {@link https://github.com/Turfjs/turf/blob/master/packages/turf-helpers/README_UNITS.md Units}.
* If you are looking for rectangles with equal width and height in linear units (e.g. kilometers) this is not the module for you.
* The cellWidth and cellHeight is converted from units provided to degrees internally, so the width and height of resulting polygons will be consistent only in degrees.
* @param {Feature<Polygon|MultiPolygon>} [options.mask] if passed a Polygon or MultiPolygon,
* the grid Points will be created only inside it
* @param {Object} [options.properties={}] passed to each point of the grid
* @returns {FeatureCollection<Polygon>} a grid of polygons
* @example
* var bbox = [-95, 30 ,-85, 40];
* var cellWidth = 50;
* var cellHeight = 20;
* var options = {units: 'miles'};
*
* var rectangleGrid = turf.rectangleGrid(bbox, cellWidth, cellHeight, options);
*
* //addToMap
* var addToMap = [rectangleGrid]
*/
function rectangleGrid<P extends GeoJsonProperties = GeoJsonProperties>(
bbox: BBox,
cellWidth: number,
cellHeight: number,
options: {
units?: Units;
properties?: P;
mask?: Feature<Polygon | MultiPolygon> | Polygon | MultiPolygon;
} = {}
): FeatureCollection<Polygon, P> {
// Containers
const results = [];
const west = bbox[0];
const south = bbox[1];
const east = bbox[2];
const north = bbox[3];
const bboxWidth = east - west;
const cellWidthDeg = convertLength(cellWidth, options.units, "degrees");
const bboxHeight = north - south;
const cellHeightDeg = convertLength(cellHeight, options.units, "degrees");
const columns = Math.floor(Math.abs(bboxWidth) / cellWidthDeg);
const rows = Math.floor(Math.abs(bboxHeight) / cellHeightDeg);
// if the grid does not fill the bbox perfectly, center it.
const deltaX = (bboxWidth - columns * cellWidthDeg) / 2;
const deltaY = (bboxHeight - rows * cellHeightDeg) / 2;
// iterate over columns & rows
let currentX = west + deltaX;
for (let column = 0; column < columns; column++) {
let currentY = south + deltaY;
for (let row = 0; row < rows; row++) {
const cellPoly = polygon(
[
[
[currentX, currentY],
[currentX, currentY + cellHeightDeg],
[currentX + cellWidthDeg, currentY + cellHeightDeg],
[currentX + cellWidthDeg, currentY],
[currentX, currentY],
],
],
options.properties
);
if (options.mask) {
if (intersect(options.mask, cellPoly)) {
results.push(cellPoly);
}
} else {
results.push(cellPoly);
}
currentY += cellHeightDeg;
}
currentX += cellWidthDeg;
}
return featureCollection(results);
}
export { rectangleGrid };
export default rectangleGrid;