All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.ymate.framework.commons.GeoUtils Maven / Gradle / Ivy

There is a newer version: 2.0.8
Show newest version
/*
 * Copyright 2007-2016 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.ymate.framework.commons;

import org.apache.commons.lang.NullArgumentException;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;

/**
 * @author 刘镇 ([email protected]) on 16/12/12 下午3:27
 * @version 1.0
 */
public class GeoUtils {

    /**
     * 地球半径
     */
    private static final double EARTH_RADIUS = 6378.137;

    /**
     * @param d 值
     * @return 弧度单位
     */
    private static double __rad(double d) {
        return d * Math.PI / 180.0;
    }

    /**
     * @param p1 坐标点1
     * @param p2 坐标点2
     * @return 计算两点间的距离(米)
     */
    public static double distance(Point p1, Point p2) {
        double _lat1 = __rad(p1.getLatitude());
        double _lat2 = __rad(p2.getLatitude());
        return Math.round(2 * Math.asin(Math.sqrt(Math.pow(Math.sin((_lat1 - _lat2) / 2), 2) + Math.cos(_lat1) * Math.cos(_lat2) * Math.pow(Math.sin((__rad(p1.getLongitude()) - __rad(p2.getLongitude())) / 2), 2))) * EARTH_RADIUS * 10000) / 10;
    }

    /**
     * @param point    坐标点
     * @param distance 距离(米)
     * @return 返回从坐标点到直定距离的矩形范围
     */
    public static Bounds rectangle(Point point, long distance) {
        if (point == null || distance <= 0) {
            return new Bounds();
        }
        float _delta = 111000;
        if (point.getLatitude() != 0 && point.getLongitude() != 0) {
            double lng1 = point.getLongitude() - distance / Math.abs(Math.cos(Math.toRadians(point.getLatitude())) * _delta);
            double lng2 = point.getLongitude() + distance / Math.abs(Math.cos(Math.toRadians(point.getLatitude())) * _delta);
            double lat1 = point.getLatitude() - (distance / _delta);
            double lat2 = point.getLatitude() + (distance / _delta);
            return new Bounds(new Point(lng1, lat1), new Point(lng2, lat2));
        } else {
            double lng1 = point.getLongitude() - distance / _delta;
            double lng2 = point.getLongitude() + distance / _delta;
            double lat1 = point.getLatitude() - (distance / _delta);
            double lat2 = point.getLatitude() + (distance / _delta);
            return new Bounds(new Point(lng1, lat1), new Point(lng2, lat2));
        }
    }

    /**
     * 地理坐标点
     */
    public static class Point {

        /**
         * 经度
         */
        private double longitude;

        /**
         * 纬度
         */
        private double latitude;

        public Point(double longitude, double latitude) {
            this.longitude = longitude;
            this.latitude = latitude;
        }

        public double getLongitude() {
            return longitude;
        }

        public void setLongitude(double longitude) {
            this.longitude = longitude;
        }

        public double getLatitude() {
            return latitude;
        }

        public void setLatitude(double latitude) {
            this.latitude = latitude;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }
            Point point = (Point) o;
            return new EqualsBuilder()
                    .append(longitude, point.longitude)
                    .append(latitude, point.latitude)
                    .isEquals();
        }

        @Override
        public int hashCode() {
            return new HashCodeBuilder(17, 37)
                    .append(longitude)
                    .append(latitude)
                    .toHashCode();
        }

        @Override
        public String toString() {
            return "Point{longitude=" + longitude + ", latitude=" + latitude + '}';
        }
    }

    /**
     * 地理坐标矩形区域
     */
    public static class Bounds {

        /**
         * 左下(西南)角坐标点
         */
        private Point southWest;

        /**
         * 右上(东北)角坐标点
         */
        private Point northEast;

        /**
         * 空矩形
         */
        public Bounds() {
        }

        /**
         * 取两个矩形区域的并集
         *
         * @param first 第一个矩形区域
         * @param other 另一个矩形区域
         */
        public Bounds(Bounds first, Bounds other) {
            if (first == null || first.isEmpty() || other == null || other.isEmpty()) {
                throw new NullArgumentException("bounds");
            }
            this.southWest = new Point(Math.min(first.southWest.getLongitude(), other.southWest.getLongitude()), Math.min(first.southWest.getLatitude(), other.southWest.getLatitude()));
            //
            this.northEast = new Point(Math.max(first.northEast.getLongitude(), other.northEast.getLongitude()), Math.max(first.northEast.getLatitude(), other.northEast.getLatitude()));
        }

        public Bounds(Point southWest, Point northEast) {
            this.southWest = southWest;
            this.northEast = northEast;
        }

        public Point getSouthWest() {
            return southWest;
        }

        public void setSouthWest(Point southWest) {
            this.southWest = southWest;
        }

        public Point getNorthEast() {
            return northEast;
        }

        public void setNorthEast(Point northEast) {
            this.northEast = northEast;
        }

        /**
         * @return 返回矩形的中心点
         */
        public Point getCenter() {
            return new Point((southWest.getLongitude() + northEast.getLongitude()) / 2, (southWest.getLatitude() + northEast.getLatitude()) / 2);
        }

        /**
         * @return 矩形区域是否为空
         */
        public boolean isEmpty() {
            return southWest == null || northEast == null;
        }

        /**
         * @param point 地理坐标点
         * @return 地理坐标点是否位于此矩形内
         */
        public boolean containsPoint(Point point) {
            return !isEmpty() && (point.getLongitude() >= southWest.getLongitude() && point.getLongitude() <= northEast.getLongitude()) && (point.getLatitude() >= southWest.getLatitude() && point.getLatitude() <= northEast.getLatitude());
        }

        /**
         * @param bounds 矩形区域
         * @return 矩形区域是否完全包含于此矩形区域中
         */
        public boolean containsBounds(Bounds bounds) {
            return containsPoint(bounds.getSouthWest()) && containsPoint(bounds.getNorthEast());
        }

        /**
         * @param bounds 矩形区域
         * @return 计算与另一矩形的交集区域
         */
        public Bounds intersects(Bounds bounds) {
            if (bounds != null && !bounds.isEmpty() && !isEmpty()) {
                Bounds _merged = new Bounds(this, bounds);
                //
                double _x1 = this.southWest.getLongitude() == _merged.southWest.getLongitude() ? bounds.southWest.getLongitude() : this.southWest.getLongitude();
                double _y1 = this.southWest.getLatitude() == _merged.southWest.getLatitude() ? bounds.southWest.getLatitude() : this.southWest.getLatitude();
                //
                double _x2 = this.northEast.getLongitude() == _merged.northEast.getLongitude() ? bounds.northEast.getLongitude() : this.northEast.getLongitude();
                double _y2 = this.northEast.getLatitude() == _merged.northEast.getLatitude() ? bounds.northEast.getLatitude() : this.northEast.getLatitude();
                //
                if (_x1 < _x2 && _y1 < _y2) {
                    return new Bounds(new Point(_x1, _y1), new Point(_x2, _y2));
                }
            }
            return new Bounds();
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }
            Bounds bounds = (Bounds) o;
            return new EqualsBuilder()
                    .append(southWest, bounds.southWest)
                    .append(northEast, bounds.northEast)
                    .isEquals();
        }

        @Override
        public int hashCode() {
            return new HashCodeBuilder(17, 37)
                    .append(southWest)
                    .append(northEast)
                    .toHashCode();
        }

        @Override
        public String toString() {
            return "Bounds{southWest=" + southWest + ", northEast=" + northEast + '}';
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy