All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
BufferDialog.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2011-2012 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/vp/BufferDialog.cpp
22 
23  \brief A dialog for buffer operation
24 */
25 
26 // TerraLib
27 #include "../../common/progress/ProgressManager.h"
28 #include "../../common/Translator.h"
29 #include "../../common/STLUtils.h"
30 #include "../../dataaccess/dataset/DataSetType.h"
31 #include "../../dataaccess/datasource/DataSourceInfo.h"
32 #include "../../dataaccess/datasource/DataSourceInfoManager.h"
33 #include "../../dataaccess/datasource/DataSourceManager.h"
34 #include "../../dataaccess/datasource/DataSourceFactory.h"
35 #include "../../dataaccess/utils/Utils.h"
36 #include "../../datatype/Enums.h"
37 #include "../../datatype/Property.h"
38 #include "../../geometry/Geometry.h"
39 #include "../../geometry/GeometryProperty.h"
40 #include "../../maptools/AbstractLayer.h"
41 #include "../../maptools/DataSetLayer.h"
42 #include "../../memory/DataSet.h"
43 #include "../../memory/DataSetItem.h"
44 #include "../../qt/widgets/datasource/selector/DataSourceSelectorDialog.h"
45 #include "../../qt/widgets/progress/ProgressViewerDialog.h"
46 #include "../../srs/Config.h"
47 #include "../Config.h"
48 #include "../Exception.h"
49 #include "../qt/widgets/layer/utils/DataSet2Layer.h"
50 #include "Buffer.h"
51 #include "BufferDialog.h"
52 #include "ui_BufferDialogForm.h"
53 #include "VectorProcessingConfig.h"
54 #include "Utils.h"
55 
56 // Qt
57 #include <QtCore/QList>
58 #include <QtCore/QSize>
59 #include <QtGui/QFileDialog>
60 #include <QtGui/QListWidget>
61 #include <QtGui/QListWidgetItem>
62 #include <QtGui/QMessageBox>
63 
64 // STL
65 #include <map>
66 
67 // BOOST
68 #include <boost/algorithm/string.hpp>
69 #include <boost/filesystem.hpp>
70 #include <boost/lexical_cast.hpp>
71 #include <boost/uuid/random_generator.hpp>
72 #include <boost/uuid/uuid_io.hpp>
73 
74 te::vp::BufferDialog::BufferDialog(QWidget* parent, Qt::WindowFlags f)
75  : QDialog(parent, f),
76  m_ui(new Ui::BufferDialogForm),
77  m_layers(std::list<te::map::AbstractLayerPtr>()),
78  m_selectedLayer(0)
79 {
80 // add controls
81  m_ui->setupUi(this);
82 
83 // add icons
84  m_ui->m_imgLabel->setPixmap(QIcon::fromTheme(VP_IMAGES"/vp-buffer-hint").pixmap(112,48));
85 
86  QSize iconSize(96, 48);
87 
88  m_ui->m_withoutBoundRadioButton->setIconSize(iconSize);
89  m_ui->m_withoutBoundRadioButton->setIcon(QIcon::fromTheme("buffer-without-boundaries"));
90 
91  m_ui->m_withBoundRadioButton->setIconSize(iconSize);
92  m_ui->m_withBoundRadioButton->setIcon(QIcon::fromTheme("buffer-with-boundaries"));
93 
94  m_ui->m_ruleImgLabel->setPixmap(QIcon::fromTheme("buffer-inside-outside").pixmap(150,60));
95  m_ui->m_targetDatasourceToolButton->setIcon(QIcon::fromTheme("datasource"));
96 
97 //add controls
98  m_ui->m_fixedDistanceLineEdit->setEnabled(true);
99  m_ui->m_fixedDistanceLineEdit->setValidator(new QDoubleValidator(this));
100 
102 
103 //signals
104  connect(m_ui->m_layersComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onLayerComboBoxChanged(int)));
105  connect(m_ui->m_filterLineEdit, SIGNAL(textChanged(const QString&)), this, SLOT(onFilterLineEditTextChanged(const QString&)));
106  connect(m_ui->m_fixedRadioButton, SIGNAL(toggled(bool)), this, SLOT(onFixedDistanceToggled()));
107  connect(m_ui->m_fromAttRadioButton, SIGNAL(toggled(bool)), this, SLOT(onAttDistanceToggled()));
108  connect(m_ui->m_ruleInOutRadioButton, SIGNAL(toggled(bool)), this, SLOT(onRuleInOutToggled()));
109  connect(m_ui->m_ruleOnlyOutRadioButton, SIGNAL(toggled(bool)), this, SLOT(onRuleOutToggled()));
110  connect(m_ui->m_ruleOnlyInRadioButton, SIGNAL(toggled(bool)), this, SLOT(onRuleInToggled()));
111  connect(m_ui->m_withoutBoundRadioButton, SIGNAL(toggled(bool)), this, SLOT(onWithoutBoundToggled()));
112  connect(m_ui->m_withBoundRadioButton, SIGNAL(toggled(bool)), this, SLOT(onWithBoundToggled()));
113 
114  connect(m_ui->m_targetDatasourceToolButton, SIGNAL(pressed()), this, SLOT(onTargetDatasourceToolButtonPressed()));
115  connect(m_ui->m_targetFileToolButton, SIGNAL(pressed()), this, SLOT(onTargetFileToolButtonPressed()));
116 
117  connect(m_ui->m_okPushButton, SIGNAL(clicked()), this, SLOT(onOkPushButtonClicked()));
118  connect(m_ui->m_cancelPushButton, SIGNAL(clicked()), this, SLOT(onCancelPushButtonClicked()));
119 
120  m_ui->m_helpPushButton->setNameSpace("dpi.inpe.br.plugins");
121  m_ui->m_helpPushButton->setPageReference("plugins/vp/vp_buffer.html");
122 }
123 
125 {
126 }
127 
128 void te::vp::BufferDialog::setLayers(std::list<te::map::AbstractLayerPtr> layers)
129 {
130  m_layers = layers;
131 
132  std::list<te::map::AbstractLayerPtr>::iterator it = m_layers.begin();
133 
134  while(it != m_layers.end())
135  {
136  std::auto_ptr<te::da::DataSetType> dsType = it->get()->getSchema();
137  if(dsType->hasGeom())
138  m_ui->m_layersComboBox->addItem(QString(it->get()->getTitle().c_str()), QVariant(it->get()->getId().c_str()));
139  ++it;
140  }
141 }
142 
144 {
145  for(int i=1; i <= 10; ++i)
146  m_ui->m_levelsNumComboBox->addItem(QString::number(i));
147 }
148 
149 void te::vp::BufferDialog::setAttributesForDistance(std::vector<te::dt::Property*> properties)
150 {
151  m_ui->m_fromAttDistanceComboBox->clear();
152 
153  for(std::size_t i = 0; i < properties.size(); ++i)
154  {
155  if(properties[i]->getType() == te::dt::CDOUBLE_TYPE ||
156  properties[i]->getType() == te::dt::CFLOAT_TYPE ||
157  properties[i]->getType() == te::dt::CINT16_TYPE ||
158  properties[i]->getType() == te::dt::CINT32_TYPE ||
159  properties[i]->getType() == te::dt::DOUBLE_TYPE ||
160  properties[i]->getType() == te::dt::INT16_TYPE ||
161  properties[i]->getType() == te::dt::INT32_TYPE ||
162  properties[i]->getType() == te::dt::INT64_TYPE ||
163  properties[i]->getType() == te::dt::FLOAT_TYPE ||
164  properties[i]->getType() == te::dt::NUMERIC_TYPE ||
165  properties[i]->getType() == te::dt::UINT16_TYPE ||
166  properties[i]->getType() == te::dt::UINT32_TYPE ||
167  properties[i]->getType() == te::dt::UINT64_TYPE)
168  m_ui->m_fromAttDistanceComboBox->addItem(properties[i]->getName().c_str());
169  }
170 
171  if(m_ui->m_fromAttDistanceComboBox->count() > 0)
172  {
173  //m_ui->m_fromAttRadioButton->setEnabled(true);
174  }
175  else
176  m_ui->m_fromAttRadioButton->setEnabled(false);
177 }
178 
180 {
181  if(m_ui->m_ruleInOutRadioButton->isChecked())
182  return te::vp::INSIDE_OUTSIDE;
183  else if(m_ui->m_ruleOnlyOutRadioButton->isChecked())
184  return te::vp::ONLY_OUTSIDE;
185  else
186  return te::vp::ONLY_INSIDE;
187 }
188 
190 {
191  if(m_ui->m_withoutBoundRadioButton->isChecked())
192  return te::vp::DISSOLVE;
193  else
194  return te::vp::NOT_DISSOLVE;
195 }
196 
198 {
199  return m_outputLayer;
200 }
201 
203 {
204  std::list<te::map::AbstractLayerPtr>::iterator it = m_layers.begin();
205  std::string layerID = m_ui->m_layersComboBox->itemData(index, Qt::UserRole).toString().toStdString();
206 
207  while(it != m_layers.end())
208  {
209  if(layerID == it->get()->getId().c_str())
210  {
211  te::map::AbstractLayerPtr selectedLayer = it->get();
212  m_selectedLayer = selectedLayer;
213  std::auto_ptr<const te::map::LayerSchema> schema(selectedLayer->getSchema());
214 
215  if(schema->size() == 0)
216  return;
217 
218  te::common::FreeContents(m_properties);
219  m_properties.clear();
220 
221  const std::vector<te::dt::Property*>& properties = schema->getProperties();
222  te::common::Clone(properties, m_properties);
223 
224  setAttributesForDistance(m_properties);
225 
226  te::map::DataSetLayer* dsLayer = dynamic_cast<te::map::DataSetLayer*>(m_selectedLayer.get());
227  te::da::DataSourcePtr inDataSource = te::da::GetDataSource(dsLayer->getDataSourceId(), true);
228  te::da::DataSetType* dsType = te::da::GetDataSetType(dsLayer->getDataSetName(), inDataSource->getId());
229  std::auto_ptr<te::gm::GeometryProperty>geomProp(te::da::GetFirstGeomProperty(dsType));
230 
231  te::gm::GeomType gmType = geomProp->getGeometryType();
232  if(gmType == te::gm::PointType || gmType == te::gm::MultiPointType ||
234  {
235  m_ui->m_ruleInOutRadioButton->setDisabled(true);
236  m_ui->m_ruleOnlyInRadioButton->setDisabled(true);
237  m_ui->m_ruleOnlyOutRadioButton->setChecked(true);
238  }
239  else
240  {
241  m_ui->m_ruleInOutRadioButton->setEnabled(true);
242  m_ui->m_ruleOnlyInRadioButton->setEnabled(true);
243  m_ui->m_ruleInOutRadioButton->setChecked(true);
244  }
245 
246  return;
247  }
248  ++it;
249  }
250 }
251 
253 {
254  std::list<te::map::AbstractLayerPtr> filteredLayers = te::vp::GetFilteredLayers(text.toStdString(), m_layers);
255 
256  m_ui->m_layersComboBox->clear();
257 
258  if(text.isEmpty())
259  filteredLayers = m_layers;
260 
261  std::list<te::map::AbstractLayerPtr>::iterator it = filteredLayers.begin();
262 
263  while(it != filteredLayers.end())
264  {
265  if(it->get()->getSchema()->hasGeom())
266  m_ui->m_layersComboBox->addItem(QString(it->get()->getTitle().c_str()), QVariant(it->get()->getId().c_str()));
267  ++it;
268  }
269 }
270 
272 {
273  m_ui->m_fixedDistanceLineEdit->setEnabled(true);
274  m_ui->m_fromAttDistanceComboBox->setEnabled(false);
275 }
276 
278 {
279  m_ui->m_fromAttDistanceComboBox->setEnabled(true);
280  m_ui->m_fixedDistanceLineEdit->setEnabled(false);
281 }
282 
284 {
285  m_ui->m_ruleImgLabel->setPixmap(QIcon::fromTheme("buffer-inside-outside").pixmap(150,60));
286 }
287 
289 {
290  m_ui->m_ruleImgLabel->setPixmap(QIcon::fromTheme("buffer_only-outside").pixmap(150,60));
291 }
292 
294 {
295  m_ui->m_ruleImgLabel->setPixmap(QIcon::fromTheme("buffer-only-inside").pixmap(150,60));
296 }
297 
299 {
300  m_ui->m_copyColumnsCheckBox->setChecked(false);
301  m_ui->m_copyColumnsCheckBox->setEnabled(false);
302 }
303 
305 {
306  m_ui->m_copyColumnsCheckBox->setEnabled(true);
307 }
308 
310 {
311  m_ui->m_newLayerNameLineEdit->clear();
312  m_ui->m_newLayerNameLineEdit->setEnabled(true);
314  dlg.exec();
315 
316  std::list<te::da::DataSourceInfoPtr> dsPtrList = dlg.getSelecteds();
317 
318  if(dsPtrList.size() <= 0)
319  return;
320 
321  std::list<te::da::DataSourceInfoPtr>::iterator it = dsPtrList.begin();
322 
323  m_ui->m_repositoryLineEdit->setText(QString(it->get()->getTitle().c_str()));
324 
325  m_outputDatasource = *it;
326 
327  m_toFile = false;
328 }
329 
331 {
332  m_ui->m_newLayerNameLineEdit->clear();
333  m_ui->m_repositoryLineEdit->clear();
334 
335  QString fileName = QFileDialog::getSaveFileName(this, tr("Save as..."),
336  QString(), tr("Shapefile (*.shp *.SHP);;"),0, QFileDialog::DontConfirmOverwrite);
337 
338  if(fileName.isEmpty())
339  return;
340 
341  boost::filesystem::path outfile(fileName.toStdString());
342  std::string aux = outfile.leaf().string();
343  m_ui->m_newLayerNameLineEdit->setText(aux.c_str());
344  aux = outfile.string();
345  m_ui->m_repositoryLineEdit->setText(aux.c_str());
346 
347  m_toFile = true;
348  m_ui->m_newLayerNameLineEdit->setEnabled(false);
349 }
350 
352 {
353  QMessageBox::information(this, "Help", "Under development");
354 }
355 
357 {
358  if(m_ui->m_layersComboBox->currentText().isEmpty())
359  {
360  QMessageBox::information(this, "Buffer", "Select an input layer.");
361  return;
362  }
363 
364  // Checking consistency of the input layer where the buffer will executed
365  te::map::DataSetLayer* dsLayer = dynamic_cast<te::map::DataSetLayer*>(m_selectedLayer.get());
366  if(!dsLayer)
367  {
368  QMessageBox::information(this, "Buffer", "Can not execute this operation on this type of layer.");
369  return;
370  }
371 
372  te::da::DataSourcePtr inDataSource = te::da::GetDataSource(dsLayer->getDataSourceId(), true);
373  if (!inDataSource.get())
374  {
375  QMessageBox::information(this, "Buffer", "The selected input data source can not be accessed.");
376  return;
377  }
378 
379  // Check consistency of buffer parameters
380  double fixedDistance;
381  std::string propDistance = "";
382  if(m_ui->m_fixedRadioButton->isChecked())
383  {
384  fixedDistance = m_ui->m_fixedDistanceLineEdit->text().toDouble();
385  if (fixedDistance <= 0)
386  {
387  QMessageBox::information(this, "Buffer", "Fixed distance value should be greater than 0.");
388  return;
389  }
390  }
391  else
392  {
393  fixedDistance = 0;
394  int i = m_ui->m_fromAttDistanceComboBox->currentIndex();
395  propDistance = m_ui->m_fromAttDistanceComboBox->itemText(i).toStdString();
396  }
397 
398  // Checking consistency of output paramenters
399  if(m_ui->m_repositoryLineEdit->text().isEmpty())
400  {
401  QMessageBox::information(this, "Buffer", "Select a repository for the resulting layer.");
402 
403  return;
404  }
405 
406  if(m_ui->m_newLayerNameLineEdit->text().isEmpty())
407  {
408  QMessageBox::information(this, "Buffer", "Define a name for the resulting layer.");
409  return;
410  }
411 
412  int bufferPolygonRule = getPolygonRule();
413  int bufferBoundariesRule = getBoundariesRule();
414  bool copyInputColumns = m_ui->m_copyColumnsCheckBox->isChecked();
415  int levels = m_ui->m_levelsNumComboBox->currentText().toInt();
416  std::string outputdataset = m_ui->m_newLayerNameLineEdit->text().toStdString();
417 
418  //progress
420  int id = te::common::ProgressManager::getInstance().addViewer(&v);
421 
422  try
423  {
424  bool res;
425 
426  if(m_toFile)
427  {
428  boost::filesystem::path uri(m_ui->m_repositoryLineEdit->text().toStdString());
429 
430  if(boost::filesystem::exists(uri))
431  {
432  QMessageBox::information(this, "Buffer", "Output file already exists. Remove it or select a new name and try again.");
433  return;
434  }
435 
436  std::size_t idx = outputdataset.find(".");
437  if(idx != std::string::npos)
438  outputdataset = outputdataset.substr(0,idx);
439 
440  std::map<std::string, std::string> dsinfo;
441  dsinfo["URI"] = uri.string();
442 
443  std::auto_ptr<te::da::DataSource> dsOGR = te::da::DataSourceFactory::make("OGR");
444  dsOGR->setConnectionInfo(dsinfo);
445  dsOGR->open();
446 
447  if(dsOGR->dataSetExists(outputdataset))
448  {
449  QMessageBox::information(this, "Buffer", "There is already a dataset with the requested name in the output data source. Remove it or select a new name and try again.");
450  return;
451  }
452 
453  this->setCursor(Qt::WaitCursor);
454  res = te::vp::Buffer( dsLayer->getDataSetName(),
455  inDataSource.get(),
456  bufferPolygonRule,
457  bufferBoundariesRule,
458  copyInputColumns,
459  levels,
460  outputdataset,
461  dsOGR.get(),
462  fixedDistance,
463  propDistance);
464 
465  if(!res)
466  {
467  dsOGR->close();
468  QMessageBox::information(this, "Buffer", "Error: could not generate the buffer.");
469  }
470  dsOGR->close();
471 
472  // let's include the new datasource in the managers
473  boost::uuids::basic_random_generator<boost::mt19937> gen;
474  boost::uuids::uuid u = gen();
475  std::string id = boost::uuids::to_string(u);
476 
478  ds->setConnInfo(dsinfo);
479  ds->setTitle(uri.stem().string());
480  ds->setAccessDriver("OGR");
481  ds->setType("OGR");
482  ds->setDescription(uri.string());
483  ds->setId(id);
484 
485  te::da::DataSourcePtr newds = te::da::DataSourceManager::getInstance().get(id, "OGR", ds->getConnInfo());
486  newds->open();
488  m_outputDatasource = ds;
489  }
490  else
491  {
492  te::da::DataSourcePtr aux = te::da::GetDataSource(m_outputDatasource->getId());
493  if (!aux)
494  {
495  QMessageBox::information(this, "Buffer", "The selected output datasource can not be accessed.");
496  return;
497  }
498  if (aux->dataSetExists(outputdataset))
499  {
500  QMessageBox::information(this, "Buffer", "Dataset already exists. Remove it or select a new name and try again. ");
501  return;
502  }
503  this->setCursor(Qt::WaitCursor);
504  res = te::vp::Buffer( dsLayer->getDataSetName(),
505  inDataSource.get(),
506  bufferPolygonRule,
507  bufferBoundariesRule,
508  copyInputColumns,
509  levels,
510  outputdataset,
511  aux.get(),
512  fixedDistance,
513  propDistance);
514  if(!res)
515  {
516  this->setCursor(Qt::ArrowCursor);
517  QMessageBox::information(this, "Buffer", "Error: could not generate the buffer.");
518  reject();
519  }
520  }
521 
522  // creating a layer for the result
523  te::da::DataSourcePtr outDataSource = te::da::GetDataSource(m_outputDatasource->getId());
524 
525  te::qt::widgets::DataSet2Layer converter(m_outputDatasource->getId());
526 
527  te::da::DataSetTypePtr dt(outDataSource->getDataSetType(outputdataset).release());
528  m_outputLayer = converter(dt);
529  }
530  catch(const std::exception& e)
531  {
532  this->setCursor(Qt::ArrowCursor);
533  QMessageBox::information(this, "Buffer", e.what());
534  te::common::ProgressManager::getInstance().removeViewer(id);
535  return;
536  }
537 
538  te::common::ProgressManager::getInstance().removeViewer(id);
539  this->setCursor(Qt::ArrowCursor);
540  accept();
541 }
542 
544 {
545  reject();
546 }
A layer with reference to a dataset.
Definition: DataSetLayer.h:47
const std::string & getDataSetName() const
A dialog for selecting a data source.
void onFilterLineEditTextChanged(const QString &text)
TEDATAACCESSEXPORT DataSourcePtr GetDataSource(const std::string &datasourceId, const bool opened=true)
Search for a data source with the informed id in the DataSourceManager.
Definition: Utils.cpp:258
TEDATAACCESSEXPORT te::gm::GeometryProperty * GetFirstGeomProperty(const DataSetType *dt)
Definition: Utils.cpp:504
void FreeContents(boost::unordered_map< K, V * > &m)
This function can be applied to a map of pointers. It will delete each pointer in the map...
Definition: BoostUtils.h:55
void setAttributesForDistance(std::vector< te::dt::Property * > properties)
std::list< te::map::AbstractLayerPtr > GetFilteredLayers(std::string text, std::list< te::map::AbstractLayerPtr > layers)
Get a list of AbstractLayer filtered by the name;.
Definition: Utils.cpp:46
A class that represents a data source component.
void Clone(const std::vector< T * > &src, std::vector< T * > &dst)
This function can be applied to a vector of pointers.
Definition: STLUtils.h:237
const std::list< te::da::DataSourceInfoPtr > & getSelecteds() const
static std::auto_ptr< DataSource > make(const std::string &dsType)
const std::string & getDataSourceId() const
BufferDialog(QWidget *parent=0, Qt::WindowFlags f=0)
std::auto_ptr< Ui::BufferDialogForm > m_ui
Definition: BufferDialog.h:118
The boundaries between buffers will be dissolved.
Definition: Enums.h:91
Utility functions for the data access module.
The buffer is generated only outside of the polygons.
Definition: Enums.h:80
void onTargetDatasourceToolButtonPressed()
te::map::AbstractLayerPtr getLayer()
GeomType
Each enumerated type is compatible with a Well-known Binary (WKB) type code.
Definition: Enums.h:41
The buffer is generated Inside and outside of the polygons.
Definition: Enums.h:79
boost::shared_ptr< DataSource > DataSourcePtr
Definition: DataSource.h:1395
TEDATAACCESSEXPORT DataSetType * GetDataSetType(const std::string &name, const std::string &datasourceId)
Definition: Utils.cpp:224
A class that models the description of a dataset.
Definition: DataSetType.h:72
void onLayerComboBoxChanged(int index)
boost::shared_ptr< DataSetType > DataSetTypePtr
Definition: DataSetType.h:653
The boundaries between buffers will not be dissolved.
Definition: Enums.h:92
The buffer is generated only inside of the polygons.
Definition: Enums.h:81
boost::intrusive_ptr< AbstractLayer > AbstractLayerPtr
void setLayers(std::list< te::map::AbstractLayerPtr > layers)
Set the layer that can be used.
Buffer Vector Processing functions.
static T & getInstance()
It returns a reference to the singleton instance.
Definition: Singleton.h:120
boost::shared_ptr< DataSourceInfo > DataSourceInfoPtr
A dialog buffer operation.
void onTargetFileToolButtonPressed()
TEVPEXPORT bool Buffer(const std::string &inDataset, te::da::DataSource *inDatasource, const int &bufferPolygonRule, const int &bufferBoundariesRule, const bool &copyInputColumns, const int &levels, const std::string &outDataset, te::da::DataSource *outDatasource, const double &fixedDistance=0, const std::string &fromAttDistance="")
Executes the Buffer Geographical Operation and persists the result as a dataset in a given output dat...
Definition: Buffer.cpp:134