@turf/hex-grid 7.0.0-alpha.1 → 7.0.0-alpha.111

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -57,26 +57,21 @@ Returns **[FeatureCollection][11]<[Polygon][9]>** a hexagonal grid
57
57
 
58
58
  [11]: https://tools.ietf.org/html/rfc7946#section-3.3
59
59
 
60
- <!-- This file is automatically generated. Please don't edit it directly:
61
- if you find an error, edit the source file (likely index.js), and re-run
62
- ./scripts/generate-readmes in the turf project. -->
60
+ <!-- This file is automatically generated. Please don't edit it directly. If you find an error, edit the source file of the module in question (likely index.js or index.ts), and re-run "yarn docs" from the root of the turf project. -->
63
61
 
64
62
  ---
65
63
 
66
- This module is part of the [Turfjs project](http://turfjs.org/), an open source
67
- module collection dedicated to geographic algorithms. It is maintained in the
68
- [Turfjs/turf](https://github.com/Turfjs/turf) repository, where you can create
69
- PRs and issues.
64
+ This module is part of the [Turfjs project](https://turfjs.org/), an open source module collection dedicated to geographic algorithms. It is maintained in the [Turfjs/turf](https://github.com/Turfjs/turf) repository, where you can create PRs and issues.
70
65
 
71
66
  ### Installation
72
67
 
73
- Install this module individually:
68
+ Install this single module individually:
74
69
 
75
70
  ```sh
76
71
  $ npm install @turf/hex-grid
77
72
  ```
78
73
 
79
- Or install the Turf module that includes it as a function:
74
+ Or install the all-encompassing @turf/turf module that includes all modules as functions:
80
75
 
81
76
  ```sh
82
77
  $ npm install @turf/turf
@@ -0,0 +1,122 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});var __defProp = Object.defineProperty;
2
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
+
4
+ // index.ts
5
+ var _distance = require('@turf/distance');
6
+ var _intersect = require('@turf/intersect');
7
+ var _helpers = require('@turf/helpers');
8
+ function hexGrid(bbox, cellSide, options = {}) {
9
+ const clonedProperties = JSON.stringify(options.properties || {});
10
+ const [west, south, east, north] = bbox;
11
+ const centerY = (south + north) / 2;
12
+ const centerX = (west + east) / 2;
13
+ const xFraction = cellSide * 2 / _distance.distance.call(void 0, [west, centerY], [east, centerY], options);
14
+ const cellWidth = xFraction * (east - west);
15
+ const yFraction = cellSide * 2 / _distance.distance.call(void 0, [centerX, south], [centerX, north], options);
16
+ const cellHeight = yFraction * (north - south);
17
+ const radius = cellWidth / 2;
18
+ const hex_width = radius * 2;
19
+ const hex_height = Math.sqrt(3) / 2 * cellHeight;
20
+ const box_width = east - west;
21
+ const box_height = north - south;
22
+ const x_interval = 3 / 4 * hex_width;
23
+ const y_interval = hex_height;
24
+ const x_span = (box_width - hex_width) / (hex_width - radius / 2);
25
+ const x_count = Math.floor(x_span);
26
+ const x_adjust = (x_count * x_interval - radius / 2 - box_width) / 2 - radius / 2 + x_interval / 2;
27
+ const y_count = Math.floor((box_height - hex_height) / hex_height);
28
+ let y_adjust = (box_height - y_count * hex_height) / 2;
29
+ const hasOffsetY = y_count * hex_height - box_height > hex_height / 2;
30
+ if (hasOffsetY) {
31
+ y_adjust -= hex_height / 4;
32
+ }
33
+ const cosines = [];
34
+ const sines = [];
35
+ for (let i = 0; i < 6; i++) {
36
+ const angle = 2 * Math.PI / 6 * i;
37
+ cosines.push(Math.cos(angle));
38
+ sines.push(Math.sin(angle));
39
+ }
40
+ const results = [];
41
+ for (let x = 0; x <= x_count; x++) {
42
+ for (let y = 0; y <= y_count; y++) {
43
+ const isOdd = x % 2 === 1;
44
+ if (y === 0 && isOdd)
45
+ continue;
46
+ if (y === 0 && hasOffsetY)
47
+ continue;
48
+ const center_x = x * x_interval + west - x_adjust;
49
+ let center_y = y * y_interval + south + y_adjust;
50
+ if (isOdd) {
51
+ center_y -= hex_height / 2;
52
+ }
53
+ if (options.triangles === true) {
54
+ hexTriangles(
55
+ [center_x, center_y],
56
+ cellWidth / 2,
57
+ cellHeight / 2,
58
+ JSON.parse(clonedProperties),
59
+ cosines,
60
+ sines
61
+ ).forEach(function(triangle) {
62
+ if (options.mask) {
63
+ if (_intersect.intersect.call(void 0, _helpers.featureCollection.call(void 0, [options.mask, triangle])))
64
+ results.push(triangle);
65
+ } else {
66
+ results.push(triangle);
67
+ }
68
+ });
69
+ } else {
70
+ const hex = hexagon(
71
+ [center_x, center_y],
72
+ cellWidth / 2,
73
+ cellHeight / 2,
74
+ JSON.parse(clonedProperties),
75
+ cosines,
76
+ sines
77
+ );
78
+ if (options.mask) {
79
+ if (_intersect.intersect.call(void 0, _helpers.featureCollection.call(void 0, [options.mask, hex])))
80
+ results.push(hex);
81
+ } else {
82
+ results.push(hex);
83
+ }
84
+ }
85
+ }
86
+ }
87
+ return _helpers.featureCollection.call(void 0, results);
88
+ }
89
+ __name(hexGrid, "hexGrid");
90
+ function hexagon(center, rx, ry, properties, cosines, sines) {
91
+ const vertices = [];
92
+ for (let i = 0; i < 6; i++) {
93
+ const x = center[0] + rx * cosines[i];
94
+ const y = center[1] + ry * sines[i];
95
+ vertices.push([x, y]);
96
+ }
97
+ vertices.push(vertices[0].slice());
98
+ return _helpers.polygon.call(void 0, [vertices], properties);
99
+ }
100
+ __name(hexagon, "hexagon");
101
+ function hexTriangles(center, rx, ry, properties, cosines, sines) {
102
+ const triangles = [];
103
+ for (let i = 0; i < 6; i++) {
104
+ const vertices = [];
105
+ vertices.push(center);
106
+ vertices.push([center[0] + rx * cosines[i], center[1] + ry * sines[i]]);
107
+ vertices.push([
108
+ center[0] + rx * cosines[(i + 1) % 6],
109
+ center[1] + ry * sines[(i + 1) % 6]
110
+ ]);
111
+ vertices.push(center);
112
+ triangles.push(_helpers.polygon.call(void 0, [vertices], properties));
113
+ }
114
+ return triangles;
115
+ }
116
+ __name(hexTriangles, "hexTriangles");
117
+ var turf_hex_grid_default = hexGrid;
118
+
119
+
120
+
121
+ exports.default = turf_hex_grid_default; exports.hexGrid = hexGrid;
122
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../index.ts"],"names":[],"mappings":"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","sourcesContent":["import { distance } from \"@turf/distance\";\nimport { intersect } from \"@turf/intersect\";\nimport {\n Feature,\n FeatureCollection,\n GeoJsonProperties,\n Polygon,\n BBox,\n} from \"geojson\";\nimport { polygon, featureCollection, Units } from \"@turf/helpers\";\n\n/**\n * Takes a bounding box and the diameter of the cell and returns a {@link FeatureCollection} of flat-topped\n * hexagons or triangles ({@link Polygon} features) aligned in an \"odd-q\" vertical grid as\n * described in [Hexagonal Grids](http://www.redblobgames.com/grids/hexagons/).\n *\n * @name hexGrid\n * @param {BBox} bbox extent in [minX, minY, maxX, maxY] order\n * @param {number} cellSide length of the side of the the hexagons or triangles, in units. It will also coincide with the\n * radius of the circumcircle of the hexagons.\n * @param {Object} [options={}] Optional parameters\n * @param {string} [options.units='kilometers'] used in calculating cell size, can be degrees, radians, miles, or kilometers\n * @param {Object} [options.properties={}] passed to each hexagon or triangle of the grid\n * @param {Feature<Polygon>} [options.mask] if passed a Polygon or MultiPolygon, the grid Points will be created only inside it\n * @param {boolean} [options.triangles=false] whether to return as triangles instead of hexagons\n * @returns {FeatureCollection<Polygon>} a hexagonal grid\n * @example\n * var bbox = [-96,31,-84,40];\n * var cellSide = 50;\n * var options = {units: 'miles'};\n *\n * var hexgrid = turf.hexGrid(bbox, cellSide, options);\n *\n * //addToMap\n * var addToMap = [hexgrid];\n */\nfunction hexGrid<P extends GeoJsonProperties = GeoJsonProperties>(\n bbox: BBox,\n cellSide: number,\n options: {\n units?: Units;\n triangles?: boolean;\n properties?: P;\n mask?: Feature<Polygon>;\n } = {}\n): FeatureCollection<Polygon, P> {\n // Issue => https://github.com/Turfjs/turf/issues/1284\n const clonedProperties = JSON.stringify(options.properties || {});\n\n const [west, south, east, north] = bbox;\n const centerY = (south + north) / 2;\n const centerX = (west + east) / 2;\n\n // https://github.com/Turfjs/turf/issues/758\n const xFraction =\n (cellSide * 2) / distance([west, centerY], [east, centerY], options);\n const cellWidth = xFraction * (east - west);\n const yFraction =\n (cellSide * 2) / distance([centerX, south], [centerX, north], options);\n const cellHeight = yFraction * (north - south);\n const radius = cellWidth / 2;\n\n const hex_width = radius * 2;\n const hex_height = (Math.sqrt(3) / 2) * cellHeight;\n\n const box_width = east - west;\n const box_height = north - south;\n\n const x_interval = (3 / 4) * hex_width;\n const y_interval = hex_height;\n\n // adjust box_width so all hexagons will be inside the bbox\n const x_span = (box_width - hex_width) / (hex_width - radius / 2);\n const x_count = Math.floor(x_span);\n\n const x_adjust =\n (x_count * x_interval - radius / 2 - box_width) / 2 -\n radius / 2 +\n x_interval / 2;\n\n // adjust box_height so all hexagons will be inside the bbox\n const y_count = Math.floor((box_height - hex_height) / hex_height);\n\n let y_adjust = (box_height - y_count * hex_height) / 2;\n\n const hasOffsetY = y_count * hex_height - box_height > hex_height / 2;\n if (hasOffsetY) {\n y_adjust -= hex_height / 4;\n }\n\n // Precompute cosines and sines of angles used in hexagon creation for performance gain\n const cosines = [];\n const sines = [];\n for (let i = 0; i < 6; i++) {\n const angle = ((2 * Math.PI) / 6) * i;\n cosines.push(Math.cos(angle));\n sines.push(Math.sin(angle));\n }\n\n const results = [];\n for (let x = 0; x <= x_count; x++) {\n for (let y = 0; y <= y_count; y++) {\n const isOdd = x % 2 === 1;\n if (y === 0 && isOdd) continue;\n if (y === 0 && hasOffsetY) continue;\n\n const center_x = x * x_interval + west - x_adjust;\n let center_y = y * y_interval + south + y_adjust;\n\n if (isOdd) {\n center_y -= hex_height / 2;\n }\n\n if (options.triangles === true) {\n hexTriangles(\n [center_x, center_y],\n cellWidth / 2,\n cellHeight / 2,\n JSON.parse(clonedProperties),\n cosines,\n sines\n ).forEach(function (triangle) {\n if (options.mask) {\n if (intersect(featureCollection([options.mask, triangle])))\n results.push(triangle);\n } else {\n results.push(triangle);\n }\n });\n } else {\n const hex = hexagon(\n [center_x, center_y],\n cellWidth / 2,\n cellHeight / 2,\n JSON.parse(clonedProperties),\n cosines,\n sines\n );\n if (options.mask) {\n if (intersect(featureCollection([options.mask, hex])))\n results.push(hex);\n } else {\n results.push(hex);\n }\n }\n }\n }\n\n return featureCollection(results) as FeatureCollection<Polygon, P>;\n}\n\n/**\n * Creates hexagon\n *\n * @private\n * @param {Array<number>} center of the hexagon\n * @param {number} rx half hexagon width\n * @param {number} ry half hexagon height\n * @param {Object} properties passed to each hexagon\n * @param {Array<number>} cosines precomputed\n * @param {Array<number>} sines precomputed\n * @returns {Feature<Polygon>} hexagon\n */\nfunction hexagon(\n center: number[],\n rx: number,\n ry: number,\n properties: GeoJsonProperties,\n cosines: number[],\n sines: number[]\n) {\n const vertices = [];\n for (let i = 0; i < 6; i++) {\n const x = center[0] + rx * cosines[i];\n const y = center[1] + ry * sines[i];\n vertices.push([x, y]);\n }\n //first and last vertex must be the same\n vertices.push(vertices[0].slice());\n return polygon([vertices], properties);\n}\n\n/**\n * Creates triangles composing an hexagon\n *\n * @private\n * @param {Array<number>} center of the hexagon\n * @param {number} rx half triangle width\n * @param {number} ry half triangle height\n * @param {Object} properties passed to each triangle\n * @param {Array<number>} cosines precomputed\n * @param {Array<number>} sines precomputed\n * @returns {Array<Feature<Polygon>>} triangles\n */\nfunction hexTriangles(\n center: number[],\n rx: number,\n ry: number,\n properties: GeoJsonProperties,\n cosines: number[],\n sines: number[]\n) {\n const triangles = [];\n for (let i = 0; i < 6; i++) {\n const vertices = [];\n vertices.push(center);\n vertices.push([center[0] + rx * cosines[i], center[1] + ry * sines[i]]);\n vertices.push([\n center[0] + rx * cosines[(i + 1) % 6],\n center[1] + ry * sines[(i + 1) % 6],\n ]);\n vertices.push(center);\n triangles.push(polygon([vertices], properties));\n }\n return triangles;\n}\n\nexport { hexGrid };\nexport default hexGrid;\n"]}
@@ -1,5 +1,6 @@
1
- import { Feature, FeatureCollection, GeoJsonProperties, Polygon, BBox } from "geojson";
2
- import { Units } from "@turf/helpers";
1
+ import { GeoJsonProperties, BBox, Feature, Polygon, FeatureCollection } from 'geojson';
2
+ import { Units } from '@turf/helpers';
3
+
3
4
  /**
4
5
  * Takes a bounding box and the diameter of the cell and returns a {@link FeatureCollection} of flat-topped
5
6
  * hexagons or triangles ({@link Polygon} features) aligned in an "odd-q" vertical grid as
@@ -25,10 +26,11 @@ import { Units } from "@turf/helpers";
25
26
  * //addToMap
26
27
  * var addToMap = [hexgrid];
27
28
  */
28
- declare function hexGrid<P = GeoJsonProperties>(bbox: BBox, cellSide: number, options?: {
29
+ declare function hexGrid<P extends GeoJsonProperties = GeoJsonProperties>(bbox: BBox, cellSide: number, options?: {
29
30
  units?: Units;
30
31
  triangles?: boolean;
31
32
  properties?: P;
32
33
  mask?: Feature<Polygon>;
33
34
  }): FeatureCollection<Polygon, P>;
34
- export default hexGrid;
35
+
36
+ export { hexGrid as default, hexGrid };
@@ -0,0 +1,36 @@
1
+ import { GeoJsonProperties, BBox, Feature, Polygon, FeatureCollection } from 'geojson';
2
+ import { Units } from '@turf/helpers';
3
+
4
+ /**
5
+ * Takes a bounding box and the diameter of the cell and returns a {@link FeatureCollection} of flat-topped
6
+ * hexagons or triangles ({@link Polygon} features) aligned in an "odd-q" vertical grid as
7
+ * described in [Hexagonal Grids](http://www.redblobgames.com/grids/hexagons/).
8
+ *
9
+ * @name hexGrid
10
+ * @param {BBox} bbox extent in [minX, minY, maxX, maxY] order
11
+ * @param {number} cellSide length of the side of the the hexagons or triangles, in units. It will also coincide with the
12
+ * radius of the circumcircle of the hexagons.
13
+ * @param {Object} [options={}] Optional parameters
14
+ * @param {string} [options.units='kilometers'] used in calculating cell size, can be degrees, radians, miles, or kilometers
15
+ * @param {Object} [options.properties={}] passed to each hexagon or triangle of the grid
16
+ * @param {Feature<Polygon>} [options.mask] if passed a Polygon or MultiPolygon, the grid Points will be created only inside it
17
+ * @param {boolean} [options.triangles=false] whether to return as triangles instead of hexagons
18
+ * @returns {FeatureCollection<Polygon>} a hexagonal grid
19
+ * @example
20
+ * var bbox = [-96,31,-84,40];
21
+ * var cellSide = 50;
22
+ * var options = {units: 'miles'};
23
+ *
24
+ * var hexgrid = turf.hexGrid(bbox, cellSide, options);
25
+ *
26
+ * //addToMap
27
+ * var addToMap = [hexgrid];
28
+ */
29
+ declare function hexGrid<P extends GeoJsonProperties = GeoJsonProperties>(bbox: BBox, cellSide: number, options?: {
30
+ units?: Units;
31
+ triangles?: boolean;
32
+ properties?: P;
33
+ mask?: Feature<Polygon>;
34
+ }): FeatureCollection<Polygon, P>;
35
+
36
+ export { hexGrid as default, hexGrid };
@@ -0,0 +1,122 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
+
4
+ // index.ts
5
+ import { distance } from "@turf/distance";
6
+ import { intersect } from "@turf/intersect";
7
+ import { polygon, featureCollection } from "@turf/helpers";
8
+ function hexGrid(bbox, cellSide, options = {}) {
9
+ const clonedProperties = JSON.stringify(options.properties || {});
10
+ const [west, south, east, north] = bbox;
11
+ const centerY = (south + north) / 2;
12
+ const centerX = (west + east) / 2;
13
+ const xFraction = cellSide * 2 / distance([west, centerY], [east, centerY], options);
14
+ const cellWidth = xFraction * (east - west);
15
+ const yFraction = cellSide * 2 / distance([centerX, south], [centerX, north], options);
16
+ const cellHeight = yFraction * (north - south);
17
+ const radius = cellWidth / 2;
18
+ const hex_width = radius * 2;
19
+ const hex_height = Math.sqrt(3) / 2 * cellHeight;
20
+ const box_width = east - west;
21
+ const box_height = north - south;
22
+ const x_interval = 3 / 4 * hex_width;
23
+ const y_interval = hex_height;
24
+ const x_span = (box_width - hex_width) / (hex_width - radius / 2);
25
+ const x_count = Math.floor(x_span);
26
+ const x_adjust = (x_count * x_interval - radius / 2 - box_width) / 2 - radius / 2 + x_interval / 2;
27
+ const y_count = Math.floor((box_height - hex_height) / hex_height);
28
+ let y_adjust = (box_height - y_count * hex_height) / 2;
29
+ const hasOffsetY = y_count * hex_height - box_height > hex_height / 2;
30
+ if (hasOffsetY) {
31
+ y_adjust -= hex_height / 4;
32
+ }
33
+ const cosines = [];
34
+ const sines = [];
35
+ for (let i = 0; i < 6; i++) {
36
+ const angle = 2 * Math.PI / 6 * i;
37
+ cosines.push(Math.cos(angle));
38
+ sines.push(Math.sin(angle));
39
+ }
40
+ const results = [];
41
+ for (let x = 0; x <= x_count; x++) {
42
+ for (let y = 0; y <= y_count; y++) {
43
+ const isOdd = x % 2 === 1;
44
+ if (y === 0 && isOdd)
45
+ continue;
46
+ if (y === 0 && hasOffsetY)
47
+ continue;
48
+ const center_x = x * x_interval + west - x_adjust;
49
+ let center_y = y * y_interval + south + y_adjust;
50
+ if (isOdd) {
51
+ center_y -= hex_height / 2;
52
+ }
53
+ if (options.triangles === true) {
54
+ hexTriangles(
55
+ [center_x, center_y],
56
+ cellWidth / 2,
57
+ cellHeight / 2,
58
+ JSON.parse(clonedProperties),
59
+ cosines,
60
+ sines
61
+ ).forEach(function(triangle) {
62
+ if (options.mask) {
63
+ if (intersect(featureCollection([options.mask, triangle])))
64
+ results.push(triangle);
65
+ } else {
66
+ results.push(triangle);
67
+ }
68
+ });
69
+ } else {
70
+ const hex = hexagon(
71
+ [center_x, center_y],
72
+ cellWidth / 2,
73
+ cellHeight / 2,
74
+ JSON.parse(clonedProperties),
75
+ cosines,
76
+ sines
77
+ );
78
+ if (options.mask) {
79
+ if (intersect(featureCollection([options.mask, hex])))
80
+ results.push(hex);
81
+ } else {
82
+ results.push(hex);
83
+ }
84
+ }
85
+ }
86
+ }
87
+ return featureCollection(results);
88
+ }
89
+ __name(hexGrid, "hexGrid");
90
+ function hexagon(center, rx, ry, properties, cosines, sines) {
91
+ const vertices = [];
92
+ for (let i = 0; i < 6; i++) {
93
+ const x = center[0] + rx * cosines[i];
94
+ const y = center[1] + ry * sines[i];
95
+ vertices.push([x, y]);
96
+ }
97
+ vertices.push(vertices[0].slice());
98
+ return polygon([vertices], properties);
99
+ }
100
+ __name(hexagon, "hexagon");
101
+ function hexTriangles(center, rx, ry, properties, cosines, sines) {
102
+ const triangles = [];
103
+ for (let i = 0; i < 6; i++) {
104
+ const vertices = [];
105
+ vertices.push(center);
106
+ vertices.push([center[0] + rx * cosines[i], center[1] + ry * sines[i]]);
107
+ vertices.push([
108
+ center[0] + rx * cosines[(i + 1) % 6],
109
+ center[1] + ry * sines[(i + 1) % 6]
110
+ ]);
111
+ vertices.push(center);
112
+ triangles.push(polygon([vertices], properties));
113
+ }
114
+ return triangles;
115
+ }
116
+ __name(hexTriangles, "hexTriangles");
117
+ var turf_hex_grid_default = hexGrid;
118
+ export {
119
+ turf_hex_grid_default as default,
120
+ hexGrid
121
+ };
122
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../index.ts"],"sourcesContent":["import { distance } from \"@turf/distance\";\nimport { intersect } from \"@turf/intersect\";\nimport {\n Feature,\n FeatureCollection,\n GeoJsonProperties,\n Polygon,\n BBox,\n} from \"geojson\";\nimport { polygon, featureCollection, Units } from \"@turf/helpers\";\n\n/**\n * Takes a bounding box and the diameter of the cell and returns a {@link FeatureCollection} of flat-topped\n * hexagons or triangles ({@link Polygon} features) aligned in an \"odd-q\" vertical grid as\n * described in [Hexagonal Grids](http://www.redblobgames.com/grids/hexagons/).\n *\n * @name hexGrid\n * @param {BBox} bbox extent in [minX, minY, maxX, maxY] order\n * @param {number} cellSide length of the side of the the hexagons or triangles, in units. It will also coincide with the\n * radius of the circumcircle of the hexagons.\n * @param {Object} [options={}] Optional parameters\n * @param {string} [options.units='kilometers'] used in calculating cell size, can be degrees, radians, miles, or kilometers\n * @param {Object} [options.properties={}] passed to each hexagon or triangle of the grid\n * @param {Feature<Polygon>} [options.mask] if passed a Polygon or MultiPolygon, the grid Points will be created only inside it\n * @param {boolean} [options.triangles=false] whether to return as triangles instead of hexagons\n * @returns {FeatureCollection<Polygon>} a hexagonal grid\n * @example\n * var bbox = [-96,31,-84,40];\n * var cellSide = 50;\n * var options = {units: 'miles'};\n *\n * var hexgrid = turf.hexGrid(bbox, cellSide, options);\n *\n * //addToMap\n * var addToMap = [hexgrid];\n */\nfunction hexGrid<P extends GeoJsonProperties = GeoJsonProperties>(\n bbox: BBox,\n cellSide: number,\n options: {\n units?: Units;\n triangles?: boolean;\n properties?: P;\n mask?: Feature<Polygon>;\n } = {}\n): FeatureCollection<Polygon, P> {\n // Issue => https://github.com/Turfjs/turf/issues/1284\n const clonedProperties = JSON.stringify(options.properties || {});\n\n const [west, south, east, north] = bbox;\n const centerY = (south + north) / 2;\n const centerX = (west + east) / 2;\n\n // https://github.com/Turfjs/turf/issues/758\n const xFraction =\n (cellSide * 2) / distance([west, centerY], [east, centerY], options);\n const cellWidth = xFraction * (east - west);\n const yFraction =\n (cellSide * 2) / distance([centerX, south], [centerX, north], options);\n const cellHeight = yFraction * (north - south);\n const radius = cellWidth / 2;\n\n const hex_width = radius * 2;\n const hex_height = (Math.sqrt(3) / 2) * cellHeight;\n\n const box_width = east - west;\n const box_height = north - south;\n\n const x_interval = (3 / 4) * hex_width;\n const y_interval = hex_height;\n\n // adjust box_width so all hexagons will be inside the bbox\n const x_span = (box_width - hex_width) / (hex_width - radius / 2);\n const x_count = Math.floor(x_span);\n\n const x_adjust =\n (x_count * x_interval - radius / 2 - box_width) / 2 -\n radius / 2 +\n x_interval / 2;\n\n // adjust box_height so all hexagons will be inside the bbox\n const y_count = Math.floor((box_height - hex_height) / hex_height);\n\n let y_adjust = (box_height - y_count * hex_height) / 2;\n\n const hasOffsetY = y_count * hex_height - box_height > hex_height / 2;\n if (hasOffsetY) {\n y_adjust -= hex_height / 4;\n }\n\n // Precompute cosines and sines of angles used in hexagon creation for performance gain\n const cosines = [];\n const sines = [];\n for (let i = 0; i < 6; i++) {\n const angle = ((2 * Math.PI) / 6) * i;\n cosines.push(Math.cos(angle));\n sines.push(Math.sin(angle));\n }\n\n const results = [];\n for (let x = 0; x <= x_count; x++) {\n for (let y = 0; y <= y_count; y++) {\n const isOdd = x % 2 === 1;\n if (y === 0 && isOdd) continue;\n if (y === 0 && hasOffsetY) continue;\n\n const center_x = x * x_interval + west - x_adjust;\n let center_y = y * y_interval + south + y_adjust;\n\n if (isOdd) {\n center_y -= hex_height / 2;\n }\n\n if (options.triangles === true) {\n hexTriangles(\n [center_x, center_y],\n cellWidth / 2,\n cellHeight / 2,\n JSON.parse(clonedProperties),\n cosines,\n sines\n ).forEach(function (triangle) {\n if (options.mask) {\n if (intersect(featureCollection([options.mask, triangle])))\n results.push(triangle);\n } else {\n results.push(triangle);\n }\n });\n } else {\n const hex = hexagon(\n [center_x, center_y],\n cellWidth / 2,\n cellHeight / 2,\n JSON.parse(clonedProperties),\n cosines,\n sines\n );\n if (options.mask) {\n if (intersect(featureCollection([options.mask, hex])))\n results.push(hex);\n } else {\n results.push(hex);\n }\n }\n }\n }\n\n return featureCollection(results) as FeatureCollection<Polygon, P>;\n}\n\n/**\n * Creates hexagon\n *\n * @private\n * @param {Array<number>} center of the hexagon\n * @param {number} rx half hexagon width\n * @param {number} ry half hexagon height\n * @param {Object} properties passed to each hexagon\n * @param {Array<number>} cosines precomputed\n * @param {Array<number>} sines precomputed\n * @returns {Feature<Polygon>} hexagon\n */\nfunction hexagon(\n center: number[],\n rx: number,\n ry: number,\n properties: GeoJsonProperties,\n cosines: number[],\n sines: number[]\n) {\n const vertices = [];\n for (let i = 0; i < 6; i++) {\n const x = center[0] + rx * cosines[i];\n const y = center[1] + ry * sines[i];\n vertices.push([x, y]);\n }\n //first and last vertex must be the same\n vertices.push(vertices[0].slice());\n return polygon([vertices], properties);\n}\n\n/**\n * Creates triangles composing an hexagon\n *\n * @private\n * @param {Array<number>} center of the hexagon\n * @param {number} rx half triangle width\n * @param {number} ry half triangle height\n * @param {Object} properties passed to each triangle\n * @param {Array<number>} cosines precomputed\n * @param {Array<number>} sines precomputed\n * @returns {Array<Feature<Polygon>>} triangles\n */\nfunction hexTriangles(\n center: number[],\n rx: number,\n ry: number,\n properties: GeoJsonProperties,\n cosines: number[],\n sines: number[]\n) {\n const triangles = [];\n for (let i = 0; i < 6; i++) {\n const vertices = [];\n vertices.push(center);\n vertices.push([center[0] + rx * cosines[i], center[1] + ry * sines[i]]);\n vertices.push([\n center[0] + rx * cosines[(i + 1) % 6],\n center[1] + ry * sines[(i + 1) % 6],\n ]);\n vertices.push(center);\n triangles.push(polygon([vertices], properties));\n }\n return triangles;\n}\n\nexport { hexGrid };\nexport default hexGrid;\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@turf/hex-grid",
3
- "version": "7.0.0-alpha.1",
3
+ "version": "7.0.0-alpha.111+08576cb50",
4
4
  "description": "turf hex-grid module",
5
5
  "author": "Turf Authors",
6
6
  "contributors": [
@@ -32,50 +32,55 @@
32
32
  "points",
33
33
  "geojson"
34
34
  ],
35
- "main": "dist/js/index.js",
36
- "module": "dist/es/index.js",
35
+ "type": "commonjs",
36
+ "main": "dist/cjs/index.cjs",
37
+ "module": "dist/esm/index.mjs",
38
+ "types": "dist/cjs/index.d.ts",
37
39
  "exports": {
38
40
  "./package.json": "./package.json",
39
41
  ".": {
40
- "types": "./dist/js/index.d.ts",
41
- "import": "./dist/es/index.js",
42
- "require": "./dist/js/index.js"
42
+ "import": {
43
+ "types": "./dist/esm/index.d.mts",
44
+ "default": "./dist/esm/index.mjs"
45
+ },
46
+ "require": {
47
+ "types": "./dist/cjs/index.d.ts",
48
+ "default": "./dist/cjs/index.cjs"
49
+ }
43
50
  }
44
51
  },
45
- "types": "dist/js/index.d.ts",
46
52
  "sideEffects": false,
47
53
  "files": [
48
54
  "dist"
49
55
  ],
50
56
  "scripts": {
51
- "bench": "tsx bench.js",
52
- "build": "npm-run-all build:*",
53
- "build:es": "tsc --outDir dist/es --module esnext --declaration false && echo '{\"type\":\"module\"}' > dist/es/package.json",
54
- "build:js": "tsc",
55
- "docs": "tsx ../../scripts/generate-readmes",
56
- "test": "npm-run-all test:*",
57
- "test:tape": "tsx test.js",
57
+ "bench": "tsx bench.ts",
58
+ "build": "tsup --config ../../tsup.config.ts",
59
+ "docs": "tsx ../../scripts/generate-readmes.ts",
60
+ "test": "npm-run-all --npm-path npm test:*",
61
+ "test:tape": "tsx test.ts",
58
62
  "test:types": "tsc --esModuleInterop --noEmit --strict types.ts"
59
63
  },
60
64
  "devDependencies": {
61
- "@turf/bbox-polygon": "^7.0.0-alpha.1",
62
- "@turf/truncate": "^7.0.0-alpha.1",
63
- "@types/tape": "*",
64
- "benchmark": "*",
65
- "load-json-file": "*",
66
- "npm-run-all": "*",
67
- "tape": "*",
68
- "tslint": "*",
69
- "tsx": "*",
70
- "typescript": "*",
71
- "write-json-file": "*"
65
+ "@turf/bbox-polygon": "^7.0.0-alpha.111+08576cb50",
66
+ "@turf/truncate": "^7.0.0-alpha.111+08576cb50",
67
+ "@types/benchmark": "^2.1.5",
68
+ "@types/tape": "^4.2.32",
69
+ "benchmark": "^2.1.4",
70
+ "load-json-file": "^7.0.1",
71
+ "npm-run-all": "^4.1.5",
72
+ "tape": "^5.7.2",
73
+ "tsup": "^8.0.1",
74
+ "tsx": "^4.6.2",
75
+ "typescript": "^5.2.2",
76
+ "write-json-file": "^5.0.0"
72
77
  },
73
78
  "dependencies": {
74
- "@turf/distance": "^7.0.0-alpha.1",
75
- "@turf/helpers": "^7.0.0-alpha.1",
76
- "@turf/intersect": "^7.0.0-alpha.1",
77
- "@turf/invariant": "^7.0.0-alpha.1",
78
- "tslib": "^2.3.0"
79
+ "@turf/distance": "^7.0.0-alpha.111+08576cb50",
80
+ "@turf/helpers": "^7.0.0-alpha.111+08576cb50",
81
+ "@turf/intersect": "^7.0.0-alpha.111+08576cb50",
82
+ "@turf/invariant": "^7.0.0-alpha.111+08576cb50",
83
+ "tslib": "^2.6.2"
79
84
  },
80
- "gitHead": "cf7a0c507b017ca066acffd0ce23bda5b393fb5a"
85
+ "gitHead": "08576cb50376e0199aea02dbd887e3af83672246"
81
86
  }
package/dist/es/index.js DELETED
@@ -1,156 +0,0 @@
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 the diameter of the cell and returns a {@link FeatureCollection} of flat-topped
6
- * hexagons or triangles ({@link Polygon} features) aligned in an "odd-q" vertical grid as
7
- * described in [Hexagonal Grids](http://www.redblobgames.com/grids/hexagons/).
8
- *
9
- * @name hexGrid
10
- * @param {BBox} bbox extent in [minX, minY, maxX, maxY] order
11
- * @param {number} cellSide length of the side of the the hexagons or triangles, in units. It will also coincide with the
12
- * radius of the circumcircle of the hexagons.
13
- * @param {Object} [options={}] Optional parameters
14
- * @param {string} [options.units='kilometers'] used in calculating cell size, can be degrees, radians, miles, or kilometers
15
- * @param {Object} [options.properties={}] passed to each hexagon or triangle of the grid
16
- * @param {Feature<Polygon>} [options.mask] if passed a Polygon or MultiPolygon, the grid Points will be created only inside it
17
- * @param {boolean} [options.triangles=false] whether to return as triangles instead of hexagons
18
- * @returns {FeatureCollection<Polygon>} a hexagonal grid
19
- * @example
20
- * var bbox = [-96,31,-84,40];
21
- * var cellSide = 50;
22
- * var options = {units: 'miles'};
23
- *
24
- * var hexgrid = turf.hexGrid(bbox, cellSide, options);
25
- *
26
- * //addToMap
27
- * var addToMap = [hexgrid];
28
- */
29
- function hexGrid(bbox, cellSide, options = {}) {
30
- // Issue => https://github.com/Turfjs/turf/issues/1284
31
- const clonedProperties = JSON.stringify(options.properties || {});
32
- const [west, south, east, north] = bbox;
33
- const centerY = (south + north) / 2;
34
- const centerX = (west + east) / 2;
35
- // https://github.com/Turfjs/turf/issues/758
36
- const xFraction = (cellSide * 2) / distance([west, centerY], [east, centerY], options);
37
- const cellWidth = xFraction * (east - west);
38
- const yFraction = (cellSide * 2) / distance([centerX, south], [centerX, north], options);
39
- const cellHeight = yFraction * (north - south);
40
- const radius = cellWidth / 2;
41
- const hex_width = radius * 2;
42
- const hex_height = (Math.sqrt(3) / 2) * cellHeight;
43
- const box_width = east - west;
44
- const box_height = north - south;
45
- const x_interval = (3 / 4) * hex_width;
46
- const y_interval = hex_height;
47
- // adjust box_width so all hexagons will be inside the bbox
48
- const x_span = (box_width - hex_width) / (hex_width - radius / 2);
49
- const x_count = Math.floor(x_span);
50
- const x_adjust = (x_count * x_interval - radius / 2 - box_width) / 2 -
51
- radius / 2 +
52
- x_interval / 2;
53
- // adjust box_height so all hexagons will be inside the bbox
54
- const y_count = Math.floor((box_height - hex_height) / hex_height);
55
- let y_adjust = (box_height - y_count * hex_height) / 2;
56
- const hasOffsetY = y_count * hex_height - box_height > hex_height / 2;
57
- if (hasOffsetY) {
58
- y_adjust -= hex_height / 4;
59
- }
60
- // Precompute cosines and sines of angles used in hexagon creation for performance gain
61
- const cosines = [];
62
- const sines = [];
63
- for (let i = 0; i < 6; i++) {
64
- const angle = ((2 * Math.PI) / 6) * i;
65
- cosines.push(Math.cos(angle));
66
- sines.push(Math.sin(angle));
67
- }
68
- const results = [];
69
- for (let x = 0; x <= x_count; x++) {
70
- for (let y = 0; y <= y_count; y++) {
71
- const isOdd = x % 2 === 1;
72
- if (y === 0 && isOdd)
73
- continue;
74
- if (y === 0 && hasOffsetY)
75
- continue;
76
- const center_x = x * x_interval + west - x_adjust;
77
- let center_y = y * y_interval + south + y_adjust;
78
- if (isOdd) {
79
- center_y -= hex_height / 2;
80
- }
81
- if (options.triangles === true) {
82
- hexTriangles([center_x, center_y], cellWidth / 2, cellHeight / 2, JSON.parse(clonedProperties), cosines, sines).forEach(function (triangle) {
83
- if (options.mask) {
84
- if (intersect(featureCollection([options.mask, triangle])))
85
- results.push(triangle);
86
- }
87
- else {
88
- results.push(triangle);
89
- }
90
- });
91
- }
92
- else {
93
- const hex = hexagon([center_x, center_y], cellWidth / 2, cellHeight / 2, JSON.parse(clonedProperties), cosines, sines);
94
- if (options.mask) {
95
- if (intersect(featureCollection([options.mask, hex])))
96
- results.push(hex);
97
- }
98
- else {
99
- results.push(hex);
100
- }
101
- }
102
- }
103
- }
104
- return featureCollection(results);
105
- }
106
- /**
107
- * Creates hexagon
108
- *
109
- * @private
110
- * @param {Array<number>} center of the hexagon
111
- * @param {number} rx half hexagon width
112
- * @param {number} ry half hexagon height
113
- * @param {Object} properties passed to each hexagon
114
- * @param {Array<number>} cosines precomputed
115
- * @param {Array<number>} sines precomputed
116
- * @returns {Feature<Polygon>} hexagon
117
- */
118
- function hexagon(center, rx, ry, properties, cosines, sines) {
119
- const vertices = [];
120
- for (let i = 0; i < 6; i++) {
121
- const x = center[0] + rx * cosines[i];
122
- const y = center[1] + ry * sines[i];
123
- vertices.push([x, y]);
124
- }
125
- //first and last vertex must be the same
126
- vertices.push(vertices[0].slice());
127
- return polygon([vertices], properties);
128
- }
129
- /**
130
- * Creates triangles composing an hexagon
131
- *
132
- * @private
133
- * @param {Array<number>} center of the hexagon
134
- * @param {number} rx half triangle width
135
- * @param {number} ry half triangle height
136
- * @param {Object} properties passed to each triangle
137
- * @param {Array<number>} cosines precomputed
138
- * @param {Array<number>} sines precomputed
139
- * @returns {Array<Feature<Polygon>>} triangles
140
- */
141
- function hexTriangles(center, rx, ry, properties, cosines, sines) {
142
- const triangles = [];
143
- for (let i = 0; i < 6; i++) {
144
- const vertices = [];
145
- vertices.push(center);
146
- vertices.push([center[0] + rx * cosines[i], center[1] + ry * sines[i]]);
147
- vertices.push([
148
- center[0] + rx * cosines[(i + 1) % 6],
149
- center[1] + ry * sines[(i + 1) % 6],
150
- ]);
151
- vertices.push(center);
152
- triangles.push(polygon([vertices], properties));
153
- }
154
- return triangles;
155
- }
156
- export default hexGrid;
@@ -1 +0,0 @@
1
- {"type":"module"}
package/dist/js/index.js DELETED
@@ -1,159 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
- const distance_1 = tslib_1.__importDefault(require("@turf/distance"));
5
- const intersect_1 = tslib_1.__importDefault(require("@turf/intersect"));
6
- const helpers_1 = require("@turf/helpers");
7
- /**
8
- * Takes a bounding box and the diameter of the cell and returns a {@link FeatureCollection} of flat-topped
9
- * hexagons or triangles ({@link Polygon} features) aligned in an "odd-q" vertical grid as
10
- * described in [Hexagonal Grids](http://www.redblobgames.com/grids/hexagons/).
11
- *
12
- * @name hexGrid
13
- * @param {BBox} bbox extent in [minX, minY, maxX, maxY] order
14
- * @param {number} cellSide length of the side of the the hexagons or triangles, in units. It will also coincide with the
15
- * radius of the circumcircle of the hexagons.
16
- * @param {Object} [options={}] Optional parameters
17
- * @param {string} [options.units='kilometers'] used in calculating cell size, can be degrees, radians, miles, or kilometers
18
- * @param {Object} [options.properties={}] passed to each hexagon or triangle of the grid
19
- * @param {Feature<Polygon>} [options.mask] if passed a Polygon or MultiPolygon, the grid Points will be created only inside it
20
- * @param {boolean} [options.triangles=false] whether to return as triangles instead of hexagons
21
- * @returns {FeatureCollection<Polygon>} a hexagonal grid
22
- * @example
23
- * var bbox = [-96,31,-84,40];
24
- * var cellSide = 50;
25
- * var options = {units: 'miles'};
26
- *
27
- * var hexgrid = turf.hexGrid(bbox, cellSide, options);
28
- *
29
- * //addToMap
30
- * var addToMap = [hexgrid];
31
- */
32
- function hexGrid(bbox, cellSide, options = {}) {
33
- // Issue => https://github.com/Turfjs/turf/issues/1284
34
- const clonedProperties = JSON.stringify(options.properties || {});
35
- const [west, south, east, north] = bbox;
36
- const centerY = (south + north) / 2;
37
- const centerX = (west + east) / 2;
38
- // https://github.com/Turfjs/turf/issues/758
39
- const xFraction = (cellSide * 2) / distance_1.default([west, centerY], [east, centerY], options);
40
- const cellWidth = xFraction * (east - west);
41
- const yFraction = (cellSide * 2) / distance_1.default([centerX, south], [centerX, north], options);
42
- const cellHeight = yFraction * (north - south);
43
- const radius = cellWidth / 2;
44
- const hex_width = radius * 2;
45
- const hex_height = (Math.sqrt(3) / 2) * cellHeight;
46
- const box_width = east - west;
47
- const box_height = north - south;
48
- const x_interval = (3 / 4) * hex_width;
49
- const y_interval = hex_height;
50
- // adjust box_width so all hexagons will be inside the bbox
51
- const x_span = (box_width - hex_width) / (hex_width - radius / 2);
52
- const x_count = Math.floor(x_span);
53
- const x_adjust = (x_count * x_interval - radius / 2 - box_width) / 2 -
54
- radius / 2 +
55
- x_interval / 2;
56
- // adjust box_height so all hexagons will be inside the bbox
57
- const y_count = Math.floor((box_height - hex_height) / hex_height);
58
- let y_adjust = (box_height - y_count * hex_height) / 2;
59
- const hasOffsetY = y_count * hex_height - box_height > hex_height / 2;
60
- if (hasOffsetY) {
61
- y_adjust -= hex_height / 4;
62
- }
63
- // Precompute cosines and sines of angles used in hexagon creation for performance gain
64
- const cosines = [];
65
- const sines = [];
66
- for (let i = 0; i < 6; i++) {
67
- const angle = ((2 * Math.PI) / 6) * i;
68
- cosines.push(Math.cos(angle));
69
- sines.push(Math.sin(angle));
70
- }
71
- const results = [];
72
- for (let x = 0; x <= x_count; x++) {
73
- for (let y = 0; y <= y_count; y++) {
74
- const isOdd = x % 2 === 1;
75
- if (y === 0 && isOdd)
76
- continue;
77
- if (y === 0 && hasOffsetY)
78
- continue;
79
- const center_x = x * x_interval + west - x_adjust;
80
- let center_y = y * y_interval + south + y_adjust;
81
- if (isOdd) {
82
- center_y -= hex_height / 2;
83
- }
84
- if (options.triangles === true) {
85
- hexTriangles([center_x, center_y], cellWidth / 2, cellHeight / 2, JSON.parse(clonedProperties), cosines, sines).forEach(function (triangle) {
86
- if (options.mask) {
87
- if (intersect_1.default(helpers_1.featureCollection([options.mask, triangle])))
88
- results.push(triangle);
89
- }
90
- else {
91
- results.push(triangle);
92
- }
93
- });
94
- }
95
- else {
96
- const hex = hexagon([center_x, center_y], cellWidth / 2, cellHeight / 2, JSON.parse(clonedProperties), cosines, sines);
97
- if (options.mask) {
98
- if (intersect_1.default(helpers_1.featureCollection([options.mask, hex])))
99
- results.push(hex);
100
- }
101
- else {
102
- results.push(hex);
103
- }
104
- }
105
- }
106
- }
107
- return helpers_1.featureCollection(results);
108
- }
109
- /**
110
- * Creates hexagon
111
- *
112
- * @private
113
- * @param {Array<number>} center of the hexagon
114
- * @param {number} rx half hexagon width
115
- * @param {number} ry half hexagon height
116
- * @param {Object} properties passed to each hexagon
117
- * @param {Array<number>} cosines precomputed
118
- * @param {Array<number>} sines precomputed
119
- * @returns {Feature<Polygon>} hexagon
120
- */
121
- function hexagon(center, rx, ry, properties, cosines, sines) {
122
- const vertices = [];
123
- for (let i = 0; i < 6; i++) {
124
- const x = center[0] + rx * cosines[i];
125
- const y = center[1] + ry * sines[i];
126
- vertices.push([x, y]);
127
- }
128
- //first and last vertex must be the same
129
- vertices.push(vertices[0].slice());
130
- return helpers_1.polygon([vertices], properties);
131
- }
132
- /**
133
- * Creates triangles composing an hexagon
134
- *
135
- * @private
136
- * @param {Array<number>} center of the hexagon
137
- * @param {number} rx half triangle width
138
- * @param {number} ry half triangle height
139
- * @param {Object} properties passed to each triangle
140
- * @param {Array<number>} cosines precomputed
141
- * @param {Array<number>} sines precomputed
142
- * @returns {Array<Feature<Polygon>>} triangles
143
- */
144
- function hexTriangles(center, rx, ry, properties, cosines, sines) {
145
- const triangles = [];
146
- for (let i = 0; i < 6; i++) {
147
- const vertices = [];
148
- vertices.push(center);
149
- vertices.push([center[0] + rx * cosines[i], center[1] + ry * sines[i]]);
150
- vertices.push([
151
- center[0] + rx * cosines[(i + 1) % 6],
152
- center[1] + ry * sines[(i + 1) % 6],
153
- ]);
154
- vertices.push(center);
155
- triangles.push(helpers_1.polygon([vertices], properties));
156
- }
157
- return triangles;
158
- }
159
- exports.default = hexGrid;