All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DataSetLayerRenderer.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2001-2009 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(TR_MAP("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(TR_MAP("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(TR_MAP("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(TR_MAP("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(TR_MAP("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(TR_MAP("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(TR_MAP("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 = TR_MAP("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(TR_MAP("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 }
GroupingType
The grouping type associated to the layer.
Definition: Enums.h:150
std::vector< te::rst::BandProperty * > & getBandProperties()
Returns a reference to the list of bands definitions.
bool isActive() const
Verify if the task is active.
A layer with reference to a dataset.
Definition: DataSetLayer.h:47
const std::string & getDataSetName() const
This class contains the parameters needed for grouping the values of a Property.
Definition: Grouping.h:59
The FeatureTypeStyle defines the styling that is to be applied to a dataset that can be viewed as a f...
A class that models the name of a dataset used in a From clause.
Definition: DataSetName.h:43
TEDATAACCESSEXPORT te::rst::RasterProperty * GetFirstRasterProperty(const DataSetType *dt)
Definition: Utils.cpp:518
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:365
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:258
Expression * clone() const
It creates a new copy of this expression.
It renders the objects associated to a dataset layer.
virtual const std::string & getTitle() const
It returns the layer title.
TEDATAACCESSEXPORT te::gm::GeometryProperty * GetFirstGeomProperty(const DataSetType *dt)
Definition: Utils.cpp:504
This is the base class for layers.
Definition: AbstractLayer.h:76
A layer with reference to a dataset.
A Select models a query to be used when retrieving data from a DataSource.
Definition: Select.h:65
A canvas is an abstraction of a drawing area.
Definition: Canvas.h:91
A Symbolizer describes how a feature is to appear on a map.
Definition: Symbolizer.h:80
Spatial intersects operator.
Definition: ST_Intersects.h:46
The Field class can be used to model an expression that takes part of the output items of a SELECT...
Definition: Field.h:50
It models the inequality operator greater than or equal to (&gt;=).
This class models a string Literal value.
Definition: LiteralString.h:46
boost::ptr_vector< FromItem > From
It models the FROM clause for a query.
Definition: From.h:37
The CoverageStyle defines the styling that is to be applied to a subset of Coverage data...
Definition: CoverageStyle.h:45
A class that models the name of any property of an object.
Definition: PropertyName.h:50
const std::string & getDataSourceId() const
#define TE_UNKNOWN_SRS
A numeric value to represent a unknown SRS identification in TerraLib.
Definition: Config.h:72
const std::string & getValue() const
It gets the value of the legend item.
virtual te::map::Grouping * getGrouping() const
It returns the Grouping associated to the Layer.
int getPropertyType() const
It gets the property type whose values will be grouped.
Definition: Grouping.cpp:58
boost::ptr_vector< Field > Fields
Fields is just a boost::ptr_vector of Field pointers.
Definition: Fields.h:37
bool isVisible() const
It gets the grouping visibility.
Definition: Grouping.cpp:119
Boolean logic operator: AND.
Definition: And.h:46
void drawGrouping(DataSetLayer *layer, te::da::DataSourcePtr ds, Canvas *canvas, const te::gm::Envelope &bbox, int srid)
TESEEXPORT Style * CreateFeatureTypeStyle(const te::gm::GeomType &geomType)
Try creates an appropriate feature type style based on given geometry type.
Definition: Utils.cpp:282
GeomType getGeometryType() const
It returns the geometry subtype allowed for the property.
An abstract class that models a source of data in a query.
Definition: FromItem.h:50
A Symbology Enconding visitor that configures a given canvas based on symbolizers elements...
Utility functions for the data access module.
An exception class for the MapTools module.
void pulse()
Calls setCurrentStep() function using getCurrentStep() + 1.
It models the inequality operator less than or equal to (&lt;=).
TESEEXPORT Style * CreateCoverageStyle(const std::vector< te::rst::BandProperty * > &properties)
Try creates an appropriate coverage style based on given band properties.
Definition: Utils.cpp:297
std::string getPropertyName() const
It gets the property name whose values will be grouped.
Definition: Grouping.cpp:47
TEDATAACCESSEXPORT std::size_t GetFirstPropertyPos(const te::da::DataSet *dataset, int datatype)
Definition: Utils.cpp:428
A class that models a literal for Envelope values.
boost::shared_ptr< DataSource > DataSourcePtr
Definition: DataSource.h:1395
A Symbology Enconding visitor that configures a given canvas based on symbolizers elements...
virtual te::se::Style * getStyle() const
It returns the Style associated to the layer.
virtual const te::gm::Envelope & getExtent() const
It returns the Layer extent (or minimum bounding box).
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.
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:89
#define TR_MAP(message)
It marks a string in order to get translated. This is a special mark used in the Map Rendering module...
The Style defines the styling that is to be applied to a geographic dataset (vector geometries or cov...
Definition: Style.h:65
This class contains the parameters needed for grouping the values of a Property.
bool intersects(const Envelope &rhs) const
It returns true if the envelopes &quot;spatially intersects&quot;.
Definition: Envelope.h:493
virtual void draw(const te::gm::Geometry *geom)=0
It draws the geometry on canvas.
const std::vector< te::se::Symbolizer * > & getSymbolizers() const
It gets the symbolizer of the legend item.
Raster property.
This is an abstract class that models a query expression.
Definition: Expression.h:47
This class can be used to inform the progress of a task.
Definition: TaskProgress.h:53
It models the comparison operator.
Definition: EqualTo.h:46
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. ...
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:532
An Envelope defines a 2D rectangular region.
Definition: Envelope.h:51
A class that can be used to model a filter expression that can be applied to a query.
Definition: Where.h:47
virtual int getSRID() const
It returns the Spatial Reference System ID associated to the Layer.
A class that models a literal for double values.
Definition: LiteralDouble.h:43
Geometric property.
const std::string & getUpperLimit() const
It gets the upper limit value of the legend item.
const std::vector< te::map::GroupingItem * > & getGroupingItems() const
It gets the vector of grouping items.
Definition: Grouping.cpp:109
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:69
A GroupingItem contains information about a grouping item associated to a layer.
Definition: GroupingItem.h:48