OTB  6.7.0
Orfeo Toolbox
otbVectorDataToLabelMapWithAttributesFilter.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 otbVectorDataToLabelMapWithAttributesFilter_hxx
22 #define otbVectorDataToLabelMapWithAttributesFilter_hxx
23 
26 #include "itkNumericTraits.h"
27 
29 
30 namespace otb
31 {
32 
33 template <class TVectorData, class TLabelMap>
36 {
38  this->SetNumberOfRequiredInputs(1);
39  m_Spacing.Fill(1.0);
40  m_Origin.Fill(0.0);
41  m_Direction.SetIdentity();
42  m_Size.Fill(0);
43  m_StartIndex.Fill(0);
44  m_InitialLabel = itk::NumericTraits<LabelType>::Zero;
45 
46  m_AutomaticSizeComputation=true;
47  m_VectorDataProperties = VectorDataPropertiesType::New();
48 }
49 
50 //----------------------------------------------------------------------------
51 template <class TVectorData, class TLabelMap>
52 void
54 ::SetSpacing(const SpacingType& spacing)
55 {
56  if (this->m_Spacing != spacing)
57  {
58  this->m_Spacing = spacing;
59  this->Modified();
60  }
61 }
62 
63 //----------------------------------------------------------------------------
64 template <class TVectorData, class TLabelMap>
65 void
67 ::SetSpacing(const double spacing[2])
68 {
69  SpacingType s(spacing);
70  this->SetSpacing(s);
71 }
72 
73 //----------------------------------------------------------------------------
74 template <class TVectorData, class TLabelMap>
75 void
77 ::SetSpacing(const float spacing[2])
78 {
79  itk::Vector<float, 2> sf(spacing);
80  SpacingType s;
81  s.CastFrom(sf);
82  this->SetSpacing(s);
83 }
84 
85 //----------------------------------------------------------------------------
86 template <class TVectorData, class TLabelMap>
87 void
89 ::SetOrigin(const double origin[2])
90 {
91  OriginType p(origin);
92  this->SetOrigin(p);
93 }
94 
95 //----------------------------------------------------------------------------
96 template <class TVectorData, class TLabelMap>
97 void
99 ::SetOrigin(const float origin[2])
100 {
101  itk::Point<float, 2> of(origin);
102  OriginType p;
103  p.CastFrom(of);
104  this->SetOrigin(p);
105 }
106 
107 
112 template <class TVectorData, class TLabelMap>
115 {
116  // we can't call the superclass method here.
117 
118  // get pointers to the input and output
119  OutputLabelMapType * outputPtr = this->GetOutput();
120 
121  if (!outputPtr)
122  {
123  return;
124  }
125 
126  RegionType outputLargestPossibleRegion;
127  if(m_AutomaticSizeComputation==false)
128  {
129  // Set the size of the output region
130  outputLargestPossibleRegion.SetSize(m_Size);
131  outputLargestPossibleRegion.SetIndex(m_StartIndex);
132  outputPtr->SetLargestPossibleRegion(outputLargestPossibleRegion);
133 
134  otbGenericMsgDebugMacro(<< "LargestPossibleRegion " << outputPtr->GetLargestPossibleRegion());
135 
136  // Set spacing and origin
137  outputPtr->SetSpacing(m_Spacing);
138  outputPtr->SetOrigin(m_Origin);
139  outputPtr->SetDirection(m_Direction);
140  }
141  else
142  {
143  //typename PolygonType::RegionType region;
144  m_VectorDataProperties->SetVectorDataObject(this->GetInput());
145  //m_VectorDataProperties->SetBoundingRegion(region);
146  //Compute the global bounding box of the vectordata
147  m_VectorDataProperties->ComputeBoundingRegion();
148 
149  // Compute origin and size
150  SizeType size;
151  SpacingType spacing = this->GetInput()->GetSpacing();
152  OriginType origin = m_VectorDataProperties->GetBoundingRegion().GetOrigin();
153  for (unsigned int i=0; i<2; ++i)
154  {
155  if (spacing[i] < 0.0)
156  {
157  origin[i] += m_VectorDataProperties->GetBoundingRegion().GetSize(i);
158  }
159  origin[i] += (0.5 - m_StartIndex[i]) * spacing[i];
160  size[i] = static_cast<unsigned long>(std::ceil(std::abs(
161  m_VectorDataProperties->GetBoundingRegion().GetSize(i)/spacing[i])));
162  }
163 
164  outputLargestPossibleRegion.SetSize(size);
165  outputLargestPossibleRegion.SetIndex(m_StartIndex);
166 
167  outputPtr->SetLargestPossibleRegion(outputLargestPossibleRegion);
168  outputPtr->SetSpacing(spacing);
169  outputPtr->SetOrigin(origin);
170  outputPtr->SetDirection(m_Direction);
171  }
172  return;
173 }
174 /*
175 template <class TVectorData, class TLabelMap >
176 void
177  VectorDataToLabelMapWithAttributesFilter<TVectorData, TLabelMap >
178 ::GenerateInputRequestedRegion()
179 {
180 
181  //call the superclass' implementation of this method
182  Superclass::GenerateInputRequestedRegion();
183 
184  // We need all the input.
185  InputVectorDataPointer input = const_cast<InputVectorDataType *>(this->GetInput());
186  if( !input )
187  {
188  return;
189  }
190  input->SetRequestedRegionToLargestPossibleRegion ();
191 }
192 
193 
194 template <class TVectorData, class TLabelMap >
195 void
196 VectorDataToLabelMapWithAttributesFilter<TVectorData, TLabelMap >
197 ::EnlargeOutputRequestedRegion(itk::DataObject *)
198 {
199  this->GetOutput()
200  ->SetRequestedRegion( this->GetOutput()->GetLargestPossibleRegion() );
201 }
202 */
203 
204 template<class TVectorData, class TLabelMap>
205 void
208 {
209 // Process object is not const-correct so the const_cast is required here
211  const_cast<InputVectorDataType *>(input));
212 }
213 
214 template<class TVectorData, class TLabelMap>
215 void
217 ::SetInput(unsigned int idx, const InputVectorDataType *input)
218 {
219  // Process object is not const-correct so the const_cast is required here
221  const_cast<InputVectorDataType *>(input));
222 }
223 
224 template<class TVectorData, class TLabelMap>
228 {
229  if (this->GetNumberOfInputs() < 1)
230  {
231  return nullptr;
232  }
233 
234  return static_cast<const TVectorData *>
235  (this->itk::ProcessObject::GetInput(0));
236 }
237 
238 template<class TVectorData, class TLabelMap>
241 ::GetInput(unsigned int idx)
242 {
243  return static_cast<const TVectorData *>
244  (this->itk::ProcessObject::GetInput(idx));
245 }
246 
247 template <class TVectorData, class TLabelMap>
248 void
251 {
252  // Allocate the output
253  this->AllocateOutputs();
254 
255  OutputLabelMapType * output = this->GetOutput();
256 
257  //For each input
258  for (unsigned int idx = 0; idx < this->GetNumberOfInputs(); ++idx)
259  {
260  if (this->GetInput(idx))
261  {
262 
263  InputVectorDataConstPointer input = this->GetInput(idx);
264  InternalTreeNodeType * inputRoot = const_cast<InternalTreeNodeType *>(input->GetDataTree()->GetRoot());
265  //Use our own value for the background
266  output->SetBackgroundValue(m_BackgroundValue);
267  //Set the value of the first label
268  m_lab = m_InitialLabel;
269 // otbGenericMsgDebugMacro(<<"input " << idx);
270 
271  //The projection information
272  output->SetMetaDataDictionary(input->GetMetaDataDictionary());
273  ProcessNode(inputRoot);
274 
275  }
276  }
277 }
278 
279 template<class TVectorData, class TLabelMap>
280 void
283 {
284 
285  // Get the children list from the input node
286  ChildrenListType children = source->GetChildrenList();
287 
288  // For each child
289  for (typename ChildrenListType::iterator it = children.begin(); it != children.end(); ++it)
290  {
291  // Copy input DataNode info
292  DataNodePointerType dataNode = (*it)->Get();
293  otbGenericMsgDebugMacro(<< "Type of node " << dataNode->GetNodeType() << " id" << dataNode->GetNodeId());
294  switch (dataNode->GetNodeType())
295  {
296  case otb::ROOT:
297  {
298  ProcessNode((*it));
299  break;
300  }
301  case otb::DOCUMENT:
302  {
303  ProcessNode((*it));
304  break;
305  }
306  case otb::FOLDER:
307  {
308  ProcessNode((*it));
309  break;
310  }
311  case FEATURE_POINT:
312  {
313  otbGenericMsgDebugMacro(<< "Insert Point from vectorData");
314  IndexType index;
315  this->GetOutput()->TransformPhysicalPointToIndex(dataNode->GetPoint(), index);
316  if (this->GetOutput()->GetLargestPossibleRegion().IsInside(index))
317  {
318  this->GetOutput()->SetPixel(index, m_lab);
319  m_lab += 1;
320  }
321  break;
322  }
323  case otb::FEATURE_LINE:
324  {
325  //TODO Bresenham
326  itkExceptionMacro(
327  << "This type (FEATURE_LINE) is not handle (yet) by VectorDataToLabelMapWithAttributesFilter(), please request for it");
328  break;
329  }
330  case FEATURE_POLYGON:
331  {
332 
334  CorrectFunctorType correct;
335  PolygonPointerType correctPolygonExtRing = correct(dataNode->GetPolygonExteriorRing());
337 
338  //typedef typename DataNodeType::PolygonType PolygonType;
339  typedef typename PolygonType::RegionType RSRegionType;
340  typedef typename PolygonType::VertexType VertexType;
341  typedef typename IndexType::IndexValueType IndexValueType;
342  RSRegionType polygonExtRingBoundReg = correctPolygonExtRing->GetBoundingRegion();
343 
344 
345  OriginType physCorners[4];
346  physCorners[0][0] = polygonExtRingBoundReg.GetOrigin(0);
347  physCorners[0][1] = polygonExtRingBoundReg.GetOrigin(1);
348  physCorners[1] = physCorners[0];
349  physCorners[2] = physCorners[0];
350  physCorners[3] = physCorners[0];
351 
352  physCorners[1][1] += polygonExtRingBoundReg.GetSize(1);
353  physCorners[2][1] += polygonExtRingBoundReg.GetSize(1);
354  physCorners[2][0] += polygonExtRingBoundReg.GetSize(0);
355  physCorners[3][0] += polygonExtRingBoundReg.GetSize(0);
356 
357  IndexType startIdx,endIdx,tmpIdx;
358 
361 
362  for (unsigned int k=0; k<4; ++k)
363  {
364  this->GetOutput()->TransformPhysicalPointToIndex(physCorners[k],tmpIdx);
365 
366  startIdx[0] = std::min(startIdx[0],tmpIdx[0]);
367  startIdx[1] = std::min(startIdx[1],tmpIdx[1]);
368  endIdx[0] = std::max(endIdx[0],tmpIdx[0]);
369  endIdx[1] = std::max(endIdx[1],tmpIdx[1]);
370  }
371  // Check that the polygon intersects the largest possible region
372  RegionType polyRegion;
373  polyRegion.SetIndex(startIdx);
374  polyRegion.SetSize(0,endIdx[0] - startIdx[0] + 1);
375  polyRegion.SetSize(1,endIdx[1] - startIdx[1] + 1);
376  if (polyRegion.Crop(this->GetOutput()->GetLargestPossibleRegion()))
377  {
378  startIdx = polyRegion.GetIndex();
379  endIdx[0] = startIdx[0] - 1 + polyRegion.GetSize(0);
380  endIdx[1] = startIdx[1] - 1 + polyRegion.GetSize(1);
381  }
382  else
383  {
384  // No intersection
385  break;
386  }
387 
388  OriginType tmpPoint;
389  VertexType vertex;
390  for (IndexValueType j=startIdx[1]; j<=endIdx[1]; ++j)
391  {
392  for (IndexValueType i=startIdx[0]; i<=endIdx[0]; ++i)
393  {
394  tmpIdx[0] = i;
395  tmpIdx[1] = j;
396  this->GetOutput()->TransformIndexToPhysicalPoint(tmpIdx,tmpPoint);
397  vertex[0] = tmpPoint[0];
398  vertex[1] = tmpPoint[1];
399  if (correctPolygonExtRing->IsInside(vertex) || correctPolygonExtRing->IsOnEdge (vertex))
400  {
401  // TODO : should also test interior rings
402  if (this->GetOutput()->HasLabel(m_lab))
403  {
404  if (!this->GetOutput()->GetLabelObject(m_lab)->HasIndex(tmpIdx))
405  { //Add a pixel to the current labelObject
406  this->GetOutput()->SetPixel(tmpIdx, m_lab);
407  }
408  }
409  else
410  {
411  //Add a pixel to the current labelObject
412  this->GetOutput()->SetPixel(tmpIdx, m_lab);
413  //add attributes
414  AttributesValueType fieldValue;
415  for(unsigned int ii=0; ii<dataNode->GetFieldList().size(); ii++)
416  {
417  fieldValue = static_cast<AttributesValueType>( dataNode->GetFieldAsString(dataNode->GetFieldList()[ii]) );
418  this->GetOutput()->GetLabelObject(m_lab)->SetAttribute( dataNode->GetFieldList()[ii].c_str(), fieldValue );
419  }
420  }
421  }
422  }
423  }
424  //Modify the label for the next layer
425  m_lab += 1;
426  break;
427  }
428  case FEATURE_MULTIPOINT:
429  {
430  itkExceptionMacro(
431  <<
432  "This type (FEATURE_MULTIPOINT) is not handle (yet) by VectorDataToLabelMapWithAttributesFilter(), please request for it");
433  break;
434  }
435  case FEATURE_MULTILINE:
436  {
437  itkExceptionMacro(
438  << "This type (FEATURE_MULTILINE) is not handle (yet) by VectorDataToLabelMapWithAttributesFilter(), please request for it");
439  break;
440  }
442  {
443  itkExceptionMacro(
444  <<
445  "This type (FEATURE_MULTIPOLYGON) is not handle (yet) by VectorDataToLabelMapWithAttributesFilter(), please request for it");
446  break;
447  }
448  case FEATURE_COLLECTION:
449  {
450  itkExceptionMacro(
451  <<
452  "This type (FEATURE_COLLECTION) is not handle (yet) by VectorDataToLabelMapWithAttributesFilter(), please request for it");
453  break;
454  }
455  }
456  }
457 }
458 
459 template <class TVectorData, class TLabelMap>
460 void
462 ::PrintSelf(std::ostream& os, itk::Indent indent) const
463 {
464  Superclass::PrintSelf(os, indent);
465  os << indent << "BackgroundValue: " << static_cast<typename itk::NumericTraits<OutputLabelMapPixelType>::PrintType>(
466  m_BackgroundValue) << std::endl;
467 }
468 
469 } // end namespace otb
470 
471 #endif
void PrintSelf(std::ostream &os, itk::Indent indent) const override
virtual void SetOrigin(OriginType _arg)
signed long IndexValueType
#define otbGenericMsgDebugMacro(x)
Definition: otbMacro.h:65
void SetSize(const SizeValueType val[VDimension])
static ITK_CONSTEXPR_FUNC T max(const T &)
This filter simplify and close the input polygon, making the last point equal to the first one...
DataObject * GetInput(const DataObjectIdentifierType &key)
InputVectorDataType::DataTreeType::TreeNodeType InternalTreeNodeType
virtual void SetNthInput(DataObjectPointerArraySizeType num, DataObject *input)
const SizeValueType * GetSize() const