新增经纬度点计算工具

This commit is contained in:
wanggeng 2021-09-09 23:24:28 +08:00
parent f94288675d
commit e2dcc3e270
3 changed files with 378 additions and 0 deletions

View File

@ -0,0 +1,33 @@
package ink.wgink.util.point;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: Circle
* @Description:
* @Author: WangGeng
* @Date: 2019-08-09 22:54
* @Version: 1.0
**/
public class Circle {
private double r;
private Point point;
public double getR() {
return r;
}
public void setR(double r) {
this.r = r;
}
public Point getPoint() {
return point;
}
public void setPoint(Point point) {
this.point = point;
}
}

View File

@ -0,0 +1,41 @@
package ink.wgink.util.point;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: Point
* @Description:
* @Author: WangGeng
* @Date: 2019-08-09 22:44
* @Version: 1.0
**/
public class Point {
private double x;
private double y;
public Point() {
}
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;
}
}

View File

@ -0,0 +1,304 @@
package ink.wgink.util.point;
import java.math.BigDecimal;
import java.util.List;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: PointUtil
* @Description: 点工具类
* @Author: WangGeng
* @Date: 2019-08-09 22:43
* @Version: 1.0
**/
public class PointUtil {
private static final double EARTH_RADIUS = 637_1393.00D;
private static final double RADIAN = Math.PI / 180.00D;
private static final double HALF = 0.5D;
/**
* 点在多边形内
*
* @param point
* @param points
* @return
*/
public static boolean isPointInPoly(Point point, List<Point> points) {
int N = points.size();
//如果点位于多边形的顶点或边上也算做点在多边形内直接返回true
boolean boundOrVertex = true;
//cross points count of x
int intersectCount = 0;
//浮点类型计算时候与0比较时候的容差
double precision = 2e-10;
//neighbour bound vertices
Point p1, p2;
//当前点
Point p = point;
//left vertex
p1 = points.get(0);
//check all rays
for (int i = 1; i <= N; ++i) {
if (p.equals(p1)) {
//p is an vertex
return boundOrVertex;
}
//right vertex
p2 = points.get(i % N);
//ray is outside of our interests
if (p.getX() < Math.min(p1.getX(), p2.getX()) || p.getX() > Math.max(p1.getX(), p2.getX())) {
p1 = p2;
continue;//next ray left point
}
//ray is crossing over by the algorithm (common part of)
if (p.getX() > Math.min(p1.getX(), p2.getX()) && p.getX() < Math.max(p1.getX(), p2.getX())) {
//x is before of ray
if (p.getY() <= Math.max(p1.getY(), p2.getY())) {
//overlies on a horizontal ray
if (p1.getX() == p2.getX() && p.getY() >= Math.min(p1.getY(), p2.getY())) {
return boundOrVertex;
}
//ray is vertical
if (p1.getY() == p2.getY()) {
//overlies on a vertical ray
if (p1.getY() == p.getY()) {
return boundOrVertex;
} else {
//before ray
++intersectCount;
}
} else {
//cross point on the left side
//cross point of y
double xinters = (p.getX() - p1.getX()) * (p2.getY() - p1.getY()) / (p2.getX() - p1.getX()) + p1.getY();
//overlies on a ray
if (Math.abs(p.getY() - xinters) < precision) {
return boundOrVertex;
}
//before ray
if (p.getY() < xinters) {
++intersectCount;
}
}
}
} else {
//special case when ray is crossing through the vertex
//p crossing over p2
if (p.getX() == p2.getX() && p.getY() <= p2.getY()) {
//next vertex
Point p3 = points.get((i + 1) % N);
//p.x lies between p1.x & p3.x
if (p.getX() >= Math.min(p1.getX(), p3.getX()) && p.getX() <= Math.max(p1.getX(), p3.getX())) {
++intersectCount;
} else {
intersectCount += 2;
}
}
}
//next ray left point
p1 = p2;
}
if (intersectCount % 2 == 0) {
//偶数在多边形外
return false;
} else {
//奇数在多边形内
return true;
}
}
/**
* 判断是否在圆形内
* <p>
* 判断点与圆心之间的距离和圆半径的关系
*
* @param p
* @param c
* @return
*/
public static int distencePC(Point p, Circle c) {
int s;
double d2 = Math.hypot((p.getX() - c.getPoint().getX()), (p.getY() - c.getPoint().getY()));
double r = c.getR();
if (d2 > r) {
// 圆外
s = -1;
} else if (d2 < r) {
// 圆内
s = 1;
} else {
// 圆上
s = 0;
}
return s;
}
/**
* 计算距离Point的x为纬度y为经度
*
* @param point1
* @param point2
* @return
*/
public static double getDistance(Point point1, Point point2) {
double lat1 = point1.getX();
double lon1 = point1.getY();
double lat2 = point2.getX();
double lon2 = point2.getY();
double x, y, a, b, distance;
lat1 *= RADIAN;
lat2 *= RADIAN;
x = lat1 - lat2;
y = lon1 - lon2;
y *= RADIAN;
a = Math.sin(x * HALF);
b = Math.sin(y * HALF);
distance = EARTH_RADIUS * Math.asin(Math.sqrt(a * a + Math.cos(lat1) * Math.cos(lat2) * b * b)) / HALF;
return new BigDecimal(distance).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
}
/**
* 计算面积
*
* @param points
* @return
*/
public static double getSqua(List<Point> points) {
double area = 0;
int size = points.size();
if (size > 2) {
double LowX = 0.0;
double LowY = 0.0;
double MiddleX = 0.0;
double MiddleY = 0.0;
double HighX = 0.0;
double HighY = 0.0;
double AM = 0.0;
double BM = 0.0;
double CM = 0.0;
double AL = 0.0;
double BL = 0.0;
double CL = 0.0;
double AH = 0.0;
double BH = 0.0;
double CH = 0.0;
double CoefficientL = 0.0;
double CoefficientH = 0.0;
double ALtangent = 0.0;
double BLtangent = 0.0;
double CLtangent = 0.0;
double AHtangent = 0.0;
double BHtangent = 0.0;
double CHtangent = 0.0;
double ANormalLine = 0.0;
double BNormalLine = 0.0;
double CNormalLine = 0.0;
double OrientationValue = 0.0;
double AngleCos = 0.0;
double Sum1 = 0.0;
double Sum2 = 0.0;
double Count2 = 0;
double Count1 = 0;
double Sum = 0.0;
double Radius = 6378000;
for (int i = 0; i < size; i++) {
if (i == 0) {
LowX = points.get(size - 1).getX() * Math.PI / 180;
LowY = points.get(size - 1).getY() * Math.PI / 180;
MiddleX = points.get(0).getX() * Math.PI / 180;
MiddleY = points.get(0).getY() * Math.PI / 180;
HighX = points.get(1).getX() * Math.PI / 180;
HighY = points.get(1).getY() * Math.PI / 180;
} else if (i == size - 1) {
LowX = points.get(size - 2).getX() * Math.PI / 180;
LowY = points.get(size - 2).getY() * Math.PI / 180;
MiddleX = points.get(size - 1).getX() * Math.PI / 180;
MiddleY = points.get(size - 1).getY() * Math.PI / 180;
HighX = points.get(0).getX() * Math.PI / 180;
HighY = points.get(0).getY() * Math.PI / 180;
} else {
LowX = points.get(i - 1).getX() * Math.PI / 180;
LowY = points.get(i - 1).getY() * Math.PI / 180;
MiddleX = points.get(i).getX() * Math.PI / 180;
MiddleY = points.get(i).getY() * Math.PI / 180;
HighX = points.get(i + 1).getX() * Math.PI / 180;
HighY = points.get(i + 1).getY() * Math.PI / 180;
}
AM = Math.cos(MiddleY) * Math.cos(MiddleX);
BM = Math.cos(MiddleY) * Math.sin(MiddleX);
CM = Math.sin(MiddleY);
AL = Math.cos(LowY) * Math.cos(LowX);
BL = Math.cos(LowY) * Math.sin(LowX);
CL = Math.sin(LowY);
AH = Math.cos(HighY) * Math.cos(HighX);
BH = Math.cos(HighY) * Math.sin(HighX);
CH = Math.sin(HighY);
CoefficientL = (AM * AM + BM * BM + CM * CM) / (AM * AL + BM * BL + CM * CL);
CoefficientH = (AM * AM + BM * BM + CM * CM) / (AM * AH + BM * BH + CM * CH);
ALtangent = CoefficientL * AL - AM;
BLtangent = CoefficientL * BL - BM;
CLtangent = CoefficientL * CL - CM;
AHtangent = CoefficientH * AH - AM;
BHtangent = CoefficientH * BH - BM;
CHtangent = CoefficientH * CH - CM;
AngleCos = (AHtangent * ALtangent + BHtangent * BLtangent + CHtangent * CLtangent) / (
Math.sqrt(AHtangent * AHtangent + BHtangent * BHtangent + CHtangent * CHtangent)
* Math.sqrt(ALtangent * ALtangent + BLtangent * BLtangent
+ CLtangent * CLtangent));
AngleCos = Math.acos(AngleCos);
ANormalLine = BHtangent * CLtangent - CHtangent * BLtangent;
BNormalLine = 0 - (AHtangent * CLtangent - CHtangent * ALtangent);
CNormalLine = AHtangent * BLtangent - BHtangent * ALtangent;
if (AM != 0) {
OrientationValue = ANormalLine / AM;
} else if (BM != 0) {
OrientationValue = BNormalLine / BM;
} else {
OrientationValue = CNormalLine / CM;
}
if (OrientationValue > 0) {
Sum1 += AngleCos;
Count1++;
} else {
Sum2 += AngleCos;
Count2++;
//Sum +=2*Math.PI-AngleCos;
}
}
if (Sum1 > Sum2) {
Sum = Sum1 + (2 * Math.PI * Count2 - Sum2);
} else {
Sum = (2 * Math.PI * Count1 - Sum1) + Sum2;
}
//平方米
area = (Sum - (size - 2) * Math.PI) * Radius * Radius;
}
return Math.abs(area);
}
}