原理:一、点与区域的距离,根据回转数法判断,点到区域所有点形成的角度和为0,注意旋转方向要向一个方向,具体原理请百度
二、点与道路,根据点与线段的距离判断,获取点到所有线段的最小距离
1.实体类,存放点数据
public class Point{
/**
* x轴坐标 经度
*/
double x;
/**
* y轴坐标 纬度
*/
double y;
public Point setPoint(Point point){
this.x = point.getX();
this.y = point.getY();
return this;
}
public Point() {
}
public Point(Float[] point){
this.x = point[0];
this.y = point[1];
}
public Point(Double[] point) {
this.x = point[0];
this.y = point[1];
}
public Point(double x, double y) {
this.x = x;
this.y = y;
}
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
}
2.枚举类,存放默认参数
public enum PointRelationEnum {
POINT_IN_SCOPE(1,"在区域内"),
POINT_OUT_SCOPE(2,"在区域外"),
POINT_ON_BORDER(3,"在区域边界上");
/**
* 编码
*/
private int code;
/**
* 描述
*/
private String description;
PointRelationEnum(int code,String description){
this.code = code;
this.description = description;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
3.工具类
public class testUtil{
private static double earth_radius = 6378245.0;
/**
判断点与多边形的关系
根据回转法
**/
public static PointRelationEnum poinWithPolygon(Point point, List<Point> points) {
double px = point.getX(), py = point.getY(), sum = 0;
for (int i = 0, l = points.size(), j = l - 1; i < l; j = i, i++) {
double sx = points.get(i).getX(), sy = points.get(i).getY(), tx = points
.get(j).getX(), ty = points.get(j).getY();
// 点与多边形定点重合或多边形的边上
if ((sx - px) * (px - tx) >= 0 && (sy - px) * (px - tx) >= 0
&& (px - sx) * (ty - sy) == (py - sy) * (tx - sx)) {
return PointRelationEnum.POINT_ON_BORDER;
}
// 点与相邻顶点连线的夹角
double angle = Math.atan2(sy - py, sx - px)
- Math.atan2(ty - py, tx - px);
// 确保夹角不超出取值范围(-π 到 π)
if (angle >= Math.PI) {
angle = angle - Math.PI * 2;
} else if (angle <= -Math.PI) {
angle = angle + Math.PI * 2;
}
sum += angle;
}
// 计算回转数并判断点和多边形的几何关系
return Math.round(sum / Math.PI) == 0 ? PointRelationEnum.POINT_OUT_SCOPE: PointRelationEnum.POINT_IN_SCOPE;
}
// 计算地球上两点的距离
private static double getTwoPointsDistance(Point pointA, Point pointB) {
double distance = 0.0;
if (pointA != null && pointB != null) {
double x1 = 0.0, y1 = 0.0, x2 = 0.0, y2 = 0.0, dx1 = 0.0, dy1 = 0.0, dx2 = 0.0, dy2 = 0.0, a = earth_radius;
x1 = getLoop(pointA.getX(), -180, 180);
y1 = getRange(pointA.getY(), -90, 90);
x2 = getLoop(pointB.getX(), -180, 180);
y2 = getRange(pointB.getY(), -90, 90);
dx1 = degreeToRad(x1);
dy1 = degreeToRad(y1);
dx2 = degreeToRad(x2);
dy2 = degreeToRad(y2);
distance = a*Math.acos((Math.sin(dy1)*Math.sin(dy2) + Math.cos(dy1) * Math.cos(dy2) * Math.cos(dx2 - dx1)));
}
return distance;
}
/** 计算地球上一点与区域边界的最小距离 **/
private static double getPointRangeDistance(Point point, List<Point> points) {
double mindis = -1.0;
if (point != null && points != null && points.size() > 0) {
double a = 0.0;
double b = 0.0;
double c = 0.0;
double dis = 0.0;
for (int i = 0; i < points.size(); i++) {
if (i < points.size() - 1) {
a = get2PointsDistance(points.get(i), points.get(i + 1));
b = get2PointsDistance(points.get(i), point);
c = get2PointsDistance(points.get(i + 1), point);
}else{
a = get2PointsDistance(points.get(i), points.get(0));
b = get2PointsDistance(points.get(i), point);
c = get2PointsDistance(points.get(0), point);
}
dis = pointToLine(a, b, c);
if (mindis < 0) {
mindis = dis;
} else if (dis < mindis) {
mindis = dis;
}
}
}
return mindis;
}
/**
* 计算地球上一点与一段道路的最小距离
*/
public static double getPointLineDistance(Point point, List<Point> points) {
double mindis = -1.0;
if (point != null && points != null && points.size() > 0) {
double a = 0.0;
double b = 0.0;
double c = 0.0;
double dis = 0.0;
for (int i = 0; i < points.size()-1; i++) {
a = get2PointsDistance(points.get(i), points.get(i + 1));
b = get2PointsDistance(points.get(i), point);
c = get2PointsDistance(points.get(i + 1), point);
dis = pointToLine(a, b, c);
if (mindis < 0) {
mindis = dis;
} else if (dis < mindis) {
mindis = dis;
}
}
}
return mindis;
}
/**
* 计算点到线的距离
*/
private static double pointToLine(double a, double b, double c) {
double space = 0;
if (c <= 0.000001 || b <= 0.000001) {
space = 0;
return space;
}
if (c * c >= a * a + b * b) {
space = b;
return space;
}
if (b * b >= a * a + c * c) {
space = c;
return space;
}
/** 半周长 */
double p = (a + b + c) / 2;
/** 海伦公式算面积 **/
double s = Math.sqrt(p * (p - a) * (p - b) * (p - c));
space = 2 * s / a;
return space;
}
// 经度用
private static double getLoop(double lng, double a, double b) {
while (lng > b) {
lng -= b - a;
}
while (lng < a) {
lng += b - a;
}
return lng;
}
// 纬度用
private static double getRange(double lat, double a, double b) {
if (a != 0) {
lat = Math.max(lat, a);
}
if (b != 0) {
lat = Math.min(lat, b);
}
return lat;
}
// 将弧度转化为度
private static double degreeToRad(double n) {
return Math.PI * n / 180;
}
}