package org.jzy3d.maths.algorithms.convexhull;
import java.util.ArrayDeque;
import java.util.Deque;
import org.jzy3d.maths.Coord2d;
import org.jzy3d.maths.algorithms.convexhull.algorithms.XYComparator;
import org.jzy3d.maths.algorithms.convexhull.utils.QuickSort;
/**
* Luokka kääntyy, muttei toimi vielä. Edit: Lista on muutettu taulukoksi.
*
* @author Ossi Lehto
*/
public class JarvisMarch implements ConvexHullFunction {
/**
* Palauttaa pinossa peitteen pisteet niin, että ensimmäinen ja viimeinen
* alkio ovat samat.
*
*
* .@pre {Q.length > 1}
*/
@Override
public Deque getConvexHull(Coord2d[] Q) {
QuickSort.sort(Q, new XYComparator());
int lowest = 0;
int highest = Q.length - 1;
int n = 0;
Deque collinear = new ArrayDeque();
boolean pass = true;
// Palautettava pino.
Deque S = new ArrayDeque();
S.push(Q[0]);
/**
* Oikea ketju *
*/
while (n < highest) {
n++;
/* Kokeillaan pistettä n seuraavaksi palautettavaksi pisteeksi */
for (int i = n + 1; i <= Q.length - 1; i++) {
// löytyi piste, joka oli viivan väärällä puolella
if (crossProduct(S.peek(), Q[n], Q[i]) < 0) {
pass = false;
break; // lopettaa ristitulojen tarkastamisen, pisteen vaihto
}
// löytyi kollineaarinen piste
if (crossProduct(S.peek(), Q[n], Q[i]) == 0) {
collinear.push(i);
}
} // for
// seuraava piste löydetty
if (pass) {
// Kollienaarisista pisteistä otetaan viimeiseksi lisätty,
// koska se on kauimmainen
if (!collinear.isEmpty()) {
n = collinear.pop();
}
S.push(Q[n]);
} // if
// alustetaan tarkistus
while (!collinear.isEmpty()) {
collinear.pop();
}
pass = true;
} // while
/**
* Vasen ketju, tässä vaiheessa n==highest *
*/
while (n > lowest) {
n--;
// Kokeillaan pistettä n seuraavaksi palautettavaksi pisteeksi
for (int i = n - 1; i >= 0; i--) {
// löytyi piste, joka oli viivan väärällä puolella
if (crossProduct(Q[n], S.peek(), Q[i]) > 0) {
pass = false;
// lopettaa ristitulojen tarkastamisen, pisteen vaihto
break;
}
// löytyi kollineaarinen piste
if (crossProduct(Q[n], S.peek(), Q[i]) == 0) {
collinear.push(i);
}
} // for
// seuraava piste löydetty
if (pass) {
// Kollienaarisista pisteistä otetaan viimeiseksi lisätty,
// koska se on kauimmainen
if (!collinear.isEmpty()) {
n = collinear.pop();
}
S.push(Q[n]);
} // if
// alustetaan tarkistus
while (!collinear.isEmpty()) {
collinear.pop();
}
pass = true;
} // while
return S;
}
/**
* @.pre {true}
*/
public JarvisMarch() {
}
/**
* Laskee kolmion p1p2p3 alan
*/
private double crossProduct(Coord2d p1, Coord2d p2, Coord2d p3) {
return (p2.getX() - p1.getX()) * (p3.getY() - p1.getY()) - (p3.getX() - p1.getX()) * (p2.getY() - p1.getY());
}
} // end of class
Ads help maintain this website.