001/*
002 * Copyright 2020 Global Biodiversity Information Facility (GBIF)
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.gbif.api.model.registry.eml.geospatial;
017
018import java.io.Serializable;
019import java.util.Locale;
020
021/**
022 * Geographic coverage geometry in the form of 4 sided bounding box.
023 */
024public class BoundingBox implements Serializable, Geometry {
025
026  private static final long serialVersionUID = 9101833933868378174L;
027
028  private static final int MIN_MIN_LONGITUDE = -180;
029  private static final int MAX_MAX_LONGITUDE = 180;
030
031  private static final int MIN_MIN_LATITUDE = -90;
032  private static final int MAX_MAX_LATITUDE = 90;
033
034  private double minLatitude;
035  private double maxLatitude;
036  private double minLongitude;
037  private double maxLongitude;
038  private boolean isGlobalCoverage;
039
040
041  public BoundingBox() {
042  }
043
044  public BoundingBox(double minLatitude, double maxLatitude, double minLongitude, double maxLongitude) {
045    this.minLatitude = minLatitude;
046    this.maxLatitude = maxLatitude;
047    this.minLongitude = minLongitude;
048    this.maxLongitude = maxLongitude;
049    this.isGlobalCoverage = checkIsGlobalCoverage(minLatitude, maxLatitude, minLongitude, maxLongitude);
050  }
051
052  public double getMaxLatitude() {
053    return maxLatitude;
054  }
055
056  public void setMaxLatitude(double maxLatitude) {
057    this.maxLatitude = maxLatitude;
058  }
059
060  public double getMaxLongitude() {
061    return maxLongitude;
062  }
063
064  public void setMaxLongitude(double maxLongitude) {
065    this.maxLongitude = maxLongitude;
066  }
067
068  public double getMinLatitude() {
069    return minLatitude;
070  }
071
072  public void setMinLatitude(double minLatitude) {
073    this.minLatitude = minLatitude;
074  }
075
076  public double getMinLongitude() {
077    return minLongitude;
078  }
079
080  public void setMinLongitude(double minLongitude) {
081    this.minLongitude = minLongitude;
082  }
083
084  @Override
085  public String toWellKnownText() {
086    return String.format(Locale.ENGLISH, "POLYGON ((%f %f, %f %f, %f %f, %f %f))",
087                         minLongitude,
088                         minLatitude,
089                         minLongitude,
090                         maxLatitude,
091                         maxLongitude,
092                         maxLatitude,
093                         maxLongitude,
094                         minLatitude);
095  }
096
097  /**
098   * @return whether the BoundingBox represents global coverage
099   */
100  public boolean isGlobalCoverage() {
101    return isGlobalCoverage;
102  }
103
104  /**
105   * Set whether this binding box represents global coverage or not. Setter ensures all 4 required params are provided.
106   *
107   * @param minLatitude  min latitude
108   * @param maxLatitude  max latitude
109   * @param minLongitude min longitude
110   * @param maxLongitude max longitude
111   */
112  public void setGlobalCoverage(double minLatitude, double maxLatitude, double minLongitude, double maxLongitude) {
113    isGlobalCoverage = checkIsGlobalCoverage(minLatitude, maxLatitude, minLongitude, maxLongitude);
114  }
115
116  /**
117   * Determine whether the bounding box represents global coverage. This is the case, when all North, East, South,
118   * and West lines represent the maximum possible degree values (90, 180, -90, -180).
119   *
120   * @param minLatitude  min latitude
121   * @param maxLatitude  max latitude
122   * @param minLongitude min longitude
123   * @param maxLongitude max longitude
124   *
125   * @return whether the bounding box represents global coverage
126   */
127  private boolean checkIsGlobalCoverage(
128    double minLatitude, double maxLatitude, double minLongitude, double maxLongitude
129  ) {
130    return minLatitude == MIN_MIN_LATITUDE
131           && maxLatitude == MAX_MAX_LATITUDE
132           && minLongitude == MIN_MIN_LONGITUDE
133           && maxLongitude == MAX_MAX_LONGITUDE;
134  }
135
136}