OTB  10.0.0
Orfeo Toolbox
otbVectorDataExtractROI.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 otbVectorDataExtractROI_hxx
22 #define otbVectorDataExtractROI_hxx
23 
25 
27 #include "itkIdentityTransform.h"
28 #include "otbGenericRSTransform.h"
29 
30 #include "otbObjectList.h"
31 #include "otbMacro.h"
32 
33 #include "itkProgressReporter.h"
34 #include "otbStopwatch.h"
35 
36 namespace otb
37 {
38 
42 template <class TVectorData>
43 VectorDataExtractROI<TVectorData>::VectorDataExtractROI() : m_ProjectionNeeded(false), m_ROI(), m_Kept(0)
44 {
45 }
46 
50 template <class TVectorData>
51 void VectorDataExtractROI<TVectorData>::PrintSelf(std::ostream& os, itk::Indent indent) const
52 {
53  Superclass::PrintSelf(os, indent);
54 }
55 
59 template <class TVectorData>
61 {
62  this->AllocateOutputs();
63  typename VectorDataType::ConstPointer inputPtr = this->GetInput();
64  typename VectorDataType::Pointer outputPtr = this->GetOutput();
66 
67  // Find out the projection needed
68  if (!inputPtr->GetProjectionRef().empty())
69  outputPtr->SetProjectionRef(inputPtr->GetProjectionRef());
70 
72  this->CompareInputAndRegionProjection();
73 
75  if (m_ProjectionNeeded)
76  {
77  otbMsgDevMacro(<< "Reprojecting region in vector data projection");
78  this->ProjectRegionToInputVectorProjection();
79  }
80  else
81  {
82  otbMsgDevMacro(<< "Region and vector data projection are similar");
83  m_GeoROI = m_ROI;
84  }
86 
87  otbMsgDevMacro(<< "ROI: " << this->m_ROI);
88  otbMsgDevMacro(<< "GeoROI: " << this->m_GeoROI);
89 
90  // Create the output tree root
91  // DataNodePointerType outputRoot = DataNodeType::New();
92  // outputRoot->SetNodeType(inputPtr->GetRoot()->GetNodeType());
93  // outputRoot->SetNodeId(inputPtr->GetRoot()->GetNodeId());
94  // outputPtr->SetRoot(outputRoot);
95 
96  m_Kept = 0;
97 
98  // Start recursive processing
100  ProcessNode(inputPtr,inputPtr->GetRoot(),outputPtr,outputPtr->GetRoot());
101  chrono.Stop();
102  otbMsgDevMacro(<< "VectorDataExtractROI: " << m_Kept << " features processed in " << chrono.GetElapsedMilliseconds() << " ms.");
103 } /*End GenerateData()*/
104 
105 template <class TVectorData>
107 {
108  // Get the children list from the input node
109  ChildrenListType children = inputVdata->GetChildrenList(source);
110  // For each child
111  for (typename ChildrenListType::iterator it = children.begin(); it != children.end(); ++it)
112  {
113  DataNodePointerType dataNode = (*it);
114  DataNodePointerType newDataNode = DataNodeType::New();
115  newDataNode->SetNodeType(dataNode->GetNodeType());
116  newDataNode->SetNodeId(dataNode->GetNodeId());
117  newDataNode->SetMetaDataDictionary(dataNode->GetMetaDataDictionary());
118 
119  switch (dataNode->GetNodeType())
120  {
121  case ROOT:
122  {
123  //outputVdata->Add(newDataNode,destination);
124  //ProcessNode(inputVdata,(*it), outputVdata, newDataNode);
125  //++m_Kept;
126  break;
127  }
128  case DOCUMENT:
129  {
130  outputVdata->Add(newDataNode,destination);
131  ++m_Kept;
132  ProcessNode(inputVdata,(*it), outputVdata, newDataNode);
133  break;
134  }
135  case FOLDER:
136  {
137  outputVdata->Add(newDataNode,destination);
138  ++m_Kept;
139  ProcessNode(inputVdata,(*it), outputVdata, newDataNode);
140  break;
141  }
142  case FEATURE_POINT:
143  {
144  if (m_GeoROI.IsInside(this->PointToContinuousIndex(dataNode->GetPoint())))
145  {
146  newDataNode->SetPoint(dataNode->GetPoint());
147  outputVdata->Add(newDataNode,destination);
148  ++m_Kept;
149  }
150  break;
151  }
152  case FEATURE_LINE:
153  {
154  if (this->IsLineIntersectionNotNull(dataNode->GetLine()))
155  {
156  newDataNode->SetLine(dataNode->GetLine());
157  outputVdata->Add(newDataNode,destination);
158  ++m_Kept;
159  }
160  break;
161  }
162  case FEATURE_POLYGON:
163  {
164  if (this->IsPolygonIntersectionNotNull(dataNode->GetPolygonExteriorRing()))
165  {
166  newDataNode->SetPolygonExteriorRing(dataNode->GetPolygonExteriorRing());
167  newDataNode->SetPolygonInteriorRings(dataNode->GetPolygonInteriorRings());
168  outputVdata->Add(newDataNode,destination);
169  ++m_Kept;
170  }
171  break;
172  }
173  case FEATURE_MULTIPOINT:
174  {
175  outputVdata->Add(newDataNode,destination);
176  ++m_Kept;
177  ProcessNode(inputVdata,(*it), outputVdata, newDataNode);
178  break;
179  }
180  case FEATURE_MULTILINE:
181  {
182  outputVdata->Add(newDataNode,destination);
183  ++m_Kept;
184  ProcessNode(inputVdata,(*it), outputVdata, newDataNode);
185  break;
186  }
188  {
189  outputVdata->Add(newDataNode,destination);
190  ++m_Kept;
191  ProcessNode(inputVdata,(*it), outputVdata, newDataNode);
192  break;
193  }
194  case FEATURE_COLLECTION:
195  {
196  outputVdata->Add(newDataNode,destination);
197  ++m_Kept;
198  ProcessNode(inputVdata,(*it), outputVdata, newDataNode);
199  break;
200  }
201  }
202  }
203 }
204 
208 template <class TVectorData>
210 {
211  // Get the VertexList
212  // -2 cause we don't want the last point
213  // which is the same as the first one (closed Ring)
214  for (unsigned int i = 0; i < polygon->GetVertexList()->Size() - 2; ++i)
215  {
216  // Get the components of the polygon 2 by 2
217  VertexType firstVertex;
218  VertexType secondVertex;
219  firstVertex = polygon->GetVertexList()->GetElement(i);
220  secondVertex = polygon->GetVertexList()->GetElement(i + 1);
222 
223  // Build a line with each two vertex
224  typename LineType::Pointer line = LineType::New();
225  line->AddVertex(firstVertex);
226  line->AddVertex(secondVertex);
227 
228  if (this->IsLineIntersectionNotNull(line))
229  return true;
230  }
231  return false;
232 }
233 
237 template <class TVectorData>
239 {
240  RegionType lineRegion(line->GetBoundingRegion());
241 
242  // if the line bounding box have a null
243  // intersection with the geoROI
244  // the line and the region do not intersect
245  if (!lineRegion.Crop(m_GeoROI))
246  {
247  return false;
248  }
249  else
250  {
251  // Get the VertexList
252  for (unsigned int i = 0; i < line->GetVertexList()->Size() - 1; ++i)
253  {
254  // Get the components of the line 2 by 2
255  VertexType firstVertex;
256  VertexType secondVertex;
257  firstVertex = line->GetVertexList()->GetElement(i);
258  secondVertex = line->GetVertexList()->GetElement(i + 1);
259 
260  // -------------------
261  // Case 1 : Check if one of the two points are in the region
262  PointType firstPoint, secondPoint;
263  firstPoint[0] = firstVertex[0];
264  firstPoint[1] = firstVertex[1];
265 
266  secondPoint[0] = secondVertex[0];
267  secondPoint[1] = secondVertex[1];
268 
269  if (m_GeoROI.IsInside(this->PointToContinuousIndex(firstPoint)) || m_GeoROI.IsInside(this->PointToContinuousIndex(secondPoint)))
270  {
271  return true;
272  }
273  else
274  {
275  // -------------------
276  // Case 2 : If any of the point is in the region
277  if (!m_GeoROI.IsInside(this->PointToContinuousIndex(firstPoint)) && !m_GeoROI.IsInside(this->PointToContinuousIndex(secondPoint)))
278  {
279  // Build a line with each two vertex
280  typename LineType::Pointer tempLine = LineType::New();
281  tempLine->AddVertex(firstVertex);
282  tempLine->AddVertex(secondVertex);
283 
284  // Check if the intersection is not null
285  RegionType region(tempLine->GetBoundingRegion());
286  if (region.Crop(m_GeoROI))
287  return true;
288 
289  // -------------------
290  // TODO : check if the segment cut
291  // one of the region edges
292  }
293  }
294  }
295  }
296 
297  return false;
298 }
299 
300 
301 template <class TVectorData>
303 {
304 
305  PointType vertexA, vertexB, vertexC, vertexD;
306 
307  vertexA = segmentLineAB->GetVertexList()->GetElement(0);
308  vertexB = segmentLineAB->GetVertexList()->GetElement(1);
309  vertexC = segmentLineCD->GetVertexList()->GetElement(0);
310  vertexD = segmentLineCD->GetVertexList()->GetElement(1);
311 
312  int CounterClockWiseValueWithC = CounterClockWise(vertexA, vertexB, vertexC);
313  int CounterClockWiseValueWithD = CounterClockWise(vertexA, vertexB, vertexD);
314 
315  if (CounterClockWiseValueWithC == CounterClockWiseValueWithD)
316  {
317  return false;
318  }
319  int CounterClockWiseValueWithA = CounterClockWise(vertexC, vertexD, vertexA);
320  int CounterClockWiseValueWithB = CounterClockWise(vertexC, vertexD, vertexB);
321 
322  if (CounterClockWiseValueWithA == CounterClockWiseValueWithB)
323  {
324  return false;
325  }
326 
327  return true;
328 }
329 
330 template <class TVectorData>
332 {
333  PointType SecondMinusFirstPoint;
334  PointType ThirdMinusFirstPoint;
335 
336  SecondMinusFirstPoint = secondPoint - firstPoint;
337  ThirdMinusFirstPoint = thirdPoint - firstPoint;
338 
339  double dX1dY2MinusdY1dX2;
340  dX1dY2MinusdY1dX2 = static_cast<double>(SecondMinusFirstPoint[0] * ThirdMinusFirstPoint[1] - SecondMinusFirstPoint[1] * ThirdMinusFirstPoint[0]);
341  if (dX1dY2MinusdY1dX2 > 0.0)
342  {
343  return 1;
344  }
345  if (dX1dY2MinusdY1dX2 < 0.0)
346  {
347  return -1;
348  }
349 
350  double dX1dX2;
351  double dY1dY2;
352  dX1dX2 = static_cast<double>(SecondMinusFirstPoint[0] * ThirdMinusFirstPoint[0]);
353  dY1dY2 = static_cast<double>(SecondMinusFirstPoint[1] * ThirdMinusFirstPoint[1]);
354  if ((dX1dX2 < 0.0) || (dY1dY2 < 0.0))
355  {
356  return -1;
357  }
358 
359  double dX1dX1, dX2dX2, dY1dY1, dY2dY2;
360  dX1dX1 = static_cast<double>(SecondMinusFirstPoint[0] * SecondMinusFirstPoint[0]);
361  dX2dX2 = static_cast<double>(ThirdMinusFirstPoint[0] * ThirdMinusFirstPoint[0]);
362  dY1dY1 = static_cast<double>(SecondMinusFirstPoint[1] * SecondMinusFirstPoint[1]);
363  dY2dY2 = static_cast<double>(ThirdMinusFirstPoint[1] * ThirdMinusFirstPoint[1]);
364 
365  if ((dX1dX1 + dY1dY1) < (dX2dX2 + dY2dY2))
366  {
367  return 1;
368  }
369 
370  return 0;
371 }
372 
373 
377 template <class TVectorData>
379 {
380  std::string regionProjection = m_ROI.GetRegionProjection();
381  std::string inputVectorProjection = this->GetInput()->GetProjectionRef();
383 
384  // FIXME: the string comparison is not sufficient to say that two
385  // projections are different
386  if (regionProjection == inputVectorProjection)
387  m_ProjectionNeeded = false;
388  else
389  m_ProjectionNeeded = true;
390 }
391 
395 template <class TVectorData>
397 {
398  /* Use the RS Generic projection */
399  typedef otb::GenericRSTransform<> GenericRSTransformType;
400  typename GenericRSTransformType::Pointer genericTransform = GenericRSTransformType::New();
402 
404  genericTransform->SetInputProjectionRef(m_ROI.GetRegionProjection());
405  genericTransform->SetInputImageMetadata(&(m_ROI.GetImageMetadata()));
406  genericTransform->SetOutputProjectionRef(this->GetInput()->GetProjectionRef());
407  //TODO: const itk::MetaDataDictionary& inputDict = this->GetInput()->GetMetaDataDictionary();
408  //TODO: genericTransform->SetOutputImageMetadata(this->GetInput()->GetImageMetadata());
409  genericTransform->SetOutputOrigin(this->GetInput()->GetOrigin());
410  genericTransform->SetOutputSpacing(this->GetInput()->GetSpacing());
411  genericTransform->InstantiateTransform();
413 
414  otbMsgDevMacro(<< genericTransform);
415 
416  typename VertexListType::Pointer regionCorners = VertexListType::New();
417  ProjPointType point1, point2, point3, point4;
418 
420  point1[0] = m_ROI.GetOrigin()[0];
421  point1[1] = m_ROI.GetOrigin()[1];
423 
424  point2[0] = m_ROI.GetOrigin()[0] + m_ROI.GetSize()[0];
425  point2[1] = m_ROI.GetOrigin()[1];
426 
427  point3[0] = m_ROI.GetOrigin()[0] + m_ROI.GetSize()[0];
428  point3[1] = m_ROI.GetOrigin()[1] + m_ROI.GetSize()[1];
429 
430  point4[0] = m_ROI.GetOrigin()[0];
431  point4[1] = m_ROI.GetOrigin()[1] + m_ROI.GetSize()[1];
432 
434  regionCorners->InsertElement(regionCorners->Size(), this->PointToContinuousIndex(genericTransform->TransformPoint(point1)));
435  regionCorners->InsertElement(regionCorners->Size(), this->PointToContinuousIndex(genericTransform->TransformPoint(point2)));
436  regionCorners->InsertElement(regionCorners->Size(), this->PointToContinuousIndex(genericTransform->TransformPoint(point3)));
437  regionCorners->InsertElement(regionCorners->Size(), this->PointToContinuousIndex(genericTransform->TransformPoint(point4)));
439 
441  m_GeoROI = this->ComputeVertexListBoundingRegion(regionCorners.GetPointer());
442  m_GeoROI.SetRegionProjection(this->GetInput()->GetProjectionRef());
443 }
444 
448 template <class TVectorData>
450 {
451 
452  VertexType vertex;
453 
454  vertex[0] = point[0];
455  vertex[1] = point[1];
456 
457  return vertex;
458 }
459 
463 template <class TVectorData>
465 VectorDataExtractROI<TVectorData>::ComputeVertexListBoundingRegion(typename VertexListType::ConstPointer vertexlist)
466 {
467  double x = 0., y = 0.;
468  IndexType index;
469  IndexType maxId;
470  SizeType size;
471 
472  index.Fill(0.);
473  maxId.Fill(0.);
474  size.Fill(0.);
475 
476  typename VertexListType::ConstIterator it = vertexlist->Begin();
477 
478  if (vertexlist->Size() > 0)
479  {
480  x = static_cast<double>(it.Value()[0]);
481  y = static_cast<double>(it.Value()[1]);
482  index[0] = x;
483  index[1] = y;
484  maxId[0] = x;
485  maxId[1] = y;
486 
487  ++it;
488  while (it != vertexlist->End())
489  {
490  x = static_cast<double>(it.Value()[0]);
491  y = static_cast<double>(it.Value()[1]);
492 
493  // Index search
494  if (x < index[0])
495  {
496  index[0] = x;
497  }
498  if (y > index[1])
499  {
500  index[1] = y;
501  }
502  // Max Id search for size computation
503  if (x > maxId[0])
504  {
505  maxId[0] = x;
506  }
507  if (y < maxId[1])
508  {
509  maxId[1] = y;
510  }
511 
512  ++it;
513  }
514 
515  size[0] = maxId[0] - index[0];
516  size[1] = maxId[1] - index[1];
517  }
518 
519  RegionType region;
520  region.SetSize(size);
521  region.SetOrigin(index);
522 
523  return region;
524 }
525 
526 } // end namespace otb
527 
528 #endif
This is the class to handle generic remote sensing transform.
void SetSize(const SizeType &size)
bool Crop(const Self &region)
void SetOrigin(const IndexType &index)
Stopwatch timer.
Definition: otbStopwatch.h:42
static Stopwatch StartNew()
DurationType GetElapsedMilliseconds() const
virtual VertexType PointToContinuousIndex(ProjPointType point)
DataNodeType::Pointer DataNodePointerType
DataNodeType::LinePointerType LinePointerType
itk::Point< typename VertexType::CoordRepType, IndexType::IndexDimension > ProjPointType
VectorDataType::ConstPointer VectorDataConstPointerType
DataNodeType::PointType PointType
bool IsSegmentIntersectSegment(LinePointerType segmentLineAB, LinePointerType segmentLineCD)
VectorDataType::ChildrenListType ChildrenListType
virtual bool IsLineIntersectionNotNull(LinePointerType line)
int CounterClockWise(PointType firstPoint, PointType secondPoint, PointType thirdPoint)
void PrintSelf(std::ostream &os, itk::Indent indent) const override
RegionType::IndexType IndexType
virtual bool IsPolygonIntersectionNotNull(PolygonPointerType polygon)
virtual RegionType ComputeVertexListBoundingRegion(typename VertexListType::ConstPointer vertexlist)
DataNodeType::PolygonPointerType PolygonPointerType
PolygonType::VertexType VertexType
virtual void ProcessNode(VectorDataConstPointerType inputVdata, DataNodePointerType source, VectorDataPointerType outputVdata, DataNodePointerType destination)
virtual void ProjectRegionToInputVectorProjection()
VectorDataType::Pointer VectorDataPointerType
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.
@ FEATURE_POLYGON
Definition: otbDataNode.h:45
@ FEATURE_MULTIPOINT
Definition: otbDataNode.h:46
@ FEATURE_MULTIPOLYGON
Definition: otbDataNode.h:48
@ FOLDER
Definition: otbDataNode.h:42
@ FEATURE_MULTILINE
Definition: otbDataNode.h:47
@ DOCUMENT
Definition: otbDataNode.h:41
@ ROOT
Definition: otbDataNode.h:40
@ FEATURE_POINT
Definition: otbDataNode.h:43
@ FEATURE_COLLECTION
Definition: otbDataNode.h:49
@ FEATURE_LINE
Definition: otbDataNode.h:44
#define otbMsgDevMacro(x)
Definition: otbMacro.h:116