Java tutorial
/* * 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.ArrayUtils; import org.apache.commons.lang.NullArgumentException; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import java.awt.geom.Point2D; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; /** * @author (suninformation@163.com) 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) { return p1.distance(p2); } /** * @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)); } } /** * ? * * @param polygon * @param point * @return true - ?, false - ? */ public static boolean contains(Polygon polygon, Point point) { return contains(polygon, point, false); } public static boolean contains(Polygon polygon, Point point, boolean on) { if (on) { // ? return polygon.on(point); } // ? return polygon.in(point); } /** * ? * * @param circle * @param point * @return -1 - , 0 - , 1 - */ public static int contains(Circle circle, Point point) { return circle.contains(point); } /** * ??? */ public static class Point implements Serializable { /** * ?, X */ private double longitude; /** * , Y */ private double latitude; /** * * * @param longitude ? * @param 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; } public Point2D.Double toPoint2D() { return new Point2D.Double(longitude, latitude); } /** * @param point ?? * @return ?() */ public double distance(Point point) { double _lat1 = __rad(latitude); double _lat2 = __rad(latitude); 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(point.getLongitude()) - __rad(point.getLongitude())) / 2), 2))) * EARTH_RADIUS * 10000) / 10; } /** * @return ???? */ public boolean isValidCoordinate() { // ?: 180 >= x >= 0 if (0.0 > longitude || 180.0 < longitude) { return false; } // : 90 >= y >= 0 return !(0.0 > latitude) && !(90.0 < 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 implements Serializable { /** * (?)?? */ 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 contains(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 contains(Bounds bounds) { return contains(bounds.getSouthWest()) && contains(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 + '}'; } } /** * ??? */ public static class Circle implements Serializable { /** * */ private Point center; /** * ? */ private double r; /** * * * @param center * @param r ? */ public Circle(Point center, double r) { this.center = center; this.r = r; } public Point getCenter() { return center; } public void setCenter(Point center) { this.center = center; } public double getR() { return r; } public void setR(double r) { this.r = r; } /** * ? * * @param point * @return -1 - , 0 - , 1 - */ public int contains(Point point) { double value = Math.hypot((point.longitude - center.longitude), (point.latitude - center.latitude)); if (value > r) { // return -1; } else if (value < r) { // return 1; } // return 0; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Circle circle = (Circle) o; return new EqualsBuilder().append(r, circle.r).append(center, circle.center).isEquals(); } @Override public int hashCode() { return new HashCodeBuilder(17, 37).append(center).append(r).toHashCode(); } @Override public String toString() { return "Circle{" + "center=" + center + ", r=" + r + '}'; } } /** * ??? */ public static class Polygon implements Serializable { /** * ?? */ private List<Point> points = new ArrayList<Point>(); public Polygon() { } public Polygon(Point[] points) { if (ArrayUtils.isNotEmpty(points)) { this.points.addAll(Arrays.asList(points)); } } public Polygon(Collection<Point> points) { if (points != null && !points.isEmpty()) { this.points.addAll(points); } } public boolean isEmpty() { return this.points.isEmpty(); } public Polygon add(Point point) { if (point != null) { this.points.add(point); } return this; } public Polygon add(double longitude, double latitude) { this.points.add(new Point(longitude, latitude)); return this; } public List<Point> getPoints() { return points; } public boolean in(Point point) { int nCross = 0; for (int i = 0; i < points.size(); i++) { Point p1 = points.get(i); Point p2 = points.get((i + 1) % points.size()); if (p1.latitude == p2.latitude) { continue; } if (point.latitude < Math.min(p1.latitude, p2.latitude)) { continue; } if (point.latitude >= Math.max(p1.latitude, p2.latitude)) { continue; } double x = (point.latitude - p1.latitude) * (p2.longitude - p1.longitude) / (p2.latitude - p1.latitude) + p1.longitude; if (x > point.longitude) { nCross++; } } return (nCross % 2 == 1); } public boolean on(Point point) { for (int i = 0; i < points.size(); i++) { Point p1 = points.get(i); Point p2 = points.get((i + 1) % points.size()); if (point.latitude < Math.min(p1.latitude, p2.latitude)) { continue; } if (point.latitude > Math.max(p1.latitude, p2.latitude)) { continue; } if (p1.latitude == p2.latitude) { double minX = Math.min(p1.longitude, p2.longitude); double maxX = Math.max(p1.longitude, p2.longitude); if ((point.latitude == p1.latitude) && (point.longitude >= minX && point.longitude <= maxX)) { return true; } } else { double x = (point.latitude - p1.latitude) * (p2.longitude - p1.longitude) / (p2.latitude - p1.latitude) + p1.longitude; if (x == point.longitude) { return true; } } } return false; } } }