@turf/hex-grid 6.5.0 → 7.0.0-alpha.1
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 +11 -10
- package/dist/es/index.js +43 -44
- package/dist/js/index.d.ts +4 -3
- package/dist/js/index.js +46 -49
- package/package.json +15 -13
package/README.md
CHANGED
|
@@ -8,18 +8,19 @@ Takes a bounding box and the diameter of the cell and returns a [FeatureCollecti
|
|
|
8
8
|
hexagons or triangles ([Polygon][2] features) aligned in an "odd-q" vertical grid as
|
|
9
9
|
described in [Hexagonal Grids][3].
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
### Parameters
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
* `bbox` **[BBox][4]** extent in \[minX, minY, maxX, maxY] order
|
|
14
|
+
* `cellSide` **[number][5]** length of the side of the the hexagons or triangles, in units. It will also coincide with the
|
|
15
15
|
radius of the circumcircle of the hexagons.
|
|
16
|
-
|
|
17
|
-
- `options.units` **[string][7]** used in calculating cell size, can be degrees, radians, miles, or kilometers (optional, default `'kilometers'`)
|
|
18
|
-
- `options.properties` **[Object][6]** passed to each hexagon or triangle of the grid (optional, default `{}`)
|
|
19
|
-
- `options.mask` **[Feature][8]<[Polygon][9]>?** if passed a Polygon or MultiPolygon, the grid Points will be created only inside it
|
|
20
|
-
- `options.triangles` **[boolean][10]** whether to return as triangles instead of hexagons (optional, default `false`)
|
|
16
|
+
* `options` **[Object][6]** Optional parameters (optional, default `{}`)
|
|
21
17
|
|
|
22
|
-
**
|
|
18
|
+
* `options.units` **[string][7]** used in calculating cell size, can be degrees, radians, miles, or kilometers (optional, default `'kilometers'`)
|
|
19
|
+
* `options.properties` **[Object][6]** passed to each hexagon or triangle of the grid (optional, default `{}`)
|
|
20
|
+
* `options.mask` **[Feature][8]<[Polygon][9]>?** if passed a Polygon or MultiPolygon, the grid Points will be created only inside it
|
|
21
|
+
* `options.triangles` **[boolean][10]** whether to return as triangles instead of hexagons (optional, default `false`)
|
|
22
|
+
|
|
23
|
+
### Examples
|
|
23
24
|
|
|
24
25
|
```javascript
|
|
25
26
|
var bbox = [-96,31,-84,40];
|
|
@@ -32,7 +33,7 @@ var hexgrid = turf.hexGrid(bbox, cellSide, options);
|
|
|
32
33
|
var addToMap = [hexgrid];
|
|
33
34
|
```
|
|
34
35
|
|
|
35
|
-
Returns **[FeatureCollection][11]
|
|
36
|
+
Returns **[FeatureCollection][11]<[Polygon][9]>** a hexagonal grid
|
|
36
37
|
|
|
37
38
|
[1]: https://tools.ietf.org/html/rfc7946#section-3.3
|
|
38
39
|
|
package/dist/es/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import distance from "@turf/distance";
|
|
2
2
|
import intersect from "@turf/intersect";
|
|
3
|
-
import { polygon, featureCollection
|
|
3
|
+
import { polygon, featureCollection } from "@turf/helpers";
|
|
4
4
|
/**
|
|
5
5
|
* Takes a bounding box and the diameter of the cell and returns a {@link FeatureCollection} of flat-topped
|
|
6
6
|
* hexagons or triangles ({@link Polygon} features) aligned in an "odd-q" vertical grid as
|
|
@@ -26,63 +26,62 @@ import { polygon, featureCollection, } from "@turf/helpers";
|
|
|
26
26
|
* //addToMap
|
|
27
27
|
* var addToMap = [hexgrid];
|
|
28
28
|
*/
|
|
29
|
-
function hexGrid(bbox, cellSide, options) {
|
|
30
|
-
if (options === void 0) { options = {}; }
|
|
29
|
+
function hexGrid(bbox, cellSide, options = {}) {
|
|
31
30
|
// Issue => https://github.com/Turfjs/turf/issues/1284
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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;
|
|
36
35
|
// https://github.com/Turfjs/turf/issues/758
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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;
|
|
48
47
|
// adjust box_width so all hexagons will be inside the bbox
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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 -
|
|
52
51
|
radius / 2 +
|
|
53
52
|
x_interval / 2;
|
|
54
53
|
// adjust box_height so all hexagons will be inside the bbox
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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;
|
|
58
57
|
if (hasOffsetY) {
|
|
59
58
|
y_adjust -= hex_height / 4;
|
|
60
59
|
}
|
|
61
60
|
// Precompute cosines and sines of angles used in hexagon creation for performance gain
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
for (
|
|
65
|
-
|
|
61
|
+
const cosines = [];
|
|
62
|
+
const sines = [];
|
|
63
|
+
for (let i = 0; i < 6; i++) {
|
|
64
|
+
const angle = ((2 * Math.PI) / 6) * i;
|
|
66
65
|
cosines.push(Math.cos(angle));
|
|
67
66
|
sines.push(Math.sin(angle));
|
|
68
67
|
}
|
|
69
|
-
|
|
70
|
-
for (
|
|
71
|
-
for (
|
|
72
|
-
|
|
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;
|
|
73
72
|
if (y === 0 && isOdd)
|
|
74
73
|
continue;
|
|
75
74
|
if (y === 0 && hasOffsetY)
|
|
76
75
|
continue;
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
const center_x = x * x_interval + west - x_adjust;
|
|
77
|
+
let center_y = y * y_interval + south + y_adjust;
|
|
79
78
|
if (isOdd) {
|
|
80
79
|
center_y -= hex_height / 2;
|
|
81
80
|
}
|
|
82
81
|
if (options.triangles === true) {
|
|
83
82
|
hexTriangles([center_x, center_y], cellWidth / 2, cellHeight / 2, JSON.parse(clonedProperties), cosines, sines).forEach(function (triangle) {
|
|
84
83
|
if (options.mask) {
|
|
85
|
-
if (intersect(options.mask, triangle))
|
|
84
|
+
if (intersect(featureCollection([options.mask, triangle])))
|
|
86
85
|
results.push(triangle);
|
|
87
86
|
}
|
|
88
87
|
else {
|
|
@@ -91,9 +90,9 @@ function hexGrid(bbox, cellSide, options) {
|
|
|
91
90
|
});
|
|
92
91
|
}
|
|
93
92
|
else {
|
|
94
|
-
|
|
93
|
+
const hex = hexagon([center_x, center_y], cellWidth / 2, cellHeight / 2, JSON.parse(clonedProperties), cosines, sines);
|
|
95
94
|
if (options.mask) {
|
|
96
|
-
if (intersect(options.mask, hex))
|
|
95
|
+
if (intersect(featureCollection([options.mask, hex])))
|
|
97
96
|
results.push(hex);
|
|
98
97
|
}
|
|
99
98
|
else {
|
|
@@ -117,10 +116,10 @@ function hexGrid(bbox, cellSide, options) {
|
|
|
117
116
|
* @returns {Feature<Polygon>} hexagon
|
|
118
117
|
*/
|
|
119
118
|
function hexagon(center, rx, ry, properties, cosines, sines) {
|
|
120
|
-
|
|
121
|
-
for (
|
|
122
|
-
|
|
123
|
-
|
|
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];
|
|
124
123
|
vertices.push([x, y]);
|
|
125
124
|
}
|
|
126
125
|
//first and last vertex must be the same
|
|
@@ -140,9 +139,9 @@ function hexagon(center, rx, ry, properties, cosines, sines) {
|
|
|
140
139
|
* @returns {Array<Feature<Polygon>>} triangles
|
|
141
140
|
*/
|
|
142
141
|
function hexTriangles(center, rx, ry, properties, cosines, sines) {
|
|
143
|
-
|
|
144
|
-
for (
|
|
145
|
-
|
|
142
|
+
const triangles = [];
|
|
143
|
+
for (let i = 0; i < 6; i++) {
|
|
144
|
+
const vertices = [];
|
|
146
145
|
vertices.push(center);
|
|
147
146
|
vertices.push([center[0] + rx * cosines[i], center[1] + ry * sines[i]]);
|
|
148
147
|
vertices.push([
|
package/dist/js/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { Feature, FeatureCollection,
|
|
1
|
+
import { Feature, FeatureCollection, GeoJsonProperties, Polygon, BBox } from "geojson";
|
|
2
|
+
import { Units } from "@turf/helpers";
|
|
2
3
|
/**
|
|
3
4
|
* Takes a bounding box and the diameter of the cell and returns a {@link FeatureCollection} of flat-topped
|
|
4
5
|
* hexagons or triangles ({@link Polygon} features) aligned in an "odd-q" vertical grid as
|
|
@@ -24,10 +25,10 @@ import { Feature, FeatureCollection, Units, Properties, Polygon, BBox } from "@t
|
|
|
24
25
|
* //addToMap
|
|
25
26
|
* var addToMap = [hexgrid];
|
|
26
27
|
*/
|
|
27
|
-
declare function hexGrid<P =
|
|
28
|
+
declare function hexGrid<P = GeoJsonProperties>(bbox: BBox, cellSide: number, options?: {
|
|
28
29
|
units?: Units;
|
|
29
30
|
triangles?: boolean;
|
|
30
31
|
properties?: P;
|
|
31
|
-
mask?: Feature<Polygon
|
|
32
|
+
mask?: Feature<Polygon>;
|
|
32
33
|
}): FeatureCollection<Polygon, P>;
|
|
33
34
|
export default hexGrid;
|
package/dist/js/index.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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");
|
|
9
7
|
/**
|
|
10
8
|
* Takes a bounding box and the diameter of the cell and returns a {@link FeatureCollection} of flat-topped
|
|
11
9
|
* hexagons or triangles ({@link Polygon} features) aligned in an "odd-q" vertical grid as
|
|
@@ -31,63 +29,62 @@ var helpers_1 = require("@turf/helpers");
|
|
|
31
29
|
* //addToMap
|
|
32
30
|
* var addToMap = [hexgrid];
|
|
33
31
|
*/
|
|
34
|
-
function hexGrid(bbox, cellSide, options) {
|
|
35
|
-
if (options === void 0) { options = {}; }
|
|
32
|
+
function hexGrid(bbox, cellSide, options = {}) {
|
|
36
33
|
// Issue => https://github.com/Turfjs/turf/issues/1284
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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;
|
|
41
38
|
// https://github.com/Turfjs/turf/issues/758
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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;
|
|
53
50
|
// adjust box_width so all hexagons will be inside the bbox
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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 -
|
|
57
54
|
radius / 2 +
|
|
58
55
|
x_interval / 2;
|
|
59
56
|
// adjust box_height so all hexagons will be inside the bbox
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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;
|
|
63
60
|
if (hasOffsetY) {
|
|
64
61
|
y_adjust -= hex_height / 4;
|
|
65
62
|
}
|
|
66
63
|
// Precompute cosines and sines of angles used in hexagon creation for performance gain
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
for (
|
|
70
|
-
|
|
64
|
+
const cosines = [];
|
|
65
|
+
const sines = [];
|
|
66
|
+
for (let i = 0; i < 6; i++) {
|
|
67
|
+
const angle = ((2 * Math.PI) / 6) * i;
|
|
71
68
|
cosines.push(Math.cos(angle));
|
|
72
69
|
sines.push(Math.sin(angle));
|
|
73
70
|
}
|
|
74
|
-
|
|
75
|
-
for (
|
|
76
|
-
for (
|
|
77
|
-
|
|
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;
|
|
78
75
|
if (y === 0 && isOdd)
|
|
79
76
|
continue;
|
|
80
77
|
if (y === 0 && hasOffsetY)
|
|
81
78
|
continue;
|
|
82
|
-
|
|
83
|
-
|
|
79
|
+
const center_x = x * x_interval + west - x_adjust;
|
|
80
|
+
let center_y = y * y_interval + south + y_adjust;
|
|
84
81
|
if (isOdd) {
|
|
85
82
|
center_y -= hex_height / 2;
|
|
86
83
|
}
|
|
87
84
|
if (options.triangles === true) {
|
|
88
85
|
hexTriangles([center_x, center_y], cellWidth / 2, cellHeight / 2, JSON.parse(clonedProperties), cosines, sines).forEach(function (triangle) {
|
|
89
86
|
if (options.mask) {
|
|
90
|
-
if (intersect_1.default(options.mask, triangle))
|
|
87
|
+
if (intersect_1.default(helpers_1.featureCollection([options.mask, triangle])))
|
|
91
88
|
results.push(triangle);
|
|
92
89
|
}
|
|
93
90
|
else {
|
|
@@ -96,9 +93,9 @@ function hexGrid(bbox, cellSide, options) {
|
|
|
96
93
|
});
|
|
97
94
|
}
|
|
98
95
|
else {
|
|
99
|
-
|
|
96
|
+
const hex = hexagon([center_x, center_y], cellWidth / 2, cellHeight / 2, JSON.parse(clonedProperties), cosines, sines);
|
|
100
97
|
if (options.mask) {
|
|
101
|
-
if (intersect_1.default(options.mask, hex))
|
|
98
|
+
if (intersect_1.default(helpers_1.featureCollection([options.mask, hex])))
|
|
102
99
|
results.push(hex);
|
|
103
100
|
}
|
|
104
101
|
else {
|
|
@@ -122,10 +119,10 @@ function hexGrid(bbox, cellSide, options) {
|
|
|
122
119
|
* @returns {Feature<Polygon>} hexagon
|
|
123
120
|
*/
|
|
124
121
|
function hexagon(center, rx, ry, properties, cosines, sines) {
|
|
125
|
-
|
|
126
|
-
for (
|
|
127
|
-
|
|
128
|
-
|
|
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];
|
|
129
126
|
vertices.push([x, y]);
|
|
130
127
|
}
|
|
131
128
|
//first and last vertex must be the same
|
|
@@ -145,9 +142,9 @@ function hexagon(center, rx, ry, properties, cosines, sines) {
|
|
|
145
142
|
* @returns {Array<Feature<Polygon>>} triangles
|
|
146
143
|
*/
|
|
147
144
|
function hexTriangles(center, rx, ry, properties, cosines, sines) {
|
|
148
|
-
|
|
149
|
-
for (
|
|
150
|
-
|
|
145
|
+
const triangles = [];
|
|
146
|
+
for (let i = 0; i < 6; i++) {
|
|
147
|
+
const vertices = [];
|
|
151
148
|
vertices.push(center);
|
|
152
149
|
vertices.push([center[0] + rx * cosines[i], center[1] + ry * sines[i]]);
|
|
153
150
|
vertices.push([
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@turf/hex-grid",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.0.0-alpha.1",
|
|
4
4
|
"description": "turf hex-grid module",
|
|
5
5
|
"author": "Turf Authors",
|
|
6
6
|
"contributors": [
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
"exports": {
|
|
38
38
|
"./package.json": "./package.json",
|
|
39
39
|
".": {
|
|
40
|
+
"types": "./dist/js/index.d.ts",
|
|
40
41
|
"import": "./dist/es/index.js",
|
|
41
42
|
"require": "./dist/js/index.js"
|
|
42
43
|
}
|
|
@@ -47,33 +48,34 @@
|
|
|
47
48
|
"dist"
|
|
48
49
|
],
|
|
49
50
|
"scripts": {
|
|
50
|
-
"bench": "
|
|
51
|
+
"bench": "tsx bench.js",
|
|
51
52
|
"build": "npm-run-all build:*",
|
|
52
53
|
"build:es": "tsc --outDir dist/es --module esnext --declaration false && echo '{\"type\":\"module\"}' > dist/es/package.json",
|
|
53
54
|
"build:js": "tsc",
|
|
54
|
-
"docs": "
|
|
55
|
+
"docs": "tsx ../../scripts/generate-readmes",
|
|
55
56
|
"test": "npm-run-all test:*",
|
|
56
|
-
"test:tape": "
|
|
57
|
-
"test:types": "tsc --esModuleInterop --noEmit types.ts"
|
|
57
|
+
"test:tape": "tsx test.js",
|
|
58
|
+
"test:types": "tsc --esModuleInterop --noEmit --strict types.ts"
|
|
58
59
|
},
|
|
59
60
|
"devDependencies": {
|
|
60
|
-
"@turf/bbox-polygon": "^
|
|
61
|
-
"@turf/truncate": "^
|
|
61
|
+
"@turf/bbox-polygon": "^7.0.0-alpha.1",
|
|
62
|
+
"@turf/truncate": "^7.0.0-alpha.1",
|
|
62
63
|
"@types/tape": "*",
|
|
63
64
|
"benchmark": "*",
|
|
64
65
|
"load-json-file": "*",
|
|
65
66
|
"npm-run-all": "*",
|
|
66
67
|
"tape": "*",
|
|
67
|
-
"ts-node": "*",
|
|
68
68
|
"tslint": "*",
|
|
69
|
+
"tsx": "*",
|
|
69
70
|
"typescript": "*",
|
|
70
71
|
"write-json-file": "*"
|
|
71
72
|
},
|
|
72
73
|
"dependencies": {
|
|
73
|
-
"@turf/distance": "^
|
|
74
|
-
"@turf/helpers": "^
|
|
75
|
-
"@turf/intersect": "^
|
|
76
|
-
"@turf/invariant": "^
|
|
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"
|
|
77
79
|
},
|
|
78
|
-
"gitHead": "
|
|
80
|
+
"gitHead": "cf7a0c507b017ca066acffd0ce23bda5b393fb5a"
|
|
79
81
|
}
|