AliceVision
Photogrammetric Computer Vision Framework
E57Reader.hpp
1 // This file is part of the AliceVision project.
2 // Copyright (c) 2024 AliceVision contributors.
3 // This Source Code Form is subject to the terms of the Mozilla Public License,
4 // v. 2.0. If a copy of the MPL was not distributed with this file,
5 // You can obtain one at https://mozilla.org/MPL/2.0/.
6 
7 #pragma once
8 
9 #include <aliceVision/system/Logger.hpp>
10 
11 #include <Eigen/Dense>
12 
13 #include <E57SimpleData.h>
14 #include <E57SimpleReader.h>
15 
16 namespace aliceVision {
17 namespace dataio {
18 
19 class E57Reader
20 {
21  public:
22  struct PointInfo
23  {
24  unsigned short idMesh;
25  Eigen::Vector3d coords;
26  float intensity;
27  };
28 
29  public:
30  E57Reader(const std::vector<std::string>& paths)
31  : _paths(paths),
32  _idPath(-1),
33  _idMesh(-1),
34  _countMeshesForFile(0),
35  _requiredIntensity(0.0)
36  {}
37 
38  void reset()
39  {
40  _idPath = -1;
41  _idMesh = -1;
42  _countMeshesForFile = 0;
43  }
44 
45  bool getNext(Eigen::Vector3d& sensorPosition, std::vector<PointInfo>& vertices, Eigen::Matrix<size_t, -1, -1>& grid)
46  {
47  // Go to next mesh of current file
48  _idMesh++;
49 
50  // Load next file if needed
51  if (_idMesh >= static_cast<int>(_countMeshesForFile))
52  {
53  _idPath++;
54  _idMesh = 0;
55  if (_idPath >= static_cast<int>(_paths.size()))
56  {
57  return false;
58  }
59 
60  // Create reader
61  _reader = std::make_unique<e57::Reader>(_paths[_idPath], e57::ReaderOptions());
62  if (!_reader->IsOpen())
63  {
64  return false;
65  }
66 
67  e57::E57Root root;
68  if (!_reader->GetE57Root(root))
69  {
70  return false;
71  }
72 
73  // Compute number of meshes in file
74  _countMeshesForFile = _reader->GetData3DCount();
75  }
76 
77  if (_idMesh >= static_cast<int>(_countMeshesForFile))
78  {
79  return false;
80  }
81 
82  if (!_reader)
83  {
84  return false;
85  }
86 
87  // Get header
88  e57::Data3D scanHeader;
89  if (!_reader->ReadData3D(_idMesh, scanHeader))
90  {
91  ALICEVISION_LOG_ERROR("Error reading mesh #" << _idMesh);
92  return false;
93  }
94 
95  // Get sensor pose (worldTsensor)
96  Eigen::Quaternion<double> q(scanHeader.pose.rotation.w, scanHeader.pose.rotation.x, scanHeader.pose.rotation.y, scanHeader.pose.rotation.z);
97 
98  Eigen::Matrix3d R = q.normalized().toRotationMatrix();
99 
100  Eigen::Vector3d t;
101  t(0) = scanHeader.pose.translation.x;
102  t(1) = scanHeader.pose.translation.y;
103  t(2) = scanHeader.pose.translation.z;
104 
105  int64_t maxRows = 0;
106  int64_t maxColumns = 0;
107  int64_t countPoints = 0;
108  int64_t countGroups = 0;
109  int64_t maxGroupSize = 0;
110  bool isColumnIndex;
111 
112  if (!_reader->GetData3DSizes(0, maxRows, maxColumns, countPoints, countGroups, maxGroupSize, isColumnIndex))
113  {
114  ALICEVISION_LOG_ERROR("Error reading content of mesh #" << _idMesh);
115  return false;
116  }
117 
118  e57::Data3DPointsFloat data3DPoints(scanHeader);
119  e57::CompressedVectorReader datareader = _reader->SetUpData3DPointsData(_idMesh, countPoints, data3DPoints);
120 
121  // Prepare list of vertices
122  vertices.clear();
123  vertices.reserve(countPoints);
124 
125  // Prepare structured grid for sensor
126  grid.resize(maxRows, maxColumns);
127  grid.fill(std::numeric_limits<size_t>::max());
128 
129  unsigned int readCount = 0;
130  while ((readCount = datareader.read()) > 0)
131  {
132  // Check input compatibility
133  if (data3DPoints.sphericalRange != nullptr)
134  {
135  ALICEVISION_LOG_ERROR("Data contains spherical coordinates, this is not currently supported");
136  continue;
137  }
138 
139  if (data3DPoints.cartesianX == nullptr)
140  {
141  ALICEVISION_LOG_ERROR("Data contains no cartesian coordinates");
142  continue;
143  }
144 
145  if (data3DPoints.columnIndex == nullptr)
146  {
147  ALICEVISION_LOG_ERROR("Data contains no 2d column coordinates");
148  continue;
149  }
150 
151  if (data3DPoints.rowIndex == nullptr)
152  {
153  ALICEVISION_LOG_ERROR("Data contains no 2d row coordinates");
154  continue;
155  }
156 
157  if (data3DPoints.intensity == nullptr)
158  {
159  ALICEVISION_LOG_ERROR("Data contains no intensities");
160  continue;
161  }
162 
163  for (unsigned int pos = 0; pos < readCount; pos++)
164  {
165  if (data3DPoints.cartesianInvalidState[pos])
166  {
167  continue;
168  }
169 
170  if (data3DPoints.intensity[pos] < _requiredIntensity)
171  {
172  continue;
173  }
174 
175  Eigen::Vector3d pt;
176  pt(0) = data3DPoints.cartesianX[pos];
177  pt(1) = data3DPoints.cartesianY[pos];
178  pt(2) = data3DPoints.cartesianZ[pos];
179 
180  // Transform point in the world frame
181  PointInfo pi;
182  pi.coords = (R * pt + t);
183  pi.idMesh = _idMesh;
184  pi.intensity = data3DPoints.intensity[pos],
185 
186  grid(data3DPoints.rowIndex[pos], data3DPoints.columnIndex[pos]) = vertices.size();
187  vertices.push_back(pi);
188  }
189  }
190 
191  sensorPosition = t;
192 
193  return true;
194  }
195 
196  bool getNext(Eigen::Vector3d& sensorPosition)
197  {
198  // Go to next mesh of current file
199  _idMesh++;
200 
201  // Load next file if needed
202  if (_idMesh >= static_cast<int>(_countMeshesForFile))
203  {
204  _idPath++;
205  _idMesh = 0;
206  if (_idPath >= static_cast<int>(_paths.size()))
207  {
208  return false;
209  }
210 
211  // Create reader
212  _reader = std::make_unique<e57::Reader>(_paths[_idPath], e57::ReaderOptions());
213  if (!_reader->IsOpen())
214  {
215  return false;
216  }
217 
218  e57::E57Root root;
219  if (!_reader->GetE57Root(root))
220  {
221  return false;
222  }
223 
224  // Compute number of meshes in file
225  _countMeshesForFile = _reader->GetData3DCount();
226  }
227 
228  if (_idMesh >= static_cast<int>(_countMeshesForFile))
229  {
230  return false;
231  }
232 
233  if (!_reader)
234  {
235  return false;
236  }
237 
238  // Get header
239  e57::Data3D scanHeader;
240  if (!_reader->ReadData3D(_idMesh, scanHeader))
241  {
242  ALICEVISION_LOG_ERROR("Error reading mesh #" << _idMesh);
243  return false;
244  }
245 
246  // Get sensor pose (worldTsensor)
247  Eigen::Vector3d t;
248  t(0) = scanHeader.pose.translation.x;
249  t(1) = scanHeader.pose.translation.y;
250  t(2) = scanHeader.pose.translation.z;
251 
252  sensorPosition = t;
253 
254  return true;
255  }
256 
257  int getIdMesh() { return _idMesh; }
258 
259  void setRequiredIntensity(double requirement) { _requiredIntensity = requirement; }
260 
261  private:
262  std::vector<std::string> _paths;
263  std::unique_ptr<e57::Reader> _reader;
264 
265  int _idPath;
266  int _idMesh;
267  size_t _countMeshesForFile;
268  double _requiredIntensity;
269 };
270 
271 } // namespace dataio
272 } // namespace aliceVision
aliceVision::dataio::E57Reader::PointInfo
Definition: E57Reader.hpp:22
aliceVision
Definition: checkerDetector.cpp:32
aliceVision::dataio::E57Reader
Definition: E57Reader.hpp:19