前提:坐标点需要有序,顺时针或逆时针(多边形),改编自百度的GeoUtil.js
public static boolean pnpoly2(Point point,List<Point> polygon){
int h = polygon.size();
boolean n = true;
int j = 0;
double g = 2e-10;
Point s, q;
Point e = point;
s = polygon.get(0);
for (int f = 1; f <= h; ++f) {
if (e.equals(s)) {
return n;
}
q = polygon.get((f % h));
if (e.getLat() < Math.min(s.getLat(), q.getLat()) || e.getLat() > Math.max(s.getLat(), q.getLat())) {
s = q;
continue;
}
if (e.getLat() > Math.min(s.getLat(), q.getLat()) && e.getLat() < Math.max(s.getLat(), q.getLat())) {
if (e.getLon() <= Math.max(s.getLon(), q.getLon())) {
if (s.getLat() ==(q.getLat()) && e.getLon() >= Math.min(s.getLon(), q.getLon())) {
return n;
}
if (s.getLon() ==(q.getLon()) ) {
if (s.getLon() ==(e.getLon()) ) {
return n;
} else {
++j;
}
} else {
double r = (e.getLat() - s.getLat()) * (q.getLon() - s.getLon()) / (q.getLat() - s.getLat()) + s.getLon();
if (Math.abs(e.getLon() - r) < g) {
return n;
}
if (e.getLon() < r) {
++j;
}
}
}
} else {
if (e.getLat() ==(q.getLat()) && e.getLon() <= q.getLon()) {
Point m = polygon.get(((f + 1) % h));
if (e.getLat() >= Math.min(s.getLat(), m.getLat()) && e.getLat() <= Math.max(s.getLat(), m.getLat())) {
++j;
} else {
j += 2;
}
}
}
s = q;
}
if (j % 2 == 0) {
return false;
} else {
return true;
}
}
class Point{
private double lon;
private double lat;
public double getLon() {
return lon;
}
public void setLon(Double lon) {
this.lon = lon;
}
public double getLat() {
return lat;
}
public void setLat(Double lat) {
this.lat = lat;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Point)){
return false;
}
Point p = (Point) obj;
boolean c1 = NumberUtil.equals(new BigDecimal(p.getLat()), new BigDecimal(this.getLat()));
boolean c2 = NumberUtil.equals(new BigDecimal(p.getLon()), new BigDecimal(this.getLon()));
if (c1 && c2){
return true;
}
return false;
}
@Override
public String toString() {
return "Point{" +
"lon=" + lon +
", lat=" + lat +
'}';
}
}