All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
AbstractLayerRenderer.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/AbstractLayerRenderer.cpp
22 
23  \brief It renders the objects associated to an abstract layer. i.e. a generic renderer.
24 */
25 
26 // TerraLib
27 #include "../color/RGBAColor.h"
28 #include "../common/progress/TaskProgress.h"
29 #include "../common/Globals.h"
30 #include "../common/STLUtils.h"
31 #include "../common/Translator.h"
32 #include "../dataaccess/dataset/DataSet.h"
33 #include "../dataaccess/dataset/DataSetType.h"
34 #include "../dataaccess/query/And.h"
35 #include "../dataaccess/query/EqualTo.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/ST_Intersects.h"
43 #include "../dataaccess/utils/Utils.h"
44 #include "../fe/Filter.h"
45 #include "../geometry/Coord2D.h"
46 #include "../geometry/Envelope.h"
47 #include "../geometry/GeometryProperty.h"
48 #include "../geometry/MultiPolygon.h"
49 #include "../geometry/Polygon.h"
50 #include "../raster/Raster.h"
51 #include "../raster/RasterProperty.h"
52 #include "../se/FeatureTypeStyle.h"
53 #include "../se/CoverageStyle.h"
54 #include "../se/Rule.h"
55 #include "../se/Utils.h"
56 #include "../srs/Config.h"
57 #include "AbstractLayer.h"
58 #include "AbstractLayerRenderer.h"
59 #include "Canvas.h"
60 #include "CanvasConfigurer.h"
61 #include "Chart.h"
62 #include "ChartRendererManager.h"
63 #include "Exception.h"
64 #include "Grouping.h"
65 #include "GroupingItem.h"
66 #include "QueryEncoder.h"
67 #include "Utils.h"
68 
69 // Boost
70 #include <boost/format.hpp>
71 #include <boost/lexical_cast.hpp>
72 
73 // STL
74 #include <cassert>
75 #include <cstdlib>
76 #include <memory>
77 #include <utility>
78 
79 
80 
82  : m_index(0)
83 {
84 }
85 
87 {
88 }
89 
91  Canvas* canvas,
92  const te::gm::Envelope& bbox,
93  int srid)
94 {
95  if(!bbox.isValid())
96  throw Exception(TE_TR("The requested box is invalid!"));
97 
98  assert(layer);
99  assert(canvas);
100 
101  // Check if layer extent intersects the drawing area and so compute bounding box intersection
102  te::gm::Envelope reprojectedBBOX(bbox);
103 
104  if((layer->getSRID() != TE_UNKNOWN_SRS) && (srid != TE_UNKNOWN_SRS))
105  {
106  reprojectedBBOX.transform(srid, layer->getSRID());
107 
108  if(!reprojectedBBOX.isValid())
109  throw Exception(TE_TR("The reprojected box is invalid!"));
110  }
111  else if(layer->getSRID() != srid)
112  {
113  throw Exception(TE_TR("The layer or map don't have a valid SRID!"));
114  }
115 
116  if(!reprojectedBBOX.intersects(layer->getExtent()))
117  return;
118 
119  // Adjust internal renderer transformer
120  m_transformer.setTransformationParameters(bbox.m_llx, bbox.m_lly, bbox.m_urx, bbox.m_ury, canvas->getWidth(), canvas->getHeight());
121 
122  // Resets internal renderer state
123  reset();
124 
125  te::gm::Envelope ibbox = reprojectedBBOX.intersection(layer->getExtent());
126 
127  assert(ibbox.isValid());
128 
129  // Gets the layer schema
130  std::auto_ptr<LayerSchema> schema(layer->getSchema());
131  assert(schema.get());
132 
133  // Gets the name of the referenced spatial property
134  std::string spatialPropertyName = layer->getGeomPropertyName();
135 
136  if(schema->hasGeom())
137  {
138  te::gm::GeometryProperty* geometryProperty = 0;
139 
140  if(spatialPropertyName.empty())
141  geometryProperty = te::da::GetFirstGeomProperty(schema.get());
142  else
143  geometryProperty = dynamic_cast<te::gm::GeometryProperty*>(schema->getProperty(spatialPropertyName));
144 
145  assert(geometryProperty);
146 
147  // If the AbstractLayer has a grouping, do not consider the style.
148  Grouping* grouping = layer->getGrouping();
149  if(grouping && grouping->isVisible())
150  {
151  drawLayerGroupingMem(layer, geometryProperty->getName(), canvas, ibbox, srid);
152  return;
153  }
154 
155  // Gets the layer style
156  te::se::Style* style = layer->getStyle();
157  if(style == 0)
158  {
159  // Try create an appropriate style. i.e. a FeatureTypeStyle
160  style = te::se::CreateFeatureTypeStyle(geometryProperty->getGeometryType());
161 
162  if(style == 0)
163  throw Exception((boost::format(TE_TR("Could not create a default feature type style to the layer %1%.")) % layer->getTitle()).str());
164 
165  layer->setStyle(style);
166  }
167 
168  // Should I render this style?
169  te::se::FeatureTypeStyle* fts = dynamic_cast<te::se::FeatureTypeStyle*>(style);
170  if(fts == 0)
171  throw Exception(TE_TR("The layer style is not a Feature Type Style!"));
172 
173  drawLayerGeometries(layer, geometryProperty->getName(), fts, canvas, ibbox, srid);
174  }
175  else if(schema->hasRaster())
176  {
177  te::rst::RasterProperty* rasterProperty = 0;
178 
179  if(spatialPropertyName.empty())
180  rasterProperty = te::da::GetFirstRasterProperty(schema.get());
181  else
182  rasterProperty = dynamic_cast<te::rst::RasterProperty*>(schema->getProperty(spatialPropertyName));
183 
184  assert(rasterProperty);
185 
186  // Get the layer style
187  te::se::Style* style = layer->getStyle();
188  if(style == 0)
189  {
190  // Try create an appropriate style. i.e. a CoverageStyle
191  style = te::se::CreateCoverageStyle(rasterProperty->getBandProperties());
192 
193  if(style == 0)
194  throw Exception((boost::format(TE_TR("Could not create a default coverage style to the layer %1%.")) % layer->getTitle()).str());
195 
196  layer->setStyle(style);
197  }
198 
199  // Should I render this style?
200  te::se::CoverageStyle* cs = dynamic_cast<te::se::CoverageStyle*>(style);
201  if(cs == 0)
202  throw Exception(TE_TR("The layer style is not a Coverage Style!"));
203 
204  // Retrieves the data
205  std::auto_ptr<te::da::DataSet> dataset = layer->getData(rasterProperty->getName(), &ibbox, te::gm::INTERSECTS);
206 
207  if(dataset.get() == 0)
208  throw Exception((boost::format(TE_TR("Could not retrieve the data set from the layer %1%.")) % layer->getTitle()).str());
209 
210  // Retrieves the raster
211  std::auto_ptr<te::rst::Raster> raster(dataset->getRaster(rasterProperty->getName()));
212  if(dataset.get() == 0)
213  throw Exception((boost::format(TE_TR("Could not retrieve the raster from the layer %1%.")) % layer->getTitle()).str());
214 
215  // Let's draw!
216  DrawRaster(raster.get(), canvas, ibbox, layer->getSRID(), bbox, srid, cs);
217  }
218  else
219  {
220  throw Exception(TE_TR("The layer don't have a geometry or raster property!"));
221  }
222 }
223 
225  const std::string& geomPropertyName,
227  Canvas* canvas,
228  const te::gm::Envelope& bbox,
229  int srid)
230 {
231  assert(!geomPropertyName.empty());
232 
233  // Creates a canvas configurer
234  CanvasConfigurer cc(canvas);
235 
236  // Number of rules defined on feature type style
237  std::size_t nRules = style->getRules().size();
238 
239  for(std::size_t i = 0; i < nRules; ++i) // for each <Rule>
240  {
241  // The current rule
242  te::se::Rule* rule = style->getRule(i);
243  assert(rule);
244 
245  // TODO: Should be verified the MinScaleDenominator and MaxScaleDenominator. Where will we put the current scale information? Method parameter?
246 
247  // Gets the rule filter
248  const te::fe::Filter* filter = rule->getFilter();
249 
250  // Let's retrieve the correct dataset
251  std::auto_ptr<te::da::DataSet> dataset(0);
252 
253  if(!filter)
254  {
255  try
256  {
257  // There isn't a Filter expression. Gets the data using only extent spatial restriction...
258  dataset = layer->getData(geomPropertyName, &bbox, te::gm::INTERSECTS);
259  }
260  catch(Exception& e)
261  {
262  throw e;
263  }
264  }
265  else
266  {
267  try
268  {
269  // Gets an enconder
270  te::map::QueryEncoder filter2Query;
271 
272  // Converts the Filter expression to a TerraLib Expression!
273  te::da::Expression* exp = filter2Query.getExpression(filter);
274  if(exp == 0)
275  throw Exception(TE_TR("Could not convert the OGC Filter expression to TerraLib expression!"));
276 
277  /* 1) Creating the final restriction. i.e. Filter expression + extent spatial restriction */
278 
279  // The extent spatial restriction
280  te::da::LiteralEnvelope* lenv = new te::da::LiteralEnvelope(bbox, layer->getSRID());
281  te::da::PropertyName* geometryPropertyName = new te::da::PropertyName(geomPropertyName);
282  te::da::ST_Intersects* intersects = new te::da::ST_Intersects(geometryPropertyName, lenv);
283 
284  // Combining the expressions (Filter expression + extent spatial restriction)
285  te::da::And* restriction = new te::da::And(exp, intersects);
286 
287  /* 2) Calling the layer query method to get the correct restricted data. */
288  dataset = layer->getData(restriction);
289  }
290  catch(std::exception& /*e*/)
291  {
292  throw Exception((boost::format(TE_TR("Could not retrieve the data set from the layer %1%.")) % layer->getTitle()).str());
293  }
294  }
295 
296  if(dataset.get() == 0)
297  throw Exception((boost::format(TE_TR("Could not retrieve the data set from the layer %1%.")) % layer->getTitle()).str());
298 
299  if(dataset->moveNext() == false)
300  continue;
301 
302  // Gets the set of symbolizers defined on current rule
303  const std::vector<te::se::Symbolizer*>& symbolizers = rule->getSymbolizers();
304 
305  // Builds task message; e.g. ("Drawing the layer Countries. Rule 1 of 3.")
306  std::string message = TE_TR("Drawing the layer");
307  message += " " + layer->getTitle() + ". ";
308  message += TE_TR("Rule");
309  message += " " + boost::lexical_cast<std::string>(i + 1) + " " + TE_TR("of") + " ";
310  message += boost::lexical_cast<std::string>(nRules) + ".";
311 
312  // Creates a draw task
314  //task.setTotalSteps(symbolizers.size() * dataset->size()); // Removed! The te::da::DataSet size() method would be too costly to compute.
315 
316  // For while, first geometry property. TODO: get which geometry property the symbolizer references
317  std::size_t gpos = te::da::GetPropertyPos(dataset.get(), geomPropertyName);
318 
319  if(symbolizers.empty())
320  {
321  // The current rule do not have a symbolizer. Try creates a default based on first geometry of dataset.
322  std::auto_ptr<te::gm::Geometry> g(dataset->getGeometry(gpos));
323  assert(g.get());
324 
325  te::se::Symbolizer* symbolizer = te::se::CreateSymbolizer(g->getGeomTypeId());
326  assert(symbolizer);
327 
328  rule->push_back(symbolizer);
329 
330  dataset->moveFirst();
331  }
332 
333  std::size_t nSymbolizers = symbolizers.size();
334 
335  for(std::size_t j = 0; j < nSymbolizers; ++j) // for each <Symbolizer>
336  {
337  // The current symbolizer
338  te::se::Symbolizer* symb = symbolizers[j];
339 
340  // Let's config the canvas based on the current symbolizer
341  cc.config(symb);
342 
343  // Let's draw! for each data set geometry...
344  if(j != nSymbolizers - 1)
345  drawDatSetGeometries(dataset.get(), gpos, canvas, layer->getSRID(), srid, 0, &task);
346  else
347  drawDatSetGeometries(dataset.get(), gpos, canvas, layer->getSRID(), srid, layer->getChart(), &task); // Here, produces the chart if exists
348 
349  // Prepares to draw the other symbolizer
350  dataset->moveFirst();
351 
352  } // end for each <Symbolizer>
353 
354  } // end for each <Rule>
355 }
356 
358  const std::string& geomPropertyName,
359  Canvas* canvas,
360  const te::gm::Envelope& bbox,
361  int srid)
362 {
363  assert(!geomPropertyName.empty());
364 
365  // Creates a canvas configurer
366  te::map::CanvasConfigurer cc(canvas);
367 
368  // The layer grouping
369  Grouping* grouping = layer->getGrouping();
370 
371  // The referenced property name
372  std::string propertyName = grouping->getPropertyName();
373  assert(!propertyName.empty());
374 
375  // The referenced property type
376  int propertyType = grouping->getPropertyType();
377 
378  // The grouping type
379  GroupingType type = grouping->getType();
380 
381  // The grouping items
382  const std::vector<GroupingItem*>& items = grouping->getGroupingItems();
383 
384  std::size_t nGroupItems = items.size();
385 
386  // Builds the task message; e.g. ("Drawing the grouping of layer Countries.")
387  std::string message = TE_TR("Drawing the grouping of layer");
388  message += " " + layer->getTitle() + ".";
389 
390  // Creates the draw task
391  te::common::TaskProgress task(message, te::common::TaskProgress::DRAW, nGroupItems);
392 
393  for(std::size_t i = 0; i < nGroupItems; ++i) // for each GroupingItem
394  {
395  // The current group item
396  GroupingItem* item = items[i];
397  assert(item);
398 
399  /* 1) Creating te::da::Where object with the group item restriction expression + extent spatial restriction */
400 
401  te::da::PropertyName* groupingPropertyName = new te::da::PropertyName(propertyName);
402 
403  // Grouping item restriction
404  te::da::Expression* exp = 0;
405 
406  if(type == UNIQUE_VALUE)
407  {
409  exp = new te::da::EqualTo(groupingPropertyName, value);
410  }
411  else
412  {
413  te::da::Expression* lowerValue = 0;
414  te::da::Expression* upperrValue = 0;
415 
416  switch(propertyType)
417  {
418  case te::dt::STRING_TYPE:
419  lowerValue = new te::da::LiteralString(item->getLowerLimit());
420  upperrValue = new te::da::LiteralString(item->getUpperLimit());
421  break;
422 
423  default:
424  lowerValue = new te::da::LiteralDouble(boost::lexical_cast<double>(item->getLowerLimit()));
425  upperrValue = new te::da::LiteralDouble(boost::lexical_cast<double>(item->getUpperLimit()));
426  }
427 
428  te::da::GreaterThanOrEqualTo* gte = new te::da::GreaterThanOrEqualTo(groupingPropertyName, lowerValue);
429  te::da::LessThanOrEqualTo* lte = new te::da::LessThanOrEqualTo(groupingPropertyName->clone(), upperrValue);
430 
431  exp = new te::da::And(gte, lte);
432  }
433 
434  // The extent spatial restriction
435  te::da::LiteralEnvelope* lenv = new te::da::LiteralEnvelope(bbox, layer->getSRID());
436  te::da::PropertyName* geometryPropertyName = new te::da::PropertyName(geomPropertyName);
437  te::da::ST_Intersects* intersects = new te::da::ST_Intersects(geometryPropertyName, lenv);
438 
439  // Combining the expressions (group item restriction expression + extent spatial restriction)
440  te::da::And* restriction = new te::da::And(exp, intersects);
441 
442  /* 2) Calling the layer query method to get the correct restricted data. */
443 
444  std::auto_ptr<te::da::DataSet> dataset(0);
445  try
446  {
447  dataset = layer->getData(restriction);
448  }
449  catch(std::exception& /*e*/)
450  {
451  continue; // TODO: deal the exceptions!
452  }
453 
454  if(dataset.get() == 0)
455  throw Exception((boost::format(TE_TR("Could not retrieve the data set from the layer %1%.")) % layer->getTitle()).str());
456 
457  if(dataset->moveNext() == false)
458  continue;
459 
460  // Gets the set of symbolizers defined on group item
461  const std::vector<te::se::Symbolizer*>& symbolizers = item->getSymbolizers();
462  std::size_t nSymbolizers = symbolizers.size();
463 
464  // For while, first geometry property. TODO: get which geometry property the symbolizer references
465  std::size_t gpos = te::da::GetPropertyPos(dataset.get(), geomPropertyName);
466 
467  for(std::size_t j = 0; j < nSymbolizers; ++j) // for each <Symbolizer>
468  {
469  // The current symbolizer
470  te::se::Symbolizer* symb = symbolizers[j];
471 
472  // Let's config the canvas based on the current symbolizer
473  cc.config(symb);
474 
475  // Let's draw! for each data set geometry...
476  if(j != nSymbolizers - 1)
477  drawDatSetGeometries(dataset.get(), gpos, canvas, layer->getSRID(), srid, 0, &task);
478  else
479  drawDatSetGeometries(dataset.get(), gpos, canvas, layer->getSRID(), srid, layer->getChart(), &task); // Here, produces the chart if exists
480 
481  // Prepares to draw the other symbolizer
482  dataset->moveFirst();
483 
484  } // end for each <Symbolizer>
485 
486  if(!task.isActive())
487  return;
488 
489  task.pulse();
490 
491  } // end for each GroupItem
492 }
493 
495  const std::string& geomPropertyName,
496  Canvas* canvas,
497  const te::gm::Envelope& bbox,
498  int srid)
499 {
500  assert(!geomPropertyName.empty());
501 
502  // Creates a canvas configurer
503  te::map::CanvasConfigurer cc(canvas);
504 
505  // The layer grouping
506  Grouping* grouping = layer->getGrouping();
507 
508  // The referenced property name
509  std::string propertyName = grouping->getPropertyName();
510  assert(!propertyName.empty());
511 
512  // The grouping type
513  GroupingType type = grouping->getType();
514 
515  // The grouping precision
516  const std::size_t& precision = grouping->getPrecision();
517 
518  // The grouping items
519  const std::vector<GroupingItem*>& items = grouping->getGroupingItems();
520 
521  std::size_t nGroupItems = items.size();
522 
523  // case UNIQUE_VALUE: for each GroupingItem, builds a map [item value] -> [symbolizers]
524  std::map<std::string, std::vector<te::se::Symbolizer*> > uniqueGroupsMap;
525 
526  // case (NOT) UNIQUE_VALUE: for each GroupingItem, builds a map [item upper limit] -> [symbolizers]
527  std::map<std::pair< double, double>, std::vector<te::se::Symbolizer*> > othersGroupsMap;
528 
529  for(std::size_t i = 0; i < nGroupItems; ++i)
530  {
531  // The current group item
532  GroupingItem* item = items[i];
533  assert(item);
534 
535  if(type == UNIQUE_VALUE)
536  {
537  uniqueGroupsMap[item->getValue()] = item->getSymbolizers();
538  }
539  else
540  {
541  double lowerLimit = atof(item->getLowerLimit().c_str());
542  double upperLimit = atof(item->getUpperLimit().c_str());
543  std::pair<double, double> range(lowerLimit, upperLimit);
544 
545  othersGroupsMap[range] = item->getSymbolizers();
546  }
547  }
548 
549  // Builds the task message; e.g. ("Drawing the grouping of layer Countries.")
550  std::string message = TE_TR("Drawing the grouping of layer");
551  message += " " + layer->getTitle() + ".";
552 
553  // Creates the draw task
555 
556  std::auto_ptr<te::da::DataSet> dataset(0);
557  try
558  {
559  dataset = layer->getData(geomPropertyName, &bbox, te::gm::INTERSECTS);
560  }
561  catch(std::exception& /*e*/)
562  {
563  return; // TODO: deal the exceptions!
564  }
565 
566  if(dataset.get() == 0)
567  throw Exception((boost::format(TE_TR("Could not retrieve the data set from the layer %1%.")) % layer->getTitle()).str());
568 
569  if(dataset->moveNext() == false)
570  return;
571 
572  // Gets the first geometry property
573  std::size_t gpos = te::da::GetPropertyPos(dataset.get(), geomPropertyName);
574 
575  // Gets the property position
576  std::auto_ptr<te::map::LayerSchema> dt(layer->getSchema());
577  std::size_t propertyPos = te::da::GetPropertyPos(dt.get(), propertyName);
578 
579  // Verifies if is necessary convert the data set geometries to the given srid
580  bool needRemap = false;
581  if((layer->getSRID() != TE_UNKNOWN_SRS) && (srid != TE_UNKNOWN_SRS) && (layer->getSRID() != srid))
582  needRemap = true;
583 
584  // The layer chart
585  Chart* chart = layer->getChart();
586 
587  do
588  {
589  std::vector<te::se::Symbolizer*> symbolizers;
590 
591  // Finds the current data set item on group map
592  std::string value;
593 
594  if(dataset->isNull(propertyPos))
596  else
597  value = dataset->getAsString(propertyPos, precision);
598 
599  if(type == UNIQUE_VALUE)
600  {
601  std::map<std::string, std::vector<te::se::Symbolizer*> >::const_iterator it = uniqueGroupsMap.find(value);
602  if(it == uniqueGroupsMap.end())
603  continue;
604  symbolizers = it->second;
605  }
606  else
607  {
608  double dvalue = atof(value.c_str());
609  std::map<std::pair< double, double>, std::vector<te::se::Symbolizer*> >::const_iterator it;
610  for(it = othersGroupsMap.begin(); it != othersGroupsMap.end(); ++it)
611  {
612  if(dvalue >= it->first.first && dvalue <= it->first.second)
613  break;
614  }
615 
616  if(it == othersGroupsMap.end())
617  {
618  te::se::Style* style = layer->getStyle();
619  if(style)
620  {
621  if(!style->getRules().empty())
622  {
623  te::se::Rule* rule = style->getRule(0);
624 
625  symbolizers = rule->getSymbolizers();
626  }
627  }
628  }
629  else
630  {
631  symbolizers = it->second;
632  }
633 
634  if(symbolizers.empty())
635  continue;
636  }
637 
638  std::auto_ptr<te::gm::Geometry> geom;
639  try
640  {
641  geom = dataset->getGeometry(gpos);
642  if(geom.get() == 0)
643  continue;
644  }
645  catch(std::exception& /*e*/)
646  {
647  continue;
648  }
649 
650  // Gets the set of symbolizers defined on group item
651  std::size_t nSymbolizers = symbolizers.size();
652 
653  for(std::size_t j = 0; j < nSymbolizers; ++j) // for each <Symbolizer>
654  {
655  // The current symbolizer
656  te::se::Symbolizer* symb = symbolizers[j];
657 
658  // Let's config the canvas based on the current symbolizer
659  cc.config(symb);
660 
661  // If necessary, geometry remap
662  if(needRemap)
663  {
664  geom->setSRID(layer->getSRID());
665  geom->transform(srid);
666  }
667 
668  canvas->draw(geom.get());
669 
670  if(chart && j == nSymbolizers - 1)
671  buildChart(chart, dataset.get(), geom.get());
672  }
673 
674  } while(dataset->moveNext());
675 
676  // Let's draw the generated charts
677  for(std::size_t i = 0; i < m_chartCoordinates.size(); ++i)
678  {
679  canvas->drawImage(static_cast<int>(m_chartCoordinates[i].x),
680  static_cast<int>(m_chartCoordinates[i].y),
681  m_chartImages[i],
682  chart->getWidth(),
683  chart->getHeight());
684 
685  te::common::Free(m_chartImages[i], chart->getHeight());
686  }
687 }
688 
689 void te::map::AbstractLayerRenderer::drawDatSetGeometries(te::da::DataSet* dataset, const std::size_t& gpos, Canvas* canvas,
690  int fromSRID, int toSRID,
691  Chart* chart, te::common::TaskProgress* task)
692 {
693  assert(dataset);
694  assert(canvas);
695 
696  // Verify if is necessary convert the data set geometries to the given srid
697  bool needRemap = false;
698  if((fromSRID != TE_UNKNOWN_SRS) && (toSRID != TE_UNKNOWN_SRS) && (fromSRID != toSRID))
699  needRemap = true;
700 
701  do
702  {
703  if(task)
704  {
705  if(!task->isActive())
706  return;
707 
708  // update the draw task
709  task->pulse();
710  }
711 
712  std::auto_ptr<te::gm::Geometry> geom(0);
713  try
714  {
715  geom = dataset->getGeometry(gpos);
716  if(geom.get() == 0)
717  continue;
718  }
719  catch(std::exception& /*e*/)
720  {
721  continue;
722  }
723 
724  // If necessary, geometry remap
725  if(needRemap)
726  {
727  geom->setSRID(fromSRID);
728  geom->transform(toSRID);
729  }
730 
731  canvas->draw(geom.get());
732 
733  if(chart)
734  buildChart(chart, dataset, geom.get());
735 
736  } while(dataset->moveNext()); // next geometry!
737 
738  // Let's draw the generated charts
739  for(std::size_t i = 0; i < m_chartCoordinates.size(); ++i)
740  {
741  canvas->drawImage(static_cast<int>(m_chartCoordinates[i].x),
742  static_cast<int>(m_chartCoordinates[i].y),
743  m_chartImages[i],
744  chart->getWidth(),
745  chart->getHeight());
746 
747  te::common::Free(m_chartImages[i], chart->getHeight());
748  }
749 }
750 
752 {
753  if(!chart->isVisible())
754  return;
755 
756  // World coordinates
757  std::auto_ptr<te::gm::Coord2D> worldCoord;
758 
759  // Try finds the geometry centroid
760  switch(geom->getGeomTypeId())
761  {
762  case te::gm::PolygonType:
763  {
764  te::gm::Polygon* p = dynamic_cast<te::gm::Polygon*>(geom);
765  worldCoord.reset(p->getCentroidCoord());
766  }
767  break;
768 
770  {
771  te::gm::MultiPolygon* mp = dynamic_cast<te::gm::MultiPolygon*>(geom);
772  worldCoord.reset(mp->getCentroidCoord());
773  }
774  break;
775 
776  default:
777  break;
778  }
779 
780  // Case not find, use the center of the MBR
781  if(worldCoord.get() == 0)
782  {
783  const te::gm::Envelope* e = geom->getMBR();
784  worldCoord.reset(new te::gm::Coord2D(e->getCenter().x, e->getCenter().y));
785  }
786 
787  // Device coordinates
788  double dx = 0.0; double dy = 0.0;
789  m_transformer.world2Device(worldCoord->x, worldCoord->y, dx, dy);
790 
791  double dw = dx + chart->getWidth();
792  double dh = dy + chart->getHeight();
793 
794  // Builds the chart envelope
795  te::gm::Envelope chartEnvelope(dx, dy, dw, dh);
796 
797  if(chart->getAvoidConflicts())
798  {
799  // Search on rtree
800  std::vector<std::size_t> report;
801  m_rtree.search(chartEnvelope, report);
802 
803  if(!report.empty())
804  return;
805 
806  // Here, no intersections considering the current chart envelope
807  m_rtree.insert(chartEnvelope, ++m_index);
808  }
809 
810  // Stores the chart coordinate
811  m_chartCoordinates.push_back(te::gm::Coord2D(dx, dy));
812 
813  // Builds the chart image
814  std::size_t width = 0;
815  te::color::RGBAColor** rgba = ChartRendererManager::getInstance().render(chart, dataset, width);
816  m_chartImages.push_back(rgba);
817 }
818 
820 {
821  m_index = 0;
822  m_chartCoordinates.clear();
823  m_chartImages.clear();
824 }
TEDATAACCESSEXPORT te::rst::RasterProperty * GetFirstRasterProperty(const DataSetType *dt)
Definition: Utils.cpp:571
MultiPolygon is a MultiSurface whose elements are Polygons.
Definition: MultiPolygon.h:50
Geometric property.
Utility functions for the data access module.
double y
y-coordinate.
Definition: Coord2D.h:114
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).
int getPropertyType() const
It gets the property type whose values will be grouped.
Definition: Grouping.cpp:79
TESEEXPORT Symbolizer * CreateSymbolizer(const te::gm::GeomType &geomType)
Try creates an appropriate symbolizer based on given geometry type.
Definition: Utils.cpp:220
const std::string & getValue() const
It gets the value of the legend item.
virtual const std::string & getTitle() const
It returns the layer title.
double x
x-coordinate.
Definition: Coord2D.h:113
A class that models the name of any property of an object.
Definition: PropertyName.h:50
const size_t getPrecision() const
It gets the precision used for the property values.
Definition: Grouping.cpp:100
A Symbolizer describes how a feature is to appear on a map.
Definition: Symbolizer.h:80
A visitor that converts a OGC Filter Expression to TerraLib Expression.
virtual int getHeight() const =0
It returns the canvas height.
The CoverageStyle defines the styling that is to be applied to a subset of Coverage data...
Definition: CoverageStyle.h:45
This is the base class for Layers.
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
TEDATAACCESSEXPORT std::size_t GetPropertyPos(const DataSet *dataset, const std::string &name)
Definition: Utils.cpp:500
This is a singleton for managing chart renderer instance available in the system. ...
double m_urx
Upper right corner x-coordinate.
Definition: Envelope.h:346
te::da::Expression * getExpression(const te::fe::Filter *f)
It converts the OGC Filter Expression to a TerraLib Expression.
It models the inequality operator greater than or equal to (>=).
virtual int getWidth() const =0
It returns the canvas width.
An utility struct for representing 2D coordinates.
Definition: Coord2D.h:40
void drawDatSetGeometries(te::da::DataSet *dataset, const std::size_t &gpos, Canvas *canvas, int fromSRID, int toSRID, Chart *chart, te::common::TaskProgress *task=0)
It draws the data set geometries in the given canvas using the informed SRS.
const te::fe::Filter * getFilter() const
Definition: Rule.cpp:97
#define TE_TR(message)
It marks a string in order to get translated.
Definition: Translator.h:347
void push_back(Symbolizer *s)
Definition: Rule.cpp:138
It renders the objects associated to an abstract layer. i.e. a generic renderer.
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
virtual te::map::Chart * getChart() const
It returns the Chart associated to the Layer.
Expression * clone() const
It creates a new copy of this expression.
An exception class for the MapTools module.
void drawLayerGrouping(AbstractLayer *layer, const std::string &geomPropertyName, Canvas *canvas, const te::gm::Envelope &bbox, int srid)
It draws the grouping of the abstract layer in the given canvas using the SRS informed.
TESEEXPORT Style * CreateFeatureTypeStyle(const te::gm::GeomType &geomType)
Try creates an appropriate feature type style based on given geometry type.
Definition: Utils.cpp:284
Rule * getRule(std::size_t i) const
Definition: Style.cpp:105
const std::vector< Rule * > & getRules() const
Definition: Style.cpp:94
virtual bool moveNext()=0
It moves the internal pointer to the next item of the collection.
This class contains the parameters needed for grouping the values of a Property.
Definition: Grouping.h:59
Coord2D getCenter() const
It returns the rectangle's center coordinate.
Definition: Envelope.cpp:51
void Free(std::vector< T * > *v)
This function can be applied to a pointer to a vector of pointers.
Definition: STLUtils.h:131
double m_llx
Lower left corner x-coordinate.
Definition: Envelope.h:344
This class represents the informations needed to build map charts.
Definition: Chart.h:51
static T & getInstance()
It returns a reference to the singleton instance.
Definition: Singleton.h:120
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
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 buildChart(Chart *chart, te::da::DataSet *dataset, te::gm::Geometry *geom)
virtual te::se::Style * getStyle() const
It returns the Style associated to the layer.
std::size_t getHeight() const
Definition: Chart.cpp:132
bool isVisible() const
It gets the chart visibility.
Definition: Chart.cpp:177
GeomType getGeometryType() const
It returns the geometry subtype allowed for the property.
virtual std::auto_ptr< te::da::DataSet > getData(te::common::TraverseType travType=te::common::FORWARDONLY, const te::common::AccessPolicy accessPolicy=te::common::RAccess) const =0
It gets the dataset identified by the layer name.
A visitor that converts a OGC Filter Expression to TerraLib Expression.
Definition: QueryEncoder.h:53
void pulse()
Calls setCurrentStep() function using getCurrentStep() + 1.
virtual void drawImage(char *src, std::size_t size, ImageType t)=0
It draws the src image over the canvas.
A filter is any valid predicate expression.
Definition: Filter.h:52
A class that models a literal for double values.
Definition: LiteralDouble.h:43
This class represents the informations needed to build map charts.
GeomType getGeomTypeId() const
It returns the geometry subclass type identifier.
Definition: Geometry.h:178
Geometry is the root class of the geometries hierarchy, it follows OGC and ISO standards.
Definition: Geometry.h:73
virtual std::auto_ptr< te::gm::Geometry > getGeometry(std::size_t i) const =0
Method for retrieving a geometric attribute value.
const std::vector< Symbolizer * > & getSymbolizers() const
Definition: Rule.cpp:158
double m_lly
Lower left corner y-coordinate.
Definition: Envelope.h:345
A dataset is the unit of information manipulated by the data access module of TerraLib.
Definition: DataSet.h:112
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
Polygon is a subclass of CurvePolygon whose rings are defined by linear rings.
Definition: Polygon.h:50
GroupingType
The grouping type associated to the layer.
Definition: Enums.h:150
A Rule is used to attach property/scale conditions to and group the individual symbols used for rende...
Definition: Rule.h:78
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.
double m_ury
Upper right corner y-coordinate.
Definition: Envelope.h:347
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. ...
Coord2D * getCentroidCoord() const
It returns the mathematical centroid for this surface as a coordinate.
virtual void setStyle(te::se::Style *style)
It sets the Style associated to the layer.
A helper class for 32-bit RGBA (Red-Green-Blue-Alpha channel) color.
Definition: RGBAColor.h:57
const GroupingType getType() const
It gets the grouping type.
Definition: Grouping.cpp:90
bool getAvoidConflicts() const
Definition: Chart.cpp:192
A class that models a literal for Envelope values.
virtual const std::string & getGeomPropertyName() const
virtual int getSRID() const
It returns the Spatial Reference System ID associated to the Layer.
void drawLayerGeometries(AbstractLayer *layer, const std::string &geomPropertyName, te::se::FeatureTypeStyle *style, Canvas *canvas, const te::gm::Envelope &bbox, int srid)
It draws the abstract layer in the given canvas using the SRS informed.
This class contains the parameters needed for grouping the values of a Property.
void drawLayerGroupingMem(AbstractLayer *layer, const std::string &geomPropertyName, Canvas *canvas, const te::gm::Envelope &bbox, int srid)
It draws the grouping of the abstract layer in the given canvas using the SRS informed.
std::vector< te::rst::BandProperty * > & getBandProperties()
Returns a reference to the list of bands definitions.
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.
const Envelope * getMBR() const
It returns the minimum bounding rectangle for the geometry in an internal representation.
Definition: Geometry.cpp:104
bool isValid() const
It tells if the rectangle is valid or not.
Definition: Envelope.h:438
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
Coord2D * getCentroidCoord() const
std::size_t getWidth() const
Definition: Chart.cpp:142
A Symbology Enconding visitor that configures a given canvas based on symbolizers elements...
virtual std::auto_ptr< LayerSchema > getSchema() const =0
It returns the layer schema.
This class models a string Literal value.
Definition: LiteralString.h:46
static const std::string sm_nanStr
Not a number string value.
Definition: Globals.h:56
const std::string & getName() const
It returns the property name.
Definition: Property.h:127
A Symbology Enconding visitor that configures a given canvas based on symbolizers elements...