index.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. 'use strict';
  2. var helpers = require('@turf/helpers');
  3. var rhumbDestination = require('@turf/rhumb-destination');
  4. var transformRotate = require('@turf/transform-rotate');
  5. var invariant = require('@turf/invariant');
  6. function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
  7. var rhumbDestination__default = /*#__PURE__*/_interopDefaultLegacy(rhumbDestination);
  8. var transformRotate__default = /*#__PURE__*/_interopDefaultLegacy(transformRotate);
  9. /**
  10. * Takes a {@link Point} and calculates the ellipse polygon given two semi-axes expressed in variable units and steps for precision.
  11. *
  12. * @param {Coord} center center point
  13. * @param {number} xSemiAxis semi (major) axis of the ellipse along the x-axis
  14. * @param {number} ySemiAxis semi (minor) axis of the ellipse along the y-axis
  15. * @param {Object} [options={}] Optional parameters
  16. * @param {number} [options.angle=0] angle of rotation in decimal degrees, positive clockwise
  17. * @param {Coord} [options.pivot='origin'] point around which the rotation will be performed
  18. * @param {number} [options.steps=64] number of steps
  19. * @param {string} [options.units='kilometers'] unit of measurement for axes
  20. * @param {Object} [options.properties={}] properties
  21. * @returns {Feature<Polygon>} ellipse polygon
  22. * @example
  23. * var center = [-75, 40];
  24. * var xSemiAxis = 5;
  25. * var ySemiAxis = 2;
  26. * var ellipse = turf.ellipse(center, xSemiAxis, ySemiAxis);
  27. *
  28. * //addToMap
  29. * var addToMap = [turf.point(center), ellipse]
  30. */
  31. function ellipse(center, xSemiAxis, ySemiAxis, options) {
  32. // Optional params
  33. options = options || {};
  34. var steps = options.steps || 64;
  35. var units = options.units || "kilometers";
  36. var angle = options.angle || 0;
  37. var pivot = options.pivot || center;
  38. var properties = options.properties || center.properties || {};
  39. // validation
  40. if (!center) throw new Error("center is required");
  41. if (!xSemiAxis) throw new Error("xSemiAxis is required");
  42. if (!ySemiAxis) throw new Error("ySemiAxis is required");
  43. if (!helpers.isObject(options)) throw new Error("options must be an object");
  44. if (!helpers.isNumber(steps)) throw new Error("steps must be a number");
  45. if (!helpers.isNumber(angle)) throw new Error("angle must be a number");
  46. var centerCoords = invariant.getCoord(center);
  47. if (units === "degrees") {
  48. var angleRad = helpers.degreesToRadians(angle);
  49. } else {
  50. xSemiAxis = rhumbDestination__default['default'](center, xSemiAxis, 90, { units: units });
  51. ySemiAxis = rhumbDestination__default['default'](center, ySemiAxis, 0, { units: units });
  52. xSemiAxis = invariant.getCoord(xSemiAxis)[0] - centerCoords[0];
  53. ySemiAxis = invariant.getCoord(ySemiAxis)[1] - centerCoords[1];
  54. }
  55. var coordinates = [];
  56. for (var i = 0; i < steps; i += 1) {
  57. var stepAngle = (i * -360) / steps;
  58. var x =
  59. (xSemiAxis * ySemiAxis) /
  60. Math.sqrt(
  61. Math.pow(ySemiAxis, 2) +
  62. Math.pow(xSemiAxis, 2) * Math.pow(getTanDeg(stepAngle), 2)
  63. );
  64. var y =
  65. (xSemiAxis * ySemiAxis) /
  66. Math.sqrt(
  67. Math.pow(xSemiAxis, 2) +
  68. Math.pow(ySemiAxis, 2) / Math.pow(getTanDeg(stepAngle), 2)
  69. );
  70. if (stepAngle < -90 && stepAngle >= -270) x = -x;
  71. if (stepAngle < -180 && stepAngle >= -360) y = -y;
  72. if (units === "degrees") {
  73. var newx = x * Math.cos(angleRad) + y * Math.sin(angleRad);
  74. var newy = y * Math.cos(angleRad) - x * Math.sin(angleRad);
  75. x = newx;
  76. y = newy;
  77. }
  78. coordinates.push([x + centerCoords[0], y + centerCoords[1]]);
  79. }
  80. coordinates.push(coordinates[0]);
  81. if (units === "degrees") {
  82. return helpers.polygon([coordinates], properties);
  83. } else {
  84. return transformRotate__default['default'](helpers.polygon([coordinates], properties), angle, {
  85. pivot: pivot,
  86. });
  87. }
  88. }
  89. /**
  90. * Get Tan Degrees
  91. *
  92. * @private
  93. * @param {number} deg Degrees
  94. * @returns {number} Tan Degrees
  95. */
  96. function getTanDeg(deg) {
  97. var rad = (deg * Math.PI) / 180;
  98. return Math.tan(rad);
  99. }
  100. module.exports = ellipse;
  101. module.exports.default = ellipse;