OTB  9.0.0
Orfeo Toolbox
otbOGRDataToSamplePositionFilter.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2022 Centre National d'Etudes Spatiales (CNES)
3  *
4  * This file is part of Orfeo Toolbox
5  *
6  * https://www.orfeo-toolbox.org/
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 
21 #ifndef otbOGRDataToSamplePositionFilter_hxx
22 #define otbOGRDataToSamplePositionFilter_hxx
23 
25 
26 namespace otb
27 {
28 // --------- otb::PersistentOGRDataToSamplePositionFilter ---------------------
29 
30 template <class TInputImage, class TMaskImage, class TSampler>
32 {
33  this->SetNumberOfRequiredOutputs(2);
34  m_OriginFieldName = std::string("originfid");
35  m_UseOriginField = true;
36 }
37 
38 template <class TInputImage, class TMaskImage, class TSampler>
40 {
41  // Reset samplers
42  for (unsigned int i = 0; i < m_Samplers.size(); ++i)
43  {
44  for (typename SamplerMapType::iterator iter = m_Samplers[i].begin(); iter != m_Samplers[i].end(); ++iter)
45  {
46  iter->second->Reset();
47  }
48  }
49 
50  // Add an extra field for the original FID
51  this->ClearAdditionalFields();
52  m_UseOriginField = (this->GetOriginFieldName().size() > 0);
53  if (m_UseOriginField)
54  {
55  this->CreateAdditionalField(this->GetOriginFieldName(), OFTInteger, 12);
56  }
57 
58  // compute label mapping
59  this->ComputeClassPartition();
60 
61  // Prepare outputs
62  ogr::DataSource* inputDS = const_cast<ogr::DataSource*>(this->GetOGRData());
63  for (unsigned int k = 0; k < this->GetNumberOfLevels(); k++)
64  {
65  otb::ogr::DataSource* output = this->GetOutputPositionContainer(k);
66  if (output)
67  {
68  this->InitializeOutputDataSource(inputDS, output);
69  }
70  }
71 }
72 
73 template <class TInputImage, class TMaskImage, class TSampler>
76 {
77  if (m_Samplers.size() < (level + 1))
78  {
79  itkExceptionMacro("The sampler level " << level << " doesn't exist !");
80  }
81  return m_Samplers[level];
82 }
83 
84 template <class TInputImage, class TMaskImage, class TSampler>
86  otb::ogr::DataSource* data, const SamplingRateCalculator::MapRateType& map, unsigned int level)
87 {
88  // set the output dataset
89  this->SetNthOutput(1 + level, data);
90  // instantiate the corresponding samplers
91  if (m_Samplers.size() < (level + 1))
92  {
93  m_Samplers.resize(level + 1);
94  }
95  m_Samplers[level].clear();
96  for (SamplingRateCalculator::MapRateType::const_iterator it = map.begin(); it != map.end(); ++it)
97  {
98  SamplerPointerType sampler = SamplerType::New();
99  sampler->SetNumberOfElements(it->second.Required, it->second.Tot);
100  m_Samplers[level][it->first] = sampler;
101  }
102 }
103 
104 template <class TInputImage, class TMaskImage, class TSampler>
106 {
107  if (this->GetNumberOfOutputs() < (level + 2))
108  {
109  return 0;
110  }
111  return static_cast<otb::ogr::DataSource*>(this->itk::ProcessObject::GetOutput(level + 1));
112 }
113 
114 template <class TInputImage, class TMaskImage, class TSampler>
116 {
117  return (this->GetNumberOfOutputs() - 1);
118 }
119 
120 template <class TInputImage, class TMaskImage, class TSampler>
122 {
123  // remove output position containers
124  for (unsigned int i = (this->GetNumberOfOutputs() - 1); i > 0; --i)
125  {
126  this->itk::ProcessObject::RemoveOutput(i);
127  }
128  // remove samplers
129  m_Samplers.clear();
130 }
131 
132 template <class TInputImage, class TMaskImage, class TSampler>
134 {
135  if (idx == 0)
136  {
137  // the output image
138  return static_cast<itk::DataObject*>(TInputImage::New().GetPointer());
139  }
140  else if (idx > 0)
141  {
142  // sample position containers
143  return static_cast<itk::DataObject*>(otb::ogr::DataSource::New().GetPointer());
144  }
145  // might as well make an image
146  return static_cast<itk::DataObject*>(TInputImage::New().GetPointer());
147 }
148 
149 template <class TInputImage, class TMaskImage, class TSampler>
151  typename TInputImage::PointType& imgPoint,
152  itk::ThreadIdType& threadid)
153 {
154  std::string className(feature.ogr().GetFieldAsString(this->GetFieldIndex()));
155  for (unsigned int i = 0; i < this->GetNumberOfLevels(); ++i)
156  {
157  if (m_Samplers[i][className]->TakeSample())
158  {
159  OGRPoint ogrTmpPoint;
160  ogrTmpPoint.setX(imgPoint[0]);
161  ogrTmpPoint.setY(imgPoint[1]);
162 
163  ogr::Layer outputLayer = this->GetInMemoryOutput(threadid, i);
164  ogr::Feature feat(outputLayer.GetLayerDefn());
165  feat.SetFrom(feature);
166  if (m_UseOriginField)
167  {
168  feat[this->GetOriginFieldName()].SetValue(static_cast<int>(feature.GetFID()));
169  }
170  feat.SetGeometry(&ogrTmpPoint);
171  outputLayer.CreateFeature(feat);
172  break;
173  }
174  }
175 }
176 
177 template <class TInputImage, class TMaskImage, class TSampler>
179 {
180  TInputImage* outputImage = this->GetOutput();
181  ogr::DataSource* vectors = const_cast<ogr::DataSource*>(this->GetOGRData());
182  ogr::Layer inLayer = vectors->GetLayer(this->GetLayerIndex());
183 
184  const RegionType& requestedRegion = outputImage->GetRequestedRegion();
185  itk::ContinuousIndex<double> startIndex(requestedRegion.GetIndex());
186  itk::ContinuousIndex<double> endIndex(requestedRegion.GetUpperIndex());
187  startIndex[0] += -0.5;
188  startIndex[1] += -0.5;
189  endIndex[0] += 0.5;
190  endIndex[1] += 0.5;
191  itk::Point<double, 2> startPoint;
192  itk::Point<double, 2> endPoint;
193  outputImage->TransformContinuousIndexToPhysicalPoint(startIndex, startPoint);
194  outputImage->TransformContinuousIndexToPhysicalPoint(endIndex, endPoint);
195 
196  // create geometric extent
197  OGRPolygon tmpPolygon;
198  OGRLinearRing ring;
199  ring.addPoint(startPoint[0], startPoint[1], 0.0);
200  ring.addPoint(startPoint[0], endPoint[1], 0.0);
201  ring.addPoint(endPoint[0], endPoint[1], 0.0);
202  ring.addPoint(endPoint[0], startPoint[1], 0.0);
203  ring.addPoint(startPoint[0], startPoint[1], 0.0);
204  tmpPolygon.addRing(&ring);
205 
206  inLayer.SetSpatialFilter(&tmpPolygon);
207 
208  unsigned int numberOfThreads = this->GetNumberOfThreads();
209  std::vector<ogr::Layer> tmpLayers;
210  for (unsigned int i = 0; i < numberOfThreads; i++)
211  {
212  tmpLayers.push_back(this->GetInMemoryInput(i));
213  }
214 
215  OGRFeatureDefn& layerDefn = inLayer.GetLayerDefn();
216  ogr::Layer::const_iterator featIt = inLayer.begin();
217  std::string className;
218  for (; featIt != inLayer.end(); ++featIt)
219  {
220  ogr::Feature dstFeature(layerDefn);
221  dstFeature.SetFrom(*featIt, TRUE);
222  dstFeature.SetFID(featIt->GetFID());
223  className = featIt->ogr().GetFieldAsString(this->GetFieldIndex());
224  tmpLayers[m_ClassPartition[className]].CreateFeature(dstFeature);
225  }
226 
227  inLayer.SetSpatialFilter(nullptr);
228 }
229 
230 template <class TInputImage, class TMaskImage, class TSampler>
232 {
233  m_ClassPartition.clear();
234  typedef std::map<std::string, unsigned long> ClassCountMapType;
235  ClassCountMapType classCounts;
236  for (typename SamplerMapType::const_iterator it = m_Samplers[0].begin(); it != m_Samplers[0].end(); ++it)
237  {
238  classCounts[it->first] = it->second->GetTotalElements();
239  }
240 
241  int numberOfThreads = this->GetNumberOfThreads();
242  typedef std::vector<unsigned long> LoadVectorType;
243  LoadVectorType currentLoad;
244  currentLoad.resize(numberOfThreads, 0UL);
245 
246  ClassCountMapType::iterator largestClass;
247  unsigned long minLoad;
248  unsigned int destThread;
249  while (classCounts.size())
250  {
251  // find class with highest number of total elements
252  largestClass = classCounts.begin();
253  for (ClassCountMapType::iterator iter = classCounts.begin(); iter != classCounts.end(); ++iter)
254  {
255  if (iter->second > largestClass->second)
256  {
257  largestClass = iter;
258  }
259  }
260 
261  // affect this class to the thread with lowest load
262  minLoad = currentLoad[0];
263  destThread = 0;
264  for (unsigned int k = 0; k < currentLoad.size(); ++k)
265  {
266  if (currentLoad[k] < minLoad)
267  {
268  minLoad = currentLoad[k];
269  destThread = k;
270  }
271  }
272  m_ClassPartition[largestClass->first] = destThread;
273  currentLoad[destThread] += largestClass->second;
274 
275  // remove class from classCounts
276  classCounts.erase(largestClass);
277  }
278 }
279 
280 template <class TInputImage, class TMaskImage, class TSampler>
282 {
283  ogr::Layer outLayer = outDS->GetLayersCount() == 1 ? outDS->GetLayer(0) : outDS->GetLayer(this->GetOutLayerName());
284 
285  OGRErr err = outLayer.ogr().StartTransaction();
286  if (err != OGRERR_NONE)
287  {
288  itkExceptionMacro(<< "Unable to start transaction for OGR layer " << outLayer.ogr().GetName() << ".");
289  }
290 
291  // output vectors sorted by class
292  for (auto& label : m_ClassPartition)
293  {
294  ogr::Layer inLayer = this->GetInMemoryOutput(label.second, outIdx);
295  if (!inLayer)
296  {
297  continue;
298  }
299 
300  // This test only uses 1 input, not compatible with multiple OGRData inputs
301  for (auto tmpIt = inLayer.begin(); tmpIt != inLayer.end(); ++tmpIt)
302  {
303  if (label.first.compare(tmpIt->ogr().GetFieldAsString(this->GetFieldIndex())) != 0)
304  continue;
305  if (update)
306  {
307  outLayer.SetFeature(*tmpIt);
308  }
309  else
310  {
311  ogr::Feature dstFeature(outLayer.GetLayerDefn());
312  dstFeature.SetFrom(*tmpIt, TRUE);
313  outLayer.CreateFeature(dstFeature);
314  }
315  }
316  }
317 
318  err = outLayer.ogr().CommitTransaction();
319  if (err != OGRERR_NONE)
320  {
321  itkExceptionMacro(<< "Unable to commit transaction for OGR layer " << outLayer.ogr().GetName() << ".");
322  }
323 }
324 
325 // -------------- otb::OGRDataToSamplePositionFilter --------------------------
326 
327 template <class TInputImage, class TMaskImage, class TSampler>
329 {
330  this->GetFilter()->SetInput(image);
331 }
332 
333 template <class TInputImage, class TMaskImage, class TSampler>
335 {
336  return this->GetFilter()->GetInput();
337 }
338 
339 template <class TInputImage, class TMaskImage, class TSampler>
341 {
342  this->GetFilter()->SetOGRData(data);
343 }
344 
345 template <class TInputImage, class TMaskImage, class TSampler>
347 {
348  return this->GetFilter()->GetOGRData();
349 }
350 
351 template <class TInputImage, class TMaskImage, class TSampler>
353 {
354  this->GetFilter()->SetMask(mask);
355 }
356 
357 template <class TInputImage, class TMaskImage, class TSampler>
359 {
360  return this->GetFilter()->GetMask();
361 }
362 
363 template <class TInputImage, class TMaskImage, class TSampler>
365 {
366  this->GetFilter()->SetFieldName(key);
367 }
368 
369 template <class TInputImage, class TMaskImage, class TSampler>
371 {
372  return this->GetFilter()->GetFieldName();
373 }
374 
375 template <class TInputImage, class TMaskImage, class TSampler>
377 {
378  this->GetFilter()->SetLayerIndex(index);
379 }
380 
381 template <class TInputImage, class TMaskImage, class TSampler>
383 {
384  return this->GetFilter()->GetLayerIndex();
385 }
386 
387 template <class TInputImage, class TMaskImage, class TSampler>
389 {
390  SamplerMapType& samplers = this->GetSamplers(level);
391  for (typename SamplerMapType::iterator it = samplers.begin(); it != samplers.end(); ++it)
392  {
393  it->second->SetParameters(param);
394  }
395 }
396 
397 template <class TInputImage, class TMaskImage, class TSampler>
400 {
401  return this->GetFilter()->GetSamplers(level);
402 }
403 
404 template <class TInputImage, class TMaskImage, class TSampler>
407  unsigned int level)
408 {
409  this->GetFilter()->SetOutputPositionContainerAndRates(data, map, level);
410 }
411 
412 template <class TInputImage, class TMaskImage, class TSampler>
414 {
415  return this->GetFilter()->GetOutputPositionContainer(level);
416 }
417 
418 template <class TInputImage, class TMaskImage, class TSampler>
420 {
421  this->GetFilter()->SetOriginFieldName(key);
422 }
423 
424 template <class TInputImage, class TMaskImage, class TSampler>
426 {
427  return this->GetFilter()->GetOriginFieldName();
428 }
429 
430 } // end of namespace otb
431 
432 #endif
otb::ogr::Layer::SetFeature
void SetFeature(Feature feature)
otbOGRDataToSamplePositionFilter.h
otb::OGRDataToSamplePositionFilter::GetInput
const TInputImage * GetInput()
Definition: otbOGRDataToSamplePositionFilter.hxx:334
otb::OGRDataToSamplePositionFilter::GetLayerIndex
int GetLayerIndex()
Definition: otbOGRDataToSamplePositionFilter.hxx:382
otb::PersistentOGRDataToSamplePositionFilter::DispatchInputVectors
void DispatchInputVectors(void) override
Definition: otbOGRDataToSamplePositionFilter.hxx:178
otb::PersistentOGRDataToSamplePositionFilter::MakeOutput
itk::DataObject::Pointer MakeOutput(DataObjectPointerArraySizeType idx) override
Definition: otbOGRDataToSamplePositionFilter.hxx:133
otb::PersistentOGRDataToSamplePositionFilter::ProcessSample
void ProcessSample(const ogr::Feature &feature, typename TInputImage::IndexType &imgIndex, typename TInputImage::PointType &imgPoint, itk::ThreadIdType &threadid) override
Definition: otbOGRDataToSamplePositionFilter.hxx:150
otb::PersistentOGRDataToSamplePositionFilter::GetNumberOfLevels
unsigned int GetNumberOfLevels()
Definition: otbOGRDataToSamplePositionFilter.hxx:115
otb::OGRDataToSamplePositionFilter::SetLayerIndex
void SetLayerIndex(int index)
Definition: otbOGRDataToSamplePositionFilter.hxx:376
otb::PersistentOGRDataToSamplePositionFilter::GetOutputPositionContainer
const otb::ogr::DataSource * GetOutputPositionContainer(unsigned int level) const
otb::OGRDataToSamplePositionFilter::SetOGRData
void SetOGRData(const otb::ogr::DataSource *data)
Definition: otbOGRDataToSamplePositionFilter.hxx:340
otb::PersistentOGRDataToSamplePositionFilter::SamplerPointerType
SamplerType::Pointer SamplerPointerType
Definition: otbOGRDataToSamplePositionFilter.h:75
otb::OGRDataToSamplePositionFilter::SetOriginFieldName
void SetOriginFieldName(std::string key)
Definition: otbOGRDataToSamplePositionFilter.hxx:419
otb::ogr::Feature::SetFrom
void SetFrom(Feature const &rhs, int *map, bool mustForgive=true)
Definition: otbOGRFeatureWrapper.hxx:51
otb::PersistentOGRDataToSamplePositionFilter::GetSamplers
SamplerMapType & GetSamplers(unsigned int level)
Definition: otbOGRDataToSamplePositionFilter.hxx:75
otb
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.
Definition: otbJoinContainer.h:32
otb::ogr::DataSource
Collection of geometric objects.
Definition: otbOGRDataSourceWrapper.h:83
otb::ogr::Layer::CreateFeature
void CreateFeature(Feature feature)
otb::OGRDataToSamplePositionFilter::SetInput
virtual void SetInput(const TInputImage *image)
Definition: otbOGRDataToSamplePositionFilter.hxx:328
otb::OGRDataToSamplePositionFilter::GetSamplers
SamplerMapType & GetSamplers(unsigned int level=0)
Definition: otbOGRDataToSamplePositionFilter.hxx:399
otb::ogr::Layer::begin
const_iterator begin() const
Definition: otbOGRLayerWrapper.h:412
otb::ogr::Layer::end
const_iterator end() const
Definition: otbOGRLayerWrapper.h:418
otb::ogr::DataSource::GetLayersCount
int GetLayersCount() const
otb::OGRDataToSamplePositionFilter::SetMask
void SetMask(const TMaskImage *mask)
Definition: otbOGRDataToSamplePositionFilter.hxx:352
otb::PersistentOGRDataToSamplePositionFilter::ClearOutputs
void ClearOutputs()
Definition: otbOGRDataToSamplePositionFilter.hxx:121
otb::ogr::Feature::GetFID
long GetFID() const
Definition: otbOGRFeatureWrapper.hxx:103
otb::PersistentOGRDataToSamplePositionFilter::DataObjectPointerArraySizeType
itk::DataObject::DataObjectPointerArraySizeType DataObjectPointerArraySizeType
Definition: otbOGRDataToSamplePositionFilter.h:81
otb::PersistentOGRDataToSamplePositionFilter::RegionType
InputImageType::RegionType RegionType
Definition: otbOGRDataToSamplePositionFilter.h:65
otb::ogr::Layer::ogr
OGRLayer & ogr()
otb::ogr::Layer::feature_iter
Implementation class for Feature iterator. This iterator is a single pass iterator....
Definition: otbOGRLayerWrapper.h:348
otb::SamplingRateCalculator::MapRateType
std::map< std::string, TripletType > MapRateType
Definition: otbSamplingRateCalculator.h:60
otb::OGRDataToSamplePositionFilter::GetMask
const TMaskImage * GetMask()
Definition: otbOGRDataToSamplePositionFilter.hxx:358
otb::OGRDataToSamplePositionFilter::SamplerParameterType
SamplerType::ParameterType SamplerParameterType
Definition: otbOGRDataToSamplePositionFilter.h:194
otb::ogr::DataSource::GetLayer
Layer GetLayer(vcl_size_t i)
Definition: otbOGRDataSourceWrapper.hxx:51
otb::PersistentOGRDataToSamplePositionFilter::PersistentOGRDataToSamplePositionFilter
PersistentOGRDataToSamplePositionFilter()
Definition: otbOGRDataToSamplePositionFilter.hxx:31
otb::OGRDataToSamplePositionFilter::GetOriginFieldName
std::string GetOriginFieldName()
Definition: otbOGRDataToSamplePositionFilter.hxx:425
otb::OGRDataToSamplePositionFilter::SetSamplerParameters
void SetSamplerParameters(SamplerParameterType param, unsigned int level=0)
Definition: otbOGRDataToSamplePositionFilter.hxx:388
otb::OGRDataToSamplePositionFilter::GetFieldName
std::string GetFieldName()
Definition: otbOGRDataToSamplePositionFilter.hxx:370
otb::ogr::Layer::SetSpatialFilter
void SetSpatialFilter(OGRGeometry const *spatialFilter)
otb::OGRDataToSamplePositionFilter::SetOutputPositionContainerAndRates
void SetOutputPositionContainerAndRates(otb::ogr::DataSource *data, const SamplingRateCalculator::MapRateType &map, unsigned int level=0)
Definition: otbOGRDataToSamplePositionFilter.hxx:405
otb::ogr::Feature::SetFID
void SetFID(long fid)
Definition: otbOGRFeatureWrapper.hxx:109
otb::PersistentOGRDataToSamplePositionFilter::ComputeClassPartition
void ComputeClassPartition(void)
Definition: otbOGRDataToSamplePositionFilter.hxx:231
otb::ogr::Feature
Geometric object with descriptive fields.
Definition: otbOGRFeatureWrapper.h:63
otb::OGRDataToSamplePositionFilter::SetFieldName
void SetFieldName(std::string key)
Definition: otbOGRDataToSamplePositionFilter.hxx:364
otb::PersistentOGRDataToSamplePositionFilter::Reset
void Reset(void) override
Definition: otbOGRDataToSamplePositionFilter.hxx:39
otb::OGRDataToSamplePositionFilter::SamplerMapType
std::map< std::string, SamplerPointerType > SamplerMapType
Definition: otbOGRDataToSamplePositionFilter.h:195
otb::PersistentOGRDataToSamplePositionFilter::SamplerMapType
std::map< std::string, SamplerPointerType > SamplerMapType
Definition: otbOGRDataToSamplePositionFilter.h:77
otb::PersistentOGRDataToSamplePositionFilter::FillOneOutput
void FillOneOutput(unsigned int outIdx, ogr::DataSource *outDS, bool update) override
Definition: otbOGRDataToSamplePositionFilter.hxx:281
otb::ogr::Layer
Layer of geometric objects.
Definition: otbOGRLayerWrapper.h:80
otb::ogr::Feature::SetGeometry
void SetGeometry(OGRGeometry const *geometry)
Definition: otbOGRFeatureWrapper.hxx:143
otb::PersistentOGRDataToSamplePositionFilter::SetOutputPositionContainerAndRates
void SetOutputPositionContainerAndRates(otb::ogr::DataSource *data, const SamplingRateCalculator::MapRateType &map, unsigned int level)
Definition: otbOGRDataToSamplePositionFilter.hxx:85
otb::ogr::Feature::ogr
OGRFeature & ogr() const
Definition: otbOGRFeatureWrapper.hxx:158
otb::OGRDataToSamplePositionFilter::GetOutputPositionContainer
otb::ogr::DataSource * GetOutputPositionContainer(unsigned int level=0)
Definition: otbOGRDataToSamplePositionFilter.hxx:413
otb::ogr::DataSource::New
static Pointer New()
otb::OGRDataToSamplePositionFilter::GetOGRData
const otb::ogr::DataSource * GetOGRData()
Definition: otbOGRDataToSamplePositionFilter.hxx:346
otb::ogr::Layer::GetLayerDefn
OGRFeatureDefn & GetLayerDefn() const