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 elevation.
051     *
052     * @param h
053     *            Elevation, in meters above sea level. Default: 0.0 m. Negative values
054     *            are silently changed to the acceptable minimum of 0.0 m.
055     * @return itself
056     * @see #elevationFt(double)
057     * @since 3.9
058     */
059    T elevation(double h);
060
061    /**
062     * Sets the elevation, in foot.
063     *
064     * @param ft
065     *            Elevation, in foot above sea level. Default: 0.0 ft. Negative values are
066     *            silently changed to the acceptable minimum of 0.0 ft.
067     * @return itself
068     * @see #elevation(double)
069     * @since 3.9
070     */
071    default T elevationFt(double ft) {
072        return elevation(ft * 0.3048);
073    }
074
075    /**
076     * Sets the height.
077     *
078     * @param h
079     *            Height, in meters above sea level. Default: 0.0 m. Negative values are
080     *            silently changed to the acceptable minimum of 0.0 m.
081     * @return itself
082     * @deprecated Use {@link #elevation(double)} instead.
083     */
084    @Deprecated
085    default T height(double h) {
086        return elevation(h);
087    }
088
089    /**
090     * Sets the height, in foot.
091     *
092     * @param ft
093     *            Height, in foot above sea level. Default: 0.0 ft. Negative values are
094     *            silently changed to the acceptable minimum of 0.0 ft.
095     * @return itself
096     * @since 3.8
097     * @deprecated Use {@link #elevationFt(double)} instead.
098     */
099    @Deprecated
100    default T heightFt(double ft) {
101        return elevationFt(ft);
102    }
103
104    /**
105     * Sets the geolocation.
106     *
107     * @param lat
108     *            Latitude, in degrees.
109     * @param lng
110     *            Longitude, in degrees.
111     * @return itself
112     */
113    default T at(double lat, double lng) {
114        latitude(lat);
115        longitude(lng);
116        return (T) this;
117    }
118
119    /**
120     * Sets the geolocation. In the given array, index 0 must contain the latitude, and
121     * index 1 must contain the longitude. An optional index 2 may contain the elevation,
122     * in meters.
123     * <p>
124     * This call is meant to be used for coordinates stored in constants.
125     *
126     * @param coords
127     *            Array containing the latitude and longitude, in degrees.
128     * @return itself
129     */
130    default T at(double[] coords) {
131        if (coords.length != 2 && coords.length != 3) {
132            throw new IllegalArgumentException("Array must contain 2 or 3 doubles");
133        }
134        if (coords.length == 3) {
135            elevation(coords[2]);
136        }
137        return at(coords[0], coords[1]);
138    }
139
140    /**
141     * Sets the latitude.
142     *
143     * @param d
144     *            Degrees
145     * @param m
146     *            Minutes
147     * @param s
148     *            Seconds (and fraction of seconds)
149     * @return itself
150     */
151    default T latitude(int d, int m, double s) {
152        return latitude(dms(d, m, s));
153    }
154
155    /**
156     * Sets the longitude.
157     *
158     * @param d
159     *            Degrees
160     * @param m
161     *            Minutes
162     * @param s
163     *            Seconds (and fraction of seconds)
164     * @return itself
165     */
166    default T longitude(int d, int m, double s) {
167        return longitude(dms(d, m, s));
168    }
169
170    /**
171     * Uses the same location as given in the {@link LocationParameter} at this moment.
172     * <p>
173     * Changes to the source parameter will not affect this parameter, though.
174     *
175     * @param l  {@link LocationParameter} to be used.
176     * @return itself
177     */
178    T sameLocationAs(LocationParameter<?> l);
179
180}