All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
DataSetLayerRenderer.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/maptools/DataSetLayerRenderer.cpp
22 
23  \brief It renders the objects associated to a dataset layer.
24 */
25 
26 // TerraLib
27 #include "../common/progress/TaskProgress.h"
28 #include "../common/Translator.h"
29 #include "../dataaccess/dataset/DataSet.h"
30 #include "../dataaccess/dataset/DataSetType.h"
31 #include "../dataaccess/datasource/DataSource.h"
32 #include "../dataaccess/query/And.h"
33 #include "../dataaccess/query/DataSetName.h"
34 #include "../dataaccess/query/EqualTo.h"
35 #include "../dataaccess/query/Field.h"
36 #include "../dataaccess/query/GreaterThanOrEqualTo.h"
37 #include "../dataaccess/query/LessThanOrEqualTo.h"
38 #include "../dataaccess/query/LiteralDouble.h"
39 #include "../dataaccess/query/LiteralEnvelope.h"
40 #include "../dataaccess/query/LiteralString.h"
41 #include "../dataaccess/query/PropertyName.h"
42 #include "../dataaccess/query/Select.h"
43 #include "../dataaccess/query/ST_Intersects.h"
44 #include "../dataaccess/query/Where.h"
45 #include "../dataaccess/utils/Utils.h"
46 #include "../geometry/Envelope.h"
47 #include "../geometry/Geometry.h"
48 #include "../geometry/GeometryProperty.h"
49 #include "../raster/RasterProperty.h"
50 #include "../se/CoverageStyle.h"
51 #include "../se/FeatureTypeStyle.h"
52 #include "../se/Utils.h"
53 #include "../srs/Config.h"
54 #include "Canvas.h"
55 #include "CanvasConfigurer.h"
56 #include "DataSetLayer.h"
57 #include "DataSetLayerRenderer.h"
58 #include "Exception.h"
59 #include "Grouping.h"
60 #include "GroupingItem.h"
61 #include "Utils.h"
62 
63 // Boost
64 #include <boost/format.hpp>
65 #include <boost/lexical_cast.hpp>
66 
67 // STL
68 #include <cassert>
69 #include <memory>
70 
72 {
73 }
74 
76 {
77 }
78 
80  Canvas* canvas,
81  const te::gm::Envelope& bbox,
82  int srid)
83 {
84 // should I render this layer?
85  DataSetLayer* dlayer = dynamic_cast<DataSetLayer*>(layer);
86 
87  if(dlayer == 0)
88  throw Exception(TE_TR("Wrong type render type for this layer!"));
89 
90 // check if layer extent intersects the drawing area and so compute bounding box intersection
91  te::gm::Envelope reprojectedBBOX(bbox);
92 
93  if((dlayer->getSRID() != TE_UNKNOWN_SRS) && (srid != TE_UNKNOWN_SRS))
94  {
95  reprojectedBBOX.transform(srid, dlayer->getSRID());
96  }
97  else if(dlayer->getSRID() != srid)
98  {
99  throw Exception(TE_TR("The layer or map don't have a valid SRID!"));
100  }
101 
102  if(!reprojectedBBOX.intersects(dlayer->getExtent()))
103  return;
104 
105  te::gm::Envelope ibbox = reprojectedBBOX.intersection(dlayer->getExtent());
106 
107 // retrieve the associated data source
109 
110 // get dataset information
111  std::string dsname = dlayer->getDataSetName();
112  assert(!dsname.empty());
113 
114  std::auto_ptr<te::da::DataSetType> dstype(ds->getDataSetType(dsname));
115 
116  if(dstype->hasGeom())
117  {
118  /* For while if the DataSetLayer has a grouping, do not consider the style.
119  TODO: - Create the GroupingRenderer?
120  - Create the StyledLayer and try build a generic renderer that look for Styles and Grouping? */
121  Grouping* grouping = dlayer->getGrouping();
122  if(grouping && grouping->isVisible())
123  {
124  drawGrouping(dlayer, ds, canvas, ibbox, srid);
125  return;
126  }
127 
128 // for while, default geometry. TODO: need a visitor to get which properties the style references
129  te::gm::GeometryProperty* geometryProperty = te::da::GetFirstGeomProperty(dstype.get());
130 
131 // get the associated layer style
132  te::se::Style* style = dlayer->getStyle();
133  if(style == 0)
134  {
135 // try create an appropriate style
136  style = te::se::CreateFeatureTypeStyle(geometryProperty->getGeometryType());
137 
138  if(style == 0)
139  throw Exception((boost::format(TE_TR("Could not create a default feature type style to the layer %1%.")) % layer->getTitle()).str());
140 
141  dlayer->setStyle(style);
142  }
143 
144 // should I render this style?
145  te::se::FeatureTypeStyle* fts = dynamic_cast<te::se::FeatureTypeStyle*>(style);
146  if(fts == 0)
147  throw Exception(TE_TR("The layer style is not a Feature Type Style!"));
148 
149  DrawGeometries(dstype.get(), ds, canvas, ibbox, dlayer->getSRID(), srid, fts);
150  }
151  else if(dstype->hasRaster())
152  {
153 // for while, first raster property
154  te::rst::RasterProperty* rasterProperty = te::da::GetFirstRasterProperty(dstype.get());
155 
156 // get the associated layer style
157  te::se::Style* style = dlayer->getStyle();
158  if(style == 0)
159  {
160 // try create an appropriate style
161  style = te::se::CreateCoverageStyle(rasterProperty->getBandProperties());
162 
163  if(style == 0)
164  throw Exception((boost::format(TE_TR("Could not create a default coverage style to the layer %1%.")) % layer->getTitle()).str());
165 
166  dlayer->setStyle(style);
167  }
168 
169 // should I render this style?
170  te::se::CoverageStyle* cs = dynamic_cast<te::se::CoverageStyle*>(style);
171  if(cs == 0)
172  throw Exception(TE_TR("The layer style is not a Coverage Style!"));
173 
174  DrawRaster(dstype.get(), ds, canvas, ibbox, dlayer->getSRID(), bbox, srid, cs);
175  }
176  else
177  {
178  throw Exception(TE_TR("The layer don't have a geometry or raster property!"));
179  }
180 }
181 
183 {
184  std::string dsname = layer->getDataSetName();
185 
186 // verify if is necessary convert the data set geometries to the given srid
187  bool needRemap = false;
188  if((layer->getSRID() != TE_UNKNOWN_SRS) && (srid != TE_UNKNOWN_SRS) && (layer->getSRID() != srid))
189  needRemap = true;
190 
191 // get the dataset type. TODO: Can we pass the datat set type as method parameter?
192  std::auto_ptr<te::da::DataSetType> dataSetType(ds->getDataSetType(dsname));
193  assert(dataSetType.get());
194 
195 // for while, default geometry. TODO: need a visitor to get which properties the style references
196  assert(dataSetType->hasGeom());
197  te::gm::GeometryProperty* geometryProperty = te::da::GetFirstGeomProperty(dataSetType.get());
198 
199 // create a canvas configurer
200  te::map::CanvasConfigurer cc(canvas);
201 
202 // the layer grouping
203  Grouping* grouping = layer->getGrouping();
204 
205 // the referenced property name
206  std::string propertyName = grouping->getPropertyName();
207  assert(!propertyName.empty());
208 
209 // the referenced property type
210  int propertyType = grouping->getPropertyType();
211 
212 // the grouping type
213  GroupingType type = grouping->getType();
214 
215 // the grouping items
216  const std::vector<GroupingItem*>& items = grouping->getGroupingItems();
217 
218  std::size_t nGroupItems = items.size();
219 
220 // build task message; e.g. ("Drawing the layer Countries. Rule 1 of 3.")
221  std::string message = TE_TR("Drawing the grouping of layer");
222  message += " " + layer->getTitle() + ".";
223 
224 // create the draw task
225  te::common::TaskProgress task(message, te::common::TaskProgress::DRAW, nGroupItems);
226 
227  for(std::size_t i = 0; i < nGroupItems; ++i) // for each GroupingItem
228  {
229 // the current group item
230  GroupingItem* item = items[i];
231  assert(item);
232 
233 /* 1) Creating te::da::Where object with the group item restriction expression + box restriction */
234 
235  te::da::PropertyName* groupingPropertyName = new te::da::PropertyName(propertyName);
236 
237 // grouping item restriction
238  te::da::Expression* exp = 0;
239  if(type == UNIQUE_VALUE)
240  {
242  exp = new te::da::EqualTo(groupingPropertyName, value);
243  }
244  else
245  {
246  te::da::Expression* lowerValue = 0;
247  te::da::Expression* upperrValue = 0;
248 
249  switch(propertyType)
250  {
251  case te::dt::STRING_TYPE:
252  lowerValue = new te::da::LiteralString(item->getLowerLimit());
253  upperrValue = new te::da::LiteralString(item->getUpperLimit());
254  break;
255 
256  default:
257  lowerValue = new te::da::LiteralDouble(boost::lexical_cast<double>(item->getLowerLimit()));
258  upperrValue = new te::da::LiteralDouble(boost::lexical_cast<double>(item->getUpperLimit()));
259  }
260 
261  te::da::GreaterThanOrEqualTo* gte = new te::da::GreaterThanOrEqualTo(groupingPropertyName, lowerValue);
262  te::da::LessThanOrEqualTo* lte = new te::da::LessThanOrEqualTo(groupingPropertyName->clone(), upperrValue);
263 
264  exp = new te::da::And(gte, lte);
265  }
266 
267 // the box restriction
268  te::da::LiteralEnvelope* lenv = new te::da::LiteralEnvelope(bbox, srid);
269  te::da::PropertyName* geometryPropertyName = new te::da::PropertyName(geometryProperty->getName());
270  te::da::ST_Intersects* intersects = new te::da::ST_Intersects(geometryPropertyName, lenv);
271 
272 // combining the expressions (Filter expression + box restriction)
273  te::da::And* finalRestriction = new te::da::And(exp, intersects);
274 
275 // the final where
276  te::da::Where* wh = new te::da::Where(finalRestriction);
277 
278 // fields
279  te::da::Fields* all = new te::da::Fields;
280  all->push_back(new te::da::Field("*"));
281 
282 // from
283  te::da::FromItem* fi = new te::da::DataSetName(dsname);
284  te::da::From* from = new te::da::From;
285  from->push_back(fi);
286 
287 // build the Select
288  te::da::Select select(all, from, wh);
289 
290 /* 2) Calling the datasource query method to get the correct restricted dataset. */
291 
292  std::auto_ptr<te::da::DataSet> dataset(0);
293  try
294  {
295  dataset = ds->query(select);
296  }
297  catch(std::exception& /*e*/)
298  {
299  continue; // TODO: deal the exceptions!
300  }
301 
302  if(dataset.get() == 0)
303  throw Exception((boost::format(TE_TR("Could not retrieve the data set %1% referenced by the layer %2%.")) % dsname % layer->getTitle()).str());
304 
305  if(dataset->moveNext() == false)
306  continue;
307 
308 // get the set of symbolizers defined on group item
309  const std::vector<te::se::Symbolizer*>& symbolizers = item->getSymbolizers();
310 
311  std::size_t nSymbolizers = symbolizers.size();
312 
313  for(std::size_t j = 0; j < nSymbolizers; ++j) // for each <Symbolizer>
314  {
315 // the current symbolizer
316  te::se::Symbolizer* symb = symbolizers[j];
317 
318 // let's config de canvas based on the current symbolizer
319  cc.config(symb);
320 
321 // for while, first geometry. TODO: get which property the symbolizer references
322  std::size_t gpos = te::da::GetFirstPropertyPos(dataset.get(), te::dt::GEOMETRY_TYPE);
323 
324 // let's draw! for each data set object...
325  do
326  {
327  if(!task.isActive())
328  return;
329 
330 // update the draw task
331  task.pulse();
332 
333  std::auto_ptr<te::gm::Geometry> geom = dataset->getGeometry(gpos);
334  if(geom.get() == 0)
335  continue;
336 
337 // if necessary, geometry remap
338  if(needRemap)
339  {
340  geom->setSRID(layer->getSRID());
341  geom->transform(srid);
342  }
343 
344  canvas->draw(geom.get());
345 
346  }while(dataset->moveNext()); // next geometry!
347 
348 // prepare to draw the other symbolizer
349  dataset->moveFirst();
350 
351  } // end for each <Symbolizer>
352 
353  if(!task.isActive())
354  return;
355 
356  task.pulse();
357 
358  } // end for each GroupItem
359 }
TEDATAACCESSEXPORT DataSourcePtr GetDataSource(const std::string &datasourceId, const bool opened=true)
Search for a data source with the informed id in the DataSourceManager.
Definition: Utils.cpp:262
TEDATAACCESSEXPORT te::rst::RasterProperty * GetFirstRasterProperty(const DataSetType *dt)
Definition: Utils.cpp:571
Geometric property.
Utility functions for the data access module.
const std::string & getDataSetName() const
An abstract class that models a source of data in a query.
Definition: FromItem.h:50
The Field class can be used to model an expression that takes part of the output items of a SELECT...
Definition: Field.h:50
bool intersects(const Envelope &rhs) const
It returns true if the envelopes "spatially intersects".
Definition: Envelope.h:493
It models the inequality operator less than or equal to (<=).
The Style defines the styling that is to be applied to a geographic dataset (vector geometries or cov...
Definition: Style.h:65
Spatial intersects operator.
Definition: ST_Intersects.h:46
This is the base class for layers.
Definition: AbstractLayer.h:76
virtual const te::gm::Envelope & getExtent() const
It returns the Layer extent (or minimum bounding box).
A class that models the name of a dataset used in a From clause.
Definition: DataSetName.h:43
int getPropertyType() const
It gets the property type whose values will be grouped.
Definition: Grouping.cpp:79
boost::shared_ptr< DataSource > DataSourcePtr
Definition: DataSource.h:1435
const std::string & getValue() const
It gets the value of the legend item.
virtual const std::string & getTitle() const
It returns the layer title.
A class that models the name of any property of an object.
Definition: PropertyName.h:50
A Symbolizer describes how a feature is to appear on a map.
Definition: Symbolizer.h:80
The CoverageStyle defines the styling that is to be applied to a subset of Coverage data...
Definition: CoverageStyle.h:45
std::string getPropertyName() const
It gets the property name whose values will be grouped.
Definition: Grouping.cpp:68
TESEEXPORT Style * CreateCoverageStyle(const std::vector< te::rst::BandProperty * > &properties)
Try creates an appropriate coverage style based on given band properties.
Definition: Utils.cpp:299
This class can be used to inform the progress of a task.
Definition: TaskProgress.h:53
It models the inequality operator greater than or equal to (>=).
A layer with reference to a dataset.
#define TE_TR(message)
It marks a string in order to get translated.
Definition: Translator.h:347
TEMAPEXPORT void DrawGeometries(te::da::DataSetType *type, te::da::DataSourcePtr ds, Canvas *canvas, const te::gm::Envelope &bbox, int bboxSRID, int srid, te::se::FeatureTypeStyle *style)
It draws the data set geometries in the given canvas using the informed SRID and style.
Definition: Utils.cpp:293
bool isActive() const
Verify if the task is active.
Raster property.
Boolean logic operator: AND.
Definition: And.h:46
This is an abstract class that models a query expression.
Definition: Expression.h:47
Expression * clone() const
It creates a new copy of this expression.
An exception class for the MapTools module.
TESEEXPORT Style * CreateFeatureTypeStyle(const te::gm::GeomType &geomType)
Try creates an appropriate feature type style based on given geometry type.
Definition: Utils.cpp:284
This class contains the parameters needed for grouping the values of a Property.
Definition: Grouping.h:59
An Envelope defines a 2D rectangular region.
Definition: Envelope.h:51
A GroupingItem contains information about a grouping item associated to a layer.
Definition: GroupingItem.h:48
const std::string & getDataSourceId() const
The FeatureTypeStyle defines the styling that is to be applied to a dataset that can be viewed as a f...
#define TE_UNKNOWN_SRS
A numeric value to represent a unknown SRS identification in TerraLib.
Definition: Config.h:44
void draw(AbstractLayer *layer, Canvas *canvas, const te::gm::Envelope &bbox, int srid)
It draws the layer geographic objects in the given canvas using the SRS informed. ...
virtual te::se::Style * getStyle() const
It returns the Style associated to the layer.
GeomType getGeometryType() const
It returns the geometry subtype allowed for the property.
boost::ptr_vector< Field > Fields
Fields is just a boost::ptr_vector of Field pointers.
Definition: Fields.h:37
A class that can be used to model a filter expression that can be applied to a query.
Definition: Where.h:47
void pulse()
Calls setCurrentStep() function using getCurrentStep() + 1.
A class that models a literal for double values.
Definition: LiteralDouble.h:43
A Select models a query to be used when retrieving data from a DataSource.
Definition: Select.h:65
boost::ptr_vector< FromItem > From
It models the FROM clause for a query.
Definition: From.h:37
A canvas is an abstraction of a drawing area.
Definition: Canvas.h:91
bool isVisible() const
It gets the grouping visibility.
Definition: Grouping.cpp:142
const std::vector< te::map::GroupingItem * > & getGroupingItems() const
It gets the vector of grouping items.
Definition: Grouping.cpp:130
GroupingType
The grouping type associated to the layer.
Definition: Enums.h:150
const std::string & getUpperLimit() const
It gets the upper limit value of the legend item.
virtual te::map::Grouping * getGrouping() const
It returns the Grouping associated to the Layer.
It models the comparison operator.
Definition: EqualTo.h:46
It renders the objects associated to a dataset layer.
virtual void setStyle(te::se::Style *style)
It sets the Style associated to the layer.
const GroupingType getType() const
It gets the grouping type.
Definition: Grouping.cpp:90
A class that models a literal for Envelope values.
void drawGrouping(DataSetLayer *layer, te::da::DataSourcePtr ds, Canvas *canvas, const te::gm::Envelope &bbox, int srid)
virtual int getSRID() const
It returns the Spatial Reference System ID associated to the Layer.
A layer with reference to a dataset.
Definition: DataSetLayer.h:47
This class contains the parameters needed for grouping the values of a Property.
std::vector< te::rst::BandProperty * > & getBandProperties()
Returns a reference to the list of bands definitions.
TEDATAACCESSEXPORT std::size_t GetFirstPropertyPos(const te::da::DataSet *dataset, int datatype)
Definition: Utils.cpp:481
Envelope intersection(const Envelope &rhs) const
It returns an envelope that represents the point set intersection with another envelope.
Definition: Envelope.h:543
const std::string & getLowerLimit() const
It gets the lower limit value of the legend item.
TEDATAACCESSEXPORT te::gm::GeometryProperty * GetFirstGeomProperty(const DataSetType *dt)
Definition: Utils.cpp:557
const std::vector< te::se::Symbolizer * > & getSymbolizers() const
It gets the symbolizer of the legend item.
void transform(int oldsrid, int newsrid)
It will transform the coordinates of the Envelope from the old SRS to the new one.
Definition: Envelope.cpp:92
virtual void draw(const te::gm::Geometry *geom)=0
It draws the geometry on canvas.
TEMAPEXPORT void DrawRaster(te::da::DataSetType *type, te::da::DataSourcePtr ds, Canvas *canvas, const te::gm::Envelope &bbox, int bboxSRID, const te::gm::Envelope &visibleArea, int srid, te::se::CoverageStyle *style)
Definition: Utils.cpp:460
A Symbology Enconding visitor that configures a given canvas based on symbolizers elements...
This class models a string Literal value.
Definition: LiteralString.h:46
A Symbology Enconding visitor that configures a given canvas based on symbolizers elements...