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