PageRenderTime 27ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/trunk/contribs/jts-source/com/vividsolutions/jts/geom/CoordinateArrays.java

https://bitbucket.org/haris_peco/debrief
Java | 437 lines | 208 code | 42 blank | 187 comment | 68 complexity | 104255dbb7ddf827de19a8ca18c88715 MD5 | raw file
  1. /*
  2. * The JTS Topology Suite is a collection of Java classes that
  3. * implement the fundamental operations required to validate a given
  4. * geo-spatial data set to a known topological specification.
  5. *
  6. * Copyright (C) 2001 Vivid Solutions
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2.1 of the License, or (at your option) any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with this library; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  21. *
  22. * For more information, contact:
  23. *
  24. * Vivid Solutions
  25. * Suite #1A
  26. * 2328 Government Street
  27. * Victoria BC V8T 5G5
  28. * Canada
  29. *
  30. * (250)385-6040
  31. * www.vividsolutions.com
  32. */
  33. package com.vividsolutions.jts.geom;
  34. import java.util.*;
  35. import com.vividsolutions.jts.math.MathUtil;
  36. /**
  37. * Useful utility functions for handling Coordinate arrays
  38. *
  39. * @version 1.7
  40. */
  41. public class CoordinateArrays {
  42. private final static Coordinate[] coordArrayType = new Coordinate[0];
  43. /**
  44. * Tests whether an array of {@link Coordinate}s forms a ring,
  45. * by checking length and closure.
  46. * Self-intersection is not checked.
  47. *
  48. * @param pts an array of Coordinates
  49. * @return true if the coordinate form a ring.
  50. */
  51. public static boolean isRing(Coordinate[] pts)
  52. {
  53. if (pts.length < 4) return false;
  54. if (! pts[0].equals2D(pts[pts.length -1])) return false;
  55. return true;
  56. }
  57. /**
  58. * Finds a point in a list of points which is not contained in another list of points
  59. * @param testPts the {@link Coordinate}s to test
  60. * @param pts an array of {@link Coordinate}s to test the input points against
  61. * @return a {@link Coordinate} from <code>testPts</code> which is not in <code>pts</code>, '
  62. * or <code>null</code>
  63. */
  64. public static Coordinate ptNotInList(Coordinate[] testPts, Coordinate[] pts)
  65. {
  66. for (int i = 0; i < testPts.length; i++) {
  67. Coordinate testPt = testPts[i];
  68. if (CoordinateArrays.indexOf(testPt, pts) < 0)
  69. return testPt;
  70. }
  71. return null;
  72. }
  73. /**
  74. * Compares two {@link Coordinate} arrays
  75. * in the forward direction of their coordinates,
  76. * using lexicographic ordering.
  77. *
  78. * @param pts1
  79. * @param pts2
  80. * @return an integer indicating the order
  81. */
  82. public static int compare(Coordinate[] pts1, Coordinate[] pts2) {
  83. int i = 0;
  84. while (i < pts1.length && i < pts2.length) {
  85. int compare = pts1[i].compareTo(pts2[i]);
  86. if (compare != 0)
  87. return compare;
  88. i++;
  89. }
  90. // handle situation when arrays are of different length
  91. if (i < pts2.length) return -1;
  92. if (i < pts1.length) return 1;
  93. return 0;
  94. }
  95. /**
  96. * A {@link Comparator} for {@link Coordinate} arrays
  97. * in the forward direction of their coordinates,
  98. * using lexicographic ordering.
  99. */
  100. public static class ForwardComparator
  101. implements Comparator
  102. {
  103. public int compare(Object o1, Object o2) {
  104. Coordinate[] pts1 = (Coordinate[]) o1;
  105. Coordinate[] pts2 = (Coordinate[]) o2;
  106. return CoordinateArrays.compare(pts1, pts2);
  107. }
  108. }
  109. /**
  110. * Determines which orientation of the {@link Coordinate} array
  111. * is (overall) increasing.
  112. * In other words, determines which end of the array is "smaller"
  113. * (using the standard ordering on {@link Coordinate}).
  114. * Returns an integer indicating the increasing direction.
  115. * If the sequence is a palindrome, it is defined to be
  116. * oriented in a positive direction.
  117. *
  118. * @param pts the array of Coordinates to test
  119. * @return <code>1</code> if the array is smaller at the start
  120. * or is a palindrome,
  121. * <code>-1</code> if smaller at the end
  122. */
  123. public static int increasingDirection(Coordinate[] pts) {
  124. for (int i = 0; i < pts.length / 2; i++) {
  125. int j = pts.length - 1 - i;
  126. // skip equal points on both ends
  127. int comp = pts[i].compareTo(pts[j]);
  128. if (comp != 0)
  129. return comp;
  130. }
  131. // array must be a palindrome - defined to be in positive direction
  132. return 1;
  133. }
  134. /**
  135. * Determines whether two {@link Coordinate} arrays of equal length
  136. * are equal in opposite directions.
  137. *
  138. * @param pts1
  139. * @param pts2
  140. * @return <code>true</code> if the two arrays are equal in opposite directions.
  141. */
  142. private static boolean isEqualReversed(Coordinate[] pts1, Coordinate[] pts2)
  143. {
  144. for (int i = 0; i < pts1.length; i++) {
  145. Coordinate p1 = pts1[i];
  146. Coordinate p2 = pts2[pts1.length - i - 1];
  147. if (p1.compareTo(p2) != 0)
  148. return false;
  149. }
  150. return true;
  151. }
  152. /**
  153. * A {@link Comparator} for {@link Coordinate} arrays
  154. * modulo their directionality.
  155. * E.g. if two coordinate arrays are identical but reversed
  156. * they will compare as equal under this ordering.
  157. * If the arrays are not equal, the ordering returned
  158. * is the ordering in the forward direction.
  159. *
  160. */
  161. public static class BidirectionalComparator
  162. implements Comparator
  163. {
  164. public int compare(Object o1, Object o2) {
  165. Coordinate[] pts1 = (Coordinate[]) o1;
  166. Coordinate[] pts2 = (Coordinate[]) o2;
  167. if (pts1.length < pts2.length) return -1;
  168. if (pts1.length > pts2.length) return 1;
  169. if (pts1.length == 0) return 0;
  170. int forwardComp = CoordinateArrays.compare(pts1, pts2);
  171. boolean isEqualRev = isEqualReversed(pts1, pts2);
  172. if (isEqualRev)
  173. return 0;
  174. return forwardComp;
  175. }
  176. public int OLDcompare(Object o1, Object o2) {
  177. Coordinate[] pts1 = (Coordinate[]) o1;
  178. Coordinate[] pts2 = (Coordinate[]) o2;
  179. if (pts1.length < pts2.length) return -1;
  180. if (pts1.length > pts2.length) return 1;
  181. if (pts1.length == 0) return 0;
  182. int dir1 = increasingDirection(pts1);
  183. int dir2 = increasingDirection(pts2);
  184. int i1 = dir1 > 0 ? 0 : pts1.length - 1;
  185. int i2 = dir2 > 0 ? 0 : pts1.length - 1;
  186. for (int i = 0; i < pts1.length; i++) {
  187. int comparePt = pts1[i1].compareTo(pts2[i2]);
  188. if (comparePt != 0)
  189. return comparePt;
  190. i1 += dir1;
  191. i2 += dir2;
  192. }
  193. return 0;
  194. }
  195. }
  196. /**
  197. * Creates a deep copy of the argument {@link Coordinate} array.
  198. *
  199. * @param coordinates an array of Coordinates
  200. * @return a deep copy of the input
  201. */
  202. public static Coordinate[] copyDeep(Coordinate[] coordinates) {
  203. Coordinate[] copy = new Coordinate[coordinates.length];
  204. for (int i = 0; i < coordinates.length; i++) {
  205. copy[i] = new Coordinate(coordinates[i]);
  206. }
  207. return copy;
  208. }
  209. /**
  210. * Creates a deep copy of a given section of a source {@link Coordinate} array
  211. * into a destination Coordinate array.
  212. * The destination array must be an appropriate size to receive
  213. * the copied coordinates.
  214. *
  215. * @param src an array of Coordinates
  216. * @param srcStart the index to start copying from
  217. * @param dest the
  218. * @param destStart the destination index to start copying to
  219. * @param length the number of items to copy
  220. */
  221. public static void copyDeep(Coordinate[] src, int srcStart, Coordinate[] dest, int destStart, int length) {
  222. for (int i = 0; i < length; i++) {
  223. dest[destStart + i] = new Coordinate(src[srcStart + i]);
  224. }
  225. }
  226. /**
  227. * Converts the given Collection of Coordinates into a Coordinate array.
  228. */
  229. public static Coordinate[] toCoordinateArray(Collection coordList)
  230. {
  231. return (Coordinate[]) coordList.toArray(coordArrayType);
  232. }
  233. /**
  234. * Returns whether #equals returns true for any two consecutive Coordinates
  235. * in the given array.
  236. */
  237. public static boolean hasRepeatedPoints(Coordinate[] coord)
  238. {
  239. for (int i = 1; i < coord.length; i++) {
  240. if (coord[i - 1].equals(coord[i]) ) {
  241. return true;
  242. }
  243. }
  244. return false;
  245. }
  246. /**
  247. * Returns either the given coordinate array if its length is greater than the
  248. * given amount, or an empty coordinate array.
  249. */
  250. public static Coordinate[] atLeastNCoordinatesOrNothing(int n, Coordinate[] c) {
  251. return c.length >= n ? c : new Coordinate[] { };
  252. }
  253. /**
  254. * If the coordinate array argument has repeated points,
  255. * constructs a new array containing no repeated points.
  256. * Otherwise, returns the argument.
  257. * @see #hasRepeatedPoints(Coordinate[])
  258. */
  259. public static Coordinate[] removeRepeatedPoints(Coordinate[] coord)
  260. {
  261. if (! hasRepeatedPoints(coord)) return coord;
  262. CoordinateList coordList = new CoordinateList(coord, false);
  263. return coordList.toCoordinateArray();
  264. }
  265. /**
  266. * Reverses the coordinates in an array in-place.
  267. */
  268. public static void reverse(Coordinate[] coord)
  269. {
  270. int last = coord.length - 1;
  271. int mid = last / 2;
  272. for (int i = 0; i <= mid; i++) {
  273. Coordinate tmp = coord[i];
  274. coord[i] = coord[last - i];
  275. coord[last - i] = tmp;
  276. }
  277. }
  278. /**
  279. * Returns true if the two arrays are identical, both null, or pointwise
  280. * equal (as compared using Coordinate#equals)
  281. * @see Coordinate#equals(Object)
  282. */
  283. public static boolean equals(
  284. Coordinate[] coord1,
  285. Coordinate[] coord2)
  286. {
  287. if (coord1 == coord2) return true;
  288. if (coord1 == null || coord2 == null) return false;
  289. if (coord1.length != coord2.length) return false;
  290. for (int i = 0; i < coord1.length; i++) {
  291. if (! coord1[i].equals(coord2[i])) return false;
  292. }
  293. return true;
  294. }
  295. /**
  296. * Returns true if the two arrays are identical, both null, or pointwise
  297. * equal, using a user-defined {@link Comparator} for {@link Coordinate} s
  298. *
  299. * @param coord1 an array of Coordinates
  300. * @param coord2 an array of Coordinates
  301. * @param coordinateComparator a Comparator for Coordinates
  302. */
  303. public static boolean equals(
  304. Coordinate[] coord1,
  305. Coordinate[] coord2,
  306. Comparator coordinateComparator)
  307. {
  308. if (coord1 == coord2) return true;
  309. if (coord1 == null || coord2 == null) return false;
  310. if (coord1.length != coord2.length) return false;
  311. for (int i = 0; i < coord1.length; i++) {
  312. if (coordinateComparator.compare(coord1[i], coord2[i]) != 0)
  313. return false;
  314. }
  315. return true;
  316. }
  317. /**
  318. * Returns the minimum coordinate, using the usual lexicographic comparison.
  319. *
  320. *@param coordinates the array to search
  321. *@return the minimum coordinate in the array, found using <code>compareTo</code>
  322. *@see Coordinate#compareTo(Object)
  323. */
  324. public static Coordinate minCoordinate(Coordinate[] coordinates)
  325. {
  326. Coordinate minCoord = null;
  327. for (int i = 0; i < coordinates.length; i++) {
  328. if (minCoord == null || minCoord.compareTo(coordinates[i]) > 0) {
  329. minCoord = coordinates[i];
  330. }
  331. }
  332. return minCoord;
  333. }
  334. /**
  335. * Shifts the positions of the coordinates until <code>firstCoordinate</code>
  336. * is first.
  337. *
  338. *@param coordinates the array to rearrange
  339. *@param firstCoordinate the coordinate to make first
  340. */
  341. public static void scroll(Coordinate[] coordinates, Coordinate firstCoordinate) {
  342. int i = indexOf(firstCoordinate, coordinates);
  343. if (i < 0) return;
  344. Coordinate[] newCoordinates = new Coordinate[coordinates.length];
  345. System.arraycopy(coordinates, i, newCoordinates, 0, coordinates.length - i);
  346. System.arraycopy(coordinates, 0, newCoordinates, coordinates.length - i, i);
  347. System.arraycopy(newCoordinates, 0, coordinates, 0, coordinates.length);
  348. }
  349. /**
  350. * Returns the index of <code>coordinate</code> in <code>coordinates</code>.
  351. * The first position is 0; the second, 1; etc.
  352. *
  353. *@param coordinate the <code>Coordinate</code> to search for
  354. *@param coordinates the array to search
  355. *@return the position of <code>coordinate</code>, or -1 if it is
  356. * not found
  357. */
  358. public static int indexOf(Coordinate coordinate, Coordinate[] coordinates) {
  359. for (int i = 0; i < coordinates.length; i++) {
  360. if (coordinate.equals(coordinates[i])) {
  361. return i;
  362. }
  363. }
  364. return -1;
  365. }
  366. /**
  367. * Extracts a subsequence of the input {@link Coordinate} array
  368. * from indices <code>start</code> to
  369. * <code>end</code> (inclusive).
  370. * The input indices are clamped to the array size;
  371. * If the end index is less than the start index,
  372. * the extracted array will be empty.
  373. *
  374. * @param pts the input array
  375. * @param start the index of the start of the subsequence to extract
  376. * @param end the index of the end of the subsequence to extract
  377. * @return a subsequence of the input array
  378. */
  379. public static Coordinate[] extract(Coordinate[] pts, int start, int end)
  380. {
  381. start = MathUtil.clamp(start, 0, pts.length);
  382. end = MathUtil.clamp(end, -1, pts.length);
  383. int npts = end - start + 1;
  384. if (end < 0) npts = 0;
  385. if (start >= pts.length) npts = 0;
  386. if (end < start) npts = 0;
  387. Coordinate[] extractPts = new Coordinate[npts];
  388. if (npts == 0) return extractPts;
  389. int iPts = 0;
  390. for (int i = start; i <= end; i++) {
  391. extractPts[iPts++] = pts[i];
  392. }
  393. return extractPts;
  394. }
  395. }