@turf/hex-grid 7.0.0-alpha.2 → 7.0.0
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 +4 -9
- package/dist/cjs/index.cjs +122 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/cjs/index.d.cts +36 -0
- package/dist/{js → esm}/index.d.ts +6 -4
- package/dist/esm/index.js +122 -0
- package/dist/esm/index.js.map +1 -0
- package/package.json +37 -32
- package/dist/es/index.js +0 -156
- package/dist/es/package.json +0 -1
- package/dist/js/index.js +0 -159
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](
|
|
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
|
|
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"]}
|
|
@@ -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 };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Units } from
|
|
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
|
-
|
|
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.js.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
|
|
3
|
+
"version": "7.0.0",
|
|
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
|
-
"
|
|
36
|
-
"
|
|
35
|
+
"type": "module",
|
|
36
|
+
"main": "dist/cjs/index.cjs",
|
|
37
|
+
"module": "dist/esm/index.js",
|
|
38
|
+
"types": "dist/esm/index.d.ts",
|
|
37
39
|
"exports": {
|
|
38
40
|
"./package.json": "./package.json",
|
|
39
41
|
".": {
|
|
40
|
-
"
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
"import": {
|
|
43
|
+
"types": "./dist/esm/index.d.ts",
|
|
44
|
+
"default": "./dist/esm/index.js"
|
|
45
|
+
},
|
|
46
|
+
"require": {
|
|
47
|
+
"types": "./dist/cjs/index.d.cts",
|
|
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.
|
|
52
|
-
"build": "
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"test": "
|
|
57
|
-
"test:tape": "tsx test.js",
|
|
58
|
-
"test:types": "tsc --esModuleInterop --noEmit --strict types.ts"
|
|
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",
|
|
62
|
+
"test:types": "tsc --esModuleInterop --module node16 --moduleResolution node16 --noEmit --strict types.ts"
|
|
59
63
|
},
|
|
60
64
|
"devDependencies": {
|
|
61
|
-
"@turf/bbox-polygon": "^7.0.0
|
|
62
|
-
"@turf/truncate": "^7.0.0
|
|
63
|
-
"@types/
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"
|
|
65
|
+
"@turf/bbox-polygon": "^7.0.0",
|
|
66
|
+
"@turf/truncate": "^7.0.0",
|
|
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
|
|
75
|
-
"@turf/helpers": "^7.0.0
|
|
76
|
-
"@turf/intersect": "^7.0.0
|
|
77
|
-
"@turf/invariant": "^7.0.0
|
|
78
|
-
"tslib": "^2.
|
|
79
|
+
"@turf/distance": "^7.0.0",
|
|
80
|
+
"@turf/helpers": "^7.0.0",
|
|
81
|
+
"@turf/intersect": "^7.0.0",
|
|
82
|
+
"@turf/invariant": "^7.0.0",
|
|
83
|
+
"tslib": "^2.6.2"
|
|
79
84
|
},
|
|
80
|
-
"gitHead": "
|
|
85
|
+
"gitHead": "3d3a7917025fbabe191dbddbc89754b86f9c7739"
|
|
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;
|
package/dist/es/package.json
DELETED
|
@@ -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;
|