ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
IcmFilter.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #include "IcmFilter.h"
9 
10 // CV_CORE_LIB
11 #include <CVLog.h>
12 
13 // CV_DB_LIB
14 #include <ecvCameraSensor.h>
15 #include <ecvImage.h>
16 
17 // Qt
18 #include <QFileInfo>
19 
20 // system
21 #include <assert.h>
22 #include <stdio.h>
23 
24 // Max number of characters per line in an ASCII file
25 // TODO: use QFile instead!
26 const int MAX_ASCII_FILE_LINE_LENGTH = 4096;
27 
29  : FileIOFilter(
30  {"_ICM Filter",
31  DEFAULT_PRIORITY, // priority
32  QStringList{"icm"}, "icm",
33  QStringList{"Clouds + calibrated images [meta][ascii] (*.icm)"},
34  QStringList(), Import}) {}
35 
37  ccHObject& container,
38  LoadParameters& parameters) {
41  QString("[ICM] Input filename contains special characters. It "
42  "might be rejected by the I/O filter..."));
43  }
44 
45  // ouverture du fichier
46  FILE* fp = fopen(qPrintable(filename), "rt");
47  if (!fp) {
48  return CC_FERR_READING;
49  }
50 
51  // buffer
52  char line[MAX_ASCII_FILE_LINE_LENGTH];
53 
54  // lecture du header
55  if (!fgets(line, MAX_ASCII_FILE_LINE_LENGTH, fp)) {
56  fclose(fp);
57  return CC_FERR_READING;
58  }
59 
60  if (strncmp(line, "#CC_ICM_FILE", 12) != 0) {
61  fclose(fp);
63  }
64 
65  // on extrait le chemin relatif
66  QString path = QFileInfo(filename).absolutePath();
67 
68  char cloudFileName[MAX_ASCII_FILE_LINE_LENGTH];
69  if (!fgets(line, MAX_ASCII_FILE_LINE_LENGTH, fp)) {
70  fclose(fp);
71  return CC_FERR_READING;
72  }
73  if (strncmp(line, "FILE_NAME=", 10) != 0) {
74  fclose(fp);
76  }
77  sscanf(line, "FILE_NAME=%s", cloudFileName);
78 
79  char subFileType[12];
80  if (!fgets(line, MAX_ASCII_FILE_LINE_LENGTH, fp)) {
81  fclose(fp);
82  return CC_FERR_READING;
83  }
84  if (strncmp(line, "FILE_TYPE=", 10) != 0) {
85  fclose(fp);
87  }
88  sscanf(line, "FILE_TYPE=%s", subFileType);
89 
90  FileIOFilter::Shared filter =
92  if (!filter) {
93  CVLog::Warning(QString("[ICM] No I/O filter found for loading file "
94  "'%1' (type = '%2')")
95  .arg(cloudFileName, subFileType));
96  fclose(fp);
97  return CC_FERR_UNKNOWN_FILE;
98  }
99 
100  // load the corresponding file (potentially containing several clouds)
103  QString("%1/%2").arg(path, cloudFileName), parameters, filter,
104  result);
105  if (!entities) {
106  fclose(fp);
107  return CC_FERR_READING;
108  }
109 
110  container.addChild(entities);
111 
112  // chargement des images
113  if (!fgets(line, MAX_ASCII_FILE_LINE_LENGTH, fp)) {
114  CVLog::Error("[ICM] Read error (IMAGES_DESCRIPTOR)! No image loaded");
115  fclose(fp);
116  return CC_FERR_READING;
117  } else {
118  if (strncmp(line, "IMAGES_DESCRIPTOR=", 18) != 0) {
119  fclose(fp);
121  }
122  char imagesDescriptorFileName[MAX_ASCII_FILE_LINE_LENGTH];
123  sscanf(line, "IMAGES_DESCRIPTOR=%s", imagesDescriptorFileName);
124 
125  int n = LoadCalibratedImages(entities, path, imagesDescriptorFileName,
126  entities->getBB_recursive());
127  CVLog::Print("[ICM] %i image(s) loaded ...", n);
128  }
129 
130  fclose(fp);
131  return CC_FERR_NO_ERROR;
132 }
133 
135  const QString& path,
136  const QString& imageDescFilename,
137  const ccBBox& globalBBox) {
138  assert(entities);
139 
140  // ouverture du fichier
141  QString completeImageDescFilename =
142  QString("%1/%2").arg(path, imageDescFilename);
143 
144  if (CheckForSpecialChars(completeImageDescFilename)) {
145  CVLog::Warning(QString("[ICM] File '%1' contains special characters. "
146  "It might be rejected by the I/O filter...")
147  .arg(completeImageDescFilename));
148  }
149 
150  FILE* fp = fopen(qPrintable(completeImageDescFilename), "rt");
151  if (fp == nullptr) {
152  CVLog::Error(QString("[IcmFilter::loadCalibratedImages] Error opening "
153  "file %1!")
154  .arg(completeImageDescFilename));
155  return -1;
156  }
157 
158  // buffers
159  char line[MAX_ASCII_FILE_LINE_LENGTH];
160 #ifdef INCLUDE_PHOTOS
161  char totalFileName[256];
162 #endif
163  int loadedImages = 0;
164 
165  // IL FAUDRAIT ETRE PLUS SOUPLE QUE CA !!!
166  while (fgets(line, MAX_ASCII_FILE_LINE_LENGTH, fp) != nullptr) {
167  if (line[0] == 'D' && line[1] == 'E' && line[2] == 'F') {
168  char imageFileName[256];
169  sscanf(line, "DEF %s Viewpoint {", imageFileName);
170 
171  // add absolute path
172  ccImage* CI = new ccImage();
173  QString errorStr;
174  if (!CI->load(QString("%1/%2").arg(path, imageFileName),
175  errorStr)) {
176  CVLog::Warning(QString("[IcmFilter] Failed to load image %1 "
177  "(%2)! Process stopped...")
178  .arg(imageFileName, errorStr));
179  delete CI;
180  fclose(fp);
181  return loadedImages;
182  }
183 
184  CVLog::Print("[IcmFilter] Image '%s' loaded", imageFileName);
185  CI->setEnabled(false);
186  CI->setName(imageFileName);
187 #ifdef INCLUDE_PHOTOS
188  CI->setCompleteFileName(totalFileName);
189 #endif
190 
191  // FOV
192  if (!fgets(line, MAX_ASCII_FILE_LINE_LENGTH, fp)) {
193  CVLog::Print("[IcmFilter] Read error (fieldOfView)!");
194  delete CI;
195  fclose(fp);
196  return loadedImages;
197  }
198 
199  float fov_rad = 0;
200  sscanf(line, "\t fieldOfView %f\n", &fov_rad);
201 
202  float fov_deg = cloudViewer::RadiansToDegrees(fov_rad);
203  CVLog::Print("\t FOV=%f (degrees)", fov_deg);
204 
205  // Position
206  float t[3];
207  if (!fgets(line, MAX_ASCII_FILE_LINE_LENGTH, fp)) {
208  CVLog::Error("[IcmFilter] Read error (position)!");
209  // delete CI;
210  fclose(fp);
211  return loadedImages;
212  }
213  sscanf(line, "\t position %f %f %f\n", t, t + 1, t + 2);
214 
215  CVLog::Print("\t Camera pos=(%f,%f,%f)", t[0], t[1], t[2]);
216 
217  // Description
218  char desc[MAX_ASCII_FILE_LINE_LENGTH];
219  if (!fgets(line, MAX_ASCII_FILE_LINE_LENGTH, fp)) {
220  CVLog::Error("[IcmFilter] Read error (description)!");
221  // delete CI;
222  fclose(fp);
223  return loadedImages;
224  }
225  sscanf(line, "\t description \"%s\"\n", desc);
226 
227  // CI->setDescription(desc);
228  CVLog::Print("\t Description: '%s'", desc);
229 
230  // Orientation
231  float axis[3], angle_rad;
232  if (!fgets(line, MAX_ASCII_FILE_LINE_LENGTH, fp)) {
233  CVLog::Error("[IcmFilter] Read error (orientation)!");
234  fclose(fp);
235  return loadedImages;
236  }
237  sscanf(line, "\t orientation %f %f %f %f\n", axis, axis + 1,
238  axis + 2, &angle_rad);
239 
240  CVLog::Print("\t Camera orientation=(%f,%f,%f)+[%f]", axis[0],
241  axis[1], axis[2], angle_rad);
242 
244  params.vFOV_rad = fov_rad;
245  params.arrayWidth = CI->getW();
246  params.arrayHeight = CI->getH();
247  params.principal_point[0] = params.arrayWidth / 2.0f;
248  params.principal_point[1] = params.arrayHeight / 2.0f;
249  params.vertFocal_pix = 1.0f; // default focal (for the 3D symbol)
250  params.pixelSize_mm[0] = params.pixelSize_mm[1] = 1.0f;
251  ccCameraSensor* sensor = new ccCameraSensor(params);
252 
253  ccGLMatrix mat;
254  mat.initFromParameters(angle_rad, CCVector3::fromArray(axis),
256  sensor->setRigidTransformation(mat);
257 
258  sensor->setGraphicScale(globalBBox.getDiagNorm() / 20);
259  sensor->setVisible(true);
260  sensor->setEnabled(false);
261  CI->addChild(sensor);
262  CI->setAssociatedSensor(sensor);
263 
264  entities->addChild(CI);
265  ++loadedImages;
266  }
267  }
268 
269  fclose(fp);
270 
271  return loadedImages;
272 }
273 //*/
std::string filename
CC_FILE_ERROR
Typical I/O filter errors.
Definition: FileIOFilter.h:20
@ CC_FERR_UNKNOWN_FILE
Definition: FileIOFilter.h:23
@ CC_FERR_NO_ERROR
Definition: FileIOFilter.h:21
@ CC_FERR_READING
Definition: FileIOFilter.h:26
@ CC_FERR_WRONG_FILE_TYPE
Definition: FileIOFilter.h:24
const int MAX_ASCII_FILE_LINE_LENGTH
Definition: IcmFilter.cpp:26
cmdLineReadable * params[]
core::Tensor result
Definition: VtkUtils.cpp:76
static bool Warning(const char *format,...)
Prints out a formatted warning message in console.
Definition: CVLog.cpp:133
static bool Print(const char *format,...)
Prints out a formatted message in console.
Definition: CVLog.cpp:113
static bool Error(const char *format,...)
Display an error dialog with formatted message.
Definition: CVLog.cpp:143
Generic file I/O filter.
Definition: FileIOFilter.h:46
static constexpr float DEFAULT_PRIORITY
Definition: FileIOFilter.h:313
static bool CheckForSpecialChars(const QString &filename)
Returns whether special characters are present in the input string.
static Shared FindBestFilterForExtension(const QString &ext)
Returns the best filter (presumably) to open a given file extension.
QSharedPointer< FileIOFilter > Shared
Shared type.
Definition: FileIOFilter.h:97
static ccHObject * LoadFromFile(const QString &filename, LoadParameters &parameters, Shared filter, CC_FILE_ERROR &result)
Loads one or more entities from a file with a known filter.
static int LoadCalibratedImages(ccHObject *entities, const QString &path, const QString &imageDescFilename, const ccBBox &globalBBox)
Definition: IcmFilter.cpp:134
virtual CC_FILE_ERROR loadFile(const QString &filename, ccHObject &container, LoadParameters &parameters) override
Loads one or more entities from a file.
Definition: IcmFilter.cpp:36
static Vector3Tpl fromArray(const int a[3])
Constructor from an int array.
Definition: CVGeom.h:268
Bounding box structure.
Definition: ecvBBox.h:25
Camera (projective) sensor.
virtual void setVisible(bool state)
Sets entity visibility.
void initFromParameters(T alpha_rad, const Vector3Tpl< T > &axis3D, const Vector3Tpl< T > &t3D)
Inits transformation from a rotation axis, an angle and a translation.
Float version of ccGLMatrixTpl.
Definition: ecvGLMatrix.h:19
Hierarchical CLOUDVIEWER Object.
Definition: ecvHObject.h:25
virtual bool addChild(ccHObject *child, int dependencyFlags=DP_PARENT_OF_OTHER, int insertIndex=-1)
Adds a child.
virtual ccBBox getBB_recursive(bool withGLFeatures=false, bool onlyEnabledChildren=true)
Returns the bounding-box of this entity and it's children.
Generic image.
Definition: ecvImage.h:19
unsigned getW() const
Returns image width.
Definition: ecvImage.h:51
bool load(const QString &filename, QString &error)
Loads image from file.
unsigned getH() const
Returns image height.
Definition: ecvImage.h:54
void setAssociatedSensor(ccCameraSensor *sensor)
Sets associated sensor.
virtual void setName(const QString &name)
Sets object name.
Definition: ecvObject.h:75
virtual void setEnabled(bool state)
Sets the "enabled" property.
Definition: ecvObject.h:102
virtual void setRigidTransformation(const ccGLMatrix &mat)
Definition: ecvSensor.h:99
void setGraphicScale(PointCoordinateType scale)
Sets the sensor graphic representation scale.
Definition: ecvSensor.h:125
T getDiagNorm() const
Returns diagonal length.
Definition: BoundingBox.h:172
static const std::string path
Definition: PointCloud.cpp:59
float RadiansToDegrees(int radians)
Convert radians to degrees.
Definition: CVMath.h:71
Generic loading parameters.
Definition: FileIOFilter.h:51
Intrinsic parameters of the camera sensor.