OTB  10.0.0
Orfeo Toolbox
otbRasterizeVectorDataFilter.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 otbRasterizeVectorDataFilter_hxx
22 #define otbRasterizeVectorDataFilter_hxx
23 
25 #include "otbOGRIOHelper.h"
26 #include "otbGdalDataTypeBridge.h"
28 
29 namespace otb
30 {
31 template <class TVectorData, class TInputImage, class TOutputImage>
33 {
34  this->SetNumberOfRequiredInputs(1);
35 }
36 
37 template <class TVectorData, class TInputImage, class TOutputImage>
39 {
40  // Process object is not const-correct so the const_cast is required
41  // here
42  if (this->GetNumberOfInputs() < 1)
43  {
44  this->itk::ProcessObject::SetNthInput(1, const_cast<VectorDataType*>(vd));
45  }
46  else
47  {
48  this->itk::ProcessObject::PushBackInput(vd);
49  }
50 }
51 
52 
53 template <class TVectorData, class TInputImage, class TOutputImage>
55 {
56  Superclass::GenerateOutputInformation();
57 
58  // Generate the OGRLayers from the input VectorDatas
59  // iteration begin from 1 cause the 0th input is a image
60  for (unsigned int idx = 1; idx < this->GetNumberOfInputs(); ++idx)
61  {
62  const VectorDataType* vd = dynamic_cast<const VectorDataType*>(this->itk::ProcessObject::GetInput(idx));
63 
64  // Get the projection ref of the current VectorData
65  std::string projectionRefWkt = vd->GetProjectionRef();
66  bool projectionInformationAvailable = !projectionRefWkt.empty();
67  OGRSpatialReference* oSRS = nullptr;
68 
69  if (projectionInformationAvailable)
70  {
71  oSRS = static_cast<OGRSpatialReference*>(OSRNewSpatialReference(projectionRefWkt.c_str()));
72  }
73  else
74  {
75  otbMsgDevMacro(<< "Projection information unavailable");
76  }
77 
78  // Get the input tree root
79  DataNodePointerType root = vd->GetRoot();
80 
81  // Iterative method to build the layers from a VectorData
82  OGRRegisterAll();
83  OGRLayer* ogrCurrentLayer = nullptr;
84  std::vector<OGRLayer*> ogrLayerVector;
86 
87  // The method ConvertDataTreeNodeToOGRLayers create the
88  // OGRDataSource but don t release it. Destruction is done in the
89  // destructor
90  m_OGRDataSourcePointer = nullptr;
91  ogrLayerVector = IOConversion->ConvertDataTreeNodeToOGRLayers(vd,root, m_OGRDataSourcePointer, ogrCurrentLayer, oSRS);
92 
93  // Cast OGRLayer* to OGRLayerH
94  for (unsigned int idx2 = 0; idx2 < ogrLayerVector.size(); ++idx2)
95  {
96  m_SrcDataSetLayers.push_back((OGRLayerH)(ogrLayerVector[idx2]));
97  }
98 
99  // Destroy the oSRS
100  if (oSRS != nullptr)
101  {
102  OSRRelease(oSRS);
103  }
104  }
105 
106  // Some checking : Check the consistency between the band list
107  // to burn and the burn values :
108  // There should be "m_BandsToBurn.size()" burn values for each layer.
109  // If not, burn values vector will be cloned as many time as the number of
110  // OGRLayer we have
111  if (m_BurnValues.size() != m_BandsToBurn.size() * m_SrcDataSetLayers.size())
112  {
113  std::ostringstream oss;
114  oss << "Inconsistency detected : expected burn vector size to be equal to( bandToBurn * nb layers = " << m_BandsToBurn.size() * m_SrcDataSetLayers.size()
115  << " ), got : " << m_BurnValues.size() << std::endl;
116  itkWarningMacro(<< oss.str());
117  }
118 
119  // Clone the burn values to fit the condition
120  for (unsigned int idx = 0; idx < m_SrcDataSetLayers.size(); ++idx)
121  {
122  for (unsigned int burnidx = 0; burnidx < m_BurnValues.size(); ++burnidx)
123  {
124  m_FullBurnValues.push_back(m_BurnValues[burnidx]);
125  }
126  }
127 }
128 
129 template <class TVectorData, class TInputImage, class TOutputImage>
131 {
132  // Call Superclass GenerateData
133  Superclass::GenerateData();
134 
135  // Get the buffered region
136  OutputImageRegionType bufferedRegion = this->GetOutput()->GetBufferedRegion();
137 
138  // nb bands
139  unsigned int nbBands = this->GetOutput()->GetNumberOfComponentsPerPixel();
140 
141  GDALDatasetWrapper::Pointer dataset =
143  this->GetOutput()->GetBufferPointer(),
144  bufferedRegion.GetSize()[0],
145  bufferedRegion.GetSize()[1], GdalDataTypeBridge::GetGDALDataType<OutputImageInternalPixelType>(),
146  sizeof(OutputImageInternalPixelType), nbBands,
148  );
149 
150  // Add the projection ref to the dataset
151  GDALSetProjection(dataset->GetDataSet(), this->GetOutput()->GetProjectionRef().c_str());
152 
153  // add the geoTransform to the dataset
154  itk::VariableLengthVector<double> geoTransform(6);
155 
156  // Reporting origin and spacing of the buffered region
157  // the spacing is unchanged, the origin is relative to the buffered region
158  InputIndexType bufferIndexOrigin = bufferedRegion.GetIndex();
159  InputPointType bufferOrigin;
160  this->GetOutput()->TransformIndexToPhysicalPoint(bufferIndexOrigin, bufferOrigin);
161  geoTransform[0] = bufferOrigin[0] - 0.5 * this->GetOutput()->GetSignedSpacing()[0];
162  geoTransform[3] = bufferOrigin[1] - 0.5 * this->GetOutput()->GetSignedSpacing()[1];
163  geoTransform[1] = this->GetOutput()->GetSignedSpacing()[0];
164  geoTransform[5] = this->GetOutput()->GetSignedSpacing()[1];
165 
166  // FIXME: Here component 1 and 4 should be replaced by the orientation parameters
167  geoTransform[2] = 0.;
168  geoTransform[4] = 0.;
169  GDALSetGeoTransform(dataset->GetDataSet(),
170  const_cast<double*>(geoTransform.GetDataPointer()));
171 
172  char** options = nullptr;
173  if (m_AllTouchedMode)
174  {
175  options = CSLSetNameValue(options, "ALL_TOUCHED", "TRUE");
176  }
177 
178  // Burn the geometries into the dataset
179  if (dataset->GetDataSet() != nullptr)
180  {
181  GDALRasterizeLayers(dataset->GetDataSet(), m_BandsToBurn.size(),
182  &(m_BandsToBurn[0]), m_SrcDataSetLayers.size(),
183  &(m_SrcDataSetLayers[0]), nullptr, nullptr,
184  &(m_FullBurnValues[0]), options, GDALDummyProgress,
185  nullptr);
186 
187  CSLDestroy(options);
188  // release the dataset
189  }
190 }
191 
192 template <class TVectorData, class TInputImage, class TOutputImage>
194 {
195  Superclass::PrintSelf(os, indent);
196 }
197 
198 } // end namespace otb
199 
200 #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::RegionType OutputImageRegionType
void PrintSelf(std::ostream &os, itk::Indent indent) const override
VectorDataType::DataNodePointerType DataNodePointerType
OutputImageType::InternalPixelType OutputImageInternalPixelType
virtual void AddVectorData(const VectorDataType *vd)
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.
#define otbMsgDevMacro(x)
Definition: otbMacro.h:116