ParsePolygon.js 5.3 KB

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