4 XCSoar Glide Computer - http://www.xcsoar.org/
5 Copyright (C) 2000-2013 The XCSoar Project
6 A detailed list of copyright holders can be found in the file "AUTHORS".
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 #ifndef XCSOAR_GeoPoint_HPP
26 #define XCSOAR_GeoPoint_HPP
28 #include "Math/Angle.hpp"
29 #include "Rough/RoughAltitude.hpp"
32 #include <type_traits>
37 * Geodetic coordinate expressed as Longitude and Latitude angles.
44 * Non-initialising constructor.
49 * Constructor (supplied location)
51 * @param _Longitude Longitude of point
52 * @param _Latitude Latitude of point
54 * @return Initialised object
57 GeoPoint(const Angle _longitude
, const Angle _latitude
) :
58 longitude(_longitude
), latitude(_latitude
) {}
61 * Construct an instance at the origin of the coordinate system.
62 * This is used to initialise the simulator when there is no better
63 * reference (home, map center). The goal is to bootstrap the
64 * simulator when XCSoar is launched for the first time with an
65 * empty profile; it is pretty useless for anything else.
68 static GeoPoint
Zero() {
69 return GeoPoint(Angle::Zero(), Angle::Zero());
73 * Construct an instance that is "invalid", i.e. IsValid() will
74 * return false. The return value must not be used in any
75 * calculation. This method may be used to explicitly declare a
76 * GeoPoint attribute as "invalid".
79 static GeoPoint
Invalid() {
80 return GeoPoint(Angle::Zero(), Angle::FullCircle());
84 * Set this instance to "invalid", i.e. IsValid() will
85 * return false. The return value must not be used in any
86 * calculation. This method may be used to explicitly declare a
87 * GeoPoint attribute as "invalid".
90 longitude
= Angle::Zero();
91 latitude
= Angle::FullCircle();
95 * Check if this object is "valid". Returns false when it was
96 * constructed by Invalid(). This is not an extensive plausibility
97 * check; it is only designed to catch instances created by
101 bool IsValid() const {
102 return latitude
<= Angle::HalfCircle();
106 * Normalize the values, so this object can be used properly in
107 * calculations, without unintended side effects (such as -1 degrees
108 * vs 359 degrees). This modification is in-place.
110 GeoPoint
&Normalize() {
111 longitude
= longitude
.AsDelta();
113 if (latitude
< -Angle::QuarterCircle())
114 latitude
= -Angle::QuarterCircle();
115 else if (latitude
> Angle::QuarterCircle())
116 latitude
= Angle::QuarterCircle();
122 * Find location a parametric distance along a vector from this point
124 * @param delta Vector to feed in
125 * @param t Parametric distance along delta to add [0,1]
127 * @return Location of point
130 GeoPoint
Parametric(const GeoPoint
&delta
, const fixed t
) const;
133 * Find location interpolated from this point towards end
135 * @param end Endpoint of interpolation
136 * @param t Parametric distance along this to end [0,1]
138 * @return Location of point
141 GeoPoint
Interpolate(const GeoPoint
&end
, const fixed t
) const;
144 * Multiply a point by a factor (used for deltas)
146 * @param x Factor to magnify
148 * @return Modified point
151 GeoPoint
operator* (const fixed x
) const {
152 GeoPoint res
= *this;
159 * Add a delta to a point
161 * @param delta Delta to add
163 * @return Modified point
166 GeoPoint
operator+ (const GeoPoint
&delta
) const {
167 GeoPoint res
= *this;
168 res
.longitude
+= delta
.longitude
;
169 res
.latitude
+= delta
.latitude
;
174 * Add a delta to a point
176 * @param delta Delta to add
178 * @return Modified point
180 const GeoPoint
& operator+= (const GeoPoint
&delta
) {
181 longitude
+= delta
.longitude
;
182 latitude
+= delta
.latitude
;
187 * Subtracts a delta from a point
189 * @param delta Delta to subtract
191 * @return Modified point
194 GeoPoint
operator- (const GeoPoint
&delta
) const {
195 GeoPoint res
= *this;
196 res
.longitude
-= delta
.longitude
;
197 res
.latitude
-= delta
.latitude
;
198 return res
.Normalize();
202 * Calculate great circle distance from this to the other
204 * @param other Other location
206 * @return Distance (m)
209 fixed
Distance(const GeoPoint
&other
) const;
212 * Calculate great circle initial bearing from this to the other
214 * @param other Other location
216 * @return Bearing (deg)
219 Angle
Bearing(const GeoPoint
&other
) const;
222 * Calculate great circle distance and initial bearing from this to the other
225 GeoVector
DistanceBearing(const GeoPoint
&other
) const;
228 * Find distance along a great-circle path that this point
231 * @param from Start location
232 * @param to End location
234 * @return Distance (m) along from-to line
237 fixed
ProjectedDistance(const GeoPoint
&from
, const GeoPoint
&to
) const;
240 * Find point a set distance along a great-circle path towards
243 * @param destination End location
244 * @param distance distance (m)
246 * @return Location of point
249 GeoPoint
IntermediatePoint(const GeoPoint
&destination
,
250 const fixed distance
) const;
253 * Find the nearest great-circle middle point between this point and
257 GeoPoint
Middle(const GeoPoint
&other
) const;
260 * Test whether two points are co-located
262 * @param other Point to compare
264 * @return True if coincident
267 bool Equals(const GeoPoint other
) const {
268 return longitude
== other
.longitude
&& latitude
== other
.latitude
;
272 * Test whether two points are co-located
274 * @param other Point to compare
276 * @return True if coincident
279 bool operator== (const GeoPoint other
) const {
280 return Equals(other
);
284 * Test whether two points are not co-located
286 * @param other Point to compare
288 * @return True if coincident
291 bool operator !=(const GeoPoint
&other
) const {
292 return !Equals(other
);
296 * Rank two points according to longitude, then latitude
298 * @param other Point to compare to
300 * @return True if this point is further left (or if equal, lower) than the other
303 bool Sort(const GeoPoint
&other
) const;
306 static_assert(std::is_trivial
<GeoPoint
>::value
, "type is not trivial");
309 * Extension of GeoPoint for altitude (3d location in spherical space)
311 struct AGeoPoint
: public GeoPoint
{
312 /**< Nav reference altitude (m) */
313 RoughAltitude altitude
;
315 AGeoPoint() = default;
318 AGeoPoint(const GeoPoint p
, const RoughAltitude alt
)
319 :GeoPoint(p
),altitude(alt
) {};
322 static_assert(std::is_trivial
<AGeoPoint
>::value
, "type is not trivial");