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