PageRenderTime 30ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

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

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