001/*
002 * Copyright (c) 2003 Objectix Pty Ltd  All rights reserved.
003 *
004 * This library is free software; you can redistribute it and/or
005 * modify it under the terms of the GNU Lesser General Public
006 * License as published by the Free Software Foundation.
007 *
008 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
009 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
010 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
011 * DISCLAIMED.  IN NO EVENT SHALL OBJECTIX PTY LTD BE LIABLE FOR ANY
012 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
013 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
014 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
015 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
016 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
017 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
018 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
019 */
020package org.openstreetmap.josm.data.projection.datum;
021
022import java.io.Serializable;
023
024import org.openstreetmap.josm.data.coor.LatLon;
025
026/**
027 * A value object for storing Longitude and Latitude of a point, the
028 * Lon and Lat shift values to get from one datum to another, and the
029 * Lon and Lat accuracy of the shift values.
030 * <p>All values are stored as Positive West Seconds, but accessors
031 * are also provided for Positive East Degrees.
032 *
033 * @author Peter Yuill
034 * Modifified for JOSM :
035 * - add a constructor for JOSM LatLon (Pieren)
036 */
037public class NTV2GridShift implements Serializable {
038
039    private static final long serialVersionUID = 1L;
040
041    private static final double METRE_PER_SECOND = 2.0 * Math.PI * 6378137.0 / 3600.0 / 360.0;
042    private static final double RADIANS_PER_SECOND = 2.0 * Math.PI / 3600.0 / 360.0;
043    private double lon;
044    private double lat;
045    private double lonShift;
046    private double latShift;
047    private double lonAccuracy;
048    private double latAccuracy;
049    private boolean latAccuracyAvailable;
050    private boolean lonAccuracyAvailable;
051    private String subGridName;
052
053    /**
054     * Constructs a new {@code NTV2GridShift}.
055     */
056    public NTV2GridShift() {
057        // contents can be set later with setters
058    }
059
060    /**
061     * Constructs a new {@code NTV2GridShift} from a {@code LatLon}.
062     * @param p lat/lon
063     */
064    public NTV2GridShift(LatLon p) {
065        setLatDegrees(p.lat());
066        setLonPositiveEastDegrees(p.lon());
067    }
068
069    /**
070     * Data access function for latitude value
071     * @return latitude in seconds
072     */
073    public double getLatSeconds() {
074        return lat;
075    }
076
077    /**
078     * Data access function for latitude value
079     * @return latitude in degree
080     */
081    public double getLatDegrees() {
082        return lat / 3600.0;
083    }
084
085    /**
086     * Data access function for latitude shift value
087     * @return latitude shift in seconds
088     */
089    public double getLatShiftSeconds() {
090        return latShift;
091    }
092
093    /**
094     * Data access function for latitude shift value
095     * @return latitude shift in degree
096     */
097    public double getLatShiftDegrees() {
098        return latShift / 3600.0;
099    }
100
101    /**
102     * Data access function for already shifted latitude value
103     * @return shifted latitude in seconds
104     */
105    public double getShiftedLatSeconds() {
106        return lat + latShift;
107    }
108
109    /**
110     * Data access function for already shifted latitude value
111     * @return shifted latitude in degree
112     */
113    public double getShiftedLatDegrees() {
114        return (lat + latShift) / 3600.0;
115    }
116
117    /**
118     * Checks whether latitude accuracy is available or not
119     * @return <code>true</code> if latitude accuracy is available
120     */
121    public boolean isLatAccuracyAvailable() {
122        return latAccuracyAvailable;
123    }
124
125    /**
126     * Data access function for latitude accuracy
127     * @return latitude accuracy in seconds
128     */
129    public double getLatAccuracySeconds() {
130        if (!latAccuracyAvailable)
131            throw new IllegalStateException("Latitude Accuracy not available");
132        return latAccuracy;
133    }
134
135    /**
136     * Data access function for latitude accuracy
137     * @return latitude accuracy in degree
138     */
139    public double getLatAccuracyDegrees() {
140        if (!latAccuracyAvailable)
141            throw new IllegalStateException("Latitude Accuracy not available");
142        return latAccuracy / 3600.0;
143    }
144
145    /**
146     * Data access function for latitude accuracy
147     * @return latitude accuracy in meter
148     */
149    public double getLatAccuracyMetres() {
150        if (!latAccuracyAvailable)
151            throw new IllegalStateException("Latitude Accuracy not available");
152        return latAccuracy * METRE_PER_SECOND;
153    }
154
155    /**
156     * Data access function for longitude value, positive values in west direction
157     * @return longitude in seconds
158     */
159    public double getLonPositiveWestSeconds() {
160        return lon;
161    }
162
163    /**
164     * Data access function for longitude value, positive values in east direction
165     * @return longitude in degree
166     */
167    public double getLonPositiveEastDegrees() {
168        return lon / -3600.0;
169    }
170
171    /**
172     * Data access function for longitude shift value, positive values in west direction
173     * @return longitude shift in seconds
174     */
175    public double getLonShiftPositiveWestSeconds() {
176        return lonShift;
177    }
178
179    /**
180     * Data access function for longitude shift value, positive values in east direction
181     * @return longitude shift in degree
182     */
183    public double getLonShiftPositiveEastDegrees() {
184        return lonShift / -3600.0;
185    }
186
187    /**
188     * Data access function for shifted longitude value, positive values in west direction
189     * @return shifted longitude in seconds
190     */
191    public double getShiftedLonPositiveWestSeconds() {
192        return lon + lonShift;
193    }
194
195    /**
196     * Data access function for shifted longitude value, positive values in east direction
197     * @return shifted longitude in degree
198     */
199    public double getShiftedLonPositiveEastDegrees() {
200        return (lon + lonShift) / -3600.0;
201    }
202
203    /**
204     * Checks whether longitude accuracy is available or not
205     * @return <code>true</code> if longitude accuracy is available
206     */
207    public boolean isLonAccuracyAvailable() {
208        return lonAccuracyAvailable;
209    }
210
211    /**
212     * Data access function for longitude accuracy
213     * @return longitude accuracy in seconds
214     */
215    public double getLonAccuracySeconds() {
216        if (!lonAccuracyAvailable)
217            throw new IllegalStateException("Longitude Accuracy not available");
218        return lonAccuracy;
219    }
220
221    /**
222     * Data access function for longitude accuracy
223     * @return longitude accuracy in degree
224     */
225    public double getLonAccuracyDegrees() {
226        if (!lonAccuracyAvailable)
227            throw new IllegalStateException("Longitude Accuracy not available");
228        return lonAccuracy / 3600.0;
229    }
230
231    /**
232     * Data access function for longitude accuracy
233     * @return longitude accuracy in meter
234     */
235    public double getLonAccuracyMetres() {
236        if (!lonAccuracyAvailable)
237            throw new IllegalStateException("Longitude Accuracy not available");
238        return lonAccuracy * METRE_PER_SECOND * Math.cos(RADIANS_PER_SECOND * lat);
239    }
240
241    /**
242     * Data store function for latitude
243     * @param d latitude value in seconds
244     */
245    public final void setLatSeconds(double d) {
246        lat = d;
247    }
248
249    /**
250     * Data store function for latitude
251     * @param d latitude value in degree
252     */
253    public final void setLatDegrees(double d) {
254        lat = d * 3600.0;
255    }
256
257    /**
258     * Data store function for latitude accuracy availability
259     * @param b availability of latitude accuracy
260     */
261    public final void setLatAccuracyAvailable(boolean b) {
262        latAccuracyAvailable = b;
263    }
264
265    /**
266     * Data store function for latitude accuracy
267     * @param d latitude accuracy in seconds
268     */
269    public final void setLatAccuracySeconds(double d) {
270        latAccuracy = d;
271    }
272
273    /**
274     * Data store function for latitude shift
275     * @param d latitude shift in seconds
276     */
277    public final void setLatShiftSeconds(double d) {
278        latShift = d;
279    }
280
281    /**
282     * Data store function for longitude
283     * @param d latitude value in seconds, west direction is positive
284     */
285    public final void setLonPositiveWestSeconds(double d) {
286        lon = d;
287    }
288
289    /**
290     * Data store function for longitude
291     * @param d latitude value in degree, est direction is positive
292     */
293    public final void setLonPositiveEastDegrees(double d) {
294        lon = d * -3600.0;
295    }
296
297    /**
298     * Data store function for longitude accuracy availability
299     * @param b availability of longitude accuracy
300     */
301    public final void setLonAccuracyAvailable(boolean b) {
302        lonAccuracyAvailable = b;
303    }
304
305    /**
306     * Data store function for longitude accuracy
307     * @param d longitude accuracy in seconds
308     */
309    public final void setLonAccuracySeconds(double d) {
310        lonAccuracy = d;
311    }
312
313    /**
314     * Data store function for longitude shift value
315     * @param d longitude shift in seconds, west direction is positive
316     */
317    public final void setLonShiftPositiveWestSeconds(double d) {
318        lonShift = d;
319    }
320
321    /**
322     * Get the name of the sub grid
323     * @return name of the sub grid
324     */
325    public String getSubGridName() {
326        return subGridName;
327    }
328
329    /**
330     * Set the name of the sub grid
331     * @param string name of the sub grid
332     */
333    public void setSubGridName(String string) {
334        subGridName = string;
335    }
336
337    /**
338     * Make this object a copy of the supplied GridShift
339     * @param gs grid to copy data from
340     */
341    public void copy(NTV2GridShift gs) {
342        this.lon = gs.lon;
343        this.lat = gs.lat;
344        this.lonShift = gs.lonShift;
345        this.latShift = gs.latShift;
346        this.lonAccuracy = gs.lonAccuracy;
347        this.latAccuracy = gs.latAccuracy;
348        this.latAccuracyAvailable = gs.latAccuracyAvailable;
349        this.lonAccuracyAvailable = gs.lonAccuracyAvailable;
350        this.subGridName = gs.subGridName;
351    }
352
353}