113 lines
4.0 KiB
JavaScript
Executable File
113 lines
4.0 KiB
JavaScript
Executable File
'use strict';
|
|
|
|
var helpers = require('@turf/helpers');
|
|
var rhumbDestination = require('@turf/rhumb-destination');
|
|
var transformRotate = require('@turf/transform-rotate');
|
|
var invariant = require('@turf/invariant');
|
|
|
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
|
|
var rhumbDestination__default = /*#__PURE__*/_interopDefaultLegacy(rhumbDestination);
|
|
var transformRotate__default = /*#__PURE__*/_interopDefaultLegacy(transformRotate);
|
|
|
|
/**
|
|
* Takes a {@link Point} and calculates the ellipse polygon given two semi-axes expressed in variable units and steps for precision.
|
|
*
|
|
* @param {Coord} center center point
|
|
* @param {number} xSemiAxis semi (major) axis of the ellipse along the x-axis
|
|
* @param {number} ySemiAxis semi (minor) axis of the ellipse along the y-axis
|
|
* @param {Object} [options={}] Optional parameters
|
|
* @param {number} [options.angle=0] angle of rotation in decimal degrees, positive clockwise
|
|
* @param {Coord} [options.pivot='origin'] point around which the rotation will be performed
|
|
* @param {number} [options.steps=64] number of steps
|
|
* @param {string} [options.units='kilometers'] unit of measurement for axes
|
|
* @param {Object} [options.properties={}] properties
|
|
* @returns {Feature<Polygon>} ellipse polygon
|
|
* @example
|
|
* var center = [-75, 40];
|
|
* var xSemiAxis = 5;
|
|
* var ySemiAxis = 2;
|
|
* var ellipse = turf.ellipse(center, xSemiAxis, ySemiAxis);
|
|
*
|
|
* //addToMap
|
|
* var addToMap = [turf.point(center), ellipse]
|
|
*/
|
|
function ellipse(center, xSemiAxis, ySemiAxis, options) {
|
|
// Optional params
|
|
options = options || {};
|
|
var steps = options.steps || 64;
|
|
var units = options.units || "kilometers";
|
|
var angle = options.angle || 0;
|
|
var pivot = options.pivot || center;
|
|
var properties = options.properties || center.properties || {};
|
|
|
|
// validation
|
|
if (!center) throw new Error("center is required");
|
|
if (!xSemiAxis) throw new Error("xSemiAxis is required");
|
|
if (!ySemiAxis) throw new Error("ySemiAxis is required");
|
|
if (!helpers.isObject(options)) throw new Error("options must be an object");
|
|
if (!helpers.isNumber(steps)) throw new Error("steps must be a number");
|
|
if (!helpers.isNumber(angle)) throw new Error("angle must be a number");
|
|
|
|
var centerCoords = invariant.getCoord(center);
|
|
if (units === "degrees") {
|
|
var angleRad = helpers.degreesToRadians(angle);
|
|
} else {
|
|
xSemiAxis = rhumbDestination__default['default'](center, xSemiAxis, 90, { units: units });
|
|
ySemiAxis = rhumbDestination__default['default'](center, ySemiAxis, 0, { units: units });
|
|
xSemiAxis = invariant.getCoord(xSemiAxis)[0] - centerCoords[0];
|
|
ySemiAxis = invariant.getCoord(ySemiAxis)[1] - centerCoords[1];
|
|
}
|
|
|
|
var coordinates = [];
|
|
for (var i = 0; i < steps; i += 1) {
|
|
var stepAngle = (i * -360) / steps;
|
|
var x =
|
|
(xSemiAxis * ySemiAxis) /
|
|
Math.sqrt(
|
|
Math.pow(ySemiAxis, 2) +
|
|
Math.pow(xSemiAxis, 2) * Math.pow(getTanDeg(stepAngle), 2)
|
|
);
|
|
var y =
|
|
(xSemiAxis * ySemiAxis) /
|
|
Math.sqrt(
|
|
Math.pow(xSemiAxis, 2) +
|
|
Math.pow(ySemiAxis, 2) / Math.pow(getTanDeg(stepAngle), 2)
|
|
);
|
|
|
|
if (stepAngle < -90 && stepAngle >= -270) x = -x;
|
|
if (stepAngle < -180 && stepAngle >= -360) y = -y;
|
|
if (units === "degrees") {
|
|
var newx = x * Math.cos(angleRad) + y * Math.sin(angleRad);
|
|
var newy = y * Math.cos(angleRad) - x * Math.sin(angleRad);
|
|
x = newx;
|
|
y = newy;
|
|
}
|
|
|
|
coordinates.push([x + centerCoords[0], y + centerCoords[1]]);
|
|
}
|
|
coordinates.push(coordinates[0]);
|
|
if (units === "degrees") {
|
|
return helpers.polygon([coordinates], properties);
|
|
} else {
|
|
return transformRotate__default['default'](helpers.polygon([coordinates], properties), angle, {
|
|
pivot: pivot,
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get Tan Degrees
|
|
*
|
|
* @private
|
|
* @param {number} deg Degrees
|
|
* @returns {number} Tan Degrees
|
|
*/
|
|
function getTanDeg(deg) {
|
|
var rad = (deg * Math.PI) / 180;
|
|
return Math.tan(rad);
|
|
}
|
|
|
|
module.exports = ellipse;
|
|
module.exports.default = ellipse;
|