OTB  6.7.0
Orfeo Toolbox
otbVectorDataToLabelImageFilter.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 otbVectorDataToLabelImageFilter_hxx
22 #define otbVectorDataToLabelImageFilter_hxx
23 
24 #include "gdal_alg.h"
25 #include "ogr_srs_api.h"
26 
28 #include "otbOGRIOHelper.h"
29 #include "otbGdalDataTypeBridge.h"
32 #include "otbImage.h"
33 
34 namespace otb
35 {
36 template<class TVectorData, class TOutputImage>
39  : m_OGRDataSourcePointer(nullptr),
40  m_BandsToBurn(1, 1),
41  m_BurnAttribute("FID"),
42  m_DefaultBurnValue(1.),
43  m_BackgroundValue(0.),
44  m_AllTouchedMode(false)
45 {
46  this->SetNumberOfRequiredInputs(1);
47 
48  // Output parameters initialization
49  m_OutputSpacing.Fill(1.0);
50  m_OutputSize.Fill(0);
51  m_OutputStartIndex.Fill(0);
52 }
53 
54 template<class TVectorData, class TOutputImage>
55 void
58 {
60 }
61 
62 template <class TVectorData, class TOutputImage>
65 ::GetInput(unsigned int idx)
66 {
67  return static_cast<const TVectorData *>
68  (this->itk::ProcessObject::GetInput(idx));
69 }
70 
71 template <class TVectorData, class TOutputImage>
72 void
75 {
76  if (this->m_OutputSpacing != spacing)
77  {
78  this->m_OutputSpacing = spacing;
79  this->Modified();
80  }
81 }
82 
83 template <class TVectorData, class TOutputImage>
84 void
86 ::SetOutputSpacing(const double spacing[2])
87 {
88  OutputSpacingType s(spacing);
89  this->SetOutputSpacing(s);
90 }
91 
92 template <class TVectorData, class TOutputImage>
93 void
95 ::SetOutputSpacing(const float spacing[2])
96 {
97  itk::Vector<float, 2> sf(spacing);
99  s.CastFrom(sf);
100  this->SetOutputSpacing(s);
101 }
102 
103 template <class TVectorData, class TOutputImage>
104 void
106 ::SetOutputOrigin(const double origin[2])
107 {
108  OutputOriginType p(origin);
109  this->SetOutputOrigin(p);
110 }
111 
112 template <class TVectorData, class TOutputImage>
113 void
115 ::SetOutputOrigin(const float origin[2])
116 {
117  itk::Point<float, 2> of(origin);
119  p.CastFrom(of);
120  this->SetOutputOrigin(p);
121 }
122 
123 template <class TVectorData, class TOutputImage>
124 void
127 {
128  this->SetOutputOrigin ( src->GetOrigin() );
129  this->SetOutputSpacing ( internal::GetSignedSpacing(src) );
130  this->SetOutputSize ( src->GetLargestPossibleRegion().GetSize() );
132  this->SetOutputProjectionRef(imi->GetProjectionRef());
133 }
134 
135 template<class TVectorData, class TOutputImage>
136 void
139 {
140  // get pointer to the output
141  OutputImagePointer outputPtr = this->GetOutput();
142  if (!outputPtr)
143  {
144  return;
145  }
146 
147  // Set the size of the output region
148  typename TOutputImage::RegionType outputLargestPossibleRegion;
149  outputLargestPossibleRegion.SetSize(m_OutputSize);
150  //outputLargestPossibleRegion.SetIndex(m_OutputStartIndex);
151  outputPtr->SetLargestPossibleRegion(outputLargestPossibleRegion);
152 
153  // Set spacing and origin
154  outputPtr->SetSignedSpacing(m_OutputSpacing);
155  outputPtr->SetOrigin(m_OutputOrigin);
156 
157  itk::MetaDataDictionary& dict = outputPtr->GetMetaDataDictionary();
158  itk::EncapsulateMetaData<std::string> (dict, MetaDataKey::ProjectionRefKey,
159  static_cast<std::string>(this->GetOutputProjectionRef()));
160 
161  // Generate the OGRLayers from the input VectorDatas
162  // iteration begin from 1 cause the 0th input is a image
163  for (unsigned int idx = 0; idx < this->GetNumberOfInputs(); ++idx)
164  {
165  const VectorDataType* vd = dynamic_cast< const VectorDataType*>(this->itk::ProcessObject::GetInput(idx));
166 
167  // Get the projection ref of the current VectorData
168  std::string projectionRefWkt = vd->GetProjectionRef();
169  bool projectionInformationAvailable = !projectionRefWkt.empty();
170  OGRSpatialReference * oSRS = nullptr;
171 
172  if (projectionInformationAvailable)
173  {
174  oSRS = static_cast<OGRSpatialReference *>(OSRNewSpatialReference(projectionRefWkt.c_str()));
175  }
176  else
177  {
178  otbMsgDevMacro(<< "Projection information unavailable");
179  }
180 
181  // Retrieving root node
182  DataTreeConstPointerType tree = vd->GetDataTree();
183 
184  // Get the input tree root
185  InternalTreeNodeType * inputRoot = const_cast<InternalTreeNodeType *>(tree->GetRoot());
186 
187  // Iterative method to build the layers from a VectorData
188  OGRLayer * ogrCurrentLayer = nullptr;
189  std::vector<OGRLayer *> ogrLayerVector;
191 
192  // The method ConvertDataTreeNodeToOGRLayers create the
193  // OGRDataSource but don t release it. Destruction is done in the
194  // desctructor
195  m_OGRDataSourcePointer = nullptr;
196  ogrLayerVector = IOConversion->ConvertDataTreeNodeToOGRLayers(inputRoot,
197  m_OGRDataSourcePointer,
198  ogrCurrentLayer,
199  oSRS);
200 
201  // From OGRLayer* to OGRGeometryH vector
202  for (unsigned int idx2 = 0; idx2 < ogrLayerVector.size(); ++idx2)
203  {
204  // test if the layers contain a field m_BurnField;
205  int burnField = -1;
206 
207  if( !m_BurnAttribute.empty() )
208  {
209  burnField = OGR_FD_GetFieldIndex( OGR_L_GetLayerDefn( (OGRLayerH)(ogrLayerVector[idx2]) ),
210  m_BurnAttribute.c_str() );
211 
212  // Get the geometries of the layer
213  OGRFeatureH hFeat;
214  OGR_L_ResetReading( (OGRLayerH)(ogrLayerVector[idx2]) );
215  while( ( hFeat = OGR_L_GetNextFeature( (OGRLayerH)(ogrLayerVector[idx2]) )) != nullptr )
216  {
217  OGRGeometryH hGeom;
218  if( OGR_F_GetGeometryRef( hFeat ) == nullptr )
219  {
220  OGR_F_Destroy( hFeat );
221  continue;
222  }
223 
224  hGeom = OGR_G_Clone( OGR_F_GetGeometryRef( hFeat ) );
225  m_SrcDataSetGeometries.push_back( hGeom );
226 
227  if (burnField == -1 )
228  {
229  // TODO : if no burnAttribute available, warning or raise an exception??
230  m_FullBurnValues.push_back(m_DefaultBurnValue++);
231  itkWarningMacro(<<"Failed to find attribute "<<m_BurnAttribute << " in layer "
232  << OGR_FD_GetName( OGR_L_GetLayerDefn( (OGRLayerH)(ogrLayerVector[idx2]) ))
233  <<" .Setting burn value to default = "
234  << m_DefaultBurnValue);
235  }
236  else
237  {
238  m_FullBurnValues.push_back( OGR_F_GetFieldAsDouble( hFeat, burnField ) );
239  }
240 
241  OGR_F_Destroy( hFeat );
242  }
243  }
244 
245  // Destroy the oSRS
246  if (oSRS != nullptr)
247  {
248  OSRRelease(oSRS);
249  }
250  }
251  }
252 }
253 
254 template<class TVectorData, class TOutputImage>
255 void
257 {
258  // Call Superclass GenerateData
259  this->AllocateOutputs();
260 
261  // Get the buffered region
262  OutputImageRegionType bufferedRegion = this->GetOutput()->GetBufferedRegion();
263 
264  // Fill the buffer with the background value
265  this->GetOutput()->FillBuffer(m_BackgroundValue);
266 
267  // nb bands
268  unsigned int nbBands = this->GetOutput()->GetNumberOfComponentsPerPixel();
269 
270  // register drivers
271  GDALAllRegister();
272 
273  std::ostringstream stream;
274  stream << "MEM:::"
275  << "DATAPOINTER=" << (uintptr_t)(this->GetOutput()->GetBufferPointer()) << ","
276  << "PIXELS=" << bufferedRegion.GetSize()[0] << ","
277  << "LINES=" << bufferedRegion.GetSize()[1]<< ","
278  << "BANDS=" << nbBands << ","
279  << "DATATYPE=" << GDALGetDataTypeName(GdalDataTypeBridge::GetGDALDataType<OutputImageInternalPixelType>()) << ","
280  << "PIXELOFFSET=" << sizeof(OutputImageInternalPixelType) * nbBands << ","
281  << "LINEOFFSET=" << sizeof(OutputImageInternalPixelType)*nbBands*bufferedRegion.GetSize()[0] << ","
282  << "BANDOFFSET=" << sizeof(OutputImageInternalPixelType);
283 
284  GDALDatasetH dataset = GDALOpen(stream.str().c_str(), GA_Update);
285 
286  // Add the projection ref to the dataset
287  GDALSetProjection (dataset, this->GetOutput()->GetProjectionRef().c_str());
288 
289  // add the geoTransform to the dataset
290  itk::VariableLengthVector<double> geoTransform(6);
291 
292  // Reporting origin and spacing of the buffered region
293  // the spacing is unchanged, the origin is relative to the buffered region
294  OutputIndexType bufferIndexOrigin = bufferedRegion.GetIndex();
295  OutputOriginType bufferOrigin;
296  this->GetOutput()->TransformIndexToPhysicalPoint(bufferIndexOrigin, bufferOrigin);
297  geoTransform[0] = bufferOrigin[0] - 0.5 * this->GetOutput()->GetSignedSpacing()[0];
298  geoTransform[3] = bufferOrigin[1] - 0.5 * this->GetOutput()->GetSignedSpacing()[1];
299  geoTransform[1] = this->GetOutput()->GetSignedSpacing()[0];
300  geoTransform[5] = this->GetOutput()->GetSignedSpacing()[1];
301 
302  // FIXME: Here component 1 and 4 should be replaced by the orientation parameters
303  geoTransform[2] = 0.;
304  geoTransform[4] = 0.;
305  GDALSetGeoTransform(dataset,const_cast<double*>(geoTransform.GetDataPointer()));
306 
307  char **options = nullptr;
308  if (m_AllTouchedMode)
309  {
310  options = CSLSetNameValue(options, "ALL_TOUCHED", "TRUE");
311  }
312 
313  // Burn the geometries into the dataset
314  if (dataset != nullptr)
315  {
316  GDALRasterizeGeometries( dataset, m_BandsToBurn.size(),
317  &(m_BandsToBurn[0]),
318  m_SrcDataSetGeometries.size(),
319  &(m_SrcDataSetGeometries[0]),
320  nullptr, nullptr, &(m_FullBurnValues[0]),
321  options,
322  GDALDummyProgress, nullptr );
323 
324  CSLDestroy(options);
325 
326  // release the dataset
327  GDALClose( dataset );
328  }
329 }
330 
331 template<class TVectorData, class TOutputImage>
332 void
334 ::PrintSelf(std::ostream& os, itk::Indent indent) const
335 {
336  Superclass::PrintSelf(os, indent);
337 }
338 
339 } // end namespace otb
340 
341 #endif
342 
static ImageMetadataInterfaceBasePointerType CreateIMI(const MetaDataDictionaryType &dict)
void PrintSelf(std::ostream &os, itk::Indent indent) const override
virtual const RegionType & GetLargestPossibleRegion() const
OutputImageType::InternalPixelType OutputImageInternalPixelType
const VectorDataType * GetInput(unsigned int idx)
OTBOSSIMAdapters_EXPORT char const * ProjectionRefKey
virtual void SetOutputSpacing(const OutputSpacingType &spacing)
MetaDataDictionary & GetMetaDataDictionary()
ImageType::SpacingType GetSignedSpacing(const ImageType *input)
Definition: otbImage.h:41
OutputImageType::Pointer OutputImagePointer
virtual void SetOutputOrigin(OutputOriginType _arg)
virtual void PushBackInput(const DataObject *input)
const SizeType & GetSize() const
virtual void AddVectorData(const VectorDataType *vd)
const TValue * GetDataPointer() const noexcept
DataObject * GetInput(const DataObjectIdentifierType &key)
static Pointer New()
OutputImageType::RegionType OutputImageRegionType
typedef::vcl_size_t uintptr_t
virtual const PointType & GetOrigin() const
void SetOutputParametersFromImage(const ImageBaseType *image)
#define otbMsgDevMacro(x)
Definition: otbMacro.h:66