Savarese Software ResearchSava Algorithms 0.1.1 C++ Unit Test Coverage
Current view: directory - libsava/spatial - Point.h
Test: Sava Algorithms 0.1.1 C++ Unit Tests
Date: 2005-10-29 Instrumented lines: 39
Code covered: 100.0 % Executed lines: 39

       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

Savarese Software Research