PageRenderTime 57ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 1ms

/modules/unsupported/geometry/src/main/java/org/geotools/geometry/iso/topograph2D/util/CoordinateArrays.java

https://github.com/thjarvin/geotools
Java | 456 lines | 228 code | 42 blank | 186 comment | 63 complexity | fe68b38d14f9eac170d4c4bcfb4ed3ee MD5 | raw file
  1. /*
  2. * GeoTools - The Open Source Java GIS Toolkit
  3. * http://geotools.org
  4. *
  5. * (C) 2001-2006 Vivid Solutions
  6. * (C) 2001-2008, Open Source Geospatial Foundation (OSGeo)
  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;
  11. * version 2.1 of the License.
  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. package org.geotools.geometry.iso.topograph2D.util;
  19. import java.util.ArrayList;
  20. import java.util.Collection;
  21. import java.util.Comparator;
  22. import java.util.List;
  23. import org.geotools.geometry.iso.coordinate.DirectPositionImpl;
  24. import org.geotools.geometry.iso.coordinate.PositionImpl;
  25. import org.geotools.geometry.iso.topograph2D.Coordinate;
  26. import org.geotools.geometry.iso.topograph2D.CoordinateList;
  27. import org.opengis.geometry.DirectPosition;
  28. import org.opengis.geometry.coordinate.Position;
  29. import org.opengis.referencing.crs.CoordinateReferenceSystem;
  30. /**
  31. * Useful utility functions for handling Coordinate arrays
  32. *
  33. * @source $URL$
  34. */
  35. public class CoordinateArrays {
  36. private final static Coordinate[] coordArrayType = new Coordinate[0];
  37. /**
  38. * Finds a point in a list of points which is not contained in another list
  39. * of points
  40. *
  41. * @param testPts
  42. * the {@link Coordinate}s to test
  43. * @param pts
  44. * an array of {@link Coordinate}s to test the input points
  45. * against
  46. * @return a {@link Coordinate} from <code>testPts</code> which is not in
  47. * <code>pts</code>, ' or <code>null</code>
  48. */
  49. public static Coordinate ptNotInList(Coordinate[] testPts, Coordinate[] pts) {
  50. for (int i = 0; i < testPts.length; i++) {
  51. Coordinate testPt = testPts[i];
  52. if (CoordinateArrays.indexOf(testPt, pts) < 0)
  53. return testPt;
  54. }
  55. return null;
  56. }
  57. /**
  58. * Compares two {@link Coordinate} arrays in the forward direction of their
  59. * coordinates, using lexicographic ordering.
  60. *
  61. * @param pts1
  62. * @param pts2
  63. * @return
  64. */
  65. public static int compare(Coordinate[] pts1, Coordinate[] pts2) {
  66. int i = 0;
  67. while (i < pts1.length && i < pts2.length) {
  68. int compare = pts1[i].compareTo(pts2[i]);
  69. if (compare != 0)
  70. return compare;
  71. i++;
  72. }
  73. // handle situation when arrays are of different length
  74. if (i < pts2.length)
  75. return -1;
  76. if (i < pts1.length)
  77. return 1;
  78. return 0;
  79. }
  80. /**
  81. * A {@link Comparator} for {@link Coordinate} arrays in the forward
  82. * direction of their coordinates, using lexicographic ordering.
  83. */
  84. public static class ForwardComparator implements Comparator {
  85. public int compare(Object o1, Object o2) {
  86. Coordinate[] pts1 = (Coordinate[]) o1;
  87. Coordinate[] pts2 = (Coordinate[]) o2;
  88. return CoordinateArrays.compare(pts1, pts2);
  89. }
  90. }
  91. /**
  92. * Determines which orientation of the {@link Coordinate} array is (overall)
  93. * increasing. In other words, determines which end of the array is
  94. * "smaller" (using the standard ordering on {@link Coordinate}). Returns
  95. * an integer indicating the increasing direction. If the sequence is a
  96. * palindrome, it is defined to be oriented in a positive direction.
  97. *
  98. * @param pts
  99. * the array of Coordinates to test
  100. * @return <code>1</code> if the array is smaller at the start or is a
  101. * palindrome, <code>-1</code> if smaller at the end
  102. */
  103. public static int increasingDirection(Coordinate[] pts) {
  104. for (int i = 0; i < pts.length / 2; i++) {
  105. int j = pts.length - 1 - i;
  106. // skip equal points on both ends
  107. int comp = pts[i].compareTo(pts[j]);
  108. if (comp != 0)
  109. return comp;
  110. }
  111. // array must be a palindrome - defined to be in positive direction
  112. return 1;
  113. }
  114. /**
  115. * Determines whether two {@link Coordinate} arrays of equal length are
  116. * equal in opposite directions.
  117. *
  118. * @param pts1
  119. * @param pts2
  120. * @return <code>true</code> if the two arrays are equal in opposite
  121. * directions.
  122. */
  123. private static boolean isEqualReversed(Coordinate[] pts1, Coordinate[] pts2) {
  124. for (int i = 0; i < pts1.length; i++) {
  125. Coordinate p1 = pts1[i];
  126. Coordinate p2 = pts2[pts1.length - i - 1];
  127. if (p1.compareTo(p2) != 0)
  128. return false;
  129. }
  130. return true;
  131. }
  132. /**
  133. * A {@link Comparator} for {@link Coordinate} arrays modulo their
  134. * directionality. E.g. if two coordinate arrays are identical but reversed
  135. * they will compare as equal under this ordering. If the arrays are not
  136. * equal, the ordering returned is the ordering in the forward direction.
  137. *
  138. */
  139. public static class BidirectionalComparator implements Comparator {
  140. public int compare(Object o1, Object o2) {
  141. Coordinate[] pts1 = (Coordinate[]) o1;
  142. Coordinate[] pts2 = (Coordinate[]) o2;
  143. if (pts1.length < pts2.length)
  144. return -1;
  145. if (pts1.length > pts2.length)
  146. return 1;
  147. if (pts1.length == 0)
  148. return 0;
  149. int forwardComp = CoordinateArrays.compare(pts1, pts2);
  150. boolean isEqualRev = isEqualReversed(pts1, pts2);
  151. if (isEqualRev)
  152. return 0;
  153. return forwardComp;
  154. }
  155. public int OLDcompare(Object o1, Object o2) {
  156. Coordinate[] pts1 = (Coordinate[]) o1;
  157. Coordinate[] pts2 = (Coordinate[]) o2;
  158. if (pts1.length < pts2.length)
  159. return -1;
  160. if (pts1.length > pts2.length)
  161. return 1;
  162. if (pts1.length == 0)
  163. return 0;
  164. int dir1 = increasingDirection(pts1);
  165. int dir2 = increasingDirection(pts2);
  166. int i1 = dir1 > 0 ? 0 : pts1.length - 1;
  167. int i2 = dir2 > 0 ? 0 : pts1.length - 1;
  168. for (int i = 0; i < pts1.length; i++) {
  169. int comparePt = pts1[i1].compareTo(pts2[i2]);
  170. if (comparePt != 0)
  171. return comparePt;
  172. i1 += dir1;
  173. i2 += dir2;
  174. }
  175. return 0;
  176. }
  177. }
  178. /**
  179. * Creates a deep copy of the argument {@link Coordinate) array.
  180. *
  181. * @param coordinates
  182. * an array of Coordinates
  183. * @return a deep copy of the input
  184. */
  185. public static Coordinate[] copyDeep(Coordinate[] coordinates) {
  186. Coordinate[] copy = new Coordinate[coordinates.length];
  187. for (int i = 0; i < coordinates.length; i++) {
  188. copy[i] = new Coordinate(coordinates[i]);
  189. }
  190. return copy;
  191. }
  192. /**
  193. * Converts the given Collection of Coordinates into a Coordinate array.
  194. */
  195. public static Coordinate[] toCoordinateArray(Collection coordList) {
  196. return (Coordinate[]) coordList.toArray(coordArrayType);
  197. }
  198. /**
  199. * Returns whether #equals returns true for any two consecutive Coordinates
  200. * in the given array.
  201. */
  202. public static boolean hasRepeatedPoints(Coordinate[] coord) {
  203. for (int i = 1; i < coord.length; i++) {
  204. if (coord[i - 1].equals(coord[i])) {
  205. return true;
  206. }
  207. }
  208. return false;
  209. }
  210. /**
  211. * Returns either the given coordinate array if its length is greater than
  212. * the given amount, or an empty coordinate array.
  213. */
  214. public static Coordinate[] atLeastNCoordinatesOrNothing(int n,
  215. Coordinate[] c) {
  216. return c.length >= n ? c : new Coordinate[] {};
  217. }
  218. /**
  219. * If the coordinate array argument has repeated points, constructs a new
  220. * array containing no repeated points. Otherwise, returns the argument.
  221. *
  222. * @see #hasRepeatedPoints(Coordinate[])
  223. */
  224. public static Coordinate[] removeRepeatedPoints(Coordinate[] coord) {
  225. if (!hasRepeatedPoints(coord))
  226. return coord;
  227. CoordinateList coordList = new CoordinateList(coord, false);
  228. return coordList.toCoordinateArray();
  229. }
  230. /**
  231. * Reverses the coordinates in an array in-place.
  232. */
  233. public static void reverse(Coordinate[] coord) {
  234. int last = coord.length - 1;
  235. int mid = last / 2;
  236. for (int i = 0; i <= mid; i++) {
  237. Coordinate tmp = coord[i];
  238. coord[i] = coord[last - i];
  239. coord[last - i] = tmp;
  240. }
  241. }
  242. /**
  243. * Returns true if the two arrays are identical, both null, or pointwise
  244. * equal (as compared using Coordinate#equals)
  245. *
  246. * @see Coordinate#equals(Object)
  247. */
  248. public static boolean equals(Coordinate[] coord1, Coordinate[] coord2) {
  249. if (coord1 == coord2)
  250. return true;
  251. if (coord1 == null || coord2 == null)
  252. return false;
  253. if (coord1.length != coord2.length)
  254. return false;
  255. for (int i = 0; i < coord1.length; i++) {
  256. if (!coord1[i].equals(coord2[i]))
  257. return false;
  258. }
  259. return true;
  260. }
  261. /**
  262. * Returns true if the two arrays are identical, both null, or pointwise
  263. * equal, using a user-defined {@link Comparator} for {@link Coordinate} s
  264. *
  265. * @param coord1
  266. * an array of Coordinates
  267. * @param coord2
  268. * an array of Coordinates
  269. * @param coordinateComparator
  270. * a Comparator for Coordinates
  271. */
  272. public static boolean equals(Coordinate[] coord1, Coordinate[] coord2,
  273. Comparator coordinateComparator) {
  274. if (coord1 == coord2)
  275. return true;
  276. if (coord1 == null || coord2 == null)
  277. return false;
  278. if (coord1.length != coord2.length)
  279. return false;
  280. for (int i = 0; i < coord1.length; i++) {
  281. if (coordinateComparator.compare(coord1[i], coord2[i]) != 0)
  282. return false;
  283. }
  284. return true;
  285. }
  286. /**
  287. * Returns the minimum coordinate, using the usual lexicographic comparison.
  288. *
  289. * @param coordinates
  290. * the array to search
  291. * @return the minimum coordinate in the array, found using
  292. * <code>compareTo</code>
  293. * @see Coordinate#compareTo(Object)
  294. */
  295. public static Coordinate minCoordinate(Coordinate[] coordinates) {
  296. Coordinate minCoord = null;
  297. for (int i = 0; i < coordinates.length; i++) {
  298. if (minCoord == null || minCoord.compareTo(coordinates[i]) > 0) {
  299. minCoord = coordinates[i];
  300. }
  301. }
  302. return minCoord;
  303. }
  304. /**
  305. * Shifts the positions of the coordinates until
  306. * <code>firstCoordinate</code> is first.
  307. *
  308. * @param coordinates
  309. * the array to rearrange
  310. * @param firstCoordinate
  311. * the coordinate to make first
  312. */
  313. public static void scroll(Coordinate[] coordinates,
  314. Coordinate firstCoordinate) {
  315. int i = indexOf(firstCoordinate, coordinates);
  316. if (i < 0)
  317. return;
  318. Coordinate[] newCoordinates = new Coordinate[coordinates.length];
  319. System.arraycopy(coordinates, i, newCoordinates, 0, coordinates.length
  320. - i);
  321. System.arraycopy(coordinates, 0, newCoordinates,
  322. coordinates.length - i, i);
  323. System.arraycopy(newCoordinates, 0, coordinates, 0, coordinates.length);
  324. }
  325. /**
  326. * Returns the index of <code>coordinate</code> in
  327. * <code>coordinates</code>. The first position is 0; the second, 1; etc.
  328. *
  329. * @param coordinate
  330. * the <code>Coordinate</code> to search for
  331. * @param coordinates
  332. * the array to search
  333. * @return the position of <code>coordinate</code>, or -1 if it is not
  334. * found
  335. */
  336. public static int indexOf(Coordinate coordinate, Coordinate[] coordinates) {
  337. for (int i = 0; i < coordinates.length; i++) {
  338. if (coordinate.equals(coordinates[i])) {
  339. return i;
  340. }
  341. }
  342. return -1;
  343. }
  344. /**
  345. * Extracts a subsequence of the input {@link Coordinate} array from indices
  346. * <code>start</code> to <code>end</code> (inclusive).
  347. *
  348. * @param pts
  349. * the input array
  350. * @param start
  351. * the index of the start of the subsequence to extract
  352. * @param end
  353. * the index of the end of the subsequence to extract
  354. * @return a subsequence of the input array
  355. */
  356. public static Coordinate[] extract(Coordinate[] pts, int start, int end) {
  357. int len = end - start + 1;
  358. Coordinate[] extractPts = new Coordinate[len];
  359. int iPts = 0;
  360. for (int i = start; i <= end; i++) {
  361. extractPts[iPts++] = pts[i];
  362. }
  363. return extractPts;
  364. }
  365. /**
  366. * SJ TODO faellt evtl weg, wenn coordinate durch DirectPosition
  367. * ausgetauscht wird
  368. *
  369. * @param aPositions
  370. * @return
  371. */
  372. public static Coordinate[] toCoordinateArray(
  373. List<DirectPosition> aPositions) {
  374. Coordinate[] rCoords = new Coordinate[aPositions.size()];
  375. for (int i = 0; i < aPositions.size(); i++) {
  376. rCoords[i] = new Coordinate(aPositions.get(i).getCoordinates());
  377. }
  378. return rCoords;
  379. }
  380. /**
  381. * Converts a Coordinate array into a list of Positions
  382. *
  383. * SJ: faellt evtl weg, wenn coordinate durch DirectPosition
  384. * ausgetauscht wird
  385. *
  386. * @param coordArray
  387. * @return
  388. */
  389. public static List<Position> toPositionList(
  390. CoordinateReferenceSystem crs, Coordinate[] coordArray) {
  391. List<Position> rList = new ArrayList<Position>();
  392. for (int i = 0; i < coordArray.length; i++) {
  393. DirectPositionImpl position = new DirectPositionImpl( crs, coordArray[i].getCoordinates() );
  394. rList.add( new PositionImpl((DirectPosition)position.clone()) );
  395. //rList.add(coordinateFactory.createPosition(coordArray[i].getCoordinates()));
  396. }
  397. return rList;
  398. }
  399. /**
  400. * Converts a Coordinate array into a list of DirectPositions
  401. *
  402. * @param crs
  403. * @param coordArray
  404. * @return
  405. */
  406. public static List<DirectPositionImpl> toDirectPositionList(
  407. CoordinateReferenceSystem crs, Coordinate[] coordArray) {
  408. List<DirectPositionImpl> rList = new ArrayList<DirectPositionImpl>();
  409. for (int i = 0; i < coordArray.length; i++) {
  410. rList.add(new DirectPositionImpl( crs, coordArray[i].getCoordinates() ));
  411. }
  412. return rList;
  413. }
  414. }