JAVA凸包算法

呵呵,有点儿像当年看着没信号的电视。。。下一步要把它用在ArcGIS Server上。

代码
源码一:JarvisMarch.java

package mtn.uis.xaltin.convex;

import static java.lang.Math.abs;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

public class JarvisMarch {

private int count;

public int getCount() {
return count;
}

public void setCount(int count) {
this.count = count;
}

private static int MAX_ANGLE = 4;
private double currentMinAngle = 0;
private List<Point> hullPointList;
private List<Integer> indexList;
private PointFactory pf;
private Point[] ps;

public Point[] getPs() {
return ps;
}

private int firstIndex;

public int getFirstIndex() {
return firstIndex;
}

public JarvisMarch() {
this(10);
}

public JarvisMarch(int count) {
pf
= PointFactory.getInstance(count);
initialize();
}

public JarvisMarch(int[] x, int[] y) {
pf
= PointFactory.getInstance(x, y);
initialize();
}

private void initialize() {
hullPointList
= new LinkedList<Point>();
indexList
= new LinkedList<Integer>();
firstIndex
= pf.getFirstIndex();
ps
= pf.getPoints();
addToHull(firstIndex);
}

private void addToHull(int index) {
indexList.add(index);
hullPointList.add(ps[index]);
}

public int calculateHull() {
for (int i = getNextIndex(firstIndex); i != firstIndex; i = getNextIndex(i)) {
addToHull(i);
}
showHullPoints();
return 0;
}

private void showHullPoints() {
Iterator
<Point> itPoint = hullPointList.iterator();
Iterator
<Integer> itIndex = indexList.iterator();
Point p;
int i;
int index = 0;
System.out.println(
"The hull points is: -> ");
while (itPoint.hasNext()) {
i
= itIndex.next();
p
= itPoint.next();
System.out.print(i
+ ":(" + p.getX() + "," + p.getY() + ") ");
index
++;
if (index % 10 == 0)
System.out.println();
}
System.out.println();
System.out.println(
"****************************************************************");
System.out.println(
"The count of all hull points is " + index);
}

public int getNextIndex(int currentIndex) {
double minAngle = MAX_ANGLE;
double pseudoAngle;
int minIndex = 0;
for (int i = 0; i < ps.length; i++) {
if (i != currentIndex) {
pseudoAngle
= getPseudoAngle(ps[i].getX() - ps[currentIndex].getX(),
ps[i].getY()
- ps[currentIndex].getY());
if (pseudoAngle >= currentMinAngle && pseudoAngle < minAngle) {
minAngle
= pseudoAngle;
minIndex
= i;
}
else if (pseudoAngle == minAngle){
if((abs(ps[i].getX() - ps[currentIndex].getX()) >
abs(ps[minIndex].getX()
- ps[currentIndex].getX()))
|| (abs(ps[i].getY() - ps[currentIndex].getY()) >
abs(ps[minIndex].getY()
- ps[currentIndex].getY()))){
minIndex
= i;
}
}
}

}
currentMinAngle
= minAngle;
return minIndex;
}

public double getPseudoAngle(double dx, double dy) {
if (dx > 0 && dy >= 0)
return dy / (dx + dy);
if (dx <= 0 && dy > 0)
return 1 + (abs(dx) / (abs(dx) + dy));
if (dx < 0 && dy <= 0)
return 2 + (dy / (dx + dy));
if (dx >= 0 && dy < 0)
return 3 + (dx / (dx + abs(dy)));
throw new Error("Impossible");
}

}


源码二:Point.java
package mtn.uis.xaltin.convex;

public class Point {

// 定义点的x,y坐标,之所以是int类型,是为了日后可以在计算机屏幕上进行可视化。
private int x;
private int y;

// x,y的get方法
public int getX() {
return x;
}

public int getY() {
return y;
}
// 定义点到屏幕边缘的距离
private static double PADDING = 20;
// 点在屏幕中的范围
private static double POINT_RANGE = (800 - PADDING * 2);

// 默认构造方法,产生随机点
public Point() {
this.x = (int) ((Math.random() * POINT_RANGE) + PADDING);
this.y = (int) ((Math.random() * POINT_RANGE) + PADDING);
}

// 带参构造方法,可以实现手动输入固定点
public Point(int x, int y) {
this.x = x;
this.y = y;
}

// 覆写hashCode()和equals()方法,实现比较和Hash
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result
= prime * result + x;
result
= prime * result + y;
return result;
}

@Override
public boolean equals(Object obj) {
Point other
= (Point) obj;
if ((x == other.x) && (y == other.y))
return true;

return false;
}


}

源码三:PointFactory.java
package mtn.uis.xaltin.convex;


public class PointFactory {
/**
* 单例模式,大批量产生Point,也可以手动产生Point
*/
private Point[] points = null;
private int newIndex;
private int firstIndex = 0;

public Point[] getPoints() {
return points;
}

public int getFirstIndex() {
return firstIndex;
}

public static PointFactory getInstance() {
return new PointFactory();
}

public static PointFactory getInstance(int count) {
return new PointFactory(count);
}

public static PointFactory getInstance(int[] x, int[] y) {
return new PointFactory(x, y);
}

private PointFactory() {
this(10);
}

private PointFactory(int count) {
points
= new Point[count];
for (int i = 0; i < count; i++) {
points[i]
= new Point();
newIndex
= i;
validatePoints();
}
firstIndex
= getFirstPoint();
}

public PointFactory(int[] x, int[] y) {
points
= new Point[y.length];
for (int i = 0; i < y.length; i++) {
points[i]
= new Point(x[i], y[i]);
}
firstIndex
= getFirstPoint();
}

private void validatePoints() {
for(int i = 0; i < newIndex; i++) {
if(points[i].equals(points[newIndex])) {
points[newIndex]
= new Point();
validatePoints();
}
}
}

public int getFirstPoint() {
int minIndex = 0;
for (int i = 1; i < points.length; i++) {
if (points[i].getY() < points[minIndex].getY()) {
minIndex
= i;
}
else if ((points[i].getY() == points[minIndex].getY())
&& (points[i].getX() < points[minIndex].getX())) {
minIndex
= i;
}
}
return minIndex;
}

}

源码四:Test.java(主函数)

package mtn.uis.xaltin.convex;


public class Test {
public static void main(String[] args) {
long start = System.currentTimeMillis();
JarvisMarch j
= new JarvisMarch(100000);
Point[] points
= j.getPs();
int firstIndex = j.getFirstIndex();

// for (int i = 0; i < points.length; i++) {
// System.out.print(i + ":(" + points[i].getX() + "," + points[i].getY() + ") ");
// if((i+1) % 10 == 0) {
// System.out.println();
// }
// }
// System.out.println();
// System.out.println("*****************************************************************");
System.out.println("the first point is: " + firstIndex + ":(" +
points[firstIndex].getX()
+ "," + points[firstIndex].getY() + ")");

System.out.println(
"*****************************************************************");
j.calculateHull();
System.out.println(
"The total running time is " + (System.currentTimeMillis() - start) + " millis.");
}
}
原文地址:https://www.cnblogs.com/frostbelt/p/1764192.html