001/*
002 * Shredzone Commons - suncalc
003 *
004 * Copyright (C) 2017 Richard "Shred" Körber
005 *   http://commons.shredzone.org
006 *
007 * Licensed under the Apache License, Version 2.0 (the "License");
008 * you may not use this file except in compliance with the License.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
013 */
014package org.shredzone.commons.suncalc.param;
015
016import static org.shredzone.commons.suncalc.util.ExtendedMath.dms;
017
018/**
019 * Location based parameters.
020 * <p>
021 * Use them to give information about the geolocation of the observer. If ommitted, the
022 * coordinates of <a href="https://en.wikipedia.org/wiki/Null_Island">Null Island</a> are
023 * used.
024 *
025 * @param <T>
026 *            Type of the final builder
027 */
028@SuppressWarnings("unchecked")
029public interface LocationParameter<T> {
030
031    /**
032     * Sets the latitude.
033     *
034     * @param lat
035     *            Latitude, in degrees.
036     * @return itself
037     */
038    T latitude(double lat);
039
040    /**
041     * Sets the longitude.
042     *
043     * @param lng
044     *            Longitude, in degrees.
045     * @return itself
046     */
047    T longitude(double lng);
048
049    /**
050     * Sets the height.
051     *
052     * @param h
053     *            Height, in meters above sea level. Default: 0.0 m. Negative values are
054     *            silently changed to the acceptable minimum of 0.0 m.
055     * @return itself
056     */
057    T height(double h);
058
059    /**
060     * Sets the geolocation.
061     *
062     * @param lat
063     *            Latitude, in degrees.
064     * @param lng
065     *            Longitude, in degrees.
066     * @return itself
067     */
068    default T at(double lat, double lng) {
069        latitude(lat);
070        longitude(lng);
071        return (T) this;
072    }
073
074    /**
075     * Sets the geolocation. In the given array, index 0 must contain the latitude, and
076     * index 1 must contain the longitude. An optional index 2 may contain the height, in
077     * meters.
078     * <p>
079     * This call is meant to be used for coordinates stored in constants.
080     *
081     * @param coords
082     *            Array containing the latitude and longitude, in degrees.
083     * @return itself
084     */
085    default T at(double[] coords) {
086        if (coords.length != 2 && coords.length != 3) {
087            throw new IllegalArgumentException("Array must contain 2 or 3 doubles");
088        }
089        if (coords.length == 3) {
090            height(coords[2]);
091        }
092        return at(coords[0], coords[1]);
093    }
094
095    /**
096     * Sets the latitude.
097     *
098     * @param d
099     *            Degrees
100     * @param m
101     *            Minutes
102     * @param s
103     *            Seconds (and fraction of seconds)
104     * @return itself
105     */
106    default T latitude(int d, int m, double s) {
107        return latitude(dms(d, m, s));
108    }
109
110    /**
111     * Sets the longitude.
112     *
113     * @param d
114     *            Degrees
115     * @param m
116     *            Minutes
117     * @param s
118     *            Seconds (and fraction of seconds)
119     * @return itself
120     */
121    default T longitude(int d, int m, double s) {
122        return longitude(dms(d, m, s));
123    }
124
125    /**
126     * Uses the same location as given in the {@link LocationParameter} at this moment.
127     * <p>
128     * Changes to the source parameter will not affect this parameter, though.
129     *
130     * @param l  {@link LocationParameter} to be used.
131     * @return itself
132     */
133    T sameLocationAs(LocationParameter<?> l);
134
135}