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