All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
TileIndexer.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2008 National Institute For Space Research (INPE) - Brazil.
2 
3  This file is part of the TerraLib - a Framework for building GIS enabled applications.
4 
5  TerraLib is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  TerraLib is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with TerraLib. See COPYING. If not, write to
17  TerraLib Team at <terralib-team@terralib.org>.
18  */
19 
20 /*!
21  \file terralib/raster/TileIndexer.cpp
22 
23  \brief Polygon tile indexing class for optmized geometrical relational tests.
24 */
25 
26 // TerraLib
27 #include "TileIndexer.h"
28 #include "Exception.h"
29 #include "../geometry.h"
30 #include "../common/STLUtils.h"
31 #include "../common/Translator.h"
32 
33 // STL
34 #include <iostream>
35 #include <memory>
36 
38  unsigned int& firstTile, unsigned int& lastTile) const
39 {
40 // Invalid tile indexer Y resolution
41  assert(m_dy > 0);
42 
43  double lowerY = ((p1.getY() < p2.getY())? p1.getY(): p2.getY());
44  double upperY = ((p1.getY() > p2.getY())? p1.getY(): p2.getY());
45 
46  if( ( lowerY < m_referencePolygon.getMBR()->getLowerLeftY() ) ||
47  ( upperY > m_referencePolygon.getMBR()->getUpperRightY() ) )
48  {
49  return false;
50  }
51  else
52  {
53  firstTile = (unsigned int)((lowerY - m_referencePolygon.getMBR()->getLowerLeftY()) / m_dy);
54  lastTile = (unsigned int)((upperY - m_referencePolygon.getMBR()->getLowerLeftY()) / m_dy);
55  return true;
56  }
57 }
58 
59 bool te::rst::TileIndexer::getTileIndex(const double& y, unsigned int& tileIndex) const
60 {
61  assert(m_dy > 0);
62 
63  if( ( y < m_referencePolygon.getMBR()->getLowerLeftY() ) ||
64  ( y > m_referencePolygon.getMBR()->getUpperRightY() ) )
65  {
66  return false;
67  }
68  else
69  {
70  tileIndex = (unsigned int)( (y - m_referencePolygon.getMBR()->getLowerLeftY() ) / m_dy );
71  return true;
72  }
73 }
74 
76 {
77  m_dy = 0;
78 }
79 
81  : m_referencePolygon(pol)
82 {
83  assert(dy > 0);
84 
85  init();
86  m_dy = dy;
87 
88 // Building new index
90  {
91  unsigned int total_tiles_number = 1 +
92  ((unsigned int) floor(m_referencePolygon.getMBR()->getHeight() / m_dy));
93 
94  for(unsigned int i = 0; i < total_tiles_number; i++)
95  m_tileIndex.push_back(new TileSegIndex);
96 
97 // for each polygon ring, we need to index its segments
98  for(unsigned int i = 0; i < m_referencePolygon.getNumRings(); i++)
99  {
100  if( ! addRing(i) )
101  {
102  throw Exception(TE_TR("Error adding ring") );
103  }
104  }
105  }
106 }
107 
109 {
110  te::common::FreeContents(m_tileIndex);
111  m_tileIndex.clear();
112  init();
113 }
114 
116 {
117  clear();
118 }
119 
120 bool te::rst::TileIndexer::addRing(const unsigned int& ri)
121 {
122  if( ri >= m_referencePolygon.getNumRings() )
123  {
124  return false;
125  }
126 
127  unsigned int num_points = m_referencePolygon[ri]->getNPoints();
128  if (num_points < 2)
129  {
130  return false;
131  }
132 
133  unsigned int numSegments = num_points - 1;
134 
135  for(unsigned int j = 0; j < numSegments; j++)
136  {
137 // creates a pointer to the segment
138  std::pair<unsigned int, unsigned int> segPointer(ri, j);
139 
140 // finds the tiles that this segment intersects
141  unsigned int firstTileIndex = 0;
142  unsigned int lastTileIndex = 0;
143 
144  std::auto_ptr< te::gm::Point > cj(
145  (static_cast<te::gm::LinearRing*> (m_referencePolygon[ri]))->getPointN(j) );
146  std::auto_ptr< te::gm::Point > cjp1(
147  (static_cast<te::gm::LinearRing*> (m_referencePolygon[ri]))->getPointN(j + 1) );
148 
149  if( getTileIndex(*cj, *cjp1, firstTileIndex, lastTileIndex) )
150  {
151  // associates the pointer segment to the tiles
152  for(unsigned int k = firstTileIndex; k <= lastTileIndex; k++)
153  m_tileIndex[k]->push_back(segPointer);
154  }
155  else
156  {
157  return false;
158  }
159  }
160 
161  return true;
162 }
163 
164 bool te::rst::TileIndexer::getTile(const double& y, TileSegIndex** index) const
165 {
166  unsigned int tidx;
167  if( getTileIndex(y, tidx) )
168  {
169  assert( tidx < m_tileIndex.size() );
170 
171  (*index) = m_tileIndex[tidx];
172  return true;
173  }
174  else
175  {
176  return false;
177  }
178 }
179 
180 bool te::rst::TileIndexer::within(const te::gm::Point& geometry) const
181 {
182  m_withinTileY = geometry.getY();
183 
184  if( getTile( m_withinTileY, &m_withinTileIndexPtr ) )
185  {
186  assert( m_withinTileIndexPtr );
187 
188  m_withinTileX = geometry.getX();
189  m_withinIsInside = false;
190 
191  for( unsigned int i = 0 ; i < m_withinTileIndexPtr->size() ; ++i )
192  {
193  assert( ( ( *m_withinTileIndexPtr )[ i ].first < m_referencePolygon.getNumRings() ) );
194  assert( dynamic_cast< te::gm::LinearRing const* >( m_referencePolygon[
195  ( *m_withinTileIndexPtr )[ i ].first ] ) );
196  m_withinRingPtr = (te::gm::LinearRing const*)m_referencePolygon[ ( *m_withinTileIndexPtr )[ i ].first ];
197 
198  assert( ( *m_withinTileIndexPtr )[ i ].second < m_withinRingPtr->getNPoints() );
199  m_withinVtx0.x = m_withinRingPtr->getX( ( *m_withinTileIndexPtr )[ i ].second );
200  m_withinVtx0.y = m_withinRingPtr->getY( ( *m_withinTileIndexPtr )[ i ].second );
201  m_withinVtx1.x = m_withinRingPtr->getX( ( *m_withinTileIndexPtr )[ i ].second + 1 );
202  m_withinVtx1.y = m_withinRingPtr->getY( ( *m_withinTileIndexPtr )[ i ].second + 1 );
203 
204  m_withinYFlag0 = (m_withinVtx0.y >= m_withinTileY);
205 
206  m_withinYFlag1 = (m_withinVtx1.y >= m_withinTileY);
207 
208  if(m_withinYFlag0 != m_withinYFlag1)
209  {
210  /* TODO - Check Boundary case */
211 
212  if(((m_withinVtx1.y - m_withinTileY) * (m_withinVtx0.x - m_withinVtx1.x) >=
213  (m_withinVtx1.x - m_withinTileX) * (m_withinVtx0.y - m_withinVtx1.y)) == m_withinYFlag1)
214  {
215  m_withinIsInside = !m_withinIsInside ;
216  }
217  }
218  }
219 
220  return m_withinIsInside;
221  }
222  else
223  {
224  return false;
225  }
226 }
227 
std::size_t getNumRings() const
It returns the number of rings in this CurvePolygon.
Definition: CurvePolygon.h:153
bool getTile(const double &y, TileSegIndex **index) const
Gets tile index.
~TileIndexer()
Destructor.
const te::gm::Polygon & m_referencePolygon
Reference polygon.
Definition: TileIndexer.h:143
bool within(const te::gm::Point &geometry) const
It returns true if the given geometry is within the indexed reference polygon.
bool addRing(const unsigned int &ri)
Update the tile index with the information of the supplied ring.
const double & getLowerLeftY() const
It returns a constant refernce to the y coordinate of the lower left corner.
Definition: Envelope.h:400
const double & getUpperRightY() const
It returns a constant refernce to the x coordinate of the upper right corner.
Definition: Envelope.h:420
#define TE_TR(message)
It marks a string in order to get translated.
Definition: Translator.h:347
bool getTileIndex(const te::gm::Point &p1, const te::gm::Point &p2, unsigned int &firstTile, unsigned int &lastTile) const
Gets tile index intervals in y direction for a given segment.
Definition: TileIndexer.cpp:37
A LinearRing is a LineString that is both closed and simple.
Definition: LinearRing.h:53
An exception class for the Raster module.
const double & getY() const
It returns the Point y-coordinate value.
Definition: Point.h:150
A point with x and y coordinate values.
Definition: Point.h:50
Polygon tile indexing class for optmized geometrical relational tests.
double m_dy
Tile resolution along "y" axis.
Definition: TileIndexer.h:142
void clear()
Clear all internal resources.
TileIndexer(const TileIndexer &)
Constructor.
Polygon is a subclass of CurvePolygon whose rings are defined by linear rings.
Definition: Polygon.h:50
std::vector< TileSegIndex * > m_tileIndex
Each tile segments index vector.
Definition: TileIndexer.h:144
std::vector< std::pair< unsigned int, unsigned int > > TileSegIndex
Definition: TileIndexer.h:58
void FreeContents(boost::unordered_map< K, V * > &m)
This function can be applied to a map of pointers. It will delete each pointer in the map...
Definition: BoostUtils.h:55
double getHeight() const
It returns the envelope height.
Definition: Envelope.h:448
const Envelope * getMBR() const
It returns the minimum bounding rectangle for the geometry in an internal representation.
Definition: Geometry.cpp:104
const double & getX() const
It returns the Point x-coordinate value.
Definition: Point.h:136
void init()
Init internal variables.
Definition: TileIndexer.cpp:75