ParsePolygon.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = void 0;
  6. var _ParseGeoPoint = _interopRequireDefault(require("./ParseGeoPoint"));
  7. function _interopRequireDefault(obj) {
  8. return obj && obj.__esModule ? obj : {
  9. default: obj
  10. };
  11. }
  12. function _defineProperty(obj, key, value) {
  13. if (key in obj) {
  14. Object.defineProperty(obj, key, {
  15. value: value,
  16. enumerable: true,
  17. configurable: true,
  18. writable: true
  19. });
  20. } else {
  21. obj[key] = value;
  22. }
  23. return obj;
  24. }
  25. /**
  26. * Creates a new Polygon with any of the following forms:<br>
  27. * <pre>
  28. * new Polygon([[0,0],[0,1],[1,1],[1,0]])
  29. * new Polygon([GeoPoint, GeoPoint, GeoPoint])
  30. * </pre>
  31. *
  32. * <p>Represents a coordinates that may be associated
  33. * with a key in a ParseObject or used as a reference point for geo queries.
  34. * This allows proximity-based queries on the key.</p>
  35. *
  36. * <p>Example:<pre>
  37. * var polygon = new Parse.Polygon([[0,0],[0,1],[1,1],[1,0]]);
  38. * var object = new Parse.Object("PlaceObject");
  39. * object.set("area", polygon);
  40. * object.save();</pre></p>
  41. *
  42. * @alias Parse.Polygon
  43. */
  44. class ParsePolygon {
  45. /**
  46. * @param {(number[][] | Parse.GeoPoint[])} coordinates An Array of coordinate pairs
  47. */
  48. constructor(coordinates
  49. /*: Array<Array<number>> | Array<ParseGeoPoint>*/
  50. ) {
  51. _defineProperty(this, "_coordinates", void 0);
  52. this._coordinates = ParsePolygon._validate(coordinates);
  53. }
  54. /**
  55. * Coordinates value for this Polygon.
  56. * Throws an exception if not valid type.
  57. *
  58. * @property {(number[][] | Parse.GeoPoint[])} coordinates list of coordinates
  59. * @returns {number[][]}
  60. */
  61. get coordinates()
  62. /*: Array<Array<number>>*/
  63. {
  64. return this._coordinates;
  65. }
  66. set coordinates(coords
  67. /*: Array<Array<number>> | Array<ParseGeoPoint>*/
  68. ) {
  69. this._coordinates = ParsePolygon._validate(coords);
  70. }
  71. /**
  72. * Returns a JSON representation of the Polygon, suitable for Parse.
  73. *
  74. * @returns {object}
  75. */
  76. toJSON()
  77. /*: { __type: string, coordinates: Array<Array<number>> }*/
  78. {
  79. ParsePolygon._validate(this._coordinates);
  80. return {
  81. __type: 'Polygon',
  82. coordinates: this._coordinates
  83. };
  84. }
  85. /**
  86. * Checks if two polygons are equal
  87. *
  88. * @param {(Parse.Polygon | object)} other
  89. * @returns {boolean}
  90. */
  91. equals(other
  92. /*: mixed*/
  93. )
  94. /*: boolean*/
  95. {
  96. if (!(other instanceof ParsePolygon) || this.coordinates.length !== other.coordinates.length) {
  97. return false;
  98. }
  99. let isEqual = true;
  100. for (let i = 1; i < this._coordinates.length; i += 1) {
  101. if (this._coordinates[i][0] !== other.coordinates[i][0] || this._coordinates[i][1] !== other.coordinates[i][1]) {
  102. isEqual = false;
  103. break;
  104. }
  105. }
  106. return isEqual;
  107. }
  108. /**
  109. *
  110. * @param {Parse.GeoPoint} point
  111. * @returns {boolean} Returns if the point is contained in the polygon
  112. */
  113. containsPoint(point
  114. /*: ParseGeoPoint*/
  115. )
  116. /*: boolean*/
  117. {
  118. let minX = this._coordinates[0][0];
  119. let maxX = this._coordinates[0][0];
  120. let minY = this._coordinates[0][1];
  121. let maxY = this._coordinates[0][1];
  122. for (let i = 1; i < this._coordinates.length; i += 1) {
  123. const p = this._coordinates[i];
  124. minX = Math.min(p[0], minX);
  125. maxX = Math.max(p[0], maxX);
  126. minY = Math.min(p[1], minY);
  127. maxY = Math.max(p[1], maxY);
  128. }
  129. const outside = point.latitude < minX || point.latitude > maxX || point.longitude < minY || point.longitude > maxY;
  130. if (outside) {
  131. return false;
  132. }
  133. let inside = false;
  134. for (let i = 0, j = this._coordinates.length - 1; i < this._coordinates.length; j = i++) {
  135. const startX = this._coordinates[i][0];
  136. const startY = this._coordinates[i][1];
  137. const endX = this._coordinates[j][0];
  138. const endY = this._coordinates[j][1];
  139. const intersect = startY > point.longitude !== endY > point.longitude && point.latitude < (endX - startX) * (point.longitude - startY) / (endY - startY) + startX;
  140. if (intersect) {
  141. inside = !inside;
  142. }
  143. }
  144. return inside;
  145. }
  146. /**
  147. * Validates that the list of coordinates can form a valid polygon
  148. *
  149. * @param {Array} coords the list of coordinates to validate as a polygon
  150. * @throws {TypeError}
  151. * @returns {number[][]} Array of coordinates if validated.
  152. */
  153. static _validate(coords
  154. /*: Array<Array<number>> | Array<ParseGeoPoint>*/
  155. )
  156. /*: Array<Array<number>>*/
  157. {
  158. if (!Array.isArray(coords)) {
  159. throw new TypeError('Coordinates must be an Array');
  160. }
  161. if (coords.length < 3) {
  162. throw new TypeError('Polygon must have at least 3 GeoPoints or Points');
  163. }
  164. const points = [];
  165. for (let i = 0; i < coords.length; i += 1) {
  166. const coord = coords[i];
  167. let geoPoint;
  168. if (coord instanceof _ParseGeoPoint.default) {
  169. geoPoint = coord;
  170. } else if (Array.isArray(coord) && coord.length === 2) {
  171. geoPoint = new _ParseGeoPoint.default(coord[0], coord[1]);
  172. } else {
  173. throw new TypeError('Coordinates must be an Array of GeoPoints or Points');
  174. }
  175. points.push([geoPoint.latitude, geoPoint.longitude]);
  176. }
  177. return points;
  178. }
  179. }
  180. var _default = ParsePolygon;
  181. exports.default = _default;