xapian-core  2.0.0
latlong_metrics.cc
Go to the documentation of this file.
1 
4 /* Copyright 2008 Lemur Consulting Ltd
5  * Copyright 2011 Richard Boulton
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 of the
10  * License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, see
19  * <https://www.gnu.org/licenses/>.
20  */
21 
22 #include <config.h>
23 
24 #include "xapian/geospatial.h"
25 #include "xapian/error.h"
26 #include "serialise-double.h"
27 
28 #include <cmath>
29 
30 using namespace Xapian;
31 using namespace std;
32 
35 #define QUAD_EARTH_RADIUS_METRES 6372797.6
36 
38 {
39 }
40 
41 double
43  const LatLongCoords& b) const
44 {
45  if (a.empty() || b.empty()) {
46  throw InvalidArgumentError("Empty coordinate list supplied to LatLongMetric::operator()()");
47  }
48  double min_dist = 0.0;
49  bool have_min = false;
50  for (LatLongCoordsIterator a_iter = a.begin();
51  a_iter != a.end();
52  ++a_iter)
53  {
54  for (LatLongCoordsIterator b_iter = b.begin();
55  b_iter != b.end();
56  ++b_iter)
57  {
58  double dist = pointwise_distance(*a_iter, *b_iter);
59  if (!have_min) {
60  min_dist = dist;
61  have_min = true;
62  } else if (dist < min_dist) {
63  min_dist = dist;
64  }
65  }
66  }
67  return min_dist;
68 }
69 
70 double
72  const char* b_ptr, size_t b_len) const
73 {
74  if (a.empty() || b_len == 0) {
75  throw InvalidArgumentError("Empty coordinate list supplied to LatLongMetric::operator()()");
76  }
77  double min_dist = 0.0;
78  bool have_min = false;
79  LatLongCoord b;
80  const char * b_end = b_ptr + b_len;
81  while (b_ptr != b_end) {
82  b.unserialise(&b_ptr, b_end);
83  for (LatLongCoordsIterator a_iter = a.begin();
84  a_iter != a.end();
85  ++a_iter)
86  {
87  double dist = pointwise_distance(*a_iter, b);
88  if (!have_min) {
89  min_dist = dist;
90  have_min = true;
91  } else if (dist < min_dist) {
92  min_dist = dist;
93  }
94  }
95  }
96  return min_dist;
97 }
98 
99 
101  : radius(QUAD_EARTH_RADIUS_METRES)
102 {}
103 
105  : radius(radius_)
106 {}
107 
108 double
110  const LatLongCoord& b) const
111 {
112  double lata = a.latitude * (M_PI / 180.0);
113  double latb = b.latitude * (M_PI / 180.0);
114 
115  double latdiff = lata - latb;
116  double longdiff = (a.longitude - b.longitude) * (M_PI / 180.0);
117 
118  double sin_half_lat = sin(latdiff / 2);
119  double sin_half_long = sin(longdiff / 2);
120  double h = sin_half_lat * sin_half_lat +
121  sin_half_long * sin_half_long * cos(lata) * cos(latb);
122  if (rare(h > 1.0)) {
123  // Clamp to 1.0, asin(1.0) = M_PI / 2.0.
124  return radius * M_PI;
125  }
126  return 2 * radius * asin(sqrt(h));
127 }
128 
131 {
132  return new GreatCircleMetric(radius);
133 }
134 
135 string
137 {
138  return "Xapian::GreatCircleMetric";
139 }
140 
141 string
143 {
144  return serialise_double(radius);
145 }
146 
148 GreatCircleMetric::unserialise(const string& s) const
149 {
150  const char * p = s.data();
151  const char * end = p + s.size();
152 
153  double new_radius = unserialise_double(&p, end);
154  if (p != end) {
155  throw Xapian::NetworkError("Bad serialised GreatCircleMetric - junk at end");
156  }
157 
158  return new GreatCircleMetric(new_radius);
159 }
LatLongMetric * unserialise(const std::string &serialised) const
Create object given string serialisation returned by serialise().
double pointwise_distance(const LatLongCoord &a, const LatLongCoord &b) const
Return the great-circle distance between points on the sphere.
LatLongMetric * clone() const
Clone the metric.
std::string serialise() const
Serialise object parameters into a string.
std::string name() const
Return the full name of the metric.
GreatCircleMetric()
Construct a GreatCircleMetric.
double radius
The radius of the sphere in metres.
Definition: geospatial.h:401
InvalidArgumentError indicates an invalid parameter value was passed to the API.
Definition: error.h:229
An iterator across the values in a LatLongCoords object.
Definition: geospatial.h:164
A sequence of latitude-longitude coordinates.
Definition: geospatial.h:231
LatLongCoordsIterator begin() const
Get a begin iterator for the coordinates.
Definition: geospatial.h:237
LatLongCoordsIterator end() const
Get an end iterator for the coordinates.
Definition: geospatial.h:242
bool empty() const
Return true if and only if there are no coordinates in the container.
Definition: geospatial.h:253
Base class for calculating distances between two lat/long coordinates.
Definition: geospatial.h:302
double operator()(const LatLongCoords &a, const LatLongCoords &b) const
Return the distance between two coordinate lists, in metres.
virtual ~LatLongMetric()
Destructor.
Indicates a problem communicating with a remote database.
Definition: error.h:791
#define rare(COND)
Definition: config.h:607
PositionList * p
Hierarchy of classes which Xapian can throw as exceptions.
Geospatial search support routines.
#define QUAD_EARTH_RADIUS_METRES
Quadratic mean radius of the Earth in metres.
The Xapian namespace contains public interfaces for the Xapian library.
Definition: compactor.cc:82
string serialise_double(double v)
Serialise a double to a string.
double unserialise_double(const char **p, const char *end)
Unserialise a double serialised by serialise_double.
functions to serialise and unserialise a double
A latitude-longitude coordinate.
Definition: geospatial.h:81
void unserialise(std::string_view serialised)
Unserialise a string and set this object to its coordinate.
Definition: latlongcoord.cc:48
double latitude
A latitude, as decimal degrees.
Definition: geospatial.h:88
double longitude
A longitude, as decimal degrees.
Definition: geospatial.h:98