MongoDB C++ Driver legacy-1.1.2
Loading...
Searching...
No Matches
geometry.h
Go to the documentation of this file.
1/* Copyright 2014 MongoDB Inc.
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
18#pragma once
19
20#include <algorithm>
21#include <limits>
22#include <vector>
23
24#include "mongo/client/export_macros.h"
25#include "mongo/db/jsobj.h"
27#include "mongo/geo/constants.h"
28#include "mongo/geo/geoobj.h"
29#include "mongo/util/assert_util.h"
30
31namespace mongo {
32namespace geo {
33
34// forward declaration needed for Geometry's static helpers
35template <typename TCoordinates>
36class Point;
37
38template <typename TCoordinates>
39class Geometry : public GeoObj<TCoordinates> {
40protected:
41 static BSONElement getCoordsField(const BSONObj& bson);
42 static std::vector<double> parseCoords(const BSONElement& coordArr);
43 static std::vector<double> parseCoords(const BSONObj& bson);
44 static Point<TCoordinates> parsePoint(const BSONElement& coordArr);
45 static std::vector<Point<TCoordinates> > parsePointArray(
46 const std::vector<BSONElement>& pointArr);
47 static std::vector<Point<TCoordinates> > parseAllPoints(const BSONObj& bson);
48
58 const std::vector<Point<TCoordinates> >& points);
59
71 const std::vector<BoundingBox<TCoordinates> >& bboxes);
72
84
85private:
86 static void findMinAndMaxCoordinatesOfDimension(const std::vector<Point<TCoordinates> >& points,
87 size_t dimension,
88 double* min,
89 double* max);
90};
91
92template <typename TCoordinates>
94 BSONElement coordsField = bson.getField(kCoordsFieldName);
95 uassert(0,
96 "bson must contain a field \"coordinates\" of type Array",
97 !coordsField.eoo() && coordsField.type() == Array);
98 return coordsField;
99}
100
101template <typename TCoordinates>
102std::vector<double> Geometry<TCoordinates>::parseCoords(const BSONElement& coordArr) {
103 std::vector<BSONElement> coordElems = coordArr.Array();
104 std::vector<double> coords;
105 for (size_t i = 0; i < coordElems.size(); ++i)
106 coords.push_back(coordElems[i].Double());
107 return coords;
108}
109
110template <typename TCoordinates>
111std::vector<double> Geometry<TCoordinates>::parseCoords(const BSONObj& bson) {
112 return parseCoords(getCoordsField(bson));
113}
114
115template <typename TCoordinates>
116Point<TCoordinates> Geometry<TCoordinates>::parsePoint(const BSONElement& coordArr) {
117 TCoordinates pointCoords(parseCoords(coordArr));
118 return Point<TCoordinates>(pointCoords);
119}
120
121template <typename TCoordinates>
122std::vector<Point<TCoordinates> > Geometry<TCoordinates>::parsePointArray(
123 const std::vector<BSONElement>& pointArr) {
124 std::vector<Point<TCoordinates> > points;
125 for (size_t i = 0; i < pointArr.size(); ++i) {
126 points.push_back(parsePoint(pointArr[i]));
127 }
128 return points;
129}
130
131template <typename TCoordinates>
132std::vector<Point<TCoordinates> > Geometry<TCoordinates>::parseAllPoints(const BSONObj& bson) {
133 return parsePointArray(getCoordsField(bson).Array());
134}
135
136template <typename TCoordinates>
138 const std::vector<Point<TCoordinates> >& points) {
139 // For a TCoordinates type with dimensions d1, d2, ..., dn,
140 // the bounding box of these points will have min coordinates
141 // whose d1 value is the minimum of all d1-axis values in points,
142 // whose d2 value is the minimum of all d2-axis values in points,
143 // and so on up through dn. Similarly for the max coordinates.
144 //
145 // So to compute the bounding box, we iterate through each dimension
146 // and find the min / max values in points for that dimension.
147 std::vector<double> minCoordComponents, maxCoordComponents;
148 for (size_t i = 0; i < TCoordinates::dimensionality(); ++i) {
149 double min, max;
150 findMinAndMaxCoordinatesOfDimension(points, i, &min, &max);
151 minCoordComponents.push_back(min);
152 maxCoordComponents.push_back(max);
153 }
154 TCoordinates minCoords(minCoordComponents);
155 TCoordinates maxCoords(maxCoordComponents);
156 return new BoundingBox<TCoordinates>(minCoords, maxCoords);
157}
158
159template <typename TCoordinates>
161 const std::vector<Point<TCoordinates> >& points, size_t dimension, double* min, double* max) {
162 // Initialize min and max to the positive and negative double values
163 // farthest from 0, respectively. Note that we initialize max to
164 // -::max(). Initializing to ::min() is incorrect because it returns
165 // the smallest positive normalized double, which is still greater than
166 // every negative double (and coordinates can have negative values).
167 *min = std::numeric_limits<double>::max();
168 *max = -std::numeric_limits<double>::max();
169
170 // Update min and max with the smallest and largest values for the given dimension.
171 for (size_t i = 0; i < points.size(); ++i) {
172 if (points[i][dimension] < *min)
173 *min = points[i][dimension];
174 if (points[i][dimension] > *max)
175 *max = points[i][dimension];
176 }
177}
178
179template <typename TCoordinates>
181 const std::vector<BoundingBox<TCoordinates> >& bboxes) {
182 if (bboxes.empty())
183 return NULL;
184
185 std::vector<double> minCoords = bboxes[0].getMin().getValues();
186 std::vector<double> maxCoords = bboxes[0].getMax().getValues();
187 for (size_t i = 1; i < bboxes.size(); ++i) {
188 std::vector<double> curMin = bboxes[i].getMin().getValues();
189 std::vector<double> curMax = bboxes[i].getMax().getValues();
190 for (size_t j = 0; j < curMin.size(); ++j) {
191 minCoords[j] = std::min(minCoords[j], curMin[j]);
192 maxCoords[j] = std::max(maxCoords[j], curMax[j]);
193 }
194 }
195
196 TCoordinates globalMin(minCoords), globalMax(maxCoords);
197 return new BoundingBox<TCoordinates>(globalMin, globalMax);
198}
199
200template <typename TCoordinates>
203 return new BoundingBox<TCoordinates>(bson);
204 return NULL;
205}
206
207} // namespace geo
208} // namespace mongo
BSONElement represents an "element" in a BSONObj.
Definition bsonelement.h:55
bool eoo() const
Indicates if it is the end-of-object element, which is present at the end of every BSON object.
Definition bsonelement.h:172
BSONType type() const
Returns the type of the element.
Definition bsonelement.h:154
C++ representation of a "BSON" object – that is, an extended JSON-style object in a binary representa...
Definition bsonobj.h:78
bool hasField(const StringData &name) const
Definition bsonobj.h:250
BSONElement getField(const StringData &name) const
Get the field of the specified name.
Represents a bounding box.
Definition boundingbox.h:67
Definition geoobj.h:34
Definition geometry.h:39
static BoundingBox< TCoordinates > * computeBoundingBox(const std::vector< Point< TCoordinates > > &points)
Compute the bounding box around the given points.
Definition geometry.h:137
static BoundingBox< TCoordinates > * parseBoundingBox(const BSONObj &bson)
Parses the bounding box defined by the given geometry shape, represented in BSON.
Definition geometry.h:201
Represents a Point.
Definition point.h:52
const char kBoundingBoxFieldName[]
The special field names defined by the GeoJSON specification.
Definition constants.h:26
BSON classes.
Utility functions for parsing numbers from strings.
Definition compare_numbers.h:20
@ Array
an embedded array
Definition bsontypes.h:50