@turf/standard-deviational-ellipse 7.0.0-alpha.0 → 7.0.0-alpha.110

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
@@ -69,26 +69,21 @@ Returns **[Feature][11]<[Polygon][12]>** an elliptical Polygon that includes app
69
69
 
70
70
  [12]: https://tools.ietf.org/html/rfc7946#section-3.1.6
71
71
 
72
- <!-- This file is automatically generated. Please don't edit it directly:
73
- if you find an error, edit the source file (likely index.js), and re-run
74
- ./scripts/generate-readmes in the turf project. -->
72
+ <!-- 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. -->
75
73
 
76
74
  ---
77
75
 
78
- This module is part of the [Turfjs project](http://turfjs.org/), an open source
79
- module collection dedicated to geographic algorithms. It is maintained in the
80
- [Turfjs/turf](https://github.com/Turfjs/turf) repository, where you can create
81
- PRs and issues.
76
+ 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.
82
77
 
83
78
  ### Installation
84
79
 
85
- Install this module individually:
80
+ Install this single module individually:
86
81
 
87
82
  ```sh
88
83
  $ npm install @turf/standard-deviational-ellipse
89
84
  ```
90
85
 
91
- Or install the Turf module that includes it as a function:
86
+ Or install the all-encompassing @turf/turf module that includes all modules as functions:
92
87
 
93
88
  ```sh
94
89
  $ npm install @turf/turf
@@ -0,0 +1,91 @@
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.js
5
+ var _meta = require('@turf/meta');
6
+ var _invariant = require('@turf/invariant');
7
+ var _helpers = require('@turf/helpers');
8
+ var _centermean = require('@turf/center-mean');
9
+ var _pointswithinpolygon = require('@turf/points-within-polygon');
10
+ var _ellipse = require('@turf/ellipse');
11
+ function standardDeviationalEllipse(points, options) {
12
+ options = options || {};
13
+ if (!_helpers.isObject.call(void 0, options))
14
+ throw new Error("options is invalid");
15
+ var steps = options.steps || 64;
16
+ var weightTerm = options.weight;
17
+ var properties = options.properties || {};
18
+ if (!_helpers.isNumber.call(void 0, steps))
19
+ throw new Error("steps must be a number");
20
+ if (!_helpers.isObject.call(void 0, properties))
21
+ throw new Error("properties must be a number");
22
+ var numberOfFeatures = _meta.coordAll.call(void 0, points).length;
23
+ var meanCenter = _centermean.centerMean.call(void 0, points, { weight: weightTerm });
24
+ var xDeviationSquaredSum = 0;
25
+ var yDeviationSquaredSum = 0;
26
+ var xyDeviationSum = 0;
27
+ _meta.featureEach.call(void 0, points, function(point) {
28
+ var weight = point.properties[weightTerm] || 1;
29
+ var deviation = getDeviations(_invariant.getCoords.call(void 0, point), _invariant.getCoords.call(void 0, meanCenter));
30
+ xDeviationSquaredSum += Math.pow(deviation.x, 2) * weight;
31
+ yDeviationSquaredSum += Math.pow(deviation.y, 2) * weight;
32
+ xyDeviationSum += deviation.x * deviation.y * weight;
33
+ });
34
+ var bigA = xDeviationSquaredSum - yDeviationSquaredSum;
35
+ var bigB = Math.sqrt(Math.pow(bigA, 2) + 4 * Math.pow(xyDeviationSum, 2));
36
+ var bigC = 2 * xyDeviationSum;
37
+ var theta = Math.atan((bigA + bigB) / bigC);
38
+ var thetaDeg = theta * 180 / Math.PI;
39
+ var sigmaXsum = 0;
40
+ var sigmaYsum = 0;
41
+ var weightsum = 0;
42
+ _meta.featureEach.call(void 0, points, function(point) {
43
+ var weight = point.properties[weightTerm] || 1;
44
+ var deviation = getDeviations(_invariant.getCoords.call(void 0, point), _invariant.getCoords.call(void 0, meanCenter));
45
+ sigmaXsum += Math.pow(
46
+ deviation.x * Math.cos(theta) - deviation.y * Math.sin(theta),
47
+ 2
48
+ ) * weight;
49
+ sigmaYsum += Math.pow(
50
+ deviation.x * Math.sin(theta) + deviation.y * Math.cos(theta),
51
+ 2
52
+ ) * weight;
53
+ weightsum += weight;
54
+ });
55
+ var sigmaX = Math.sqrt(2 * sigmaXsum / weightsum);
56
+ var sigmaY = Math.sqrt(2 * sigmaYsum / weightsum);
57
+ var theEllipse = _ellipse.ellipse.call(void 0, meanCenter, sigmaX, sigmaY, {
58
+ units: "degrees",
59
+ angle: thetaDeg,
60
+ steps,
61
+ properties
62
+ });
63
+ var pointsWithinEllipse = _pointswithinpolygon.pointsWithinPolygon.call(void 0,
64
+ points,
65
+ _helpers.featureCollection.call(void 0, [theEllipse])
66
+ );
67
+ var standardDeviationalEllipseProperties = {
68
+ meanCenterCoordinates: _invariant.getCoords.call(void 0, meanCenter),
69
+ semiMajorAxis: sigmaX,
70
+ semiMinorAxis: sigmaY,
71
+ numberOfFeatures,
72
+ angle: thetaDeg,
73
+ percentageWithinEllipse: 100 * _meta.coordAll.call(void 0, pointsWithinEllipse).length / numberOfFeatures
74
+ };
75
+ theEllipse.properties.standardDeviationalEllipse = standardDeviationalEllipseProperties;
76
+ return theEllipse;
77
+ }
78
+ __name(standardDeviationalEllipse, "standardDeviationalEllipse");
79
+ function getDeviations(coordinates, center) {
80
+ return {
81
+ x: coordinates[0] - center[0],
82
+ y: coordinates[1] - center[1]
83
+ };
84
+ }
85
+ __name(getDeviations, "getDeviations");
86
+ var turf_standard_deviational_ellipse_default = standardDeviationalEllipse;
87
+
88
+
89
+
90
+ exports.default = turf_standard_deviational_ellipse_default; exports.standardDeviationalEllipse = standardDeviationalEllipse;
91
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../index.js"],"names":[],"mappings":";;;;AAAA,SAAS,UAAU,mBAAmB;AACtC,SAAS,iBAAiB;AAC1B,SAAS,mBAAmB,UAAU,gBAAgB;AACtD,SAAS,kBAAkB;AAC3B,SAAS,2BAA2B;AACpC,SAAS,eAAe;AAwCxB,SAAS,2BAA2B,QAAQ,SAAS;AAEnD,YAAU,WAAW,CAAC;AACtB,MAAI,CAAC,SAAS,OAAO;AAAG,UAAM,IAAI,MAAM,oBAAoB;AAC5D,MAAI,QAAQ,QAAQ,SAAS;AAC7B,MAAI,aAAa,QAAQ;AACzB,MAAI,aAAa,QAAQ,cAAc,CAAC;AAGxC,MAAI,CAAC,SAAS,KAAK;AAAG,UAAM,IAAI,MAAM,wBAAwB;AAC9D,MAAI,CAAC,SAAS,UAAU;AAAG,UAAM,IAAI,MAAM,6BAA6B;AAGxE,MAAI,mBAAmB,SAAS,MAAM,EAAE;AACxC,MAAI,aAAa,WAAW,QAAQ,EAAE,QAAQ,WAAW,CAAC;AAS1D,MAAI,uBAAuB;AAC3B,MAAI,uBAAuB;AAC3B,MAAI,iBAAiB;AAErB,cAAY,QAAQ,SAAU,OAAO;AACnC,QAAI,SAAS,MAAM,WAAW,UAAU,KAAK;AAC7C,QAAI,YAAY,cAAc,UAAU,KAAK,GAAG,UAAU,UAAU,CAAC;AACrE,4BAAwB,KAAK,IAAI,UAAU,GAAG,CAAC,IAAI;AACnD,4BAAwB,KAAK,IAAI,UAAU,GAAG,CAAC,IAAI;AACnD,sBAAkB,UAAU,IAAI,UAAU,IAAI;AAAA,EAChD,CAAC;AAED,MAAI,OAAO,uBAAuB;AAClC,MAAI,OAAO,KAAK,KAAK,KAAK,IAAI,MAAM,CAAC,IAAI,IAAI,KAAK,IAAI,gBAAgB,CAAC,CAAC;AACxE,MAAI,OAAO,IAAI;AACf,MAAI,QAAQ,KAAK,MAAM,OAAO,QAAQ,IAAI;AAC1C,MAAI,WAAY,QAAQ,MAAO,KAAK;AAKpC,MAAI,YAAY;AAChB,MAAI,YAAY;AAChB,MAAI,YAAY;AAChB,cAAY,QAAQ,SAAU,OAAO;AACnC,QAAI,SAAS,MAAM,WAAW,UAAU,KAAK;AAC7C,QAAI,YAAY,cAAc,UAAU,KAAK,GAAG,UAAU,UAAU,CAAC;AACrE,iBACE,KAAK;AAAA,MACH,UAAU,IAAI,KAAK,IAAI,KAAK,IAAI,UAAU,IAAI,KAAK,IAAI,KAAK;AAAA,MAC5D;AAAA,IACF,IAAI;AACN,iBACE,KAAK;AAAA,MACH,UAAU,IAAI,KAAK,IAAI,KAAK,IAAI,UAAU,IAAI,KAAK,IAAI,KAAK;AAAA,MAC5D;AAAA,IACF,IAAI;AACN,iBAAa;AAAA,EACf,CAAC;AAED,MAAI,SAAS,KAAK,KAAM,IAAI,YAAa,SAAS;AAClD,MAAI,SAAS,KAAK,KAAM,IAAI,YAAa,SAAS;AAElD,MAAI,aAAa,QAAQ,YAAY,QAAQ,QAAQ;AAAA,IACnD,OAAO;AAAA,IACP,OAAO;AAAA,IACP;AAAA,IACA;AAAA,EACF,CAAC;AACD,MAAI,sBAAsB;AAAA,IACxB;AAAA,IACA,kBAAkB,CAAC,UAAU,CAAC;AAAA,EAChC;AACA,MAAI,uCAAuC;AAAA,IACzC,uBAAuB,UAAU,UAAU;AAAA,IAC3C,eAAe;AAAA,IACf,eAAe;AAAA,IACf;AAAA,IACA,OAAO;AAAA,IACP,yBACG,MAAM,SAAS,mBAAmB,EAAE,SAAU;AAAA,EACnD;AACA,aAAW,WAAW,6BACpB;AAEF,SAAO;AACT;AAzFS;AAmGT,SAAS,cAAc,aAAa,QAAQ;AAC1C,SAAO;AAAA,IACL,GAAG,YAAY,CAAC,IAAI,OAAO,CAAC;AAAA,IAC5B,GAAG,YAAY,CAAC,IAAI,OAAO,CAAC;AAAA,EAC9B;AACF;AALS;AAQT,IAAO,4CAAQ","sourcesContent":["import { coordAll, featureEach } from \"@turf/meta\";\nimport { getCoords } from \"@turf/invariant\";\nimport { featureCollection, isObject, isNumber } from \"@turf/helpers\";\nimport { centerMean } from \"@turf/center-mean\";\nimport { pointsWithinPolygon } from \"@turf/points-within-polygon\";\nimport { ellipse } from \"@turf/ellipse\";\n\n/**\n * Takes a {@link FeatureCollection} and returns a standard deviational ellipse,\n * also known as a “directional distribution.” The standard deviational ellipse\n * aims to show the direction and the distribution of a dataset by drawing\n * an ellipse that contains about one standard deviation’s worth (~ 70%) of the\n * data.\n *\n * This module mirrors the functionality of [Directional Distribution](http://desktop.arcgis.com/en/arcmap/10.3/tools/spatial-statistics-toolbox/directional-distribution.htm)\n * in ArcGIS and the [QGIS Standard Deviational Ellipse Plugin](http://arken.nmbu.no/~havatv/gis/qgisplugins/SDEllipse/)\n *\n * **Bibliography**\n *\n * • Robert S. Yuill, “The Standard Deviational Ellipse; An Updated Tool for\n * Spatial Description,” _Geografiska Annaler_ 53, no. 1 (1971): 28–39,\n * doi:{@link https://doi.org/10.2307/490885|10.2307/490885}.\n *\n * • Paul Hanly Furfey, “A Note on Lefever’s “Standard Deviational Ellipse,”\n * _American Journal of Sociology_ 33, no. 1 (1927): 94—98,\n * doi:{@link https://doi.org/10.1086/214336|10.1086/214336}.\n *\n *\n * @name standardDeviationalEllipse\n * @param {FeatureCollection<Point>} points GeoJSON points\n * @param {Object} [options={}] Optional parameters\n * @param {string} [options.weight] the property name used to weight the center\n * @param {number} [options.steps=64] number of steps for the polygon\n * @param {Object} [options.properties={}] properties to pass to the resulting ellipse\n * @returns {Feature<Polygon>} an elliptical Polygon that includes approximately 1 SD of the dataset within it.\n * @example\n *\n * var bbox = [-74, 40.72, -73.98, 40.74];\n * var points = turf.randomPoint(400, {bbox: bbox});\n * var sdEllipse = turf.standardDeviationalEllipse(points);\n *\n * //addToMap\n * var addToMap = [points, sdEllipse];\n *\n */\nfunction standardDeviationalEllipse(points, options) {\n // Optional params\n options = options || {};\n if (!isObject(options)) throw new Error(\"options is invalid\");\n var steps = options.steps || 64;\n var weightTerm = options.weight;\n var properties = options.properties || {};\n\n // Validation:\n if (!isNumber(steps)) throw new Error(\"steps must be a number\");\n if (!isObject(properties)) throw new Error(\"properties must be a number\");\n\n // Calculate mean center & number of features:\n var numberOfFeatures = coordAll(points).length;\n var meanCenter = centerMean(points, { weight: weightTerm });\n\n // Calculate angle of rotation:\n // [X, Y] = mean center of all [x, y].\n // theta = arctan( (A + B) / C )\n // A = sum((x - X)^2) - sum((y - Y)^2)\n // B = sqrt(A^2 + 4(sum((x - X)(y - Y))^2))\n // C = 2(sum((x - X)(y - Y)))\n\n var xDeviationSquaredSum = 0;\n var yDeviationSquaredSum = 0;\n var xyDeviationSum = 0;\n\n featureEach(points, function (point) {\n var weight = point.properties[weightTerm] || 1;\n var deviation = getDeviations(getCoords(point), getCoords(meanCenter));\n xDeviationSquaredSum += Math.pow(deviation.x, 2) * weight;\n yDeviationSquaredSum += Math.pow(deviation.y, 2) * weight;\n xyDeviationSum += deviation.x * deviation.y * weight;\n });\n\n var bigA = xDeviationSquaredSum - yDeviationSquaredSum;\n var bigB = Math.sqrt(Math.pow(bigA, 2) + 4 * Math.pow(xyDeviationSum, 2));\n var bigC = 2 * xyDeviationSum;\n var theta = Math.atan((bigA + bigB) / bigC);\n var thetaDeg = (theta * 180) / Math.PI;\n\n // Calculate axes:\n // sigmaX = sqrt((1 / n - 2) * sum((((x - X) * cos(theta)) - ((y - Y) * sin(theta)))^2))\n // sigmaY = sqrt((1 / n - 2) * sum((((x - X) * sin(theta)) - ((y - Y) * cos(theta)))^2))\n var sigmaXsum = 0;\n var sigmaYsum = 0;\n var weightsum = 0;\n featureEach(points, function (point) {\n var weight = point.properties[weightTerm] || 1;\n var deviation = getDeviations(getCoords(point), getCoords(meanCenter));\n sigmaXsum +=\n Math.pow(\n deviation.x * Math.cos(theta) - deviation.y * Math.sin(theta),\n 2\n ) * weight;\n sigmaYsum +=\n Math.pow(\n deviation.x * Math.sin(theta) + deviation.y * Math.cos(theta),\n 2\n ) * weight;\n weightsum += weight;\n });\n\n var sigmaX = Math.sqrt((2 * sigmaXsum) / weightsum);\n var sigmaY = Math.sqrt((2 * sigmaYsum) / weightsum);\n\n var theEllipse = ellipse(meanCenter, sigmaX, sigmaY, {\n units: \"degrees\",\n angle: thetaDeg,\n steps: steps,\n properties: properties,\n });\n var pointsWithinEllipse = pointsWithinPolygon(\n points,\n featureCollection([theEllipse])\n );\n var standardDeviationalEllipseProperties = {\n meanCenterCoordinates: getCoords(meanCenter),\n semiMajorAxis: sigmaX,\n semiMinorAxis: sigmaY,\n numberOfFeatures: numberOfFeatures,\n angle: thetaDeg,\n percentageWithinEllipse:\n (100 * coordAll(pointsWithinEllipse).length) / numberOfFeatures,\n };\n theEllipse.properties.standardDeviationalEllipse =\n standardDeviationalEllipseProperties;\n\n return theEllipse;\n}\n\n/**\n * Get x_i - X and y_i - Y\n *\n * @private\n * @param {Array} coordinates Array of [x_i, y_i]\n * @param {Array} center Array of [X, Y]\n * @returns {Object} { x: n, y: m }\n */\nfunction getDeviations(coordinates, center) {\n return {\n x: coordinates[0] - center[0],\n y: coordinates[1] - center[1],\n };\n}\n\nexport { standardDeviationalEllipse };\nexport default standardDeviationalEllipse;\n"]}
@@ -0,0 +1,32 @@
1
+ import { Position, Feature, Polygon, FeatureCollection, Point, GeoJsonProperties } from 'geojson';
2
+
3
+ /**
4
+ * http://turfjs.org/docs/#standarddeviational-ellipse
5
+ */
6
+
7
+ declare interface SDEProps {
8
+ meanCenterCoordinates: Position;
9
+ semiMajorAxis: number;
10
+ semiMinorAxis: number;
11
+ numberOfFeatures: number;
12
+ angle: number;
13
+ percentageWithinEllipse: number;
14
+ }
15
+
16
+ declare interface StandardDeviationalEllipse extends Feature<Polygon> {
17
+ properties: {
18
+ standardDeviationalEllipse: SDEProps;
19
+ [key: string]: any;
20
+ };
21
+ }
22
+
23
+ declare function standardDeviationalEllipse(
24
+ points: FeatureCollection<Point>,
25
+ options?: {
26
+ properties?: GeoJsonProperties;
27
+ weight?: string;
28
+ steps?: number;
29
+ }
30
+ ): StandardDeviationalEllipse;
31
+
32
+ export { type SDEProps, type StandardDeviationalEllipse, standardDeviationalEllipse as default, standardDeviationalEllipse };
@@ -0,0 +1,32 @@
1
+ import { Position, Feature, Polygon, FeatureCollection, Point, GeoJsonProperties } from 'geojson';
2
+
3
+ /**
4
+ * http://turfjs.org/docs/#standarddeviational-ellipse
5
+ */
6
+
7
+ declare interface SDEProps {
8
+ meanCenterCoordinates: Position;
9
+ semiMajorAxis: number;
10
+ semiMinorAxis: number;
11
+ numberOfFeatures: number;
12
+ angle: number;
13
+ percentageWithinEllipse: number;
14
+ }
15
+
16
+ declare interface StandardDeviationalEllipse extends Feature<Polygon> {
17
+ properties: {
18
+ standardDeviationalEllipse: SDEProps;
19
+ [key: string]: any;
20
+ };
21
+ }
22
+
23
+ declare function standardDeviationalEllipse(
24
+ points: FeatureCollection<Point>,
25
+ options?: {
26
+ properties?: GeoJsonProperties;
27
+ weight?: string;
28
+ steps?: number;
29
+ }
30
+ ): StandardDeviationalEllipse;
31
+
32
+ export { type SDEProps, type StandardDeviationalEllipse, standardDeviationalEllipse as default, standardDeviationalEllipse };
@@ -0,0 +1,91 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
+
4
+ // index.js
5
+ import { coordAll, featureEach } from "@turf/meta";
6
+ import { getCoords } from "@turf/invariant";
7
+ import { featureCollection, isObject, isNumber } from "@turf/helpers";
8
+ import { centerMean } from "@turf/center-mean";
9
+ import { pointsWithinPolygon } from "@turf/points-within-polygon";
10
+ import { ellipse } from "@turf/ellipse";
11
+ function standardDeviationalEllipse(points, options) {
12
+ options = options || {};
13
+ if (!isObject(options))
14
+ throw new Error("options is invalid");
15
+ var steps = options.steps || 64;
16
+ var weightTerm = options.weight;
17
+ var properties = options.properties || {};
18
+ if (!isNumber(steps))
19
+ throw new Error("steps must be a number");
20
+ if (!isObject(properties))
21
+ throw new Error("properties must be a number");
22
+ var numberOfFeatures = coordAll(points).length;
23
+ var meanCenter = centerMean(points, { weight: weightTerm });
24
+ var xDeviationSquaredSum = 0;
25
+ var yDeviationSquaredSum = 0;
26
+ var xyDeviationSum = 0;
27
+ featureEach(points, function(point) {
28
+ var weight = point.properties[weightTerm] || 1;
29
+ var deviation = getDeviations(getCoords(point), getCoords(meanCenter));
30
+ xDeviationSquaredSum += Math.pow(deviation.x, 2) * weight;
31
+ yDeviationSquaredSum += Math.pow(deviation.y, 2) * weight;
32
+ xyDeviationSum += deviation.x * deviation.y * weight;
33
+ });
34
+ var bigA = xDeviationSquaredSum - yDeviationSquaredSum;
35
+ var bigB = Math.sqrt(Math.pow(bigA, 2) + 4 * Math.pow(xyDeviationSum, 2));
36
+ var bigC = 2 * xyDeviationSum;
37
+ var theta = Math.atan((bigA + bigB) / bigC);
38
+ var thetaDeg = theta * 180 / Math.PI;
39
+ var sigmaXsum = 0;
40
+ var sigmaYsum = 0;
41
+ var weightsum = 0;
42
+ featureEach(points, function(point) {
43
+ var weight = point.properties[weightTerm] || 1;
44
+ var deviation = getDeviations(getCoords(point), getCoords(meanCenter));
45
+ sigmaXsum += Math.pow(
46
+ deviation.x * Math.cos(theta) - deviation.y * Math.sin(theta),
47
+ 2
48
+ ) * weight;
49
+ sigmaYsum += Math.pow(
50
+ deviation.x * Math.sin(theta) + deviation.y * Math.cos(theta),
51
+ 2
52
+ ) * weight;
53
+ weightsum += weight;
54
+ });
55
+ var sigmaX = Math.sqrt(2 * sigmaXsum / weightsum);
56
+ var sigmaY = Math.sqrt(2 * sigmaYsum / weightsum);
57
+ var theEllipse = ellipse(meanCenter, sigmaX, sigmaY, {
58
+ units: "degrees",
59
+ angle: thetaDeg,
60
+ steps,
61
+ properties
62
+ });
63
+ var pointsWithinEllipse = pointsWithinPolygon(
64
+ points,
65
+ featureCollection([theEllipse])
66
+ );
67
+ var standardDeviationalEllipseProperties = {
68
+ meanCenterCoordinates: getCoords(meanCenter),
69
+ semiMajorAxis: sigmaX,
70
+ semiMinorAxis: sigmaY,
71
+ numberOfFeatures,
72
+ angle: thetaDeg,
73
+ percentageWithinEllipse: 100 * coordAll(pointsWithinEllipse).length / numberOfFeatures
74
+ };
75
+ theEllipse.properties.standardDeviationalEllipse = standardDeviationalEllipseProperties;
76
+ return theEllipse;
77
+ }
78
+ __name(standardDeviationalEllipse, "standardDeviationalEllipse");
79
+ function getDeviations(coordinates, center) {
80
+ return {
81
+ x: coordinates[0] - center[0],
82
+ y: coordinates[1] - center[1]
83
+ };
84
+ }
85
+ __name(getDeviations, "getDeviations");
86
+ var turf_standard_deviational_ellipse_default = standardDeviationalEllipse;
87
+ export {
88
+ turf_standard_deviational_ellipse_default as default,
89
+ standardDeviationalEllipse
90
+ };
91
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../index.js"],"sourcesContent":["import { coordAll, featureEach } from \"@turf/meta\";\nimport { getCoords } from \"@turf/invariant\";\nimport { featureCollection, isObject, isNumber } from \"@turf/helpers\";\nimport { centerMean } from \"@turf/center-mean\";\nimport { pointsWithinPolygon } from \"@turf/points-within-polygon\";\nimport { ellipse } from \"@turf/ellipse\";\n\n/**\n * Takes a {@link FeatureCollection} and returns a standard deviational ellipse,\n * also known as a “directional distribution.” The standard deviational ellipse\n * aims to show the direction and the distribution of a dataset by drawing\n * an ellipse that contains about one standard deviation’s worth (~ 70%) of the\n * data.\n *\n * This module mirrors the functionality of [Directional Distribution](http://desktop.arcgis.com/en/arcmap/10.3/tools/spatial-statistics-toolbox/directional-distribution.htm)\n * in ArcGIS and the [QGIS Standard Deviational Ellipse Plugin](http://arken.nmbu.no/~havatv/gis/qgisplugins/SDEllipse/)\n *\n * **Bibliography**\n *\n * • Robert S. Yuill, “The Standard Deviational Ellipse; An Updated Tool for\n * Spatial Description,” _Geografiska Annaler_ 53, no. 1 (1971): 28–39,\n * doi:{@link https://doi.org/10.2307/490885|10.2307/490885}.\n *\n * • Paul Hanly Furfey, “A Note on Lefever’s “Standard Deviational Ellipse,”\n * _American Journal of Sociology_ 33, no. 1 (1927): 94—98,\n * doi:{@link https://doi.org/10.1086/214336|10.1086/214336}.\n *\n *\n * @name standardDeviationalEllipse\n * @param {FeatureCollection<Point>} points GeoJSON points\n * @param {Object} [options={}] Optional parameters\n * @param {string} [options.weight] the property name used to weight the center\n * @param {number} [options.steps=64] number of steps for the polygon\n * @param {Object} [options.properties={}] properties to pass to the resulting ellipse\n * @returns {Feature<Polygon>} an elliptical Polygon that includes approximately 1 SD of the dataset within it.\n * @example\n *\n * var bbox = [-74, 40.72, -73.98, 40.74];\n * var points = turf.randomPoint(400, {bbox: bbox});\n * var sdEllipse = turf.standardDeviationalEllipse(points);\n *\n * //addToMap\n * var addToMap = [points, sdEllipse];\n *\n */\nfunction standardDeviationalEllipse(points, options) {\n // Optional params\n options = options || {};\n if (!isObject(options)) throw new Error(\"options is invalid\");\n var steps = options.steps || 64;\n var weightTerm = options.weight;\n var properties = options.properties || {};\n\n // Validation:\n if (!isNumber(steps)) throw new Error(\"steps must be a number\");\n if (!isObject(properties)) throw new Error(\"properties must be a number\");\n\n // Calculate mean center & number of features:\n var numberOfFeatures = coordAll(points).length;\n var meanCenter = centerMean(points, { weight: weightTerm });\n\n // Calculate angle of rotation:\n // [X, Y] = mean center of all [x, y].\n // theta = arctan( (A + B) / C )\n // A = sum((x - X)^2) - sum((y - Y)^2)\n // B = sqrt(A^2 + 4(sum((x - X)(y - Y))^2))\n // C = 2(sum((x - X)(y - Y)))\n\n var xDeviationSquaredSum = 0;\n var yDeviationSquaredSum = 0;\n var xyDeviationSum = 0;\n\n featureEach(points, function (point) {\n var weight = point.properties[weightTerm] || 1;\n var deviation = getDeviations(getCoords(point), getCoords(meanCenter));\n xDeviationSquaredSum += Math.pow(deviation.x, 2) * weight;\n yDeviationSquaredSum += Math.pow(deviation.y, 2) * weight;\n xyDeviationSum += deviation.x * deviation.y * weight;\n });\n\n var bigA = xDeviationSquaredSum - yDeviationSquaredSum;\n var bigB = Math.sqrt(Math.pow(bigA, 2) + 4 * Math.pow(xyDeviationSum, 2));\n var bigC = 2 * xyDeviationSum;\n var theta = Math.atan((bigA + bigB) / bigC);\n var thetaDeg = (theta * 180) / Math.PI;\n\n // Calculate axes:\n // sigmaX = sqrt((1 / n - 2) * sum((((x - X) * cos(theta)) - ((y - Y) * sin(theta)))^2))\n // sigmaY = sqrt((1 / n - 2) * sum((((x - X) * sin(theta)) - ((y - Y) * cos(theta)))^2))\n var sigmaXsum = 0;\n var sigmaYsum = 0;\n var weightsum = 0;\n featureEach(points, function (point) {\n var weight = point.properties[weightTerm] || 1;\n var deviation = getDeviations(getCoords(point), getCoords(meanCenter));\n sigmaXsum +=\n Math.pow(\n deviation.x * Math.cos(theta) - deviation.y * Math.sin(theta),\n 2\n ) * weight;\n sigmaYsum +=\n Math.pow(\n deviation.x * Math.sin(theta) + deviation.y * Math.cos(theta),\n 2\n ) * weight;\n weightsum += weight;\n });\n\n var sigmaX = Math.sqrt((2 * sigmaXsum) / weightsum);\n var sigmaY = Math.sqrt((2 * sigmaYsum) / weightsum);\n\n var theEllipse = ellipse(meanCenter, sigmaX, sigmaY, {\n units: \"degrees\",\n angle: thetaDeg,\n steps: steps,\n properties: properties,\n });\n var pointsWithinEllipse = pointsWithinPolygon(\n points,\n featureCollection([theEllipse])\n );\n var standardDeviationalEllipseProperties = {\n meanCenterCoordinates: getCoords(meanCenter),\n semiMajorAxis: sigmaX,\n semiMinorAxis: sigmaY,\n numberOfFeatures: numberOfFeatures,\n angle: thetaDeg,\n percentageWithinEllipse:\n (100 * coordAll(pointsWithinEllipse).length) / numberOfFeatures,\n };\n theEllipse.properties.standardDeviationalEllipse =\n standardDeviationalEllipseProperties;\n\n return theEllipse;\n}\n\n/**\n * Get x_i - X and y_i - Y\n *\n * @private\n * @param {Array} coordinates Array of [x_i, y_i]\n * @param {Array} center Array of [X, Y]\n * @returns {Object} { x: n, y: m }\n */\nfunction getDeviations(coordinates, center) {\n return {\n x: coordinates[0] - center[0],\n y: coordinates[1] - center[1],\n };\n}\n\nexport { standardDeviationalEllipse };\nexport default standardDeviationalEllipse;\n"],"mappings":"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","names":[]}
package/index.d.ts CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  * http://turfjs.org/docs/#standarddeviational-ellipse
12
12
  */
13
13
 
14
- export interface SDEProps {
14
+ declare interface SDEProps {
15
15
  meanCenterCoordinates: Position;
16
16
  semiMajorAxis: number;
17
17
  semiMinorAxis: number;
@@ -20,14 +20,14 @@ export interface SDEProps {
20
20
  percentageWithinEllipse: number;
21
21
  }
22
22
 
23
- export interface StandardDeviationalEllipse extends Feature<Polygon> {
23
+ declare interface StandardDeviationalEllipse extends Feature<Polygon> {
24
24
  properties: {
25
25
  standardDeviationalEllipse: SDEProps;
26
26
  [key: string]: any;
27
27
  };
28
28
  }
29
29
 
30
- export default function (
30
+ declare function standardDeviationalEllipse(
31
31
  points: FeatureCollection<Point>,
32
32
  options?: {
33
33
  properties?: GeoJsonProperties;
@@ -35,3 +35,6 @@ export default function (
35
35
  steps?: number;
36
36
  }
37
37
  ): StandardDeviationalEllipse;
38
+
39
+ export { SDEProps, StandardDeviationalEllipse, standardDeviationalEllipse };
40
+ export default standardDeviationalEllipse;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@turf/standard-deviational-ellipse",
3
- "version": "7.0.0-alpha.0",
3
+ "version": "7.0.0-alpha.110+1411d63a7",
4
4
  "description": "turf standard-deviational-ellipse module",
5
5
  "author": "Turf Authors",
6
6
  "contributors": [
@@ -25,46 +25,54 @@
25
25
  "geostatistics",
26
26
  "directional distribution"
27
27
  ],
28
- "main": "dist/js/index.js",
29
- "module": "dist/es/index.js",
28
+ "type": "commonjs",
29
+ "main": "dist/cjs/index.cjs",
30
+ "module": "dist/esm/index.mjs",
31
+ "types": "dist/cjs/index.d.ts",
30
32
  "exports": {
31
33
  "./package.json": "./package.json",
32
34
  ".": {
33
- "import": "./dist/es/index.js",
34
- "require": "./dist/js/index.js"
35
+ "import": {
36
+ "types": "./dist/esm/index.d.mts",
37
+ "default": "./dist/esm/index.mjs"
38
+ },
39
+ "require": {
40
+ "types": "./dist/cjs/index.d.ts",
41
+ "default": "./dist/cjs/index.cjs"
42
+ }
35
43
  }
36
44
  },
37
- "types": "index.d.ts",
38
45
  "sideEffects": false,
39
46
  "files": [
40
47
  "dist",
41
48
  "index.d.ts"
42
49
  ],
43
50
  "scripts": {
44
- "bench": "node -r esm bench.js",
45
- "build": "rollup -c ../../rollup.config.js && echo '{\"type\":\"module\"}' > dist/es/package.json",
46
- "docs": "node ../../scripts/generate-readmes",
47
- "test": "npm-run-all test:*",
48
- "test:tape": "node -r esm test.js",
51
+ "bench": "tsx bench.ts",
52
+ "build": "tsup --config ../../tsup.config.ts",
53
+ "docs": "tsx ../../scripts/generate-readmes.ts",
54
+ "test": "npm-run-all --npm-path npm test:*",
55
+ "test:tape": "tsx test.ts",
49
56
  "test:types": "tsc --esModuleInterop --noEmit --strict types.ts"
50
57
  },
51
58
  "devDependencies": {
52
- "@turf/random": "^7.0.0-alpha.0",
53
- "@turf/truncate": "^7.0.0-alpha.0",
54
- "benchmark": "*",
55
- "load-json-file": "*",
56
- "npm-run-all": "*",
57
- "rollup": "*",
58
- "tape": "*",
59
- "write-json-file": "*"
59
+ "@turf/random": "^7.0.0-alpha.110+1411d63a7",
60
+ "@turf/truncate": "^7.0.0-alpha.110+1411d63a7",
61
+ "benchmark": "^2.1.4",
62
+ "load-json-file": "^7.0.1",
63
+ "npm-run-all": "^4.1.5",
64
+ "tape": "^5.7.2",
65
+ "tsup": "^8.0.1",
66
+ "tsx": "^4.6.2",
67
+ "write-json-file": "^5.0.0"
60
68
  },
61
69
  "dependencies": {
62
- "@turf/center-mean": "^7.0.0-alpha.0",
63
- "@turf/ellipse": "^7.0.0-alpha.0",
64
- "@turf/helpers": "^7.0.0-alpha.0",
65
- "@turf/invariant": "^7.0.0-alpha.0",
66
- "@turf/meta": "^7.0.0-alpha.0",
67
- "@turf/points-within-polygon": "^7.0.0-alpha.0"
70
+ "@turf/center-mean": "^7.0.0-alpha.110+1411d63a7",
71
+ "@turf/ellipse": "^7.0.0-alpha.110+1411d63a7",
72
+ "@turf/helpers": "^7.0.0-alpha.110+1411d63a7",
73
+ "@turf/invariant": "^7.0.0-alpha.110+1411d63a7",
74
+ "@turf/meta": "^7.0.0-alpha.110+1411d63a7",
75
+ "@turf/points-within-polygon": "^7.0.0-alpha.110+1411d63a7"
68
76
  },
69
- "gitHead": "0edc4c491b999e5ace770a61e1cf549f7c004189"
77
+ "gitHead": "1411d63a74c275c9216fe48e9d3cb2d48a359068"
70
78
  }
package/dist/es/index.js DELETED
@@ -1,151 +0,0 @@
1
- import { coordAll, featureEach } from '@turf/meta';
2
- import { getCoords } from '@turf/invariant';
3
- import { isObject, isNumber, featureCollection } from '@turf/helpers';
4
- import centerMean from '@turf/center-mean';
5
- import pointsWithinPolygon from '@turf/points-within-polygon';
6
- import ellipse from '@turf/ellipse';
7
-
8
- /**
9
- * Takes a {@link FeatureCollection} and returns a standard deviational ellipse,
10
- * also known as a “directional distribution.” The standard deviational ellipse
11
- * aims to show the direction and the distribution of a dataset by drawing
12
- * an ellipse that contains about one standard deviation’s worth (~ 70%) of the
13
- * data.
14
- *
15
- * This module mirrors the functionality of [Directional Distribution](http://desktop.arcgis.com/en/arcmap/10.3/tools/spatial-statistics-toolbox/directional-distribution.htm)
16
- * in ArcGIS and the [QGIS Standard Deviational Ellipse Plugin](http://arken.nmbu.no/~havatv/gis/qgisplugins/SDEllipse/)
17
- *
18
- * **Bibliography**
19
- *
20
- * • Robert S. Yuill, “The Standard Deviational Ellipse; An Updated Tool for
21
- * Spatial Description,” _Geografiska Annaler_ 53, no. 1 (1971): 28–39,
22
- * doi:{@link https://doi.org/10.2307/490885|10.2307/490885}.
23
- *
24
- * • Paul Hanly Furfey, “A Note on Lefever’s “Standard Deviational Ellipse,”
25
- * _American Journal of Sociology_ 33, no. 1 (1927): 94—98,
26
- * doi:{@link https://doi.org/10.1086/214336|10.1086/214336}.
27
- *
28
- *
29
- * @name standardDeviationalEllipse
30
- * @param {FeatureCollection<Point>} points GeoJSON points
31
- * @param {Object} [options={}] Optional parameters
32
- * @param {string} [options.weight] the property name used to weight the center
33
- * @param {number} [options.steps=64] number of steps for the polygon
34
- * @param {Object} [options.properties={}] properties to pass to the resulting ellipse
35
- * @returns {Feature<Polygon>} an elliptical Polygon that includes approximately 1 SD of the dataset within it.
36
- * @example
37
- *
38
- * var bbox = [-74, 40.72, -73.98, 40.74];
39
- * var points = turf.randomPoint(400, {bbox: bbox});
40
- * var sdEllipse = turf.standardDeviationalEllipse(points);
41
- *
42
- * //addToMap
43
- * var addToMap = [points, sdEllipse];
44
- *
45
- */
46
- function standardDeviationalEllipse(points, options) {
47
- // Optional params
48
- options = options || {};
49
- if (!isObject(options)) throw new Error("options is invalid");
50
- var steps = options.steps || 64;
51
- var weightTerm = options.weight;
52
- var properties = options.properties || {};
53
-
54
- // Validation:
55
- if (!isNumber(steps)) throw new Error("steps must be a number");
56
- if (!isObject(properties)) throw new Error("properties must be a number");
57
-
58
- // Calculate mean center & number of features:
59
- var numberOfFeatures = coordAll(points).length;
60
- var meanCenter = centerMean(points, { weight: weightTerm });
61
-
62
- // Calculate angle of rotation:
63
- // [X, Y] = mean center of all [x, y].
64
- // theta = arctan( (A + B) / C )
65
- // A = sum((x - X)^2) - sum((y - Y)^2)
66
- // B = sqrt(A^2 + 4(sum((x - X)(y - Y))^2))
67
- // C = 2(sum((x - X)(y - Y)))
68
-
69
- var xDeviationSquaredSum = 0;
70
- var yDeviationSquaredSum = 0;
71
- var xyDeviationSum = 0;
72
-
73
- featureEach(points, function (point) {
74
- var weight = point.properties[weightTerm] || 1;
75
- var deviation = getDeviations(getCoords(point), getCoords(meanCenter));
76
- xDeviationSquaredSum += Math.pow(deviation.x, 2) * weight;
77
- yDeviationSquaredSum += Math.pow(deviation.y, 2) * weight;
78
- xyDeviationSum += deviation.x * deviation.y * weight;
79
- });
80
-
81
- var bigA = xDeviationSquaredSum - yDeviationSquaredSum;
82
- var bigB = Math.sqrt(Math.pow(bigA, 2) + 4 * Math.pow(xyDeviationSum, 2));
83
- var bigC = 2 * xyDeviationSum;
84
- var theta = Math.atan((bigA + bigB) / bigC);
85
- var thetaDeg = (theta * 180) / Math.PI;
86
-
87
- // Calculate axes:
88
- // sigmaX = sqrt((1 / n - 2) * sum((((x - X) * cos(theta)) - ((y - Y) * sin(theta)))^2))
89
- // sigmaY = sqrt((1 / n - 2) * sum((((x - X) * sin(theta)) - ((y - Y) * cos(theta)))^2))
90
- var sigmaXsum = 0;
91
- var sigmaYsum = 0;
92
- var weightsum = 0;
93
- featureEach(points, function (point) {
94
- var weight = point.properties[weightTerm] || 1;
95
- var deviation = getDeviations(getCoords(point), getCoords(meanCenter));
96
- sigmaXsum +=
97
- Math.pow(
98
- deviation.x * Math.cos(theta) - deviation.y * Math.sin(theta),
99
- 2
100
- ) * weight;
101
- sigmaYsum +=
102
- Math.pow(
103
- deviation.x * Math.sin(theta) + deviation.y * Math.cos(theta),
104
- 2
105
- ) * weight;
106
- weightsum += weight;
107
- });
108
-
109
- var sigmaX = Math.sqrt((2 * sigmaXsum) / weightsum);
110
- var sigmaY = Math.sqrt((2 * sigmaYsum) / weightsum);
111
-
112
- var theEllipse = ellipse(meanCenter, sigmaX, sigmaY, {
113
- units: "degrees",
114
- angle: thetaDeg,
115
- steps: steps,
116
- properties: properties,
117
- });
118
- var pointsWithinEllipse = pointsWithinPolygon(
119
- points,
120
- featureCollection([theEllipse])
121
- );
122
- var standardDeviationalEllipseProperties = {
123
- meanCenterCoordinates: getCoords(meanCenter),
124
- semiMajorAxis: sigmaX,
125
- semiMinorAxis: sigmaY,
126
- numberOfFeatures: numberOfFeatures,
127
- angle: thetaDeg,
128
- percentageWithinEllipse:
129
- (100 * coordAll(pointsWithinEllipse).length) / numberOfFeatures,
130
- };
131
- theEllipse.properties.standardDeviationalEllipse = standardDeviationalEllipseProperties;
132
-
133
- return theEllipse;
134
- }
135
-
136
- /**
137
- * Get x_i - X and y_i - Y
138
- *
139
- * @private
140
- * @param {Array} coordinates Array of [x_i, y_i]
141
- * @param {Array} center Array of [X, Y]
142
- * @returns {Object} { x: n, y: m }
143
- */
144
- function getDeviations(coordinates, center) {
145
- return {
146
- x: coordinates[0] - center[0],
147
- y: coordinates[1] - center[1],
148
- };
149
- }
150
-
151
- export default standardDeviationalEllipse;
@@ -1 +0,0 @@
1
- {"type":"module"}
package/dist/js/index.js DELETED
@@ -1,160 +0,0 @@
1
- 'use strict';
2
-
3
- var meta = require('@turf/meta');
4
- var invariant = require('@turf/invariant');
5
- var helpers = require('@turf/helpers');
6
- var centerMean = require('@turf/center-mean');
7
- var pointsWithinPolygon = require('@turf/points-within-polygon');
8
- var ellipse = require('@turf/ellipse');
9
-
10
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
11
-
12
- var centerMean__default = /*#__PURE__*/_interopDefaultLegacy(centerMean);
13
- var pointsWithinPolygon__default = /*#__PURE__*/_interopDefaultLegacy(pointsWithinPolygon);
14
- var ellipse__default = /*#__PURE__*/_interopDefaultLegacy(ellipse);
15
-
16
- /**
17
- * Takes a {@link FeatureCollection} and returns a standard deviational ellipse,
18
- * also known as a “directional distribution.” The standard deviational ellipse
19
- * aims to show the direction and the distribution of a dataset by drawing
20
- * an ellipse that contains about one standard deviation’s worth (~ 70%) of the
21
- * data.
22
- *
23
- * This module mirrors the functionality of [Directional Distribution](http://desktop.arcgis.com/en/arcmap/10.3/tools/spatial-statistics-toolbox/directional-distribution.htm)
24
- * in ArcGIS and the [QGIS Standard Deviational Ellipse Plugin](http://arken.nmbu.no/~havatv/gis/qgisplugins/SDEllipse/)
25
- *
26
- * **Bibliography**
27
- *
28
- * • Robert S. Yuill, “The Standard Deviational Ellipse; An Updated Tool for
29
- * Spatial Description,” _Geografiska Annaler_ 53, no. 1 (1971): 28–39,
30
- * doi:{@link https://doi.org/10.2307/490885|10.2307/490885}.
31
- *
32
- * • Paul Hanly Furfey, “A Note on Lefever’s “Standard Deviational Ellipse,”
33
- * _American Journal of Sociology_ 33, no. 1 (1927): 94—98,
34
- * doi:{@link https://doi.org/10.1086/214336|10.1086/214336}.
35
- *
36
- *
37
- * @name standardDeviationalEllipse
38
- * @param {FeatureCollection<Point>} points GeoJSON points
39
- * @param {Object} [options={}] Optional parameters
40
- * @param {string} [options.weight] the property name used to weight the center
41
- * @param {number} [options.steps=64] number of steps for the polygon
42
- * @param {Object} [options.properties={}] properties to pass to the resulting ellipse
43
- * @returns {Feature<Polygon>} an elliptical Polygon that includes approximately 1 SD of the dataset within it.
44
- * @example
45
- *
46
- * var bbox = [-74, 40.72, -73.98, 40.74];
47
- * var points = turf.randomPoint(400, {bbox: bbox});
48
- * var sdEllipse = turf.standardDeviationalEllipse(points);
49
- *
50
- * //addToMap
51
- * var addToMap = [points, sdEllipse];
52
- *
53
- */
54
- function standardDeviationalEllipse(points, options) {
55
- // Optional params
56
- options = options || {};
57
- if (!helpers.isObject(options)) throw new Error("options is invalid");
58
- var steps = options.steps || 64;
59
- var weightTerm = options.weight;
60
- var properties = options.properties || {};
61
-
62
- // Validation:
63
- if (!helpers.isNumber(steps)) throw new Error("steps must be a number");
64
- if (!helpers.isObject(properties)) throw new Error("properties must be a number");
65
-
66
- // Calculate mean center & number of features:
67
- var numberOfFeatures = meta.coordAll(points).length;
68
- var meanCenter = centerMean__default['default'](points, { weight: weightTerm });
69
-
70
- // Calculate angle of rotation:
71
- // [X, Y] = mean center of all [x, y].
72
- // theta = arctan( (A + B) / C )
73
- // A = sum((x - X)^2) - sum((y - Y)^2)
74
- // B = sqrt(A^2 + 4(sum((x - X)(y - Y))^2))
75
- // C = 2(sum((x - X)(y - Y)))
76
-
77
- var xDeviationSquaredSum = 0;
78
- var yDeviationSquaredSum = 0;
79
- var xyDeviationSum = 0;
80
-
81
- meta.featureEach(points, function (point) {
82
- var weight = point.properties[weightTerm] || 1;
83
- var deviation = getDeviations(invariant.getCoords(point), invariant.getCoords(meanCenter));
84
- xDeviationSquaredSum += Math.pow(deviation.x, 2) * weight;
85
- yDeviationSquaredSum += Math.pow(deviation.y, 2) * weight;
86
- xyDeviationSum += deviation.x * deviation.y * weight;
87
- });
88
-
89
- var bigA = xDeviationSquaredSum - yDeviationSquaredSum;
90
- var bigB = Math.sqrt(Math.pow(bigA, 2) + 4 * Math.pow(xyDeviationSum, 2));
91
- var bigC = 2 * xyDeviationSum;
92
- var theta = Math.atan((bigA + bigB) / bigC);
93
- var thetaDeg = (theta * 180) / Math.PI;
94
-
95
- // Calculate axes:
96
- // sigmaX = sqrt((1 / n - 2) * sum((((x - X) * cos(theta)) - ((y - Y) * sin(theta)))^2))
97
- // sigmaY = sqrt((1 / n - 2) * sum((((x - X) * sin(theta)) - ((y - Y) * cos(theta)))^2))
98
- var sigmaXsum = 0;
99
- var sigmaYsum = 0;
100
- var weightsum = 0;
101
- meta.featureEach(points, function (point) {
102
- var weight = point.properties[weightTerm] || 1;
103
- var deviation = getDeviations(invariant.getCoords(point), invariant.getCoords(meanCenter));
104
- sigmaXsum +=
105
- Math.pow(
106
- deviation.x * Math.cos(theta) - deviation.y * Math.sin(theta),
107
- 2
108
- ) * weight;
109
- sigmaYsum +=
110
- Math.pow(
111
- deviation.x * Math.sin(theta) + deviation.y * Math.cos(theta),
112
- 2
113
- ) * weight;
114
- weightsum += weight;
115
- });
116
-
117
- var sigmaX = Math.sqrt((2 * sigmaXsum) / weightsum);
118
- var sigmaY = Math.sqrt((2 * sigmaYsum) / weightsum);
119
-
120
- var theEllipse = ellipse__default['default'](meanCenter, sigmaX, sigmaY, {
121
- units: "degrees",
122
- angle: thetaDeg,
123
- steps: steps,
124
- properties: properties,
125
- });
126
- var pointsWithinEllipse = pointsWithinPolygon__default['default'](
127
- points,
128
- helpers.featureCollection([theEllipse])
129
- );
130
- var standardDeviationalEllipseProperties = {
131
- meanCenterCoordinates: invariant.getCoords(meanCenter),
132
- semiMajorAxis: sigmaX,
133
- semiMinorAxis: sigmaY,
134
- numberOfFeatures: numberOfFeatures,
135
- angle: thetaDeg,
136
- percentageWithinEllipse:
137
- (100 * meta.coordAll(pointsWithinEllipse).length) / numberOfFeatures,
138
- };
139
- theEllipse.properties.standardDeviationalEllipse = standardDeviationalEllipseProperties;
140
-
141
- return theEllipse;
142
- }
143
-
144
- /**
145
- * Get x_i - X and y_i - Y
146
- *
147
- * @private
148
- * @param {Array} coordinates Array of [x_i, y_i]
149
- * @param {Array} center Array of [X, Y]
150
- * @returns {Object} { x: n, y: m }
151
- */
152
- function getDeviations(coordinates, center) {
153
- return {
154
- x: coordinates[0] - center[0],
155
- y: coordinates[1] - center[1],
156
- };
157
- }
158
-
159
- module.exports = standardDeviationalEllipse;
160
- module.exports.default = standardDeviationalEllipse;