All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
QueryLayerRenderer.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/QueryLayerRenderer.cpp
22 
23  \brief It renders the objects associated to a query layer.
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/StringUtils.h"
32 #include "../common/Translator.h"
33 #include "../dataaccess/dataset/DataSet.h"
34 #include "../dataaccess/dataset/DataSetType.h"
35 #include "../dataaccess/query/And.h"
36 #include "../dataaccess/query/EqualTo.h"
37 #include "../dataaccess/query/GreaterThanOrEqualTo.h"
38 #include "../dataaccess/query/LessThanOrEqualTo.h"
39 #include "../dataaccess/query/LiteralDouble.h"
40 #include "../dataaccess/query/LiteralEnvelope.h"
41 #include "../dataaccess/query/LiteralString.h"
42 #include "../dataaccess/query/PropertyName.h"
43 #include "../dataaccess/query/ST_Intersects.h"
44 #include "../dataaccess/utils/Utils.h"
45 #include "../fe/Filter.h"
46 #include "../geometry/Coord2D.h"
47 #include "../geometry/Envelope.h"
48 #include "../geometry/GeometryProperty.h"
49 #include "../geometry/MultiPolygon.h"
50 #include "../geometry/Polygon.h"
51 #include "../raster/Raster.h"
52 #include "../raster/RasterProperty.h"
53 #include "../se/FeatureTypeStyle.h"
54 #include "../se/CoverageStyle.h"
55 #include "../se/Rule.h"
56 #include "../se/Utils.h"
57 #include "../srs/Config.h"
58 #include "AbstractLayer.h"
59 #include "QueryLayerRenderer.h"
60 #include "Canvas.h"
61 #include "CanvasConfigurer.h"
62 #include "Chart.h"
63 #include "ChartRendererManager.h"
64 #include "Exception.h"
65 #include "Grouping.h"
66 #include "GroupingItem.h"
67 #include "QueryEncoder.h"
68 #include "Utils.h"
69 #include "QueryLayer.h"
70 #include "../dataaccess/query/OrderBy.h"
71 #include "../dataaccess/query/OrderByItem.h"
72 #include "../dataaccess/query/Select.h"
73 
74 // Boost
75 #include <boost/format.hpp>
76 #include <boost/lexical_cast.hpp>
77 #include <boost/math/special_functions/round.hpp>
78 
79 // STL
80 #include <cassert>
81 #include <cstdlib>
82 #include <memory>
83 #include <utility>
84 
86  : m_index(0)
87 {
88 }
89 
91 {
92 }
93 
95  Canvas* canvas,
96  const te::gm::Envelope& bbox,
97  int srid)
98 {
99  if(!bbox.isValid())
100  throw Exception(TE_TR("The requested box is invalid!"));
101 
102  assert(layer);
103  assert(canvas);
104 
105  // Check if layer extent intersects the drawing area and so compute bounding box intersection
106  te::gm::Envelope reprojectedBBOX(bbox);
107 
108  if((layer->getSRID() != TE_UNKNOWN_SRS) && (srid != TE_UNKNOWN_SRS))
109  {
110  reprojectedBBOX.transform(srid, layer->getSRID());
111 
112  if(!reprojectedBBOX.isValid())
113  throw Exception(TE_TR("The reprojected box is invalid!"));
114  }
115  else if(layer->getSRID() != srid)
116  {
117  throw Exception(TE_TR("The layer or map don't have a valid SRID!"));
118  }
119 
120  if(!reprojectedBBOX.intersects(layer->getExtent()))
121  return;
122 
123  // Adjust internal renderer transformer
124  m_transformer.setTransformationParameters(bbox.m_llx, bbox.m_lly, bbox.m_urx, bbox.m_ury, canvas->getWidth(), canvas->getHeight());
125 
126  // Resets internal renderer state
127  reset();
128 
129  te::gm::Envelope ibbox = reprojectedBBOX.intersection(layer->getExtent());
130 
131  assert(ibbox.isValid());
132 
133  // Gets the layer schema
134  std::auto_ptr<LayerSchema> schema(layer->getSchema());
135  assert(schema.get());
136 
137  // Gets the name of the referenced spatial property
138  std::string spatialPropertyName = layer->getGeomPropertyName();
139 
140  if(schema->hasGeom())
141  {
142  te::gm::GeometryProperty* geometryProperty = 0;
143 
144  if(spatialPropertyName.empty())
145  geometryProperty = te::da::GetFirstGeomProperty(schema.get());
146  else
147  geometryProperty = dynamic_cast<te::gm::GeometryProperty*>(schema->getProperty(spatialPropertyName));
148 
149  assert(geometryProperty);
150 
151  // If the AbstractLayer has a grouping, do not consider the style.
152  Grouping* grouping = layer->getGrouping();
153  if(grouping && grouping->isVisible())
154  {
155  drawLayerGroupingMem(layer, geometryProperty->getName(), canvas, ibbox, srid);
156  return;
157  }
158 
159  // Gets the layer style
160  te::se::Style* style = layer->getStyle();
161  if(style == 0)
162  {
163  // Try create an appropriate style. i.e. a FeatureTypeStyle
164  style = te::se::CreateFeatureTypeStyle(geometryProperty->getGeometryType());
165 
166  if(style == 0)
167  throw Exception((boost::format(TE_TR("Could not create a default feature type style to the layer %1%.")) % layer->getTitle()).str());
168 
169  layer->setStyle(style);
170  }
171 
172  // Should I render this style?
173  te::se::FeatureTypeStyle* fts = dynamic_cast<te::se::FeatureTypeStyle*>(style);
174  if(fts == 0)
175  throw Exception(TE_TR("The layer style is not a Feature Type Style!"));
176 
177  drawLayerGeometries(layer, geometryProperty->getName(), fts, canvas, ibbox, srid);
178  }
179  else if(schema->hasRaster())
180  {
181  te::rst::RasterProperty* rasterProperty = 0;
182 
183  if(spatialPropertyName.empty())
184  rasterProperty = te::da::GetFirstRasterProperty(schema.get());
185  else
186  rasterProperty = dynamic_cast<te::rst::RasterProperty*>(schema->getProperty(spatialPropertyName));
187 
188  assert(rasterProperty);
189 
190  // Get the layer style
191  te::se::Style* style = layer->getStyle();
192  if(style == 0)
193  {
194  // Try create an appropriate style. i.e. a CoverageStyle
195  style = te::se::CreateCoverageStyle(rasterProperty->getBandProperties());
196 
197  if(style == 0)
198  throw Exception((boost::format(TE_TR("Could not create a default coverage style to the layer %1%.")) % layer->getTitle()).str());
199 
200  layer->setStyle(style);
201  }
202 
203  // Should I render this style?
204  te::se::CoverageStyle* cs = dynamic_cast<te::se::CoverageStyle*>(style);
205  if(cs == 0)
206  throw Exception(TE_TR("The layer style is not a Coverage Style!"));
207 
208  // Retrieves the data
209  std::auto_ptr<te::da::DataSet> dataset = layer->getData(rasterProperty->getName(), &ibbox, te::gm::INTERSECTS);
210 
211  if(dataset.get() == 0)
212  throw Exception((boost::format(TE_TR("Could not retrieve the data set from the layer %1%.")) % layer->getTitle()).str());
213 
214  // Retrieves the raster
215  std::auto_ptr<te::rst::Raster> raster(dataset->getRaster(rasterProperty->getName()));
216  if(dataset.get() == 0)
217  throw Exception((boost::format(TE_TR("Could not retrieve the raster from the layer %1%.")) % layer->getTitle()).str());
218 
219  // Let's draw!
220  DrawRaster(raster.get(), canvas, ibbox, layer->getSRID(), bbox, srid, cs);
221  }
222  else
223  {
224  throw Exception(TE_TR("The layer don't have a geometry or raster property!"));
225  }
226 }
227 
229  const std::string& geomPropertyName,
231  Canvas* canvas,
232  const te::gm::Envelope& bbox,
233  int srid)
234 {
235  assert(!geomPropertyName.empty());
236  m_oid.clear();
237  te::map::QueryLayer* qlayer = 0;
238  te::da::Select* select = 0;
239 
240  bool linked = te::da::HasLinkedTable(layer->getSchema().get());
241  if(linked)
242  {
243  // make sorting by object id
244  qlayer = dynamic_cast<te::map::QueryLayer*>(layer);
245  select = dynamic_cast<te::da::Select*>(qlayer->getQuery()->clone());
246  te::da::Select* selectaux = dynamic_cast<te::da::Select*>(select->clone());
247  te::da::OrderBy* orderBy = new te::da::OrderBy;
248 
249  std::auto_ptr<te::da::DataSetType> schema = layer->getSchema();
250  std::vector<te::dt::Property*> props = schema->getPrimaryKey()->getProperties();
251  size_t pksize = 0;
252  while(++pksize < props.size())
253  {
254  m_oid.push_back(props[pksize-1]->getName());
255  if(props[pksize-1]->getDatasetName() != props[pksize]->getDatasetName())
256  break;
257  }
258 
259  for(size_t i = 0; i < pksize; ++i)
260  orderBy->push_back(new te::da::OrderByItem(m_oid[i]));
261 
262  selectaux->setOrderBy(orderBy);
263  qlayer->setQuery(selectaux);
264  }
265 
266  // Creates a canvas configurer
267  CanvasConfigurer cc(canvas);
268 
269  // Number of rules defined on feature type style
270  std::size_t nRules = style->getRules().size();
271 
272  for(std::size_t i = 0; i < nRules; ++i) // for each <Rule>
273  {
274  // The current rule
275  te::se::Rule* rule = style->getRule(i);
276  assert(rule);
277 
278  // TODO: Should be verified the MinScaleDenominator and MaxScaleDenominator. Where will we put the current scale information? Method parameter?
279 
280  // Gets the rule filter
281  const te::fe::Filter* filter = rule->getFilter();
282 
283  // Let's retrieve the correct dataset
284  std::auto_ptr<te::da::DataSet> dataset(0);
285 
286  if(!filter)
287  {
288  try
289  {
290  // There isn't a Filter expression. Gets the data using only extent spatial restriction...
291  dataset = layer->getData(geomPropertyName, &bbox, te::gm::INTERSECTS);
292  if(linked)
293  qlayer->setQuery(select);
294  }
295  catch(std::exception& /*e*/)
296  {
297  continue; // TODO: deal the exceptions!
298  }
299  }
300  else
301  {
302  try
303  {
304  // Gets an enconder
305  te::map::QueryEncoder filter2Query;
306 
307  // Converts the Filter expression to a TerraLib Expression!
308  te::da::Expression* exp = filter2Query.getExpression(filter);
309  if(exp == 0)
310  throw Exception(TE_TR("Could not convert the OGC Filter expression to TerraLib expression!"));
311 
312  /* 1) Creating the final restriction. i.e. Filter expression + extent spatial restriction */
313 
314  // The extent spatial restriction
315  te::da::LiteralEnvelope* lenv = new te::da::LiteralEnvelope(bbox, layer->getSRID());
316  te::da::PropertyName* geometryPropertyName = new te::da::PropertyName(geomPropertyName);
317  te::da::ST_Intersects* intersects = new te::da::ST_Intersects(geometryPropertyName, lenv);
318 
319  // Combining the expressions (Filter expression + extent spatial restriction)
320  te::da::And* restriction = new te::da::And(exp, intersects);
321 
322  /* 2) Calling the layer query method to get the correct restricted data. */
323  dataset = layer->getData(restriction);
324  if(linked)
325  qlayer->setQuery(select);
326  }
327  catch(std::exception& /*e*/)
328  {
329  continue; // TODO: deal the exceptions!
330  }
331  }
332 
333  if(dataset.get() == 0)
334  throw Exception((boost::format(TE_TR("Could not retrieve the data set from the layer %1%.")) % layer->getTitle()).str());
335 
336  if(dataset->moveNext() == false)
337  continue;
338 
339  // Gets the set of symbolizers defined on current rule
340  const std::vector<te::se::Symbolizer*>& symbolizers = rule->getSymbolizers();
341 
342  // Builds task message; e.g. ("Drawing the layer Countries. Rule 1 of 3.")
343  std::string message = TE_TR("Drawing the layer");
344  message += " " + layer->getTitle() + ". ";
345  message += TE_TR("Rule");
346  message += " " + boost::lexical_cast<std::string>(i + 1) + " " + TE_TR("of") + " ";
347  message += boost::lexical_cast<std::string>(nRules) + ".";
348 
349  // Creates a draw task
351  //task.setTotalSteps(symbolizers.size() * dataset->size()); // Removed! The te::da::DataSet size() method would be too costly to compute.
352 
353  // For while, first geometry property. TODO: get which geometry property the symbolizer references
354  std::size_t gpos = te::da::GetPropertyPos(dataset.get(), geomPropertyName);
355 
356  if(symbolizers.empty())
357  {
358  // The current rule do not have a symbolizer. Try creates a default based on first geometry of dataset.
359  std::auto_ptr<te::gm::Geometry> g(dataset->getGeometry(gpos));
360  assert(g.get());
361 
362  te::se::Symbolizer* symbolizer = te::se::CreateSymbolizer(g->getGeomTypeId());
363  assert(symbolizer);
364 
365  rule->push_back(symbolizer);
366 
367  dataset->moveFirst();
368  }
369 
370  std::size_t nSymbolizers = symbolizers.size();
371 
372  for(std::size_t j = 0; j < nSymbolizers; ++j) // for each <Symbolizer>
373  {
374  // The current symbolizer
375  te::se::Symbolizer* symb = symbolizers[j];
376 
377  // Let's config the canvas based on the current symbolizer
378  cc.config(symb);
379 
380  // Let's draw! for each data set geometry...
381  if(j != nSymbolizers - 1)
382  drawDatSetGeometries(dataset.get(), gpos, canvas, layer->getSRID(), srid, 0, &task);
383  else
384  drawDatSetGeometries(dataset.get(), gpos, canvas, layer->getSRID(), srid, layer->getChart(), &task); // Here, produces the chart if exists
385 
386  // Prepares to draw the other symbolizer
387  dataset->moveFirst();
388 
389  } // end for each <Symbolizer>
390 
391  } // end for each <Rule>
392 }
393 
395  const std::string& geomPropertyName,
396  Canvas* canvas,
397  const te::gm::Envelope& bbox,
398  int srid)
399 {
400  //assert(!geomPropertyName.empty());
401 
402  //// Creates a canvas configurer
403  //te::map::CanvasConfigurer cc(canvas);
404 
405  //// The layer grouping
406  //Grouping* grouping = layer->getGrouping();
407 
408  //// The referenced property name
409  //std::string propertyName = grouping->getPropertyName();
410  //assert(!propertyName.empty());
411 
412  //// The referenced property type
413  //int propertyType = grouping->getPropertyType();
414 
415  //// The grouping type
416  //GroupingType type = grouping->getType();
417 
418  //// The grouping items
419  //const std::vector<GroupingItem*>& items = grouping->getGroupingItems();
420  //
421  //std::size_t nGroupItems = items.size();
422 
423  //// Builds the task message; e.g. ("Drawing the grouping of layer Countries.")
424  //std::string message = TE_TR("Drawing the grouping of layer");
425  //message += " " + layer->getTitle() + ".";
426 
427  //// Creates the draw task
428  //te::common::TaskProgress task(message, te::common::TaskProgress::DRAW, nGroupItems);
429 
430  //for(std::size_t i = 0; i < nGroupItems; ++i) // for each GroupingItem
431  //{
432  // // The current group item
433  // GroupingItem* item = items[i];
434  // assert(item);
435 
436  // /* 1) Creating te::da::Where object with the group item restriction expression + extent spatial restriction */
437 
438  // te::da::PropertyName* groupingPropertyName = new te::da::PropertyName(propertyName);
439 
440  // // Grouping item restriction
441  // te::da::Expression* exp = 0;
442 
443  // if(type == UNIQUE_VALUE)
444  // {
445  // te::da::LiteralString* value = new te::da::LiteralString(item->getValue());
446  // exp = new te::da::EqualTo(groupingPropertyName, value);
447  // }
448  // else
449  // {
450  // te::da::Expression* lowerValue = 0;
451  // te::da::Expression* upperrValue = 0;
452 
453  // switch(propertyType)
454  // {
455  // case te::dt::STRING_TYPE:
456  // lowerValue = new te::da::LiteralString(item->getLowerLimit());
457  // upperrValue = new te::da::LiteralString(item->getUpperLimit());
458  // break;
459 
460  // default:
461  // lowerValue = new te::da::LiteralDouble(boost::lexical_cast<double>(item->getLowerLimit()));
462  // upperrValue = new te::da::LiteralDouble(boost::lexical_cast<double>(item->getUpperLimit()));
463  // }
464 
465  // te::da::GreaterThanOrEqualTo* gte = new te::da::GreaterThanOrEqualTo(groupingPropertyName, lowerValue);
466  // te::da::LessThanOrEqualTo* lte = new te::da::LessThanOrEqualTo(groupingPropertyName->clone(), upperrValue);
467 
468  // exp = new te::da::And(gte, lte);
469  // }
470 
471  // // The extent spatial restriction
472  // te::da::LiteralEnvelope* lenv = new te::da::LiteralEnvelope(bbox, layer->getSRID());
473  // te::da::PropertyName* geometryPropertyName = new te::da::PropertyName(geomPropertyName);
474  // te::da::ST_Intersects* intersects = new te::da::ST_Intersects(geometryPropertyName, lenv);
475 
476  // // Combining the expressions (group item restriction expression + extent spatial restriction)
477  // te::da::And* restriction = new te::da::And(exp, intersects);
478 
479  // /* 2) Calling the layer query method to get the correct restricted data. */
480 
481  // std::auto_ptr<te::da::DataSet> dataset(0);
482  // try
483  // {
484  // dataset = layer->getData(restriction);
485  // }
486  // catch(std::exception& /*e*/)
487  // {
488  // continue; // TODO: deal the exceptions!
489  // }
490 
491  // if(dataset.get() == 0)
492  // throw Exception((boost::format(TE_TR("Could not retrieve the data set from the layer %1%.")) % layer->getTitle()).str());
493 
494  // if(dataset->moveNext() == false)
495  // continue;
496 
497  // // Gets the set of symbolizers defined on group item
498  // const std::vector<te::se::Symbolizer*>& symbolizers = item->getSymbolizers();
499  // std::size_t nSymbolizers = symbolizers.size();
500 
501  // // For while, first geometry property. TODO: get which geometry property the symbolizer references
502  // std::size_t gpos = te::da::GetPropertyPos(dataset.get(), geomPropertyName);
503 
504  // for(std::size_t j = 0; j < nSymbolizers; ++j) // for each <Symbolizer>
505  // {
506  // // The current symbolizer
507  // te::se::Symbolizer* symb = symbolizers[j];
508 
509  // // Let's config the canvas based on the current symbolizer
510  // cc.config(symb);
511 
512  // // Let's draw! for each data set geometry...
513  // if(j != nSymbolizers - 1)
514  // drawDatSetGeometries(dataset.get(), gpos, canvas, layer->getSRID(), srid, 0, &task);
515  // else
516  // drawDatSetGeometries(dataset.get(), gpos, canvas, layer->getSRID(), srid, layer->getChart(), &task); // Here, produces the chart if exists
517 
518  // // Prepares to draw the other symbolizer
519  // dataset->moveFirst();
520 
521  // } // end for each <Symbolizer>
522 
523  // if(!task.isActive())
524  // return;
525 
526  // task.pulse();
527 
528  //} // end for each GroupItem
529 }
530 
532  const std::string& geomPropertyName,
533  Canvas* canvas,
534  const te::gm::Envelope& bbox,
535  int srid)
536 {
537  assert(!geomPropertyName.empty());
538 
539  if(te::da::HasLinkedTable(layer->getSchema().get()))
540  {
541  drawLayerLinkedGroupingMem(layer, geomPropertyName, canvas, bbox, srid);
542  return;
543  }
544 
545  // Creates a canvas configurer
546  te::map::CanvasConfigurer cc(canvas);
547 
548  // The layer grouping
549  Grouping* grouping = layer->getGrouping();
550 
551  // The referenced property name
552  std::string propertyName = grouping->getPropertyName();
553  assert(!propertyName.empty());
554 
555  // The grouping type
556  GroupingType type = grouping->getType();
557 
558  // The grouping precision
559  const std::size_t& precision = grouping->getPrecision();
560 
561  // The grouping items
562  const std::vector<GroupingItem*>& items = grouping->getGroupingItems();
563 
564  std::size_t nGroupItems = items.size();
565 
566  // case UNIQUE_VALUE: for each GroupingItem, builds a map [item value] -> [symbolizers]
567  std::map<std::string, std::vector<te::se::Symbolizer*> > uniqueGroupsMap;
568 
569  // case (NOT) UNIQUE_VALUE: for each GroupingItem, builds a map [item upper limit] -> [symbolizers]
570  std::map<std::pair< double, double>, std::vector<te::se::Symbolizer*> > othersGroupsMap;
571 
572  for(std::size_t i = 0; i < nGroupItems; ++i)
573  {
574  // The current group item
575  GroupingItem* item = items[i];
576  assert(item);
577 
578  if(type == UNIQUE_VALUE)
579  {
580  uniqueGroupsMap[item->getValue()] = item->getSymbolizers();
581  }
582  else
583  {
584  double lowerLimit = atof(item->getLowerLimit().c_str());
585  double upperLimit = atof(item->getUpperLimit().c_str());
586  std::pair<double, double> range(lowerLimit, upperLimit);
587 
588  othersGroupsMap[range] = item->getSymbolizers();
589  }
590  }
591 
592  // Builds the task message; e.g. ("Drawing the grouping of layer Countries.")
593  std::string message = TE_TR("Drawing the grouping of layer");
594  message += " " + layer->getTitle() + ".";
595 
596  // Creates the draw task
598 
599  std::auto_ptr<te::da::DataSet> dataset(0);
600  try
601  {
602  dataset = layer->getData(geomPropertyName, &bbox, te::gm::INTERSECTS);
603  }
604  catch(std::exception& /*e*/)
605  {
606  return; // TODO: deal the exceptions!
607  }
608 
609  if(dataset.get() == 0)
610  throw Exception((boost::format(TE_TR("Could not retrieve the data set from the layer %1%.")) % layer->getTitle()).str());
611 
612  if(dataset->moveNext() == false)
613  return;
614 
615  // Gets the first geometry property
616  std::size_t gpos = te::da::GetPropertyPos(dataset.get(), geomPropertyName);
617 
618  // Gets the property position
619  std::auto_ptr<te::map::LayerSchema> dt(layer->getSchema());
620  std::size_t propertyPos = te::da::GetPropertyPos(dt.get(), propertyName);
621 
622  // Verifies if is necessary convert the data set geometries to the given srid
623  bool needRemap = false;
624  if((layer->getSRID() != TE_UNKNOWN_SRS) && (srid != TE_UNKNOWN_SRS) && (layer->getSRID() != srid))
625  needRemap = true;
626 
627  // The layer chart
628  Chart* chart = layer->getChart();
629 
630  do
631  {
632  std::vector<te::se::Symbolizer*> symbolizers;
633 
634  if(dataset->isNull(propertyPos) == false)
635  {
636  // Finds the current data set item on group map
637 
638  if(type == UNIQUE_VALUE)
639  {
640  std::string svalue = dataset->getAsString(propertyPos, precision);
641  std::map<std::string, std::vector<te::se::Symbolizer*> >::const_iterator it = uniqueGroupsMap.find(svalue);
642  if(it == uniqueGroupsMap.end())
643  continue;
644  symbolizers = it->second;
645  }
646  else
647  {
648  double dvalue = te::da::GetValueAsDouble(dataset.get(), propertyPos);
649  std::map<std::pair< double, double>, std::vector<te::se::Symbolizer*> >::const_iterator it;
650  for(it = othersGroupsMap.begin(); it != othersGroupsMap.end(); ++it)
651  {
652  if(dvalue >= it->first.first && dvalue <= it->first.second)
653  break;
654  }
655 
656  if(it == othersGroupsMap.end())
657  {
658  te::se::Style* style = layer->getStyle();
659  if(style)
660  {
661  if(!style->getRules().empty())
662  {
663  te::se::Rule* rule = style->getRule(0);
664 
665  symbolizers = rule->getSymbolizers();
666  }
667  }
668  }
669  else
670  {
671  symbolizers = it->second;
672  }
673 
674  if(symbolizers.empty())
675  continue;
676  }
677  }
678  else
679  {
680  te::se::Style* style = layer->getStyle();
681  if(style)
682  {
683  if(!style->getRules().empty())
684  {
685  te::se::Rule* rule = style->getRule(0);
686 
687  symbolizers = rule->getSymbolizers();
688  }
689  }
690  }
691 
692  std::auto_ptr<te::gm::Geometry> geom;
693  try
694  {
695  geom = dataset->getGeometry(gpos);
696  if(geom.get() == 0)
697  continue;
698  }
699  catch(std::exception& /*e*/)
700  {
701  continue;
702  }
703 
704  // Gets the set of symbolizers defined on group item
705  std::size_t nSymbolizers = symbolizers.size();
706 
707  for(std::size_t j = 0; j < nSymbolizers; ++j) // for each <Symbolizer>
708  {
709  // The current symbolizer
710  te::se::Symbolizer* symb = symbolizers[j];
711 
712  // Let's config the canvas based on the current symbolizer
713  cc.config(symb);
714 
715  // If necessary, geometry remap
716  if(needRemap)
717  {
718  geom->setSRID(layer->getSRID());
719  geom->transform(srid);
720  }
721 
722  canvas->draw(geom.get());
723 
724  if(chart && j == nSymbolizers - 1)
725  buildChart(chart, dataset.get(), geom.get());
726  }
727 
728  } while(dataset->moveNext());
729 
730  // Let's draw the generated charts
731  for(std::size_t i = 0; i < m_chartCoordinates.size(); ++i)
732  {
733  canvas->drawImage(static_cast<int>(m_chartCoordinates[i].x),
734  static_cast<int>(m_chartCoordinates[i].y),
735  m_chartImages[i],
736  chart->getWidth(),
737  chart->getHeight());
738 
739  te::common::Free(m_chartImages[i], chart->getHeight());
740  }
741 }
742 
744  const std::string& geomPropertyName,
745  Canvas* canvas,
746  const te::gm::Envelope& bbox,
747  int srid)
748 {
749  assert(!geomPropertyName.empty());
750 
751  m_oid.clear();
752 
753  te::map::QueryLayer* qlayer = dynamic_cast<te::map::QueryLayer*>(layer);
754  te::da::Select* select = dynamic_cast<te::da::Select*>(qlayer->getQuery()->clone());
755 
756  std::auto_ptr<te::da::DataSetType> schema = layer->getSchema();
757  std::vector<te::dt::Property*> props = schema->getPrimaryKey()->getProperties();
758  size_t pksize = 0;
759  while(++pksize < props.size())
760  {
761  m_oid.push_back(props[pksize-1]->getName());
762  if(props[pksize-1]->getDatasetName() != props[pksize]->getDatasetName())
763  break;
764  }
765 
766  te::da::OrderBy* orderBy = new te::da::OrderBy;
767  for(size_t i = 0; i < pksize; ++i)
768  orderBy->push_back(new te::da::OrderByItem(m_oid[i]));
769 
770  te::da::Select* selectaux = dynamic_cast<te::da::Select*>(select->clone());
771  selectaux->setOrderBy(orderBy);
772  qlayer->setQuery(selectaux);
773 
774  // Creates a canvas configurer
775  te::map::CanvasConfigurer cc(canvas);
776 
777  // The layer grouping
778  Grouping* grouping = layer->getGrouping();
779 
780  // The referenced property name
781  std::string propertyName = grouping->getPropertyName();
782  assert(!propertyName.empty());
783 
784  // The grouping type
785  GroupingType type = grouping->getType();
786 
787  // The grouping precision
788  const std::size_t& precision = grouping->getPrecision();
789 
790  // The grouping sumarization
791  const std::string gfunction = grouping->getSummary();
792 
793  // The grouping items
794  const std::vector<GroupingItem*>& items = grouping->getGroupingItems();
795 
796  std::size_t nGroupItems = items.size();
797 
798  // case UNIQUE_VALUE: for each GroupingItem, builds a map [item value] -> [symbolizers]
799  std::map<std::string, std::vector<te::se::Symbolizer*> > uniqueGroupsMap;
800 
801  // case (NOT) UNIQUE_VALUE: for each GroupingItem, builds a map [item upper limit] -> [symbolizers]
802  std::map<std::pair< double, double>, std::vector<te::se::Symbolizer*> > othersGroupsMap;
803 
804  for(std::size_t i = 0; i < nGroupItems; ++i)
805  {
806  // The current group item
807  GroupingItem* item = items[i];
808  assert(item);
809 
810  if(type == UNIQUE_VALUE)
811  {
812  uniqueGroupsMap[item->getValue()] = item->getSymbolizers();
813  }
814  else
815  {
816  double lowerLimit = atof(item->getLowerLimit().c_str());
817  double upperLimit = atof(item->getUpperLimit().c_str());
818  std::pair<double, double> range(lowerLimit, upperLimit);
819 
820  othersGroupsMap[range] = item->getSymbolizers();
821  }
822  }
823 
824  // Builds the task message; e.g. ("Drawing the grouping of layer Countries.")
825  std::string message = TE_TR("Drawing the grouping of layer");
826  message += " " + layer->getTitle() + ".";
827 
828  // Creates the draw task
830 
831  std::auto_ptr<te::da::DataSet> dataset(0);
832  try
833  {
834  dataset = layer->getData(geomPropertyName, &bbox, te::gm::INTERSECTS);
835  qlayer->setQuery(select);
836  }
837  catch(std::exception& /*e*/)
838  {
839  return; // TODO: deal the exceptions!
840  }
841 
842  if(dataset.get() == 0)
843  throw Exception((boost::format(TE_TR("Could not retrieve the data set from the layer %1%.")) % layer->getTitle()).str());
844 
845  if(dataset->moveNext() == false)
846  return;
847 
848  // Gets the first geometry property
849  std::size_t gpos = te::da::GetPropertyPos(dataset.get(), geomPropertyName);
850 
851  // Gets the property position
852  std::auto_ptr<te::map::LayerSchema> dt(layer->getSchema());
853  std::size_t propertyPos = te::da::GetPropertyPos(dt.get(), propertyName);
854  size_t ptype = dataset->getPropertyDataType(te::da::GetPropertyPos(dataset.get(), propertyName));
855 
856  // Verifies if is necessary convert the data set geometries to the given srid
857  bool needRemap = false;
858  if((layer->getSRID() != TE_UNKNOWN_SRS) && (srid != TE_UNKNOWN_SRS) && (layer->getSRID() != srid))
859  needRemap = true;
860 
861  std::vector<std::string> pkdata(pksize), pkdataaux(pksize);
862  std::vector<double> values;
863  double value;
864  std::vector<std::string> svalues;
865  std::string svalue;
866 
867  // The layer chart
868  Chart* chart = layer->getChart();
869 
870  // The chart sumarization
871  std::string cfunction;
872  std::map<std::string, std::vector<double> > chartValues;
873  std::map<std::string, double> chartValue;
874  bool hasGroupNullValue = false;
875  bool hasGroupNullValueAux = false;
876  bool hasChartNullValue = false;
877  bool hasChartNullValueAux = false;
878  size_t csize = 0;
879  if(chart)
880  {
881  cfunction = chart->getSummary();
882  csize = chart->getProperties().size();
883  std::vector<size_t> propPos;
884  for(std::size_t i = 0; i < csize; ++i)
885  {
886  std::vector<double> v;
887  chartValues[chart->getProperties()[i]] = v;
888  propPos.push_back(te::da::GetPropertyPos(dataset.get(), chart->getProperties()[i]));
889  }
890  chart->setPropertiesPos(propPos);
891  }
892 
893  te::gm::Geometry *geom = 0, *geomaux = 0;
894  do
895  {
896  try
897  {
898  if(geomaux == 0)
899  geomaux = dataset->getGeometry(gpos).release();
900  if(geomaux == 0)
901  continue;
902  }
903  catch(std::exception& /*e*/)
904  {
905  continue;
906  }
907 
908  std::vector<te::se::Symbolizer*> symbolizers;
909 
910  // Finds the current data set item on group map
911  size_t i;
912  for(i = 0; i < pksize; ++i)
913  pkdata[i] = dataset->getAsString(m_oid[i]);
914 
915  for(i = 0; i < pksize; ++i)
916  {
917  if(dataset->isAtBegin())
918  pkdataaux[i] = dataset->getAsString(m_oid[i]);
919  else
920  {
921  if(pkdata[i] != pkdataaux[i])
922  {
923  pkdataaux = pkdata;
924  break;
925  }
926  }
927  }
928  if(i == pksize) // it is the same object
929  {
930  // read value
931  if(hasGroupNullValue == false && dataset->isNull(propertyPos) == false)
932  {
933  if(type == UNIQUE_VALUE)
934  {
935  if(ptype == te::dt::STRING_TYPE)
936  svalues.push_back(dataset->getAsString(propertyPos, precision));
937  else
938  values.push_back(te::da::GetValueAsDouble(dataset.get(), propertyPos));
939  }
940  else
941  values.push_back(te::da::GetValueAsDouble(dataset.get(), propertyPos));
942  }
943  else
944  hasGroupNullValue = true;
945 
946  if(hasChartNullValue == false)
947  {
948  for(std::size_t i = 0; i < csize; ++i)
949  {
950  if(dataset->isNull(chart->getProperties()[i]))
951  {
952  hasChartNullValue = true;
953  break;
954  }
955  }
956  if(hasChartNullValue == false)
957  {
958  for(std::size_t i = 0; i < csize; ++i)
959  chartValues[chart->getProperties()[i]].push_back(te::da::GetValueAsDouble(dataset.get(), chart->getPropertiesPos()[i]));
960  }
961  }
962 
963  // read other values
964  continue;
965  }
966  else // it is other object
967  {
968  delete geom;
969  geom = geomaux;
970 
971  // sumarize value
972  // computing a value according to the required summarization
973  // get symbolizers
974  if(hasGroupNullValue == false)
975  {
976  if(type == UNIQUE_VALUE)
977  {
978  if(ptype == te::dt::STRING_TYPE)
979  {
980  value = te::da::GetSummarizedValue(values, gfunction);
981  value = te::da::Round(value, precision);
982  svalue = boost::lexical_cast<std::string>(value);
983  }
984  else
985  svalue = te::da::GetSummarizedValue(svalues, gfunction);
986 
987  std::map<std::string, std::vector<te::se::Symbolizer*> >::const_iterator it = uniqueGroupsMap.find(svalue);
988  if(it == uniqueGroupsMap.end())
989  continue;
990  symbolizers = it->second;
991  }
992  else
993  {
994  value = te::da::GetSummarizedValue(values, gfunction);
995  value = te::da::Round(value, precision);
996 
997  std::map<std::pair<double, double>, std::vector<te::se::Symbolizer*> >::const_iterator it;
998  for(it = othersGroupsMap.begin(); it != othersGroupsMap.end(); ++it)
999  {
1000  if(value >= it->first.first && value <= it->first.second)
1001  break;
1002  }
1003 
1004  if(it == othersGroupsMap.end())
1005  {
1006  te::se::Style* style = layer->getStyle();
1007  if(style)
1008  {
1009  if(!style->getRules().empty())
1010  {
1011  te::se::Rule* rule = style->getRule(0);
1012 
1013  symbolizers = rule->getSymbolizers();
1014  }
1015  }
1016  }
1017  else
1018  symbolizers = it->second;
1019  }
1020  }
1021  else
1022  {
1023  te::se::Style* style = layer->getStyle();
1024  if(style)
1025  {
1026  if(!style->getRules().empty())
1027  {
1028  te::se::Rule* rule = style->getRule(0);
1029 
1030  symbolizers = rule->getSymbolizers();
1031  }
1032  }
1033  }
1034 
1035  if(hasChartNullValue == false)
1036  {
1037  for(std::size_t i = 0; i < csize; ++i)
1038  chartValue[chart->getProperties()[i]] = te::da::GetSummarizedValue(chartValues[chart->getProperties()[i]], cfunction);
1039  }
1040 
1041  // store the values of the other object (for next loop).
1042  try
1043  {
1044  geomaux = dataset->getGeometry(gpos).release();
1045  }
1046  catch(std::exception& /*e*/)
1047  {
1048  geomaux = 0;
1049  continue;
1050  }
1051 
1052  for(std::size_t i = 0; i < csize; ++i)
1053  chartValues[chart->getProperties()[i]].clear();
1054  values.clear();
1055  svalues.clear();
1056 
1057  if(dataset->isNull(propertyPos) == false)
1058  {
1059  if(type == UNIQUE_VALUE)
1060  {
1061  if(ptype == te::dt::STRING_TYPE)
1062  svalues.push_back(dataset->getAsString(propertyPos, precision));
1063  else
1064  values.push_back(te::da::GetValueAsDouble(dataset.get(), propertyPos));
1065  }
1066  else
1067  values.push_back(te::da::GetValueAsDouble(dataset.get(), propertyPos));
1068  }
1069  else
1070  hasGroupNullValueAux = true;
1071 
1072  for(std::size_t i = 0; i < csize; ++i)
1073  {
1074  if(dataset->isNull(chart->getProperties()[i]))
1075  {
1076  hasChartNullValueAux = true;
1077  break;
1078  }
1079  }
1080  if(hasChartNullValueAux == false)
1081  {
1082  for(std::size_t i = 0; i < csize; ++i)
1083  chartValues[chart->getProperties()[i]].push_back(te::da::GetValueAsDouble(dataset.get(), chart->getPropertiesPos()[i]));
1084  }
1085  }
1086 
1087  // Gets the set of symbolizers defined on group item
1088  std::size_t nSymbolizers = symbolizers.size();
1089 
1090  for(std::size_t j = 0; j < nSymbolizers; ++j) // for each <Symbolizer>
1091  {
1092  // The current symbolizer
1093  te::se::Symbolizer* symb = symbolizers[j];
1094 
1095  // Let's config the canvas based on the current symbolizer
1096  cc.config(symb);
1097 
1098  // If necessary, geometry remap
1099  if(needRemap)
1100  {
1101  geom->setSRID(layer->getSRID());
1102  geom->transform(srid);
1103  }
1104 
1105  canvas->draw(geom);
1106 
1107  if(chart && hasChartNullValue == false && j == nSymbolizers - 1)
1108  buildChart(chart, chartValue, geom);
1109  }
1110 
1111  hasChartNullValue = hasChartNullValueAux;
1112  hasGroupNullValue = hasGroupNullValueAux;
1113  hasChartNullValueAux = false;
1114  hasGroupNullValueAux = false;
1115  } while(dataset->moveNext());
1116 
1117  delete geom;
1118  geom = geomaux;
1119 
1120  std::vector<te::se::Symbolizer*> symbolizers;
1121  if(hasGroupNullValue == false)
1122  {
1123  if(type == UNIQUE_VALUE)
1124  {
1125  if(ptype == te::dt::STRING_TYPE)
1126  {
1127  value = te::da::GetSummarizedValue(values, gfunction);
1128  value = te::da::Round(value, precision);
1129  svalue = boost::lexical_cast<std::string>(value);
1130  }
1131  else
1132  svalue = te::da::GetSummarizedValue(svalues, gfunction);
1133 
1134  std::map<std::string, std::vector<te::se::Symbolizer*> >::const_iterator it = uniqueGroupsMap.find(svalue);
1135  if(it != uniqueGroupsMap.end())
1136  symbolizers = it->second;
1137  }
1138  else
1139  {
1140  value = te::da::GetSummarizedValue(values, gfunction);
1141  value = te::da::Round(value, precision);
1142 
1143  std::map<std::pair<double, double>, std::vector<te::se::Symbolizer*> >::const_iterator it;
1144  for(it = othersGroupsMap.begin(); it != othersGroupsMap.end(); ++it)
1145  {
1146  if(value >= it->first.first && value <= it->first.second)
1147  break;
1148  }
1149 
1150  if(it == othersGroupsMap.end())
1151  {
1152  te::se::Style* style = layer->getStyle();
1153  if(style)
1154  {
1155  if(!style->getRules().empty())
1156  {
1157  te::se::Rule* rule = style->getRule(0);
1158  symbolizers = rule->getSymbolizers();
1159  }
1160  }
1161  }
1162  else
1163  symbolizers = it->second;
1164  }
1165  }
1166 
1167  if(hasChartNullValue == false)
1168  {
1169  for(std::size_t i = 0; i < csize; ++i)
1170  {
1171  chartValue[chart->getProperties()[i]] = te::da::GetSummarizedValue(chartValues[chart->getProperties()[i]], cfunction);
1172  }
1173  }
1174 
1175  // Gets the set of symbolizers defined on group item
1176  std::size_t nSymbolizers = symbolizers.size();
1177 
1178  if(hasGroupNullValue == false)
1179  {
1180 
1181  for(std::size_t j = 0; j < nSymbolizers; ++j) // for each <Symbolizer>
1182  {
1183  // The current symbolizer
1184  te::se::Symbolizer* symb = symbolizers[j];
1185 
1186  // Let's config the canvas based on the current symbolizer
1187  cc.config(symb);
1188 
1189  // If necessary, geometry remap
1190  if(needRemap)
1191  {
1192  geom->setSRID(layer->getSRID());
1193  geom->transform(srid);
1194  }
1195 
1196  canvas->draw(geom);
1197 
1198  if(chart && hasChartNullValue == false && j == nSymbolizers - 1)
1199  buildChart(chart, chartValue, geom);
1200  }
1201  }
1202  if(nSymbolizers == 0 && chart && hasChartNullValue == false)
1203  buildChart(chart, chartValue, geom);
1204 
1205  delete geom;
1206 
1207  // Let's draw the generated charts
1208  for(std::size_t i = 0; i < m_chartCoordinates.size(); ++i)
1209  {
1210  canvas->drawImage(static_cast<int>(m_chartCoordinates[i].x),
1211  static_cast<int>(m_chartCoordinates[i].y),
1212  m_chartImages[i],
1213  chart->getWidth(),
1214  chart->getHeight());
1215 
1216  te::common::Free(m_chartImages[i], chart->getHeight());
1217  }
1218 }
1219 
1220 void te::map::QueryLayerRenderer::drawDatSetGeometries(te::da::DataSet* dataset, const std::size_t& gpos, Canvas* canvas,
1221  int fromSRID, int toSRID,
1222  Chart* chart, te::common::TaskProgress* task)
1223 {
1224  assert(dataset);
1225  assert(canvas);
1226 
1227  std::string s;
1228  size_t pksize = m_oid.size();
1229  std::vector<std::string> pkdata(pksize), pkdataaux(pksize);
1230 
1231  // Verify if is necessary convert the data set geometries to the given srid
1232  bool needRemap = false;
1233  if((fromSRID != TE_UNKNOWN_SRS) && (toSRID != TE_UNKNOWN_SRS) && (fromSRID != toSRID))
1234  needRemap = true;
1235 
1236  // The chart sumarization
1237  std::string cfunction;
1238  std::map<std::string, std::vector<double> > chartValues;
1239  std::map<std::string, double> chartValue;
1240  bool hasChartNullValue = false;
1241  bool hasChartNullValueAux = false;
1242  size_t csize = 0;
1243  if(chart)
1244  {
1245  cfunction = chart->getSummary();
1246  csize = chart->getProperties().size();
1247  std::vector<size_t> propPos;
1248  for(std::size_t i = 0; i < csize; ++i)
1249  {
1250  std::vector<double> v;
1251  chartValues[chart->getProperties()[i]] = v;
1252  propPos.push_back(te::da::GetPropertyPos(dataset, chart->getProperties()[i]));
1253  }
1254  chart->setPropertiesPos(propPos);
1255  }
1256 
1257  te::gm::Geometry *geom = 0, *geomaux = 0;
1258  do
1259  {
1260  try
1261  {
1262  if(geomaux == 0)
1263  geomaux = dataset->getGeometry(gpos).release();
1264  if(geomaux == 0)
1265  continue;
1266  }
1267  catch(std::exception& /*e*/)
1268  {
1269  continue;
1270  }
1271 
1272  if(pksize) // if linked
1273  {
1274  // it is linked. Remove redundancies.
1275  size_t i;
1276  for(i = 0; i < pksize; ++i)
1277  pkdata[i] = dataset->getAsString(m_oid[i]);
1278 
1279  for(i = 0; i < pksize; ++i)
1280  {
1281  if(dataset->isAtBegin())
1282  pkdataaux[i] = dataset->getAsString(m_oid[i]);
1283  else
1284  {
1285  if(pkdata[i] != pkdataaux[i])
1286  {
1287  pkdataaux = pkdata;
1288  break;
1289  }
1290  }
1291  }
1292  if(i == pksize) // it is the same object
1293  {
1294  if(hasChartNullValue == false)
1295  {
1296  // read value chart value
1297  for(std::size_t i = 0; i < csize; ++i)
1298  {
1299  if(dataset->isNull(chart->getProperties()[i]) == false)
1300  chartValues[chart->getProperties()[i]].push_back(te::da::GetValueAsDouble(dataset, chart->getPropertiesPos()[i]));
1301  else
1302  {
1303  hasChartNullValue = true;
1304  break;
1305  }
1306  }
1307  }
1308  // read other values
1309  continue;
1310  }
1311  else // it is other object
1312  {
1313  // sumarize chart value according to the required summarization
1314  if(hasChartNullValue == false)
1315  {
1316  for(std::size_t i = 0; i < csize; ++i)
1317  chartValue[chart->getProperties()[i]] = te::da::GetSummarizedValue(chartValues[chart->getProperties()[i]], cfunction);
1318  }
1319 
1320  // prepare the next loop
1321  for(std::size_t i = 0; i < csize; ++i)
1322  chartValues[chart->getProperties()[i]].clear();
1323 
1324  hasChartNullValueAux = false;
1325  for(std::size_t i = 0; i < csize; ++i)
1326  {
1327  if(dataset->isNull(chart->getProperties()[i]))
1328  {
1329  hasChartNullValueAux = true;
1330  break;
1331  }
1332  }
1333  if(hasChartNullValueAux == false)
1334  {
1335  for(std::size_t i = 0; i < csize; ++i)
1336  chartValues[chart->getProperties()[i]].push_back(te::da::GetValueAsDouble(dataset, chart->getPropertiesPos()[i]));
1337  }
1338  }
1339  }
1340  else // if not linked
1341  {
1342  // read chart value
1343  for(std::size_t i = 0; i < csize; ++i)
1344  {
1345  if(dataset->isNull(chart->getProperties()[i]) == false)
1346  chartValue[chart->getProperties()[i]] = te::da::GetValueAsDouble(dataset, chart->getPropertiesPos()[i]);
1347  else
1348  {
1349  chartValue.clear();
1350  hasChartNullValue = true;
1351  break;
1352  }
1353  }
1354  }
1355 
1356  delete geom;
1357  geom = geomaux;
1358 
1359  // store the values of the other object (for next loop).
1360  try
1361  {
1362  geomaux = dataset->getGeometry(gpos).release();
1363  }
1364  catch(std::exception& /*e*/)
1365  {
1366  geomaux = 0;
1367  continue;
1368  }
1369 
1370  if(task)
1371  {
1372  if(!task->isActive())
1373  return;
1374 
1375  // update the draw task
1376  task->pulse();
1377  }
1378 
1379  // If necessary, geometry remap
1380  if(needRemap)
1381  {
1382  geom->setSRID(fromSRID);
1383  geom->transform(toSRID);
1384  }
1385 
1386  canvas->draw(geom);
1387 
1388  if(chart && hasChartNullValue == false)
1389  buildChart(chart, chartValue, geom);
1390 
1391  hasChartNullValue = hasChartNullValueAux;
1392  hasChartNullValueAux = false;
1393 
1394  } while(dataset->moveNext()); // next geometry!
1395 
1396  delete geom;
1397  geom = geomaux;
1398 
1399  if(needRemap)
1400  {
1401  geom->setSRID(fromSRID);
1402  geom->transform(toSRID);
1403  }
1404 
1405  canvas->draw(geom);
1406  if(chart && hasChartNullValue == false)
1407  {
1408  if(chartValues.empty() == false)
1409  {
1410  for(std::size_t i = 0; i < csize; ++i)
1411  {
1412  chartValue[chart->getProperties()[i]] = te::da::GetSummarizedValue(chartValues[chart->getProperties()[i]], cfunction);
1413  }
1414  }
1415  buildChart(chart, chartValue, geom);
1416  }
1417  delete geom;
1418 
1419  // Let's draw the generated charts
1420  for(std::size_t i = 0; i < m_chartCoordinates.size(); ++i)
1421  {
1422  canvas->drawImage(static_cast<int>(m_chartCoordinates[i].x),
1423  static_cast<int>(m_chartCoordinates[i].y),
1424  m_chartImages[i],
1425  chart->getWidth(),
1426  chart->getHeight());
1427 
1428  te::common::Free(m_chartImages[i], chart->getHeight());
1429  }
1430 }
1431 
1432 void te::map::QueryLayerRenderer::buildChart(const Chart* chart, const std::map<std::string, double>& chartValue, te::gm::Geometry* geom)
1433 {
1434  if(!chart->isVisible())
1435  return;
1436 
1437  // World coordinates
1438  const te::gm::Envelope* e = geom->getMBR();
1439  std::auto_ptr<te::gm::Coord2D> worldCoord(new te::gm::Coord2D(e->getCenter().x, e->getCenter().y));
1440 
1441  // Try finds the geometry centroid
1442  if(geom->getGeomTypeId() == te::gm::PolygonType)
1443  {
1444  te::gm::Polygon* p = dynamic_cast<te::gm::Polygon*>(geom);
1445  worldCoord.reset(p->getCentroidCoord());
1446  }
1447  else if (geom->getGeomTypeId() == te::gm::MultiPolygonType)
1448  {
1449  te::gm::MultiPolygon* mp = dynamic_cast<te::gm::MultiPolygon*>(geom);
1450  worldCoord.reset(mp->getCentroidCoord());
1451  }
1452 
1453  // Device coordinates
1454  double dx = 0.0; double dy = 0.0;
1455  m_transformer.world2Device(worldCoord->x, worldCoord->y, dx, dy);
1456 
1457  double dw = dx + chart->getWidth();
1458  double dh = dy + chart->getHeight();
1459 
1460  // Builds the chart envelope
1461  te::gm::Envelope chartEnvelope(dx, dy, dw, dh);
1462 
1463  if(chart->getAvoidConflicts())
1464  {
1465  // Search on rtree
1466  std::vector<std::size_t> report;
1467  m_rtree.search(chartEnvelope, report);
1468 
1469  if(!report.empty())
1470  return;
1471 
1472  // Here, no intersections considering the current chart envelope
1473  m_rtree.insert(chartEnvelope, ++m_index);
1474  }
1475 
1476  // Stores the chart coordinate
1477  m_chartCoordinates.push_back(te::gm::Coord2D(dx, dy));
1478 
1479  // Builds the chart image
1480  std::size_t width = 0;
1481  te::color::RGBAColor** rgba = ChartRendererManager::getInstance().render(chart, chartValue, width);
1482  m_chartImages.push_back(rgba);
1483 }
1484 
1486 {
1487  if(!chart->isVisible())
1488  return;
1489 
1490  // World coordinates
1491  const te::gm::Envelope* e = geom->getMBR();
1492  std::auto_ptr<te::gm::Coord2D> worldCoord(new te::gm::Coord2D(e->getCenter().x, e->getCenter().y));
1493 
1494  // Try finds the geometry centroid
1495  if (geom->getGeomTypeId() == te::gm::PolygonType)
1496  {
1497  te::gm::Polygon* p = dynamic_cast<te::gm::Polygon*>(geom);
1498  worldCoord.reset(p->getCentroidCoord());
1499  }
1500  else if (geom->getGeomTypeId() == te::gm::MultiPolygonType)
1501  {
1502  te::gm::MultiPolygon* mp = dynamic_cast<te::gm::MultiPolygon*>(geom);
1503  worldCoord.reset(mp->getCentroidCoord());
1504  }
1505 
1506  // Device coordinates
1507  double dx = 0.0; double dy = 0.0;
1508  m_transformer.world2Device(worldCoord->x, worldCoord->y, dx, dy);
1509 
1510  double dw = dx + chart->getWidth();
1511  double dh = dy + chart->getHeight();
1512 
1513  // Builds the chart envelope
1514  te::gm::Envelope chartEnvelope(dx, dy, dw, dh);
1515 
1516  if(chart->getAvoidConflicts())
1517  {
1518  // Search on rtree
1519  std::vector<std::size_t> report;
1520  m_rtree.search(chartEnvelope, report);
1521 
1522  if(!report.empty())
1523  return;
1524 
1525  // Here, no intersections considering the current chart envelope
1526  m_rtree.insert(chartEnvelope, ++m_index);
1527  }
1528 
1529  // Stores the chart coordinate
1530  m_chartCoordinates.push_back(te::gm::Coord2D(dx, dy));
1531 
1532  // Builds the chart image
1533  std::size_t width = 0;
1534  te::color::RGBAColor** rgba = ChartRendererManager::getInstance().render(chart, dataset, width);
1535  m_chartImages.push_back(rgba);
1536 }
1537 
1539 {
1540  m_index = 0;
1541  m_chartCoordinates.clear();
1542  m_chartImages.clear();
1543 }
TEDATAACCESSEXPORT te::rst::RasterProperty * GetFirstRasterProperty(const DataSetType *dt)
Definition: Utils.cpp:571
MultiPolygon is a MultiSurface whose elements are Polygons.
Definition: MultiPolygon.h:50
const std::vector< std::string > & getProperties() const
Definition: Chart.cpp:83
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
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).
std::string getSummary() const
It gets the grouping summary. It is used only in case 1 to n.
Definition: Chart.cpp:197
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
TEDATAACCESSEXPORT bool HasLinkedTable(te::da::DataSetType *type)
It checks if the datasettype has a linked table.
Definition: Utils.cpp:1175
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
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. ...
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
boost::ptr_vector< OrderByItem > OrderBy
A class that can be used to model an ORDER BY clause.
Definition: OrderBy.h:37
te::da::Expression * getExpression(const te::fe::Filter *f)
It converts the OGC Filter Expression to a TerraLib Expression.
virtual void transform(int srid)=0
It converts the coordinate values of the geometry to the new spatial reference system.
A layer resulting from a query.
Definition: QueryLayer.h:50
virtual int getWidth() const =0
It returns the canvas width.
An utility struct for representing 2D coordinates.
Definition: Coord2D.h:40
TEDATAACCESSEXPORT double GetValueAsDouble(const te::da::DataSet *ds, const size_t pos)
It gets the value as double.
Definition: Utils.cpp:1337
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 a query layer.
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.
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
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
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.
double m_llx
Lower left corner x-coordinate.
Definition: Envelope.h:344
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.
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
void buildChart(const Chart *chart, te::da::DataSet *dataset, te::gm::Geometry *geom)
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 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.
virtual bool isNull(std::size_t i) const =0
It checks if the attribute value is NULL.
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
TEDATAACCESSEXPORT double GetSummarizedValue(std::vector< double > &values, const std::string &summary)
It gets the summarized value.
Definition: Utils.cpp:1196
void pulse()
Calls setCurrentStep() function using getCurrentStep() + 1.
virtual std::string getAsString(std::size_t i, int precision=0) const
Method for retrieving a data value as a string plain representation.
Definition: DataSet.cpp:218
virtual void drawImage(char *src, std::size_t size, ImageType t)=0
It draws the src image over the canvas.
te::da::Select * getQuery() const
Definition: QueryLayer.cpp:340
A filter is any valid predicate expression.
Definition: Filter.h:52
Query * clone() const
It creates a new copy of this query.
Definition: Select.cpp:424
This class represents the informations needed to build map charts.
GeomType getGeomTypeId() const
It returns the geometry subclass type identifier.
Definition: Geometry.h:178
void setOrderBy(OrderBy *o)
It sets the list of expressions used to sort the output result.
Definition: Select.cpp:977
Geometry is the root class of the geometries hierarchy, it follows OGC and ISO standards.
Definition: Geometry.h:73
A Select models a query to be used when retrieving data from a DataSource.
Definition: Select.h:65
virtual std::auto_ptr< te::gm::Geometry > getGeometry(std::size_t i) const =0
Method for retrieving a geometric attribute value.
TEDATAACCESSEXPORT double Round(const double &value, const size_t &precision)
It gets the round value.
Definition: Utils.cpp:1329
const std::vector< Symbolizer * > & getSymbolizers() const
Definition: Rule.cpp:158
double m_lly
Lower left corner y-coordinate.
Definition: Envelope.h:345
void setPropertiesPos(const std::vector< size_t > &propPos)
Definition: Chart.cpp:93
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.
const std::vector< size_t > & getPropertiesPos() const
Definition: Chart.cpp:88
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
void setQuery(te::da::Select *s)
Definition: QueryLayer.cpp:345
std::string getSummary() const
It gets the grouping summary. It is used only in case 1 to n.
Definition: Grouping.cpp:152
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 layer resulting from a query.
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.
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.
void config(const te::se::Symbolizer *symbolizer)
It configs the canvas based on given symbolizer.
Envelope intersection(const Envelope &rhs) const
It returns an envelope that represents the point set intersection with another envelope.
Definition: Envelope.h:543
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.
A class that can be used in an ORDER BY clause to sort the items of a resulting query.
Definition: OrderByItem.h:53
virtual bool isAtBegin() const =0
It tells if the dataset internal pointer is on the first element of the collection or not...
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
virtual void setSRID(int srid)=0
It sets the Spatial Reference System ID of the geometry and all its parts if it is a GeometryCollecti...
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.
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...
void drawLayerLinkedGroupingMem(AbstractLayer *layer, const std::string &geomPropertyName, Canvas *canvas, const te::gm::Envelope &bbox, int srid)