/usr/include/mongo/geo/geometry.h is in libmongoclient-dev 1.1.2-6ubuntu3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 | /* Copyright 2014 MongoDB Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** @file */
#pragma once
#include <algorithm>
#include <limits>
#include <vector>
#include "mongo/client/export_macros.h"
#include "mongo/db/jsobj.h"
#include "mongo/geo/boundingbox.h"
#include "mongo/geo/constants.h"
#include "mongo/geo/geoobj.h"
#include "mongo/util/assert_util.h"
namespace mongo {
namespace geo {
// forward declaration needed for Geometry's static helpers
template <typename TCoordinates>
class Point;
template <typename TCoordinates>
class Geometry : public GeoObj<TCoordinates> {
protected:
static BSONElement getCoordsField(const BSONObj& bson);
static std::vector<double> parseCoords(const BSONElement& coordArr);
static std::vector<double> parseCoords(const BSONObj& bson);
static Point<TCoordinates> parsePoint(const BSONElement& coordArr);
static std::vector<Point<TCoordinates> > parsePointArray(
const std::vector<BSONElement>& pointArr);
static std::vector<Point<TCoordinates> > parseAllPoints(const BSONObj& bson);
/**
* Compute the bounding box around the given points. Caller has ownership of
* the returned pointer.
*
* @param points The points that the computed bounding box will surround.
*
* @return A pointer to a bounding box around the given points.
*/
static BoundingBox<TCoordinates>* computeBoundingBox(
const std::vector<Point<TCoordinates> >& points);
/**
* Compute the smallest bounding box that contains the given bounding boxes.
* This can also be thought of as the one large bounding box around the union
* of points contained in the several smaller bounding boxes passed to this function.
* Caller had ownership of the returned pointer.
*
* @param bboxes the bounding boxes that the computed bounding box will surround.
*
* @return A pointer to a bounding box around the given bounding boxes.
*/
static BoundingBox<TCoordinates>* computeBoundingBox(
const std::vector<BoundingBox<TCoordinates> >& bboxes);
/**
* Parses the bounding box defined by the given geometry shape, represented
* in BSON. Caller had ownership of the returned pointer.
*
* @param bson The BSON for the geometry shape.
*
* @return If the shape defines its own bounding box with the "bbox" field,
* returns a pointer to an instantiated bounding box around the shape.
* Otherwise returns NULL.
*/
static BoundingBox<TCoordinates>* parseBoundingBox(const BSONObj& bson);
private:
static void findMinAndMaxCoordinatesOfDimension(const std::vector<Point<TCoordinates> >& points,
size_t dimension,
double* min,
double* max);
};
template <typename TCoordinates>
BSONElement Geometry<TCoordinates>::getCoordsField(const BSONObj& bson) {
BSONElement coordsField = bson.getField(kCoordsFieldName);
uassert(0,
"bson must contain a field \"coordinates\" of type Array",
!coordsField.eoo() && coordsField.type() == Array);
return coordsField;
}
template <typename TCoordinates>
std::vector<double> Geometry<TCoordinates>::parseCoords(const BSONElement& coordArr) {
std::vector<BSONElement> coordElems = coordArr.Array();
std::vector<double> coords;
for (size_t i = 0; i < coordElems.size(); ++i)
coords.push_back(coordElems[i].Double());
return coords;
}
template <typename TCoordinates>
std::vector<double> Geometry<TCoordinates>::parseCoords(const BSONObj& bson) {
return parseCoords(getCoordsField(bson));
}
template <typename TCoordinates>
Point<TCoordinates> Geometry<TCoordinates>::parsePoint(const BSONElement& coordArr) {
TCoordinates pointCoords(parseCoords(coordArr));
return Point<TCoordinates>(pointCoords);
}
template <typename TCoordinates>
std::vector<Point<TCoordinates> > Geometry<TCoordinates>::parsePointArray(
const std::vector<BSONElement>& pointArr) {
std::vector<Point<TCoordinates> > points;
for (size_t i = 0; i < pointArr.size(); ++i) {
points.push_back(parsePoint(pointArr[i]));
}
return points;
}
template <typename TCoordinates>
std::vector<Point<TCoordinates> > Geometry<TCoordinates>::parseAllPoints(const BSONObj& bson) {
return parsePointArray(getCoordsField(bson).Array());
}
template <typename TCoordinates>
BoundingBox<TCoordinates>* Geometry<TCoordinates>::computeBoundingBox(
const std::vector<Point<TCoordinates> >& points) {
// For a TCoordinates type with dimensions d1, d2, ..., dn,
// the bounding box of these points will have min coordinates
// whose d1 value is the minimum of all d1-axis values in points,
// whose d2 value is the minimum of all d2-axis values in points,
// and so on up through dn. Similarly for the max coordinates.
//
// So to compute the bounding box, we iterate through each dimension
// and find the min / max values in points for that dimension.
std::vector<double> minCoordComponents, maxCoordComponents;
for (size_t i = 0; i < TCoordinates::dimensionality(); ++i) {
double min, max;
findMinAndMaxCoordinatesOfDimension(points, i, &min, &max);
minCoordComponents.push_back(min);
maxCoordComponents.push_back(max);
}
TCoordinates minCoords(minCoordComponents);
TCoordinates maxCoords(maxCoordComponents);
return new BoundingBox<TCoordinates>(minCoords, maxCoords);
}
template <typename TCoordinates>
void Geometry<TCoordinates>::findMinAndMaxCoordinatesOfDimension(
const std::vector<Point<TCoordinates> >& points, size_t dimension, double* min, double* max) {
// Initialize min and max to the positive and negative double values
// farthest from 0, respectively. Note that we initialize max to
// -::max(). Initializing to ::min() is incorrect because it returns
// the smallest positive normalized double, which is still greater than
// every negative double (and coordinates can have negative values).
*min = std::numeric_limits<double>::max();
*max = -std::numeric_limits<double>::max();
// Update min and max with the smallest and largest values for the given dimension.
for (size_t i = 0; i < points.size(); ++i) {
if (points[i][dimension] < *min)
*min = points[i][dimension];
if (points[i][dimension] > *max)
*max = points[i][dimension];
}
}
template <typename TCoordinates>
BoundingBox<TCoordinates>* Geometry<TCoordinates>::computeBoundingBox(
const std::vector<BoundingBox<TCoordinates> >& bboxes) {
if (bboxes.empty())
return NULL;
std::vector<double> minCoords = bboxes[0].getMin().getValues();
std::vector<double> maxCoords = bboxes[0].getMax().getValues();
for (size_t i = 1; i < bboxes.size(); ++i) {
std::vector<double> curMin = bboxes[i].getMin().getValues();
std::vector<double> curMax = bboxes[i].getMax().getValues();
for (size_t j = 0; j < curMin.size(); ++j) {
minCoords[j] = std::min(minCoords[j], curMin[j]);
maxCoords[j] = std::max(maxCoords[j], curMax[j]);
}
}
TCoordinates globalMin(minCoords), globalMax(maxCoords);
return new BoundingBox<TCoordinates>(globalMin, globalMax);
}
template <typename TCoordinates>
BoundingBox<TCoordinates>* Geometry<TCoordinates>::parseBoundingBox(const BSONObj& bson) {
if (bson.hasField(kBoundingBoxFieldName))
return new BoundingBox<TCoordinates>(bson);
return NULL;
}
} // namespace geo
} // namespace mongo
|