• 【Java开发笔记】JAVA根据经纬度坐标点集合计算面积


    前言

    写着玩的,随便记录一下思路什么的

    代码

    PolygonAreaUtil(工具类)

    package com.area.util;
    
    import com.area.entity.Location;
    
    import java.util.List;
    
    /**
     * @author Yuang
     */
    public class PolygonAreaUtil {
    
        /**
         * 球面积计算公式
         *
         * @param locationList
         * @return
         */
        public static double calculatePolygonArea(List<Location> locationList) {
            double area = 0;
            int size = locationList.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 = locationList.get(size - 1).getLon().doubleValue() * Math.PI / 180;
                        LowY = locationList.get(size - 1).getLat().doubleValue() * Math.PI / 180;
                        MiddleX = locationList.get(0).getLon().doubleValue() * Math.PI / 180;
                        MiddleY = locationList.get(0).getLat().doubleValue() * Math.PI / 180;
                        HighX = locationList.get(1).getLon().doubleValue() * Math.PI / 180;
                        HighY = locationList.get(1).getLat().doubleValue() * Math.PI / 180;
                    } else if (i == size - 1) {
                        LowX = locationList.get(size - 2).getLon().doubleValue() * Math.PI / 180;
                        LowY = locationList.get(size - 2).getLat().doubleValue() * Math.PI / 180;
                        MiddleX = locationList.get(size - 1).getLon().doubleValue() * Math.PI / 180;
                        MiddleY = locationList.get(size - 1).getLat().doubleValue() * Math.PI / 180;
                        HighX = locationList.get(0).getLon().doubleValue() * Math.PI / 180;
                        HighY = locationList.get(0).getLat().doubleValue() * Math.PI / 180;
                    } else {
                        LowX = locationList.get(i - 1).getLon().doubleValue() * Math.PI / 180;
                        LowY = locationList.get(i - 1).getLat().doubleValue() * Math.PI / 180;
                        MiddleX = locationList.get(i).getLon().doubleValue() * Math.PI / 180;
                        MiddleY = locationList.get(i).getLat().doubleValue() * Math.PI / 180;
                        HighX = locationList.get(i + 1).getLon().doubleValue() * Math.PI / 180;
                        HighY = locationList.get(i + 1).getLat().doubleValue() * 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);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150

    Location(实体类)

    package com.area.entity;
    
    import java.math.BigDecimal;
    
    /**
     * 经纬度坐标实体类
     *
     */
    public class Location {
    
        private BigDecimal lon;
    
        private BigDecimal lat;
    
        public Location() {
        }
    
        public Location(BigDecimal lon, BigDecimal lat) {
            this.lon = lon;
            this.lat = lat;
        }
    
        public BigDecimal getLon() {
            return lon;
        }
    
        public void setLon(BigDecimal lon) {
            this.lon = lon;
        }
    
        public BigDecimal getLat() {
            return lat;
        }
    
        public void setLat(BigDecimal lat) {
            this.lat = lat;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    areaTest (Main方法)

    package com.area.demo;
    
    import com.area.entity.Location;
    import com.area.util.PolygonAreaUtil;
    import java.math.BigDecimal;
    import java.util.ArrayList;
    import java.util.List;
    
    
    public class areaTest {
    
        public static void main(String[] args) {
            
            //依次存入经纬度坐标
            double[] doubles = new double[]{116.319993,39.980839,116.321087,39.980848,116.321194,39.979771,116.321114,39.979729,
                    116.321141,39.979536,116.321199,39.979495,116.3212,39.979212,116.320057,39.979237,116.319993,39.980838};
            Location location = null;
            List<Location> locationList = new ArrayList<>();
            //循环添加元素
            for (int i = 0; i < doubles.length; i += 2) {
                //将double类型转换成字符串格式
                String lon = String.valueOf(doubles[i]);
                String lat = String.valueOf(doubles[i+1]);
                //保存经纬度
                location = new Location();
                location.setLon(new BigDecimal(lon));
                location.setLat(new BigDecimal(lat));
                //添加到List集合
                locationList.add(location);
            }
            double area = PolygonAreaUtil.calculatePolygonArea(locationList);
            System.out.println("面积为: " + area + "平方米");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    补充:

    1、经纬度坐标系一共有三种坐标系,网上有很多这三种坐标系之间转换的工具类

    2、MySQL有字段类型为point,是专门存储经纬度坐标的

    3、Java有专门处理空间数据的工具类

    4、前端实现比较简单

    拓展

    三种经纬度坐标系:大地经纬度 - 不同经纬度、坐标系的区别 - 八九网

    MySql的point字段:mysql point类型的简单使用 - 简书

    Java中的Point对象:Point (Java SE 11 & JDK 11 )

    java.math包中提供的API类BigDecimalJava之BigDecimal详解 - HuaToDevelop - 博客园

  • 相关阅读:
    从Spring为什么要用IoC的支点,我撬动了整个Spring的源码脉络
    【香橙派】Orange pi AIpro开发板使用之一键部署springboot项目
    python自学入门(打卡五)2022-10-29
    2022年首家民营征信机构浙江同信获企业征信备案公示
    JavaScript中函数的声明方式、作用域
    go-cqhttp系列教程-go-cqhttp安装
    HTML5期末大作业——HTML+CSS+JavaScript平遥古城旅游景点介绍(6页)
    1.Kubeadm部署K8s集群
    c++基础知识-数据类型(详解)
    SQL sever中表数据管理
  • 原文地址:https://blog.csdn.net/qq_48556886/article/details/127862936