DefaultFeatureInfoMaker.cpp
Go to the documentation of this file.
2 
3 //TerraLib
4 #include "../../../../geometry/Envelope.h"
5 #include "../../../widgets/canvas/MapDisplay.h"
6 #include "../../../../common/STLUtils.h"
7 #include "../../../../dataaccess/dataset/DataSet.h"
8 #include "../../../../dataaccess/dataset/DataSetType.h"
9 #include "../../../../dataaccess/utils/Utils.h"
10 #include "../../../../geometry/Coord2D.h"
11 #include "../../../../geometry/Envelope.h"
12 #include "../../../../geometry/Geometry.h"
13 #include "../../../../geometry/GeometryProperty.h"
14 #include "../../../../geometry/Point.h"
15 #include "../../../..//geometry/Utils.h"
16 #include "../../../../maptools/MarkRendererManager.h"
17 #include "../../../../raster/Raster.h"
18 #include "../../../../raster/RasterProperty.h"
19 #include "../../../../raster/Utils.h"
20 #include "../../../../se/Fill.h"
21 #include "../../../../se/Stroke.h"
22 #include "../../../../se/Mark.h"
23 #include "../../../../se/Utils.h"
24 #include "../../../../srs/Config.h"
25 #include "../../canvas/Canvas.h"
26 #include "../../canvas/MapDisplay.h"
27 #include "../../Utils.h"
28 
29 // Qt
30 #include <QtCore/QPointF>
31 #include <QtCore/QString>
32 #include <QtCore/QStringList>
33 #include <QMessageBox>
34 #include <QMouseEvent>
35 #include <QObject>
36 
37 // STL
38 #include <cassert>
39 #include <memory>
40 
42 
44 
46  const te::map::AbstractLayerPtr& layer, const te::gm::Envelope& e)
47 {
48  if(layer->getVisibility() != te::map::VISIBLE)
49  return;
50 
51  bool needRemap = false;
52  te::gm::Envelope reprojectedEnvelope(e);
53 
54  if((layer->getSRID() != TE_UNKNOWN_SRS) &&
55  (display->getSRID() != TE_UNKNOWN_SRS) &&
56  (layer->getSRID() != display->getSRID()))
57  {
58  needRemap = true;
59  reprojectedEnvelope.transform(display->getSRID(), layer->getSRID());
60  }
61 
62  if(!reprojectedEnvelope.intersects(layer->getExtent()))
63  return;
64 
65  try
66  {
67  // Gets the Layer Schema
68  std::unique_ptr<const te::map::LayerSchema> ls(layer->getSchema());
69 
70  // Gets the name of the referenced spatial property
71  std::string spatialPropertyName = layer->getGeomPropertyName();
72 
73  if(ls->hasGeom())
74  {
75  te::gm::GeometryProperty* gp = nullptr;
76 
77  if(spatialPropertyName.empty())
78  gp = te::da::GetFirstGeomProperty(ls.get());
79  else
80  gp = dynamic_cast<te::gm::GeometryProperty*>(
81  ls->getProperty(spatialPropertyName));
82 
83  assert(gp);
84 
85  // Retrieves the data from layer
86  std::unique_ptr<te::da::DataSet> dataset(
87  layer->getData(gp->getName(), &reprojectedEnvelope,
88  te::gm::INTERSECTS).release());
89 
90  getGeometryInfo(layerItem, display, dataset.get(), layer->getGeomPropertyName(),
91  reprojectedEnvelope, layer->getSRID(), needRemap);
92  }
93 
94  if(ls->hasRaster())
95  {
96  te::rst::RasterProperty* rp = nullptr;
97 
98  if(spatialPropertyName.empty())
99  rp = te::da::GetFirstRasterProperty(ls.get());
100  else
101  rp = dynamic_cast<te::rst::RasterProperty*>(
102  ls->getProperty(spatialPropertyName));
103 
104  assert(rp);
105 
106  // Retrieves the data from layer
107  std::unique_ptr<te::da::DataSet> dataset(
108  layer->getData(rp->getName(), &reprojectedEnvelope,
109  te::gm::INTERSECTS).release());
110 
111  if(!dataset->moveNext())
112  return;
113 
114  std::unique_ptr<te::rst::Raster> raster(dataset->getRaster(rp->getName()));
115  assert(raster.get());
116 
117  getRasterInfo(layerItem, display, raster.get(), reprojectedEnvelope,
118  layer->getSRID(), needRemap);
119  }
120  }
121  catch(...)
122  {
123  delete layerItem;
124  // TODO: catch the exceptions...
125  }
126 }
127 
129  MapDisplay* display,
130  te::da::DataSet* dataset,
131  const std::string& geomPropertyName,
132  const te::gm::Envelope& e, int srid,
133  bool needRemap)
134 {
135  // Generates a geometry from the given extent. It will be used to refine the
136  // results
137  std::unique_ptr<te::gm::Geometry> geometryFromEnvelope(
138  te::gm::GetGeomFromEnvelope(&e, srid));
139 
140  // The restriction point. It will be used to refine the results
141  te::gm::Coord2D center = e.getCenter();
142  te::gm::Point point(center.x, center.y, srid);
143 
144  std::size_t gpos = std::string::npos;
145  geomPropertyName.empty()
147  : gpos = te::da::GetPropertyPos(dataset, geomPropertyName);
148 
149  while(dataset->moveNext())
150  {
151  std::unique_ptr<te::gm::Geometry> g(dataset->getGeometry(gpos));
152 
153  if(g.get() == nullptr)
154  continue;
155 
157  bool isValid = te::gm::CheckValidity(g.get(), err);
158  if(!isValid)
159  {
160  QString message = QObject::tr("Invalid geometry: ") + err.m_message.c_str();
161  QMessageBox::warning(display, QObject::tr("Information"), message);
162  return;
163  }
164 
165  g->setSRID(srid);
166 
167  if(g->contains(&point) || g->crosses(geometryFromEnvelope.get()) ||
168  geometryFromEnvelope->contains(g.get()))
169  {
170  // Feature found! Building the list of property values...
171  for(std::size_t i = 0; i < dataset->getNumProperties(); ++i)
172  {
173  if(dataset->getPropertyDataType(i) == te::dt::RASTER_TYPE)
174  continue;
175 
176  QTreeWidgetItem* propertyItem = new QTreeWidgetItem(layerItem);
177  propertyItem->setText(0, dataset->getPropertyName(i).c_str());
178 
179  if(dataset->getPropertyDataType(i) == te::dt::GEOMETRY_TYPE)
180  propertyItem->setIcon(0, QIcon::fromTheme("geometry"));
181 
182  if(!dataset->isNull(i))
183  {
184  QString qvalue;
185 
186  if(dataset->getPropertyDataType(i) == te::dt::STRING_TYPE)
187  {
188  std::string value = dataset->getString(i);
189  qvalue = QString::fromUtf8(value.c_str());
190  }
191  else
192  {
193  if (dataset->getPropertyDataType(i) == te::dt::GEOMETRY_TYPE)
194  {
195  qvalue = (dataset->getAsString(i)).c_str();
196  }
197  else
198  qvalue = dataset->getAsString(i, 3).c_str();
199  }
200 
201  propertyItem->setText(1, qvalue);
202  }
203  else // property null value!
204  propertyItem->setText(1, "");
205  }
206 
207  if(needRemap)
208  {
209  g->setSRID(srid);
210  g->transform(display->getSRID());
211  }
212 
213  drawGeometry(display, g.get()); // to show feedback!
214 
215  break;
216  }
217  }
218 }
219 
221  QTreeWidgetItem* layerItem, MapDisplay* /*display*/,
222  te::rst::Raster* raster, const te::gm::Envelope& e, int /*srid*/,
223  bool /*needRemap*/)
224 {
225  te::gm::Coord2D center = e.getCenter();
226  te::gm::Coord2D coord = raster->getGrid()->geoToGrid(center.x, center.y);
227 
228  int x = te::rst::Round(coord.x);
229  int y = te::rst::Round(coord.y);
230 
231  if((x < 0 || x >= static_cast<int>(raster->getNumberOfColumns())) ||
232  (y < 0 || y >= static_cast<int>(raster->getNumberOfRows())))
233  return;
234 
235  // Raster location informations
236  QTreeWidgetItem* lineItem = new QTreeWidgetItem(layerItem);
237  lineItem->setText(0, QObject::tr("Line"));
238  lineItem->setText(1, QString::number(y));
239 
240  QTreeWidgetItem* columnItem = new QTreeWidgetItem(layerItem);
241  columnItem->setText(0, QObject::tr("Column"));
242  columnItem->setText(1, QString::number(x));
243 
244  QTreeWidgetItem* coordXItem = new QTreeWidgetItem(layerItem);
245  coordXItem->setText(0, QObject::tr("Coordinate X"));
246  coordXItem->setText(1, QString::number(center.x));
247 
248  QTreeWidgetItem* coordYItem = new QTreeWidgetItem(layerItem);
249  coordYItem->setText(0, QObject::tr("Coordinate Y"));
250  coordYItem->setText(1, QString::number(center.y));
251 
252  // Raster value informations for each band
253  double value = 0.0;
254  for(std::size_t b = 0; b < raster->getNumberOfBands(); ++b)
255  {
256  raster->getValue(x, y, value, b);
257 
258  QTreeWidgetItem* bandValueItem = new QTreeWidgetItem(layerItem);
259  bandValueItem->setIcon(0, QIcon::fromTheme("channel-gray"));
260  bandValueItem->setText(0, QObject::tr("Band") + " " + QString::number(b));
261  bandValueItem->setText(1, QString::number(value));
262  }
263 }
264 
266 {
267  QPixmap* draft = display->getDraftPixmap();
268 
269  const te::gm::Envelope& displayExtent = display->getExtent();
270 
271  Canvas canvas(draft);
272  canvas.setWindow(displayExtent.m_llx, displayExtent.m_lly, displayExtent.m_urx, displayExtent.m_ury);
273  canvas.setRenderHint(QPainter::Antialiasing, true);
274 
275  switch(g->getGeomTypeId())
276  {
277  case te::gm::PolygonType:
285  {
286  canvas.setPolygonContourWidth(2);
287  canvas.setPolygonContourColor(te::color::RGBAColor(255, 0, 0, 128));
288  canvas.setPolygonFillColor(te::color::RGBAColor(255, 255, 255, 128));
289  }
290  break;
291 
300  {
301  canvas.setLineColor(te::color::RGBAColor(255, 0, 0, 128));
302  canvas.setLineWidth(6);
303  }
304  break;
305 
306  case te::gm::PointType:
307  case te::gm::PointZType:
308  case te::gm::PointMType:
309  case te::gm::PointZMType:
314  {
315  std::size_t size = 24;
316 
317  te::se::Stroke* stroke = te::se::CreateStroke("#FF0000", "2","0.5");
318  te::se::Fill* fill = te::se::CreateFill("#FFFFFF", "0.5");
319  te::se::Mark* mark = te::se::CreateMark("square", stroke, fill);
320 
322 
324  canvas.setPointPattern(rgba, static_cast<int>(size), static_cast<int>(size));
325 
326  te::common::Free(rgba, size);
327  delete mark;
328  }
329  break;
330 
331  default:
332  return;
333  }
334 
335  canvas.draw(g);
336 }
virtual std::unique_ptr< te::gm::Geometry > getGeometry(std::size_t i) const =0
Method for retrieving a geometric attribute value.
TEDATAACCESSEXPORT te::rst::RasterProperty * GetFirstRasterProperty(const DataSetType *dt)
Geometric property.
double y
y-coordinate.
Definition: Coord2D.h:114
bool intersects(const Envelope &rhs) const
It returns true if the envelopes "spatially intersects".
A Mark specifies a geometric shape and applies coloring to it.
Definition: Mark.h:84
#define TE_UNKNOWN_SRS
A numeric value to represent a unknown SRS identification in TerraLib.
double x
x-coordinate.
Definition: Coord2D.h:113
unsigned int getNumberOfColumns() const
Returns the raster number of columns.
GeomType getGeomTypeId() const _NOEXCEPT_OP(true)
It returns the geometry subclass type identifier.
TEDATAACCESSEXPORT std::size_t GetPropertyPos(const DataSet *dataset, const std::string &name)
double m_urx
Upper right corner x-coordinate.
void setPolygonFillColor(const te::color::RGBAColor &color)
It sets the color used to fill the draw of polygon geometries.
void setPolygonContourColor(const te::color::RGBAColor &color)
It sets the pen color used to draw the boundary of polygon geometries.
A widget to control the display of a set of layers.
An utility struct for representing 2D coordinates.
Definition: Coord2D.h:40
DefaultFeatureInfoMaker is a default implementation of AbstractFeatureInfoMaker that could be used to...
void draw(const te::gm::Geometry *geom)
It draws the geometry on canvas.
Raster property.
void geoToGrid(const double &x, const double &y, double &col, double &row) const
Get the grid point associated to a spatial location.
virtual bool moveNext()=0
It moves the internal pointer to the next item of the collection.
int b
Definition: TsRtree.cpp:32
Coord2D getCenter() const
It returns the rectangle&#39;s center coordinate.
void Free(std::vector< T * > *v)
This function can be applied to a pointer to a vector of pointers.
Definition: STLUtils.h:131
void setRenderHint(QPainter::RenderHint hint, bool on=true)
Sets the given render hint on the canvas painter if on is true; otherwise clears the render hint...
void setWindow(const double &llx, const double &lly, const double &urx, const double &ury)
It sets the world (or window) coordinates area (supposing a cartesian reference system).
double m_llx
Lower left corner x-coordinate.
static MarkRendererManager & getInstance()
It returns a reference to the singleton instance.
A point with x and y coordinate values.
Definition: Point.h:50
virtual int getPropertyDataType(std::size_t i) const =0
It returns the underlying data type of the property at position pos.
void getInfo(QTreeWidgetItem *layerItem, MapDisplay *display, const te::map::AbstractLayerPtr &layer, const te::gm::Envelope &e)
This function is an implementation to get feature information. The information based on vector or ras...
An Envelope defines a 2D rectangular region.
void setLineWidth(int w)
It sets the line width.
void setPointColor(const te::color::RGBAColor &color)
It sets the point drawing color.
An abstract class for raster data strucutures.
unsigned int getNumberOfRows() const
Returns the raster number of rows.
virtual std::size_t getNumberOfBands() const =0
Returns the number of bands (dimension of cells attribute values) in the raster.
virtual int getSRID() const
It return the Spatial Reference System used by the Map Display.
void setLineColor(const te::color::RGBAColor &color)
It sets the pen color used to draw line geometries.
void getGeometryInfo(QTreeWidgetItem *layerItem, MapDisplay *display, te::da::DataSet *dataset, const std::string &geomPropertyName, const te::gm::Envelope &e, int srid, bool needRemap)
TERASTEREXPORT int Round(double val)
Round a double value to a integer value.
void setPolygonContourWidth(int w)
It sets the polygon contour width.
virtual const te::gm::Envelope & getExtent() const
It returns the world extent showned by the MapDisplay.
virtual std::string getAsString(std::size_t i, int precision=0) const
Method for retrieving a data value as a string plain representation.
A Fill specifies the pattern for filling an area geometry.
Definition: Fill.h:59
Grid * getGrid()
It returns the raster grid.
TESEEXPORT Mark * CreateMark(const std::string &wellKnownName, Stroke *stroke, Fill *fill)
Creates a mark.
Geometry is the root class of the geometries hierarchy, it follows OGC and ISO standards.
virtual void getValue(unsigned int c, unsigned int r, double &value, std::size_t b=0) const
Returns the attribute value of a band of a cell.
double m_lly
Lower left corner y-coordinate.
void getRasterInfo(QTreeWidgetItem *layerItem, MapDisplay *display, te::rst::Raster *raster, const te::gm::Envelope &e, int srid, bool needRemap)
TESEEXPORT Stroke * CreateStroke(const std::string &color, const std::string &width)
Creates a stroke.
A dataset is the unit of information manipulated by the data access module of TerraLib.
virtual QPixmap * getDraftPixmap() const
It returns the map display draft pixmap.
double m_ury
Upper right corner y-coordinate.
A Stroke specifies the appearance of a linear geometry.
Definition: Stroke.h:67
A helper class for 32-bit RGBA (Red-Green-Blue-Alpha channel) color.
Definition: RGBAColor.h:57
TEGEOMEXPORT bool CheckValidity(const Geometry *geom, te::gm::TopologyValidationError &error)
It check geometry validity using GEOS.
void setPointPattern(te::color::RGBAColor **pattern, int ncols, int nrows)
It sets the point pattern.
virtual bool isNull(std::size_t i) const =0
It checks if the attribute value is NULL.
void drawGeometry(MapDisplay *display, te::gm::Geometry *g)
TEDATAACCESSEXPORT std::size_t GetFirstPropertyPos(const te::da::DataSet *dataset, int datatype)
virtual std::size_t getNumProperties() const =0
It returns the number of properties that composes an item of the dataset.
virtual std::string getPropertyName(std::size_t i) const =0
It returns the property name at position pos.
TEDATAACCESSEXPORT te::gm::GeometryProperty * GetFirstGeomProperty(const DataSetType *dt)
#define TE_TRANSPARENT
For an RGBA color this is the value of the alpha-channel for totally transparent. ...
This struct contains informations about GEOS TopologyValidationError.
boost::intrusive_ptr< AbstractLayer > AbstractLayerPtr
void transform(int oldsrid, int newsrid)
It will transform the coordinates of the Envelope from the old SRS to the new one.
virtual std::string getString(std::size_t i) const =0
Method for retrieving a string value attribute.
TEGEOMEXPORT Geometry * GetGeomFromEnvelope(const Envelope *const e, int srid)
It creates a Geometry (a polygon) from the given envelope.
TESEEXPORT Fill * CreateFill(const std::string &color, const std::string &opacity)
Creates a fill.
const std::string & getName() const
It returns the property name.
Definition: Property.h:127