diff --git a/basic-util/src/main/java/ink/wgink/util/point/Circle.java b/basic-util/src/main/java/ink/wgink/util/point/Circle.java new file mode 100644 index 00000000..aace8028 --- /dev/null +++ b/basic-util/src/main/java/ink/wgink/util/point/Circle.java @@ -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; + } + +} diff --git a/basic-util/src/main/java/ink/wgink/util/point/Point.java b/basic-util/src/main/java/ink/wgink/util/point/Point.java new file mode 100644 index 00000000..f8a03b80 --- /dev/null +++ b/basic-util/src/main/java/ink/wgink/util/point/Point.java @@ -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; + } +} diff --git a/basic-util/src/main/java/ink/wgink/util/point/PointUtil.java b/basic-util/src/main/java/ink/wgink/util/point/PointUtil.java new file mode 100644 index 00000000..fcdb130c --- /dev/null +++ b/basic-util/src/main/java/ink/wgink/util/point/PointUtil.java @@ -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 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; + } + } + + /** + * 判断是否在圆形内 + *

+ * 判断点与圆心之间的距离和圆半径的关系 + * + * @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 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); + } + +}