OTB  9.0.0
Orfeo Toolbox
otbOGRLayerStreamStitchingFilter.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2022 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 otbOGRLayerStreamStitchingFilter_hxx
22 #define otbOGRLayerStreamStitchingFilter_hxx
23 
25 #include "itkContinuousIndex.h"
26 
27 #include <iomanip>
28 #include "ogrsf_frmts.h"
29 #include <set>
30 
31 namespace otb
32 {
33 
34 template <class TImage>
36 {
37  m_StreamSize.Fill(0);
38 }
39 
40 template <class TInputImage>
42 {
43  this->Superclass::SetNthInput(0, const_cast<InputImageType*>(input));
44 }
45 
46 template <class TInputImage>
48 {
49  if (this->GetNumberOfInputs() < 1)
50  {
51  return nullptr;
52  }
53 
54  return static_cast<const InputImageType*>(this->Superclass::GetInput(0));
55 }
56 
57 template <class TInputImage>
59 {
60  m_OGRLayer = ogrLayer;
61  this->Modified();
62 }
63 
64 template <class TInputImage>
66 {
67  return m_OGRLayer;
68 }
69 
70 template <class TInputImage>
72 {
73  double dfLength = 0.0;
74  for (int iGeom = 0; iGeom < intersection->getNumGeometries(); iGeom++)
75  {
76  OGRGeometry* geom = intersection->getGeometryRef(iGeom);
77  switch (wkbFlatten(geom->getGeometryType()))
78  {
79  case wkbLinearRing:
80  case wkbLineString:
81  dfLength += ((OGRCurve*)geom)->get_Length();
82  break;
83  case wkbGeometryCollection:
84  dfLength += GetLengthOGRGeometryCollection(dynamic_cast<OGRGeometryCollection*>(geom));
85  break;
86  default:
87  break;
88  }
89  }
90  return dfLength;
91 }
92 template <class TInputImage>
93 void OGRLayerStreamStitchingFilter<TInputImage>::ProcessStreamingLine(bool line, itk::ProgressReporter& progress)
94 {
95  typename InputImageType::ConstPointer inputImage = this->GetInput();
96 
97  // compute the number of stream division in row and column
98  SizeType imageSize = this->GetInput()->GetLargestPossibleRegion().GetSize();
99  unsigned int nbRowStream = static_cast<unsigned int>(imageSize[1] / m_StreamSize[1] + 1);
100  unsigned int nbColStream = static_cast<unsigned int>(imageSize[0] / m_StreamSize[0] + 1);
101 
102  /*unsigned long startReporter;
103  unsigned long stopReporter;
104  if (!line)
105  {
106  startReporter = 0;
107  stopReporter = 50;
108  }
109  else
110  {
111  startReporter = 50;
112  stopReporter = 100;
113  }
114  itk::ProgressReporter progress(this,0,2*nbRowStream*nbColStream,100,startReporter); */
115 
116  for (unsigned int x = 1; x <= nbColStream; x++)
117  {
118  OGRErr errStart = m_OGRLayer.ogr().StartTransaction();
119 
120  if (errStart != OGRERR_NONE)
121  {
122  itkExceptionMacro(<< "Unable to start transaction for OGR layer " << m_OGRLayer.ogr().GetName() << ".");
123  }
124 
125  for (unsigned int y = 1; y <= nbRowStream; y++)
126  {
127 
128  // Compute Stream line
129  OGRLineString streamLine;
130  itk::ContinuousIndex<double, 2> startIndex;
131  itk::ContinuousIndex<double, 2> endIndex;
132  if (!line)
133  {
134  // Treat vertical stream line
135  startIndex[0] = static_cast<double>(m_StreamSize[0] * x) - 0.5;
136  startIndex[1] = static_cast<double>(m_StreamSize[1] * (y - 1)) - 0.5;
137  endIndex = startIndex;
138  endIndex[1] += static_cast<double>(m_StreamSize[1]);
139  }
140  else
141  { // Treat horizontal stream line
142  startIndex[0] = static_cast<double>(m_StreamSize[0] * (x - 1)) - 0.5;
143  startIndex[1] = static_cast<double>(m_StreamSize[1] * y) - 0.5;
144  endIndex = startIndex;
145  endIndex[0] += static_cast<double>(m_StreamSize[0]);
146  }
147  OriginType startPoint;
148  inputImage->TransformContinuousIndexToPhysicalPoint(startIndex, startPoint);
149  OriginType endPoint;
150  inputImage->TransformContinuousIndexToPhysicalPoint(endIndex, endPoint);
151  streamLine.addPoint(startPoint[0], startPoint[1]);
152  streamLine.addPoint(endPoint[0], endPoint[1]);
153 
154 
155  // First we get all the feature that intersect the streaming line of the Upper/left stream
156  std::vector<FeatureStruct> upperStreamFeatureList;
157  upperStreamFeatureList.clear();
158  IndexType UpperLeftCorner;
159  IndexType LowerRightCorner;
160 
161  if (!line)
162  {
163  // Treat Row stream
164  // Compute the spatial filter of the upper stream
165  UpperLeftCorner[0] = x * m_StreamSize[0] - 1 - m_Radius;
166  UpperLeftCorner[1] = m_StreamSize[1] * (y - 1);
167 
168  LowerRightCorner[0] = m_StreamSize[0] * x - 1;
169  LowerRightCorner[1] = m_StreamSize[1] * y - 1;
170  }
171  else
172  { // Treat Column stream
173  // Compute the spatial filter of the left stream
174  UpperLeftCorner[0] = (x - 1) * m_StreamSize[0];
175  UpperLeftCorner[1] = m_StreamSize[1] * y - 1 - m_Radius;
176 
177  LowerRightCorner[0] = m_StreamSize[0] * x - 1;
178  LowerRightCorner[1] = m_StreamSize[1] * y - 1; //-1 to stop just before stream line
179  }
180 
181  OriginType ulCorner;
182  inputImage->TransformIndexToPhysicalPoint(UpperLeftCorner, ulCorner);
183  OriginType lrCorner;
184  inputImage->TransformIndexToPhysicalPoint(LowerRightCorner, lrCorner);
185 
186  m_OGRLayer.SetSpatialFilterRect(ulCorner[0], lrCorner[1], lrCorner[0], ulCorner[1]);
187 
188  std::set<unsigned int> upperFIDs;
189  OGRLayerType::const_iterator featIt = m_OGRLayer.begin();
190  for (; featIt != m_OGRLayer.end(); ++featIt)
191  {
192  FeatureStruct s(m_OGRLayer.GetLayerDefn());
193  s.feat = *featIt;
194  s.fusioned = false;
195  upperStreamFeatureList.push_back(s);
196  upperFIDs.insert((*featIt).GetFID());
197  }
198 
199  // Do the same thing for the lower/right stream
200  std::vector<FeatureStruct> lowerStreamFeatureList;
201  lowerStreamFeatureList.clear();
202 
203  if (!line)
204  {
205  // Compute the spatial filter of the lower stream
206  UpperLeftCorner[0] = x * m_StreamSize[0];
207  UpperLeftCorner[1] = m_StreamSize[1] * (y - 1);
208 
209  LowerRightCorner[0] = m_StreamSize[0] * x + m_Radius;
210  LowerRightCorner[1] = m_StreamSize[1] * y - 1;
211  }
212  else
213  {
214  // Compute the spatial filter of the right stream
215  UpperLeftCorner[0] = (x - 1) * m_StreamSize[0];
216  UpperLeftCorner[1] = m_StreamSize[1] * y;
217 
218  LowerRightCorner[0] = m_StreamSize[0] * x - 1;
219  LowerRightCorner[1] = m_StreamSize[1] * y + m_Radius;
220  }
221 
222  inputImage->TransformIndexToPhysicalPoint(UpperLeftCorner, ulCorner);
223  inputImage->TransformIndexToPhysicalPoint(LowerRightCorner, lrCorner);
224 
225  m_OGRLayer.SetSpatialFilterRect(ulCorner[0], lrCorner[1], lrCorner[0], ulCorner[1]);
226 
227  for (featIt = m_OGRLayer.begin(); featIt != m_OGRLayer.end(); ++featIt)
228  {
229  if (upperFIDs.find((*featIt).GetFID()) == upperFIDs.end())
230  {
231  FeatureStruct s(m_OGRLayer.GetLayerDefn());
232  s.feat = *featIt;
233  s.fusioned = false;
234  lowerStreamFeatureList.push_back(s);
235  }
236  }
237 
238  unsigned int nbUpperPolygons = upperStreamFeatureList.size();
239  unsigned int nbLowerPolygons = lowerStreamFeatureList.size();
240  std::vector<FusionStruct> fusionList;
241  fusionList.clear();
242  for (unsigned int u = 0; u < nbUpperPolygons; u++)
243  {
244  for (unsigned int l = 0; l < nbLowerPolygons; l++)
245  {
246  FeatureStruct upper = upperStreamFeatureList[u];
247  FeatureStruct lower = lowerStreamFeatureList[l];
248  if (!(upper.feat == lower.feat) && upper.feat.GetGeometry()->IsValid() && lower.feat.GetGeometry()->IsValid())
249  {
250  if (ogr::Intersects(*upper.feat.GetGeometry(), *lower.feat.GetGeometry()))
251  {
252  ogr::UniqueGeometryPtr intersection2 = ogr::Intersection(*upper.feat.GetGeometry(), *lower.feat.GetGeometry());
253  ogr::UniqueGeometryPtr intersection = ogr::Intersection(*intersection2, streamLine);
254  // ogr::UniqueGeometryPtr intersection = ogr::Intersection(*upper.feat.GetGeometry(),*lower.feat.GetGeometry());
255  if (intersection)
256  {
257  FusionStruct fusion;
258  fusion.indStream1 = u;
259  fusion.indStream2 = l;
260  fusion.overlap = 0.;
261 
262  if (intersection->getGeometryType() == wkbPolygon)
263  {
264  fusion.overlap = dynamic_cast<OGRPolygon*>(intersection.get())->get_Area();
265  }
266  else if (intersection->getGeometryType() == wkbMultiPolygon)
267  {
268  fusion.overlap = dynamic_cast<OGRMultiPolygon*>(intersection.get())->get_Area();
269  }
270  else if (intersection->getGeometryType() == wkbGeometryCollection)
271  {
272  fusion.overlap = dynamic_cast<OGRGeometryCollection*>(intersection.get())->get_Area();
273  }
274  else if (intersection->getGeometryType() == wkbLineString)
275  {
276  fusion.overlap = dynamic_cast<OGRLineString*>(intersection.get())->get_Length();
277  }
278  else if (intersection->getGeometryType() == wkbMultiLineString)
279  {
280  fusion.overlap = dynamic_cast<OGRMultiLineString*>(intersection.get())->get_Length();
281  }
282 
287  fusionList.push_back(fusion);
288  }
289  }
290  }
291  }
292  }
293  unsigned int fusionListSize = fusionList.size();
294  std::sort(fusionList.begin(), fusionList.end(), SortFeature);
295  for (unsigned int i = 0; i < fusionListSize; i++)
296  {
297  FeatureStruct upper = upperStreamFeatureList.at(fusionList.at(i).indStream1);
298  FeatureStruct lower = lowerStreamFeatureList.at(fusionList.at(i).indStream2);
299  if (!upper.fusioned && !lower.fusioned)
300  {
301  upperStreamFeatureList[fusionList[i].indStream1].fusioned = true;
302  lowerStreamFeatureList[fusionList[i].indStream2].fusioned = true;
303  ogr::UniqueGeometryPtr fusionPolygon = ogr::Union(*upper.feat.GetGeometry(), *lower.feat.GetGeometry());
304  OGRFeatureType fusionFeature(m_OGRLayer.GetLayerDefn());
305  fusionFeature.SetGeometry(fusionPolygon.get());
307 
308  ogr::Field field = upper.feat[0];
309  try
310  {
311  switch (field.GetType())
312  {
313  case OFTInteger64:
314  {
315  fusionFeature[0].SetValue(field.GetValue<GIntBig>());
316  break;
317  }
318  default:
319  {
320  fusionFeature[0].SetValue(field.GetValue<int>());
321  }
322  }
323  m_OGRLayer.CreateFeature(fusionFeature);
324  m_OGRLayer.DeleteFeature(lower.feat.GetFID());
325  m_OGRLayer.DeleteFeature(upper.feat.GetFID());
326  }
327  catch (itk::ExceptionObject& err)
328  {
329  otbWarningMacro(<< "An exception was caught during fusion: " << err);
330  }
331  }
332  }
333 
334  // Update progress
335  progress.CompletedPixel();
336 
337  } // end for x
338 
339  if (m_OGRLayer.ogr().TestCapability("Transactions"))
340  {
341 
342  OGRErr errCommitX = m_OGRLayer.ogr().CommitTransaction();
343  if (errCommitX != OGRERR_NONE)
344  {
345  itkExceptionMacro(<< "Unable to commit transaction for OGR layer " << m_OGRLayer.ogr().GetName() << ".");
346  }
347  }
348  } // end for y
349 }
350 template <class TImage>
352 {
353  if (!m_OGRLayer)
354  {
355  itkExceptionMacro(<< "Input OGR layer is null!");
356  }
357 
358  this->InvokeEvent(itk::StartEvent());
359 
360  typename InputImageType::ConstPointer inputImage = this->GetInput();
361 
362  // compute the number of stream division in row and column
363  SizeType imageSize = this->GetInput()->GetLargestPossibleRegion().GetSize();
364  unsigned int nbRowStream = static_cast<unsigned int>(imageSize[1] / m_StreamSize[1] + 1);
365  unsigned int nbColStream = static_cast<unsigned int>(imageSize[0] / m_StreamSize[0] + 1);
366 
367  itk::ProgressReporter progress(this, 0, 2 * nbRowStream * nbColStream, 100, 0);
368  // Process column
369  this->ProcessStreamingLine(false, progress);
370  // Process row
371  this->ProcessStreamingLine(true, progress);
372 
373  this->InvokeEvent(itk::EndEvent());
374 }
375 
376 
377 } // end namespace otb
378 
379 #endif
otb::OGRLayerStreamStitchingFilter::InputImageType
TInputImage InputImageType
Definition: otbOGRLayerStreamStitchingFilter.h:65
otb::OGRLayerStreamStitchingFilter::FeatureStruct::feat
OGRFeatureType feat
Definition: otbOGRLayerStreamStitchingFilter.h:125
otb::OGRLayerStreamStitchingFilter::FusionStruct
Definition: otbOGRLayerStreamStitchingFilter.h:114
otb::OGRLayerStreamStitchingFilter::OGRLayerStreamStitchingFilter
OGRLayerStreamStitchingFilter()
Definition: otbOGRLayerStreamStitchingFilter.hxx:35
otb::OGRLayerStreamStitchingFilter::FeatureStruct::fusioned
bool fusioned
Definition: otbOGRLayerStreamStitchingFilter.h:126
otb::OGRLayerStreamStitchingFilter::FusionStruct::indStream2
unsigned int indStream2
Definition: otbOGRLayerStreamStitchingFilter.h:117
otb::OGRLayerStreamStitchingFilter::OriginType
InputImageType::PointType OriginType
Definition: otbOGRLayerStreamStitchingFilter.h:71
otb
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.
Definition: otbJoinContainer.h:32
otb::OGRLayerStreamStitchingFilter::IndexType
InputImageType::IndexType IndexType
Definition: otbOGRLayerStreamStitchingFilter.h:72
otb::OGRLayerStreamStitchingFilter::SetOGRLayer
void SetOGRLayer(const OGRLayerType &ogrLayer)
Definition: otbOGRLayerStreamStitchingFilter.hxx:58
otb::OGRLayerStreamStitchingFilter::GetOGRLayer
const OGRLayerType & GetOGRLayer(void) const
Definition: otbOGRLayerStreamStitchingFilter.hxx:65
otb::OGRLayerStreamStitchingFilter::m_StreamSize
SizeType m_StreamSize
Definition: otbOGRLayerStreamStitchingFilter.h:152
otb::ogr::UniqueGeometryPtr
boost::interprocess::unique_ptr< OGRGeometry, internal::GeometryDeleter > UniqueGeometryPtr
Definition: otbOGRGeometryWrapper.h:109
otb::OGRLayerStreamStitchingFilter::FusionStruct::overlap
double overlap
Definition: otbOGRLayerStreamStitchingFilter.h:118
otb::OGRLayerStreamStitchingFilter::ProcessStreamingLine
void ProcessStreamingLine(bool line, itk::ProgressReporter &progress)
Definition: otbOGRLayerStreamStitchingFilter.hxx:93
otb::OGRLayerStreamStitchingFilter::GetLengthOGRGeometryCollection
double GetLengthOGRGeometryCollection(OGRGeometryCollection *intersection)
Definition: otbOGRLayerStreamStitchingFilter.hxx:71
otb::ogr::Feature::GetFID
long GetFID() const
Definition: otbOGRFeatureWrapper.hxx:103
otb::OGRLayerStreamStitchingFilter::FusionStruct::indStream1
unsigned int indStream1
Definition: otbOGRLayerStreamStitchingFilter.h:116
otb::OGRLayerStreamStitchingFilter::GetInput
virtual const InputImageType * GetInput(void)
Definition: otbOGRLayerStreamStitchingFilter.hxx:47
otb::ogr::Feature::GetGeometry
OGRGeometry const * GetGeometry() const
Definition: otbOGRFeatureWrapper.hxx:149
otbWarningMacro
#define otbWarningMacro(x)
Definition: otbMacro.h:65
otb::ogr::Intersects
OTBGdalAdapters_EXPORT bool Intersects(OGRGeometry const &lhs, OGRGeometry const &rhs)
Do these features intersect?
otb::ogr::Layer::feature_iter
Implementation class for Feature iterator. This iterator is a single pass iterator....
Definition: otbOGRLayerWrapper.h:348
otb::OGRLayerStreamStitchingFilter::SetInput
virtual void SetInput(const InputImageType *input)
Definition: otbOGRLayerStreamStitchingFilter.hxx:41
otb::ogr::Field
Encapsulation of OGRField Instances of Field are expected to be built from an existing Feature with w...
Definition: otbOGRFieldWrapper.h:117
otbOGRLayerStreamStitchingFilter.h
otb::ogr::Field::GetValue
T GetValue() const
Definition: otbOGRFieldWrapper.hxx:463
otb::ogr::Union
OTBGdalAdapters_EXPORT UniqueGeometryPtr Union(OGRGeometry const &lhs, OGRGeometry const &rhs)
Computes union.
otb::ogr::Feature
Geometric object with descriptive fields.
Definition: otbOGRFeatureWrapper.h:63
otb::OGRLayerStreamStitchingFilter::SizeType
InputImageType::SizeType SizeType
Definition: otbOGRLayerStreamStitchingFilter.h:68
otb::ogr::Layer
Layer of geometric objects.
Definition: otbOGRLayerWrapper.h:80
otb::ogr::Feature::SetGeometry
void SetGeometry(OGRGeometry const *geometry)
Definition: otbOGRFeatureWrapper.hxx:143
otb::ogr::Intersection
OTBGdalAdapters_EXPORT UniqueGeometryPtr Intersection(OGRGeometry const &lhs, OGRGeometry const &rhs)
Computes intersection.
otb::ogr::Field::GetType
OGRFieldType GetType() const
Field type accessor.
Definition: otbOGRFieldWrapper.h:134
otb::OGRLayerStreamStitchingFilter::FeatureStruct
Definition: otbOGRLayerStreamStitchingFilter.h:120
otb::OGRLayerStreamStitchingFilter::GenerateData
void GenerateData() override
Definition: otbOGRLayerStreamStitchingFilter.hxx:351