/src/org/mt4j/util/math/ConvexQuickHull2D.java

http://mt4j.googlecode.com/ · Java · 159 lines · 87 code · 13 blank · 59 comment · 20 complexity · d893d15bf956b14128a651108a69cfaf MD5 · raw file

  1. /***********************************************************************
  2. * mt4j Copyright (c) 2008 - 2009 C.Ruff, Fraunhofer-Gesellschaft All rights reserved.
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. *
  17. ***********************************************************************/
  18. package org.mt4j.util.math;
  19. import java.util.ArrayList;
  20. /**
  21. * The Class ConvexQuickHull2D.
  22. */
  23. public class ConvexQuickHull2D{
  24. /**
  25. * Gets the convex hull2 d.
  26. *
  27. * @param Vector3Ds the vector3 ds
  28. *
  29. * @return the convex hull2 d
  30. */
  31. @SuppressWarnings("unchecked")
  32. public static ArrayList<Vector3D> getConvexHull2D(ArrayList<Vector3D> Vector3Ds) {
  33. ArrayList<Vector3D> convexHull = new ArrayList<Vector3D>();
  34. if (Vector3Ds.size() < 3) return (ArrayList<Vector3D>) Vector3Ds.clone();
  35. // find extremals
  36. int minVector3D = -1, maxVector3D = -1;
  37. float minX = Float.POSITIVE_INFINITY;
  38. float maxX = Float.NEGATIVE_INFINITY;
  39. for (int i = 0; i < Vector3Ds.size(); i++) {
  40. if (Vector3Ds.get(i).getX() < minX) {
  41. minX = Vector3Ds.get(i).getX();
  42. minVector3D = i;
  43. }
  44. if (Vector3Ds.get(i).getX() > maxX) {
  45. maxX = Vector3Ds.get(i).getX();
  46. maxVector3D = i;
  47. }
  48. }
  49. Vector3D A = Vector3Ds.get(minVector3D);
  50. Vector3D B = Vector3Ds.get(maxVector3D);
  51. convexHull.add(A);
  52. convexHull.add(B);
  53. Vector3Ds.remove(A);
  54. Vector3Ds.remove(B);
  55. ArrayList<Vector3D> leftSet = new ArrayList<Vector3D>();
  56. ArrayList<Vector3D> rightSet = new ArrayList<Vector3D>();
  57. for (Vector3D p : Vector3Ds) {
  58. if (Vector3DLocation(A, B, p) == -1)
  59. leftSet.add(p);
  60. else
  61. rightSet.add(p);
  62. }
  63. hullSet(A,B,rightSet,convexHull);
  64. hullSet(B,A,leftSet,convexHull);
  65. return convexHull;
  66. }
  67. /*
  68. * Computes the square of the distance of Vector3D C to the segment defined by Vector3Ds AB
  69. */
  70. /**
  71. * Distance.
  72. *
  73. * @param A the a
  74. * @param B the b
  75. * @param C the c
  76. *
  77. * @return the float
  78. */
  79. private static float distance(Vector3D A, Vector3D B, Vector3D C) {
  80. float ABx = B.getX()-A.getX();
  81. float ABy = B.getY()-A.getY();
  82. float num = ABx*(A.getY()-C.getY())-ABy*(A.getX()-C.getX());
  83. if (num < 0) num = -num;
  84. return num;
  85. }
  86. /**
  87. * Hull set.
  88. *
  89. * @param A the a
  90. * @param B the b
  91. * @param set the set
  92. * @param hull the hull
  93. */
  94. private static void hullSet(Vector3D A, Vector3D B, ArrayList<Vector3D> set, ArrayList<Vector3D> hull) {
  95. int insertPosition = hull.indexOf(B);
  96. if (set.size() == 0) return;
  97. if (set.size() == 1) {
  98. Vector3D p = set.get(0);
  99. set.remove(p);
  100. hull.add(insertPosition,p);
  101. return;
  102. }
  103. float dist = Float.NEGATIVE_INFINITY;
  104. int furthestVector3D = -1;
  105. for (int i = 0; i < set.size(); i++) {
  106. Vector3D p = set.get(i);
  107. float distance = distance(A,B,p);
  108. if (distance > dist) {
  109. dist = distance;
  110. furthestVector3D = i;
  111. }
  112. }
  113. Vector3D P = set.get(furthestVector3D);
  114. set.remove(furthestVector3D);
  115. hull.add(insertPosition,P);
  116. // Determine who's to the left of AP
  117. ArrayList<Vector3D> leftSetAP = new ArrayList<Vector3D>();
  118. for (Vector3D M : set) {
  119. if (Vector3DLocation(A, P, M) == 1) {
  120. leftSetAP.add(M);
  121. }
  122. }
  123. // Determine who's to the left of PB
  124. ArrayList<Vector3D> leftSetPB = new ArrayList<Vector3D>();
  125. for (Vector3D M : set) {
  126. if (Vector3DLocation(P, B, M) == 1) {
  127. leftSetPB.add(M);
  128. }
  129. }
  130. hullSet(A,P,leftSetAP,hull);
  131. hullSet(P,B,leftSetPB,hull);
  132. }
  133. /**
  134. * Vector3 d location.
  135. *
  136. * @param A the a
  137. * @param B the b
  138. * @param P the p
  139. *
  140. * @return the float
  141. */
  142. private static float Vector3DLocation(Vector3D A, Vector3D B, Vector3D P) {
  143. float cp1 = (B.getX()-A.getX())*(P.getY()-A.getY()) - (B.getY()-A.getY())*(P.getX()-A.getX());
  144. return (cp1>0)?1:-1;
  145. }
  146. }