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