![]() | ||||||||||||||||||||
|
||||||||||||||||||||
![]() |
1 : /* 2 : * $Id: Point.h 5871 2005-10-28 02:10:33Z dfs $ 3 : * 4 : * Copyright 2003-2005 Daniel F. Savarese 5 : * Copyright 2005 Savarese Software Research 6 : * 7 : * Licensed under the Apache License, Version 2.0 (the "License"); 8 : * you may not use this file except in compliance with the License. 9 : * You may obtain a copy of the License at 10 : * 11 : * https://www.savarese.com/software/ApacheLicense-2.0 12 : * 13 : * Unless required by applicable law or agreed to in writing, software 14 : * distributed under the License is distributed on an "AS IS" BASIS, 15 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 : * See the License for the specific language governing permissions and 17 : * limitations under the License. 18 : */ 19 : 20 : /** 21 : * @file 22 : * This header defines the Point, Point2D, and Point3D classes 23 : * and supporting operations. 24 : */ 25 : 26 : #ifndef __SAVA_SPATIAL_POINT_H 27 : #define __SAVA_SPATIAL_POINT_H 28 : 29 : #include <limits> 30 : #include <cstring> 31 : 32 : #include <libsava/packages.h> 33 : 34 : __BEGIN_PACKAGE_SAVA_SPATIAL 35 : 36 : /** 37 : * PointTraits stores metadata about Point instances. 38 : * 39 : * @author <a href="https://www.savarese.com/">Daniel F. Savarese</a> 40 : */ 41 : template<typename P> 42 : struct PointTraits { 43 : /** 44 : * The type of the point. 45 : */ 46 : typedef P point_type; 47 : 48 : /** 49 : * The type of coordinates stored in the point. 50 : */ 51 : typedef typename point_type::coordinate_type coordinate_type; 52 : 53 : /** 54 : * Returns the maximum value a coordinate may assume. 55 : * 56 : * @return The maximum value a coordinate may assume. 57 : */ 58 131084 : static inline const coordinate_type max_coordinate() { 59 131084 : return std::numeric_limits<coordinate_type>::max(); 60 : } 61 : 62 : /** 63 : * Returns the minimum value a coordinate may assume. 64 : * 65 : * @return The minimum value a coordinate may assume. 66 : */ 67 8 : static inline const coordinate_type min_coordinate() { 68 8 : return std::numeric_limits<coordinate_type>::min(); 69 : } 70 : 71 : /** 72 : * Returns the number of dimensions in the point. 73 : * 74 : * @return The number of dimensions in the point. 75 : */ 76 393276 : static inline const unsigned int dimensions() { 77 393276 : return point_type::dimensions(); 78 : } 79 : }; 80 : 81 : 82 : /** 83 : * A Point is a k-dimensional tuple of coordinates. 84 : * 85 : * @param Dimensions The number of dimensons in the point (default is 2). 86 : * @param CoordType The type of th coordinates (default is unsigned int). 87 : * 88 : * @author <a href="https://www.savarese.com/">Daniel F. Savarese</a> 89 : */ 90 : template<unsigned int Dimensions = 2, class CoordType = unsigned int> 91 262144 : class Point { 92 : public: 93 : /** 94 : * The type of coordinates stored in the point. 95 : */ 96 : typedef CoordType coordinate_type; 97 : 98 : /** 99 : * Returns the number of dimensions in the point. 100 : * 101 : * @return The number of dimensions in the point. 102 : */ 103 393276 : static inline const unsigned int dimensions() { 104 393276 : return Dimensions; 105 : } 106 : 107 : private: 108 : coordinate_type coordinates[Dimensions]; 109 : 110 : public: 111 : 112 : /** 113 : * Constructs a point with all coordinate values set to zero. 114 : */ 115 458859 : Point() { 116 : // This is the wrong thing to do for non-primitive types. 117 : // Place in a specialization of the class. 118 458859 : std::memset(coordinates, 0, sizeof(coordinates)); 119 : } 120 : 121 : /** 122 : * Returns the coordinate at the specified index. 123 : * 124 : * @param index The index of the coordinate to retrieve. 125 : * @return The coordinate at the specified index. 126 : */ 127 4927253 : coordinate_type & operator[](const unsigned int index) { 128 4927253 : return coordinates[index]; 129 : } 130 : 131 : /** 132 : * Returns the coordinate at the specified index as a const reference. 133 : * 134 : * @param index The index of the coordinate to retrieve. 135 : * @return The coordinate at the specified index. 136 : */ 137 62003554 : const coordinate_type & operator[](const unsigned int index) const { 138 62003554 : return coordinates[index]; 139 : } 140 : 141 : // Rely on default assignment operator. 142 : /* 143 : Point & operator=(const Point & point) { 144 : // This is the wrong thing to do for non-primitive types. 145 : // Place in a specialization of the class. 146 : if(this != &point) 147 : std::memcpy(coordinates, point.coordinates, sizeof(coordinates)); 148 : return *this; 149 : } 150 : */ 151 : }; 152 : 153 : 154 : /** 155 : * Returns true if each of the coordinates in point1 is equal to its 156 : * corresponding coordinate in point2, otherwise false. 157 : * 158 : * @param point1 The first point to compare. 159 : * @param point2 The second point to compare. 160 : * @return true if the two points are equal, false if not. 161 : */ 162 : template<unsigned int Dimensions, class CoordType> 163 : inline bool operator==(const Point<Dimensions, CoordType> & point1, 164 4 : const Point<Dimensions, CoordType> & point2) 165 : { 166 4 : unsigned int d = Dimensions; 167 16 : while(d-- > 0) { 168 10 : if(point1[d] != point2[d]) 169 2 : return false; 170 : } 171 2 : return true; 172 : } 173 : 174 : /** 175 : * Returns true if there is an index j where point1[i] <= point2[i] 176 : * and point1[j] < point2[j] for all i <= j, otherwise false. In 177 : * other words, the points are ordered lexicographically. This is 178 : * done only for sorting purposes in STL containers. 179 : * 180 : * @param point1 The first point to compare. 181 : * @param point2 The second point to compare. 182 : * @return true if point1 is lexicographically less than point2, false if not. 183 : */ 184 : template<unsigned int Dimensions, class CoordType> 185 : inline bool operator<(const Point<Dimensions, CoordType> & point1, 186 : const Point<Dimensions, CoordType> & point2) 187 : { 188 : unsigned int d = Dimensions; 189 : while(d-- > 0) { 190 : if(point1[d] < point2[d]) 191 : return true; 192 : else if(point1[d] != point2[d]) 193 : break; 194 : } 195 : return false; 196 : } 197 : 198 : /** 199 : * Returns true if there is an index j where point1[i] >= point2[i] 200 : * and point1[j] > point2[j] for all i <= j, otherwise false. In 201 : * other words, the points are ordered lexicographically. This is 202 : * done only for sorting purposes in STL containers. 203 : * 204 : * @param point1 The first point to compare. 205 : * @param point2 The second point to compare. 206 : * @return true if point1 is lexicographically greater than point2, 207 : * false if not. 208 : */ 209 : template<unsigned int Dimensions, class CoordType> 210 : inline bool operator>(const Point<Dimensions, CoordType> & point1, 211 : const Point<Dimensions, CoordType> & point2) 212 : { 213 : unsigned int d = Dimensions; 214 : while(d-- > 0) { 215 : if(point1[d] > point2[d]) 216 : return true; 217 : else if(point1[d] != point2[d]) 218 : break; 219 : } 220 : return false; 221 : } 222 : 223 : template<class CoordType> 224 : inline bool operator==(const Point<2, CoordType> & point1, 225 2334348 : const Point<2, CoordType> & point2) 226 : { 227 2334348 : return (point1[0] == point2[0] && point1[1] == point2[1]); 228 : } 229 : 230 : template<class CoordType> 231 : inline bool operator<(const Point<2, CoordType> & point1, 232 3901783 : const Point<2, CoordType> & point2) 233 : { 234 : return (point1[0] < point2[0] || 235 3901783 : (point1[0] == point2[0] && point1[1] < point2[1])); 236 : } 237 : 238 : template<class CoordType> 239 : inline bool operator>(const Point<2, CoordType> & point1, 240 : const Point<2, CoordType> & point2) 241 : { 242 : return (point1[0] > point2[0] || 243 : (point1[0] == point2[0] && point1[1] > point2[1])); 244 : } 245 : 246 : template<class CoordType> 247 : inline bool operator==(const Point<3, CoordType> & point1, 248 2 : const Point<3, CoordType> & point2) 249 : { 250 : return (point1[0] == point2[0] && point1[1] == point2[1] && 251 2 : point1[2] == point2[2]); 252 : } 253 : 254 : template<class CoordType> 255 : inline bool operator<(const Point<3, CoordType> & point1, 256 : const Point<3, CoordType> & point2) 257 : { 258 : return (point1[0] < point2[0] || 259 : (point1[0] == point2[0] && 260 : (point1[1] < point2[1] || 261 : (point1[1] == point2[1] && point1[2] < point2[2])))); 262 : 263 : } 264 : 265 : template<class CoordType> 266 : inline bool operator>(const Point<3, CoordType> & point1, 267 : const Point<3, CoordType> & point2) 268 : { 269 : return (point1[0] > point2[0] || 270 : (point1[0] == point2[0] && 271 : (point1[1] > point2[1] || 272 : (point1[1] == point2[1] && point1[2] > point2[2])))); 273 : 274 : } 275 : 276 : template<unsigned int Dimensions, class CoordType> 277 : inline bool operator!=(const Point<Dimensions, CoordType> & point1, 278 1 : const Point<Dimensions, CoordType> & point2) 279 : { 280 1 : return !(point1 == point2); 281 : } 282 : 283 : template<unsigned int Dimensions, class CoordType> 284 : inline bool operator>=(const Point<Dimensions, CoordType> & point1, 285 : const Point<Dimensions, CoordType> & point2) 286 : { 287 : return !(point1 < point2); 288 : } 289 : 290 : template<unsigned int Dimensions, class CoordType> 291 : inline bool operator<=(const Point<Dimensions, CoordType> & point1, 292 : const Point<Dimensions, CoordType> & point2) 293 : { 294 : return !(point1 > point2); 295 : } 296 : 297 : /** 298 : * A two-dimensional specialization of the Point class. 299 : * 300 : * @author <a href="https://www.savarese.com/">Daniel F. Savarese</a> 301 : */ 302 : template <class CoordType = unsigned int> 303 : class Point2D : public Point<2, CoordType> { 304 : 305 : public: 306 : typedef CoordType coordinate_type; 307 : 308 : Point2D() { 309 : (*this)[0] = coordinate_type(); 310 : (*this)[1] = coordinate_type(); 311 : } 312 : 313 262152 : Point2D(const coordinate_type & x, const coordinate_type & y) { 314 262152 : (*this)[0] = x; 315 262152 : (*this)[1] = y; 316 : } 317 : }; 318 : 319 : /** 320 : * A three-dimensional specialization of the Point class. 321 : * 322 : * @author <a href="https://www.savarese.com/">Daniel F. Savarese</a> 323 : */ 324 : template <class CoordType = unsigned int> 325 : class Point3D : public Point<3, CoordType> { 326 : 327 : public: 328 : typedef CoordType coordinate_type; 329 : 330 : Point3D() { 331 : (*this)[0] = coordinate_type(); 332 : (*this)[1] = coordinate_type(); 333 : (*this)[2] = coordinate_type(); 334 : } 335 : 336 : Point3D(const coordinate_type & x, const coordinate_type & y, 337 2 : const coordinate_type & z) 338 2 : { 339 2 : (*this)[0] = x; 340 2 : (*this)[1] = y; 341 2 : (*this)[2] = z; 342 : } 343 : }; 344 : 345 : 346 : // Will have to replace isContained with an abstraction for testing 347 : // containment in arbitrarily shaped regions. 348 : 349 : template <unsigned int Dimensions, class CoordType> 350 : inline bool isContained(const Point<Dimensions, CoordType> & point, 351 : const Point<Dimensions, CoordType> & lower, 352 : const Point<Dimensions, CoordType> & upper) 353 : { 354 : for(unsigned int i = 0; i < Dimensions; ++i) { 355 : if(point[i] < lower[i] || point[i] > upper[i]) 356 : return false; 357 : } 358 : 359 : return true; 360 : } 361 : 362 : 363 : template <class CoordType> 364 : inline bool isContained(const Point<2, CoordType> & point, 365 : const Point<2, CoordType> & lower, 366 32778 : const Point<2, CoordType> & upper) 367 : { 368 : return !(point[0] < lower[0] || point[1] < lower[1] || 369 32778 : point[0] > upper[0] || point[1] > upper[1]); 370 : } 371 : 372 : 373 : template <class CoordType> 374 : inline bool isContained(const Point<3, CoordType> & point, 375 : const Point<3, CoordType> & lower, 376 : const Point<3, CoordType> & upper) 377 : { 378 : return !(point[0] < lower[0] || point[1] < lower[1] || point[2] < lower[2] || 379 : point[0] > upper[0] || point[1] > upper[1] || point[2] > upper[2]); 380 : 381 : } 382 : 383 : __END_PACKAGE_SAVA_SPATIAL 384 : 385 : #endif |
![]() |
![]() |