OTB  6.7.0
Orfeo Toolbox
otbOGRDataToSamplePositionFilter.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2019 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>
33 {
34  this->SetNumberOfRequiredOutputs(2);
35  m_OriginFieldName = std::string("originfid");
36  m_UseOriginField = true;
37 }
38 
39 template<class TInputImage, class TMaskImage, class TSampler>
40 void
42 ::Reset(void)
43 {
44  // Reset samplers
45  for (unsigned int i=0 ; i < m_Samplers.size() ; ++i)
46  {
47  for (typename SamplerMapType::iterator iter = m_Samplers[i].begin();
48  iter != m_Samplers[i].end();
49  ++iter)
50  {
51  iter->second->Reset();
52  }
53  }
54 
55  // Add an extra field for the original FID
56  this->ClearAdditionalFields();
57  m_UseOriginField = (this->GetOriginFieldName().size() > 0);
58  if (m_UseOriginField)
59  {
60  this->CreateAdditionalField(this->GetOriginFieldName(),OFTInteger,12);
61  }
62 
63  // compute label mapping
64  this->ComputeClassPartition();
65 
66  // Prepare outputs
67  ogr::DataSource* inputDS = const_cast<ogr::DataSource*>(this->GetOGRData());
68  for (unsigned int k=0 ; k < this->GetNumberOfLevels() ; k++)
69  {
70  otb::ogr::DataSource* output = this->GetOutputPositionContainer(k);
71  if (output)
72  {
73  this->InitializeOutputDataSource(inputDS, output);
74  }
75  }
76 }
77 
78 template<class TInputImage, class TMaskImage, class TSampler>
81 ::GetSamplers(unsigned int level)
82 {
83  if (m_Samplers.size() < (level + 1))
84  {
85  itkExceptionMacro("The sampler level "<< level << " doesn't exist !");
86  }
87  return m_Samplers[level];
88 }
89 
90 template<class TInputImage, class TMaskImage, class TSampler>
91 void
96  unsigned int level)
97 {
98  // set the output dataset
99  this->SetNthOutput(1+level,data);
100  // instantiate the corresponding samplers
101  if (m_Samplers.size() < (level + 1))
102  {
103  m_Samplers.resize(level + 1);
104  }
105  m_Samplers[level].clear();
106  for (SamplingRateCalculator::MapRateType::const_iterator it = map.begin() ;
107  it != map.end();
108  ++it)
109  {
110  SamplerPointerType sampler = SamplerType::New();
111  sampler->SetNumberOfElements(it->second.Required,it->second.Tot);
112  m_Samplers[level][it->first] = sampler;
113  }
114 }
115 
116 template<class TInputImage, class TMaskImage, class TSampler>
119 ::GetOutputPositionContainer(unsigned int level)
120 {
121  if (this->GetNumberOfOutputs() < (level + 2))
122  {
123  return 0;
124  }
125  return static_cast<otb::ogr::DataSource *>(this->itk::ProcessObject::GetOutput(level + 1));
126 }
127 
128 template<class TInputImage, class TMaskImage, class TSampler>
129 unsigned int
132 {
133  return (this->GetNumberOfOutputs() - 1);
134 }
135 
136 template<class TInputImage, class TMaskImage, class TSampler>
137 void
140 {
141  // remove output position containers
142  for (unsigned int i = (this->GetNumberOfOutputs() - 1) ; i > 0 ; --i)
143  {
145  }
146  // remove samplers
147  m_Samplers.clear();
148 }
149 
150 template<class TInputImage, class TMaskImage, class TSampler>
154 {
155  if (idx == 0)
156  {
157  // the output image
158  return static_cast<itk::DataObject*>(TInputImage::New().GetPointer());
159  }
160  else if (idx > 0)
161  {
162  // sample position containers
163  return static_cast<itk::DataObject*>(otb::ogr::DataSource::New().GetPointer());
164  }
165  // might as well make an image
166  return static_cast<itk::DataObject*>(TInputImage::New().GetPointer());
167 }
168 
169 template<class TInputImage, class TMaskImage, class TSampler>
170 void
173  typename TInputImage::IndexType&,
174  typename TInputImage::PointType& imgPoint,
175  itk::ThreadIdType& threadid)
176 {
177  std::string className(feature.ogr().GetFieldAsString(this->GetFieldIndex()));
178  for (unsigned int i=0 ; i<this->GetNumberOfLevels() ; ++i)
179  {
180  if (m_Samplers[i][className]->TakeSample())
181  {
182  OGRPoint ogrTmpPoint;
183  ogrTmpPoint.setX(imgPoint[0]);
184  ogrTmpPoint.setY(imgPoint[1]);
185 
186  ogr::Layer outputLayer = this->GetInMemoryOutput(threadid,i);
187  ogr::Feature feat(outputLayer.GetLayerDefn());
188  feat.SetFrom(feature);
189  if (m_UseOriginField)
190  {
191  feat[this->GetOriginFieldName()].SetValue(static_cast<int>(feature.GetFID()));
192  }
193  feat.SetGeometry(&ogrTmpPoint);
194  outputLayer.CreateFeature(feat);
195  break;
196  }
197  }
198 }
199 
200 template<class TInputImage, class TMaskImage, class TSampler>
201 void
204 {
205  TInputImage* outputImage = this->GetOutput();
206  ogr::DataSource* vectors = const_cast<ogr::DataSource*>(this->GetOGRData());
207  ogr::Layer inLayer = vectors->GetLayer(this->GetLayerIndex());
208 
209  const RegionType& requestedRegion = outputImage->GetRequestedRegion();
210  itk::ContinuousIndex<double> startIndex(requestedRegion.GetIndex());
211  itk::ContinuousIndex<double> endIndex(requestedRegion.GetUpperIndex());
212  startIndex[0] += -0.5;
213  startIndex[1] += -0.5;
214  endIndex[0] += 0.5;
215  endIndex[1] += 0.5;
216  itk::Point<double, 2> startPoint;
217  itk::Point<double, 2> endPoint;
218  outputImage->TransformContinuousIndexToPhysicalPoint(startIndex, startPoint);
219  outputImage->TransformContinuousIndexToPhysicalPoint(endIndex, endPoint);
220 
221  // create geometric extent
222  OGRPolygon tmpPolygon;
223  OGRLinearRing ring;
224  ring.addPoint(startPoint[0],startPoint[1],0.0);
225  ring.addPoint(startPoint[0],endPoint[1] ,0.0);
226  ring.addPoint(endPoint[0] ,endPoint[1] ,0.0);
227  ring.addPoint(endPoint[0] ,startPoint[1],0.0);
228  ring.addPoint(startPoint[0],startPoint[1],0.0);
229  tmpPolygon.addRing(&ring);
230 
231  inLayer.SetSpatialFilter(&tmpPolygon);
232 
233  unsigned int numberOfThreads = this->GetNumberOfThreads();
234  std::vector<ogr::Layer> tmpLayers;
235  for (unsigned int i=0 ; i<numberOfThreads ; i++)
236  {
237  tmpLayers.push_back(this->GetInMemoryInput(i));
238  }
239 
240  OGRFeatureDefn &layerDefn = inLayer.GetLayerDefn();
241  ogr::Layer::const_iterator featIt = inLayer.begin();
242  std::string className;
243  for(; featIt!=inLayer.end(); ++featIt)
244  {
245  ogr::Feature dstFeature(layerDefn);
246  dstFeature.SetFrom( *featIt, TRUE );
247  dstFeature.SetFID(featIt->GetFID());
248  className = featIt->ogr().GetFieldAsString(this->GetFieldIndex());
249  tmpLayers[m_ClassPartition[className]].CreateFeature( dstFeature );
250  }
251 
252  inLayer.SetSpatialFilter(nullptr);
253 }
254 
255 template<class TInputImage, class TMaskImage, class TSampler>
256 void
259 {
260  m_ClassPartition.clear();
261  typedef std::map<std::string, unsigned long> ClassCountMapType;
262  ClassCountMapType classCounts;
263  for (typename SamplerMapType::const_iterator it = m_Samplers[0].begin() ;
264  it != m_Samplers[0].end();
265  ++it)
266  {
267  classCounts[it->first] = it->second->GetTotalElements();
268  }
269 
270  int numberOfThreads = this->GetNumberOfThreads();
271  typedef std::vector<unsigned long> LoadVectorType;
272  LoadVectorType currentLoad;
273  currentLoad.resize(numberOfThreads, 0UL);
274 
275  ClassCountMapType::iterator largestClass;
276  unsigned long minLoad;
277  unsigned int destThread;
278  while (classCounts.size())
279  {
280  // find class with highest number of total elements
281  largestClass = classCounts.begin();
282  for (ClassCountMapType::iterator iter = classCounts.begin() ;
283  iter != classCounts.end() ;
284  ++iter)
285  {
286  if (iter->second > largestClass->second)
287  {
288  largestClass = iter;
289  }
290  }
291 
292  // affect this class to the thread with lowest load
293  minLoad = currentLoad[0];
294  destThread = 0;
295  for (unsigned int k = 0 ; k < currentLoad.size() ; ++k)
296  {
297  if (currentLoad[k] < minLoad)
298  {
299  minLoad = currentLoad[k];
300  destThread = k;
301  }
302  }
303  m_ClassPartition[largestClass->first] = destThread;
304  currentLoad[destThread] += largestClass->second;
305 
306  // remove class from classCounts
307  classCounts.erase(largestClass);
308  }
309 }
310 
311 template<class TInputImage, class TMaskImage, class TSampler>
312 void
314 ::FillOneOutput(unsigned int outIdx, ogr::DataSource* outDS, bool update)
315 {
316  ogr::Layer outLayer = outDS->GetLayersCount() == 1
317  ? outDS->GetLayer(0)
318  : outDS->GetLayer(this->GetOutLayerName());
319 
320  OGRErr err = outLayer.ogr().StartTransaction();
321  if (err != OGRERR_NONE)
322  {
323  itkExceptionMacro(<< "Unable to start transaction for OGR layer " << outLayer.ogr().GetName() << ".");
324  }
325 
326  // output vectors sorted by class
327  for (auto& label : m_ClassPartition)
328  {
329  ogr::Layer inLayer = this->GetInMemoryOutput(label.second,outIdx);
330  if (!inLayer)
331  {
332  continue;
333  }
334 
335  // This test only uses 1 input, not compatible with multiple OGRData inputs
336  for(auto tmpIt = inLayer.begin(); tmpIt!=inLayer.end(); ++tmpIt)
337  {
338  if( label.first.compare(tmpIt->ogr().GetFieldAsString(this->GetFieldIndex())) != 0 )
339  continue;
340  if(update)
341  {
342  outLayer.SetFeature( *tmpIt );
343  }
344  else
345  {
346  ogr::Feature dstFeature(outLayer.GetLayerDefn());
347  dstFeature.SetFrom( *tmpIt, TRUE );
348  outLayer.CreateFeature( dstFeature );
349  }
350  }
351  }
352 
353  err = outLayer.ogr().CommitTransaction();
354  if (err != OGRERR_NONE)
355  {
356  itkExceptionMacro(<< "Unable to commit transaction for OGR layer " << outLayer.ogr().GetName() << ".");
357  }
358 }
359 
360 // -------------- otb::OGRDataToSamplePositionFilter --------------------------
361 
362 template<class TInputImage, class TMaskImage, class TSampler>
363 void
365 ::SetInput(const TInputImage* image)
366 {
367  this->GetFilter()->SetInput(image);
368 }
369 
370 template<class TInputImage, class TMaskImage, class TSampler>
371 const TInputImage*
374 {
375  return this->GetFilter()->GetInput();
376 }
377 
378 template<class TInputImage, class TMaskImage, class TSampler>
379 void
382 {
383  this->GetFilter()->SetOGRData(data);
384 }
385 
386 template<class TInputImage, class TMaskImage, class TSampler>
390 {
391  return this->GetFilter()->GetOGRData();
392 }
393 
394 template<class TInputImage, class TMaskImage, class TSampler>
395 void
397 ::SetMask(const TMaskImage* mask)
398 {
399  this->GetFilter()->SetMask(mask);
400 }
401 
402 template<class TInputImage, class TMaskImage, class TSampler>
403 const TMaskImage*
406 {
407  return this->GetFilter()->GetMask();
408 }
409 
410 template<class TInputImage, class TMaskImage, class TSampler>
411 void
413 ::SetFieldName(std::string key)
414 {
415  this->GetFilter()->SetFieldName(key);
416 }
417 
418 template<class TInputImage, class TMaskImage, class TSampler>
419 std::string
422 {
423  return this->GetFilter()->GetFieldName();
424 }
425 
426 template<class TInputImage, class TMaskImage, class TSampler>
427 void
429 ::SetLayerIndex(int index)
430 {
431  this->GetFilter()->SetLayerIndex(index);
432 }
433 
434 template<class TInputImage, class TMaskImage, class TSampler>
435 int
438 {
439  return this->GetFilter()->GetLayerIndex();
440 }
441 
442 template<class TInputImage, class TMaskImage, class TSampler>
443 void
446 {
447  SamplerMapType &samplers = this->GetSamplers(level);
448  for (typename SamplerMapType::iterator it = samplers.begin() ; it != samplers.end() ; ++it)
449  {
450  it->second->SetParameters(param);
451  }
452 }
453 
454 template<class TInputImage, class TMaskImage, class TSampler>
457 ::GetSamplers(unsigned int level)
458 {
459  return this->GetFilter()->GetSamplers(level);
460 }
461 
462 template<class TInputImage, class TMaskImage, class TSampler>
463 void
466  otb::ogr::DataSource* data,
468  unsigned int level)
469 {
470  this->GetFilter()->SetOutputPositionContainerAndRates(data,map,level);
471 }
472 
473 template<class TInputImage, class TMaskImage, class TSampler>
476 ::GetOutputPositionContainer(unsigned int level)
477 {
478  return this->GetFilter()->GetOutputPositionContainer(level);
479 }
480 
481 template<class TInputImage, class TMaskImage, class TSampler>
482 void
484 ::SetOriginFieldName(std::string key)
485 {
486  this->GetFilter()->SetOriginFieldName(key);
487 }
488 
489 template<class TInputImage, class TMaskImage, class TSampler>
490 std::string
493 {
494  return this->GetFilter()->GetOriginFieldName();
495 }
496 
497 } // end of namespace otb
498 
499 #endif
Superclass::DataObjectPointerArraySizeType DataObjectPointerArraySizeType
Collection of geometric objects.
itk::DataObject::Pointer MakeOutput(DataObjectPointerArraySizeType idx) override
OGRFeatureDefn & GetLayerDefn() const
Layer GetLayer(vcl_size_t i)
Layer of geometric objets.
void SetOutputPositionContainerAndRates(otb::ogr::DataSource *data, const SamplingRateCalculator::MapRateType &map, unsigned int level)
void FillOneOutput(unsigned int outIdx, ogr::DataSource *outDS, bool update) override
OGRFeature & ogr() const
const otb::ogr::DataSource * GetOutputPositionContainer(unsigned int level) const
ObjectType * GetPointer() const
virtual void SetInput(const TInputImage *image)
Implementation class for Feature iterator. This iterator is a single pass iterator. We may fetch the Feature referenced by an iterator previously stored, but never resume the iteration after a call to Layer::begin(), Layer::start_at(), Layer::CreateFeature(), Layer::DeleteFeature(), Layer::GetFeature(), Layer::SetFeature(), nor fork the iteration.
const_iterator begin() const
virtual void RemoveOutput(const DataObjectIdentifierType &key)
itk::Index< Monteverdi_DIMENSION > IndexType
Definition: mvdTypes.h:133
void CreateFeature(Feature feature)
static Pointer New()
void ProcessSample(const ogr::Feature &feature, typename TInputImage::IndexType &imgIndex, typename TInputImage::PointType &imgPoint, itk::ThreadIdType &threadid) override
std::map< std::string, TripletType > MapRateType
SamplerMapType & GetSamplers(unsigned int level=0)
unsigned int ThreadIdType
void SetSamplerParameters(SamplerParameterType param, unsigned int level=0)
OGRLayer & ogr()
void SetOutputPositionContainerAndRates(otb::ogr::DataSource *data, const SamplingRateCalculator::MapRateType &map, unsigned int level=0)
int GetLayersCount() const
void SetFrom(Feature const &rhs, int *map, bool mustForgive=true)
std::map< std::string, SamplerPointerType > SamplerMapType
Geometric objet with descriptive fields.
otb::ogr::DataSource * GetOutputPositionContainer(unsigned int level=0)
std::map< std::string, SamplerPointerType > SamplerMapType
void SetOGRData(const otb::ogr::DataSource *data)
void SetFeature(Feature feature)
VectorImageType::PointType PointType
Definition: mvdTypes.h:189
void SetSpatialFilter(OGRGeometry const *spatialFilter)
const_iterator end() const
DataObject * GetOutput(const DataObjectIdentifierType &key)