| New file |
| | |
| | | package org.springblade.common.utils; |
| | | |
| | | import java.awt.geom.Point2D; |
| | | import java.math.BigDecimal; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 根据经纬度计算面积工具类 |
| | | * |
| | | * @author hwl |
| | | * @version 1.0.0 2018-01-17 |
| | | */ |
| | | public class PolyginArea { |
| | | |
| | | // 地球半径 - 米 |
| | | // 源码中使用半径为 6367460.0; |
| | | private static double earthRadiusMeters = 6371000.0; |
| | | private static double metersPerDegree = 2.0 * Math.PI * earthRadiusMeters / 360.0; |
| | | private static double radiansPerDegree = Math.PI / 180.0; |
| | | private static double degreesPerRadian = 180.0 / Math.PI; |
| | | |
| | | // /** |
| | | // * 传入经纬度集合计算面积 |
| | | // * @param points |
| | | // */ |
| | | // private void calculateArea(List<double[]> points) { |
| | | // if (points.size() > 2) { |
| | | // double areaMeters2 = PlanarPolygonAreaMeters2(points); |
| | | // // if (areaMeters2 > 1000000.0) { |
| | | // areaMeters2 = SphericalPolygonAreaMeters2(points); |
| | | // System.out.println("面积为:" + areaMeters2 + "(平方米)"); |
| | | // // } |
| | | // |
| | | // } |
| | | // } |
| | | |
| | | /** |
| | | * 球面多边形面积计算 |
| | | * |
| | | * @param points |
| | | * @return |
| | | */ |
| | | private double SphericalPolygonAreaMeters2(List<double[]> points) { |
| | | double totalAngle = 0.0; |
| | | for (int i = 0; i < points.size(); i++) { |
| | | int j = (i + 1) % points.size(); |
| | | int k = (i + 2) % points.size(); |
| | | totalAngle += Angle(points.get(i), points.get(j), points.get(k)); |
| | | } |
| | | |
| | | double planarTotalAngle = (points.size() - 2) * 180.0; |
| | | double sphericalExcess = totalAngle - planarTotalAngle; |
| | | |
| | | if (sphericalExcess > 420.0) { |
| | | totalAngle = points.size() * 360.0 - totalAngle; |
| | | sphericalExcess = totalAngle - planarTotalAngle; |
| | | } else if (sphericalExcess > 300.0 && sphericalExcess < 420.0) { |
| | | sphericalExcess = Math.abs(360.0 - sphericalExcess); |
| | | } |
| | | |
| | | return sphericalExcess * radiansPerDegree * earthRadiusMeters |
| | | * earthRadiusMeters; |
| | | } |
| | | |
| | | /** |
| | | * 角度 |
| | | * |
| | | * @param p1 |
| | | * @param p2 |
| | | * @param p3 |
| | | * @return |
| | | */ |
| | | private double Angle(double[] p1, double[] p2, double[] p3) { |
| | | double bearing21 = Bearing(p2, p1); |
| | | double bearing23 = Bearing(p2, p3); |
| | | double angle = bearing21 - bearing23; |
| | | if (angle < 0.0) { |
| | | angle += 360.0; |
| | | } |
| | | return angle; |
| | | } |
| | | |
| | | /** |
| | | * 方向 |
| | | * |
| | | * @param from |
| | | * @param to |
| | | * @return |
| | | */ |
| | | private double Bearing(double[] from, double[] to) { |
| | | double lat1 = from[1] * radiansPerDegree; |
| | | double lon1 = from[0] * radiansPerDegree; |
| | | double lat2 = to[1] * radiansPerDegree; |
| | | double lon2 = to[0] * radiansPerDegree; |
| | | double angle = -Math.atan2( |
| | | Math.sin(lon1 - lon2) * Math.cos(lat2), |
| | | Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) |
| | | * Math.cos(lat2) * Math.cos(lon1 - lon2)); |
| | | if (angle < 0.0) { |
| | | angle += Math.PI * 2.0; |
| | | } |
| | | angle = angle * degreesPerRadian; |
| | | return angle; |
| | | } |
| | | |
| | | /*** |
| | | * 平面多边形面积 |
| | | * |
| | | * @param points |
| | | * Point2D.Double |
| | | * @return |
| | | * */ |
| | | public static double getAreaByxy(List<Point2D.Double> points) { |
| | | double a = 0.0; |
| | | if(points.size() > 2){ |
| | | for (int i = 0; i < points.size(); ++i) { |
| | | int j = (i + 1) % points.size(); |
| | | double xi = points.get(i).x * metersPerDegree |
| | | * Math.cos(points.get(i).y * radiansPerDegree); |
| | | double yi = points.get(i).y * metersPerDegree; |
| | | double xj = points.get(j).x * metersPerDegree |
| | | * Math.cos(points.get(j).y * radiansPerDegree); |
| | | double yj = points.get(j).y * metersPerDegree; |
| | | a += xi * yj - xj * yi; |
| | | } |
| | | } |
| | | a = BigDecimal.valueOf(Math.abs(a / 2.0)).setScale(1,BigDecimal.ROUND_DOWN).doubleValue(); |
| | | return a; |
| | | } |
| | | |
| | | public static void main(String[] args) { |
| | | List<Point2D.Double> points = new ArrayList<Point2D.Double>(); |
| | | |
| | | /** |
| | | * x1 = 84.86258; y1 = 44.46333; |
| | | * |
| | | * x2 = 84.86075; y2 = 44.45999; |
| | | * |
| | | * x3 = 84.86229; y3 = 44.45971; |
| | | * |
| | | * x4 = 84.86414; y4 = 44.46309; |
| | | */ |
| | | // String s = "112.5293197631836,37.868892669677734;" + |
| | | // "112.5170669555664,37.8605842590332;" + |
| | | // "112.52099609375,37.849857330322266;" + |
| | | // "112.54137420654297,37.85125732421875;" + |
| | | // "112.53511810302734,37.858699798583984"; |
| | | String s = "114.917883,25.816108;114.917207,25.815577;114.918162,25.815519;114.917883,25.816108"; |
| | | String[] s1 = s.split(";"); |
| | | for (String ss : s1) { |
| | | String[] temp = ss.split(","); |
| | | Point2D.Double point = new Point2D.Double(Double.parseDouble(temp[0]), |
| | | Double.parseDouble(temp[1])); |
| | | points.add(point); |
| | | System.out.println(temp[1] + "," + temp[0]); |
| | | } |
| | | PolyginArea tp = new PolyginArea(); |
| | | double area = tp.getAreaByxy(points); |
| | | System.out.println("面积是: " + area); |
| | | } |
| | | |
| | | } |