| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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 org.apache.unomi.api; |
| |
| |
| import java.util.Map; |
| |
| /** |
| * GeoPoint represents a point in geographical coordinate system using latitude and longitude. |
| */ |
| public class GeoPoint { |
| |
| /** |
| * Latitude of the geo point |
| */ |
| private Double lat; |
| |
| /** |
| * Longitude of the geo point |
| */ |
| private Double lon; |
| |
| /** |
| * Instantiates a new GeoPoint |
| * |
| * @param lat latitude of the geo point |
| * @param lon longitude of the geo point |
| */ |
| public GeoPoint(Double lat, Double lon) { |
| this.lat = lat; |
| this.lon = lon; |
| } |
| |
| /** |
| * Retrieves latitude of the geo point |
| * |
| * @return geo point latitude |
| */ |
| public Double getLat() { |
| return lat; |
| } |
| |
| /** |
| * Retrieves longitude of the geo point |
| * |
| * @return geo point longitude |
| */ |
| public Double getLon() { |
| return lon; |
| } |
| |
| /** |
| * Returns a string representation in the following format: "lat, long" |
| * |
| * @return String representation of geo point |
| */ |
| public String asString() { |
| return lat + ", " + lon; |
| } |
| |
| /** |
| * Calculates distance to geo point using <a href="https://en.wikipedia.org/wiki/Haversine_formula">Haversine formula</a> in meters |
| * Note: does not account for altitude |
| * |
| * @param other GeoPoint to calculate distance to |
| * @return Distance in meters |
| */ |
| public double distanceTo(final GeoPoint other) { |
| if (other == null) { |
| return 0; |
| } |
| final int R = 6371; // Radius of the earth |
| |
| final double lat2 = other.lat; |
| final double lon2 = other.lon; |
| |
| double latDistance = Math.toRadians(lat2 - lat); |
| double lonDistance = Math.toRadians(lon2 - lon); |
| double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2) |
| + Math.cos(Math.toRadians(lat)) * Math.cos(Math.toRadians(lat2)) |
| * Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2); |
| double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); |
| return R * c * 1000; // convert to meters |
| } |
| |
| /** |
| * Instantiates geo point from map of coordinates |
| * |
| * @param map Map containing coordinates with keys "lat" and "lon" |
| * @return New geo point or null if map is not a valid geo point |
| * @throws IllegalArgumentException Thrown if the input is not valid |
| */ |
| public static GeoPoint fromMap(Map<String, Double> map) { |
| if (map == null || map.isEmpty() || !map.containsKey("lat") || !map.containsKey("lon")) { |
| throw new IllegalArgumentException("Map should be not null and contain \"lat\" and \"lon\" fields"); |
| } |
| return new GeoPoint(map.get("lat"), map.get("lon")); |
| } |
| |
| /** |
| * Instantiates geo point from string representation |
| * |
| * @param input String geo point representation in the following format: "lat, lon" |
| * @return New geo point or null if string is not a valid geo point |
| * @throws IllegalArgumentException Thrown if the input is not valid |
| */ |
| public static GeoPoint fromString(final String input) { |
| if (input == null || input.trim().length() == 0) { |
| return null; |
| } |
| final String[] parts = input.split(","); |
| if (parts.length == 2) { |
| try { |
| return new GeoPoint(Double.valueOf(parts[0].trim()), Double.valueOf(parts[1].trim())); |
| } catch (NumberFormatException ex) { |
| throw new IllegalArgumentException(String.format("Could not parse \"lat\" or \"lon\" from: %s", input), ex); |
| } |
| } else { |
| throw new IllegalArgumentException(String.format("Incorrect geo point format. Expected: \"lat, lon\", was: %s", input)); |
| } |
| } |
| } |