【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);
    }
}

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;
    }
}

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、MySQL有字段类型为point,是专门存储经纬度坐标的

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

4、前端实现比较简单

拓展

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

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

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

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

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

KEY的航行日记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值