| 1 | // Copyright 2005 Google Inc. All Rights Reserved. |
| 2 | |
| 3 | #ifndef UTIL_GEOMETRY_S2CELL_H_ |
| 4 | #define UTIL_GEOMETRY_S2CELL_H_ |
| 5 | |
| 6 | #include "base/basictypes.h" |
| 7 | #include "base/logging.h" |
| 8 | #include "s2.h" |
| 9 | #include "s2cellid.h" |
| 10 | #include "s2region.h" |
| 11 | #include "util/math/vector2.h" |
| 12 | |
| 13 | // An S2Cell is an S2Region object that represents a cell. Unlike S2CellIds, |
| 14 | // it supports efficient containment and intersection tests. However, it is |
| 15 | // also a more expensive representation (currently 48 bytes rather than 8). |
| 16 | |
| 17 | // This class is intended to be copied by value as desired. It uses |
| 18 | // the default copy constructor and assignment operator, however it is |
| 19 | // not a "plain old datatype" (POD) because it has virtual functions. |
| 20 | class S2Cell : public S2Region { |
| 21 | public: |
| 22 | // The default constructor is required in order to use freelists. |
| 23 | // Cells should otherwise always be constructed explicitly. |
| 24 | S2Cell() {} |
| 25 | |
| 26 | // An S2Cell always corresponds to a particular S2CellId. The other |
| 27 | // constructors are just convenience methods. |
| 28 | explicit S2Cell(S2CellId const& id) { Init(id); } |
| 29 | |
| 30 | static S2Cell FromFacePosLevel(int face, uint64 pos, int level) { |
| 31 | // This is a static method in order to provide named parameters. |
| 32 | return S2Cell(S2CellId::FromFacePosLevel(face, pos, level)); |
| 33 | } |
| 34 | // Convenience methods. The S2LatLng must be normalized. |
| 35 | explicit S2Cell(S2Point const& p) { Init(S2CellId::FromPoint(p)); } |
| 36 | explicit S2Cell(S2LatLng const& ll) { Init(S2CellId::FromLatLng(ll)); } |
| 37 | |
| 38 | inline S2CellId id() const { return id_; } |
| 39 | inline int face() const { return face_; } |
| 40 | inline int level() const { return level_; } |
| 41 | inline int orientation() const { return orientation_; } |
| 42 | inline bool is_leaf() const { return level_ == S2CellId::kMaxLevel; } |
| 43 | |
| 44 | // These are equivalent to the S2CellId methods, but have a more efficient |
| 45 | // implementation since the level has been precomputed. |
| 46 | int GetSizeIJ() const; |
| 47 | double GetSizeST() const; |
| 48 | |
| 49 | // Return the k-th vertex of the cell (k = 0,1,2,3). Vertices are returned |
| 50 | // in CCW order. The points returned by GetVertexRaw are not necessarily |
| 51 | // unit length. |
| 52 | S2Point GetVertex(int k) const { return GetVertexRaw(k).Normalize(); } |
| 53 | S2Point GetVertexRaw(int k) const; |
| 54 | |
| 55 | // Return the inward-facing normal of the great circle passing through |
| 56 | // the edge from vertex k to vertex k+1 (mod 4). The normals returned |
| 57 | // by GetEdgeRaw are not necessarily unit length. |
| 58 | S2Point GetEdge(int k) const { return GetEdgeRaw(k).Normalize(); } |
| 59 | S2Point GetEdgeRaw(int k) const; |
| 60 | |
| 61 | // If this is not a leaf cell, set children[0..3] to the four children of |
| 62 | // this cell (in traversal order) and return true. Otherwise returns false. |
| 63 | // This method is equivalent to the following: |
| 64 | // |
| 65 | // for (pos=0, id=child_begin(); id != child_end(); id = id.next(), ++pos) |
| 66 | // children[i] = S2Cell(id); |
| 67 | // |
| 68 | // except that it is more than two times faster. |
| 69 | bool Subdivide(S2Cell children[4]) const; |
| 70 | |
| 71 | // Return the direction vector corresponding to the center in (s,t)-space of |
| 72 | // the given cell. This is the point at which the cell is divided into four |
| 73 | // subcells; it is not necessarily the centroid of the cell in (u,v)-space |
| 74 | // or (x,y,z)-space. The point returned by GetCenterRaw is not necessarily |
| 75 | // unit length. |
| 76 | S2Point GetCenter() const { return GetCenterRaw().Normalize(); } |
| 77 | S2Point GetCenterRaw() const; |
| 78 | |
| 79 | // Return the average area for cells at the given level. |
| 80 | static double AverageArea(int level); |
| 81 | |
| 82 | // Return the average area of cells at this level. This is accurate to |
| 83 | // within a factor of 1.7 (for S2_QUADRATIC_PROJECTION) and is extremely |
| 84 | // cheap to compute. |
| 85 | double AverageArea() const { return AverageArea(level_); } |
| 86 | |
| 87 | // Return the approximate area of this cell. This method is accurate to |
| 88 | // within 3% percent for all cell sizes and accurate to within 0.1% for |
| 89 | // cells at level 5 or higher (i.e. squares 350km to a side or smaller |
| 90 | // on the Earth's surface). It is moderately cheap to compute. |
| 91 | double ApproxArea() const; |
| 92 | |
| 93 | // Return the area of this cell as accurately as possible. This method is |
| 94 | // more expensive but it is accurate to 6 digits of precision even for leaf |
| 95 | // cells (whose area is approximately 1e-18). |
| 96 | double ExactArea() const; |
| 97 | |
| 98 | //////////////////////////////////////////////////////////////////////// |
| 99 | // S2Region interface (see s2region.h for details): |
| 100 | |
| 101 | virtual S2Cell* Clone() const; |
| 102 | virtual S2Cap GetCapBound() const; |
| 103 | virtual S2LatLngRect GetRectBound() const; |
| 104 | virtual bool Contains(S2Cell const& cell) const; |
| 105 | virtual bool MayIntersect(S2Cell const& cell) const; |
| 106 | virtual bool VirtualContainsPoint(S2Point const& p) const { |
| 107 | return Contains(p); // The same as Contains() below, just virtual. |
| 108 | } |
| 109 | |
| 110 | // The point 'p' does not need to be normalized. |
| 111 | bool Contains(S2Point const& p) const; |
| 112 | |
| 113 | virtual void Encode(Encoder* const encoder) const { |
| 114 | LOG(FATAL) << "Unimplemented" ; |
| 115 | } |
| 116 | virtual bool Decode(Decoder* const decoder) { return false; } |
| 117 | |
| 118 | private: |
| 119 | // Internal method that does the actual work in the constructors. |
| 120 | void Init(S2CellId const& id); |
| 121 | |
| 122 | // Return the latitude or longitude of the cell vertex given by (i,j), |
| 123 | // where "i" and "j" are either 0 or 1. |
| 124 | inline double GetLatitude(int i, int j) const; |
| 125 | inline double GetLongitude(int i, int j) const; |
| 126 | |
| 127 | // This structure occupies 44 bytes plus one pointer for the vtable. |
| 128 | int8 face_; |
| 129 | int8 level_; |
| 130 | int8 orientation_; |
| 131 | S2CellId id_; |
| 132 | double uv_[2][2]; |
| 133 | }; |
| 134 | |
| 135 | inline int S2Cell::GetSizeIJ() const { |
| 136 | return S2CellId::GetSizeIJ(level()); |
| 137 | } |
| 138 | |
| 139 | inline double S2Cell::GetSizeST() const { |
| 140 | return S2CellId::GetSizeST(level()); |
| 141 | } |
| 142 | |
| 143 | #endif // UTIL_GEOMETRY_S2CELL_H_ |
| 144 | |