package org.andengine.extension.physics.box2d.util.hull;
import com.badlogic.gdx.math.Vector2;
/**
* (c) 2010 Nicolas Gramlich
* (c) 2011 Zynga Inc.
*
* @author Nicolas Gramlich
* @since 14:00:50 - 14.09.2010
* @see http://www.iti.fh-flensburg.de/lang/algorithmen/geo/
*/
public class GrahamScan extends BaseHullAlgorithm {
// ===========================================================
// Constants
// ===========================================================
// ===========================================================
// Fields
// ===========================================================
// ===========================================================
// Constructors
// ===========================================================
// ===========================================================
// Getter & Setter
// ===========================================================
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
@Override
public int computeHull(final Vector2[] pVertices) {
this.mVertices = pVertices;
this.mVertexCount = pVertices.length;
if (this.mVertexCount < 3) {
return this.mVertexCount;
}
this.mHullVertexCount = 0;
this.grahamScan();
return this.mHullVertexCount;
}
// ===========================================================
// Methods
// ===========================================================
private void grahamScan() {
this.swap(0, this.indexOfLowestVertex());
final Vector2 pl = new Vector2(this.mVertices[0]);
this.makeAllVerticesRelativeTo(pl);
this.sort();
this.makeAllVerticesRelativeTo(new Vector2(pl).mul(-1));
int i = 3;
int k = 3;
while (k < this.mVertexCount) {
this.swap(i, k);
while (!this.isConvex(i - 1)) {
this.swap(i - 1, i--);
}
k++;
i++;
}
this.mHullVertexCount = i;
}
private void makeAllVerticesRelativeTo(final Vector2 pVector) {
final Vector2[] vertices = this.mVertices;
final int vertexCount = this.mVertexCount;
final Vector2 vertexCopy = new Vector2(pVector); // necessary, as pVector might be in mVertices[]
for (int i = 0; i < vertexCount; i++) {
vertices[i].sub(vertexCopy);
}
}
private boolean isConvex(final int pIndex) {
final Vector2[] vertices = this.mVertices;
return Vector2Util.isConvex(vertices[pIndex], vertices[pIndex - 1], vertices[pIndex + 1]);
}
private void sort() {
this.quicksort(1, this.mVertexCount - 1); // without Vertex 0
}
private void quicksort(final int pFromIndex, final int pToIndex) {
final Vector2[] vertices = this.mVertices;
int i = pFromIndex;
int j = pToIndex;
final Vector2 q = vertices[(pFromIndex + pToIndex) / 2];
while (i <= j) {
while (Vector2Util.isLess(vertices[i], q)) {
i++;
}
while (Vector2Util.isLess(q, vertices[j])) {
j--;
}
if (i <= j) {
this.swap(i++, j--);
}
}
if (pFromIndex < j) {
this.quicksort(pFromIndex, j);
}
if (i < pToIndex) {
this.quicksort(i, pToIndex);
}
}
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
}