PageRenderTime 24ms CodeModel.GetById 13ms app.highlight 7ms RepoModel.GetById 1ms app.codeStats 0ms

/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 ***********************************************************************/
 18package org.mt4j.util.math;
 19
 20import java.util.ArrayList;
 21
 22/**
 23 * The Class ConvexQuickHull2D.
 24 */
 25public class ConvexQuickHull2D{
 26 
 27  /**
 28   * Gets the convex hull2 d.
 29   * 
 30   * @param Vector3Ds the vector3 ds
 31   * 
 32   * @return the convex hull2 d
 33   */
 34  @SuppressWarnings("unchecked")
 35public static ArrayList<Vector3D> getConvexHull2D(ArrayList<Vector3D> Vector3Ds) {
 36    ArrayList<Vector3D> convexHull = new ArrayList<Vector3D>();
 37    if (Vector3Ds.size() < 3) return (ArrayList<Vector3D>) Vector3Ds.clone();
 38    // find extremals
 39    int minVector3D = -1, maxVector3D = -1;
 40    float minX = Float.POSITIVE_INFINITY;
 41    float maxX = Float.NEGATIVE_INFINITY;
 42    for (int i = 0; i < Vector3Ds.size(); i++) {
 43      if (Vector3Ds.get(i).getX() < minX) {
 44        minX = Vector3Ds.get(i).getX();
 45        minVector3D = i;
 46      } 
 47      if (Vector3Ds.get(i).getX() > maxX) {
 48        maxX = Vector3Ds.get(i).getX();
 49        maxVector3D = i;       
 50      }
 51    }
 52    Vector3D A = Vector3Ds.get(minVector3D);
 53    Vector3D B = Vector3Ds.get(maxVector3D);
 54    convexHull.add(A);
 55    convexHull.add(B);
 56    Vector3Ds.remove(A);
 57    Vector3Ds.remove(B);
 58    
 59    ArrayList<Vector3D> leftSet = new ArrayList<Vector3D>();
 60    ArrayList<Vector3D> rightSet = new ArrayList<Vector3D>();
 61
 62      for (Vector3D p : Vector3Ds) {
 63          if (Vector3DLocation(A, B, p) == -1)
 64              leftSet.add(p);
 65          else
 66              rightSet.add(p);
 67      }
 68    hullSet(A,B,rightSet,convexHull);
 69    hullSet(B,A,leftSet,convexHull);
 70    
 71    return convexHull;
 72  }
 73  
 74  /*
 75   * Computes the square of the distance of Vector3D C to the segment defined by Vector3Ds AB
 76   */
 77  /**
 78   * Distance.
 79   * 
 80   * @param A the a
 81   * @param B the b
 82   * @param C the c
 83   * 
 84   * @return the float
 85   */
 86  private static float distance(Vector3D A, Vector3D B, Vector3D C) {
 87    float ABx = B.getX()-A.getX();
 88    float ABy = B.getY()-A.getY();
 89    float num = ABx*(A.getY()-C.getY())-ABy*(A.getX()-C.getX());
 90    if (num < 0) num = -num;
 91    return num;
 92  }
 93  
 94  /**
 95   * Hull set.
 96   * 
 97   * @param A the a
 98   * @param B the b
 99   * @param set the set
100   * @param hull the hull
101   */
102  private static void hullSet(Vector3D A, Vector3D B, ArrayList<Vector3D> set, ArrayList<Vector3D> hull) {
103    int insertPosition = hull.indexOf(B);
104    if (set.size() == 0) return;
105    if (set.size() == 1) {
106      Vector3D p = set.get(0);
107      set.remove(p);
108      hull.add(insertPosition,p);
109      return;
110    }
111    float dist = Float.NEGATIVE_INFINITY;
112    int furthestVector3D = -1;
113    for (int i = 0; i < set.size(); i++) {
114      Vector3D p = set.get(i);
115      float distance  = distance(A,B,p);
116      if (distance > dist) {
117        dist = distance;
118        furthestVector3D = i;
119      }
120    }
121    Vector3D P = set.get(furthestVector3D);
122    set.remove(furthestVector3D);
123    hull.add(insertPosition,P);
124    
125    // Determine who's to the left of AP
126    ArrayList<Vector3D> leftSetAP = new ArrayList<Vector3D>();
127      for (Vector3D M : set) {
128          if (Vector3DLocation(A, P, M) == 1) {
129              leftSetAP.add(M);
130          }
131      }
132    
133    // Determine who's to the left of PB
134    ArrayList<Vector3D> leftSetPB = new ArrayList<Vector3D>();
135      for (Vector3D M : set) {
136          if (Vector3DLocation(P, B, M) == 1) {
137              leftSetPB.add(M);
138          }
139      }
140    hullSet(A,P,leftSetAP,hull);
141    hullSet(P,B,leftSetPB,hull);
142    
143  }
144
145  /**
146   * Vector3 d location.
147   * 
148   * @param A the a
149   * @param B the b
150   * @param P the p
151   * 
152   * @return the float
153   */
154  private static float Vector3DLocation(Vector3D A, Vector3D B, Vector3D P) {
155    float cp1 = (B.getX()-A.getX())*(P.getY()-A.getY()) - (B.getY()-A.getY())*(P.getX()-A.getX());
156    return (cp1>0)?1:-1;
157  }
158  
159}