ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
SalomeHydroFilter.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 "SalomeHydroFilter.h"
9 
10 // CV_DB_LIB
11 #include <CVLog.h>
12 #include <ecvPointCloud.h>
13 #include <ecvPolyline.h>
14 
15 // Qt
16 #include <QFile>
17 #include <QStringList>
18 
19 // Qt5/Qt6 Compatibility
20 #include <QtCompat.h>
21 
23  : FileIOFilter({"_SalomeHydro Filter",
24  DEFAULT_PRIORITY, // priority
25  QStringList{"poly"}, "poly",
26  QStringList{"Salome Hydro polylines (*.poly)"},
27  QStringList{"Salome Hydro polylines (*.poly)"},
28  Import | Export}) {}
29 
31  bool& multiple,
32  bool& exclusive) const {
33  if (type == CV_TYPES::POLY_LINE) {
34  multiple = true;
35  exclusive = true;
36  return true;
37  }
38  return false;
39 }
40 
42  const QString& filename,
43  const SaveParameters& parameters) {
44  if (!entity || filename.isEmpty()) return CC_FERR_BAD_ARGUMENT;
45 
46  // get all polylines
47  std::vector<ccPolyline*> candidates;
48  try {
49  if (entity->isA(CV_TYPES::POLY_LINE)) {
50  candidates.push_back(static_cast<ccPolyline*>(entity));
51  } else if (entity->isA(CV_TYPES::HIERARCHY_OBJECT)) {
52  for (unsigned i = 0; i < entity->getChildrenNumber(); ++i)
53  if (entity->getChild(i) &&
54  entity->getChild(i)->isA(CV_TYPES::POLY_LINE))
55  candidates.push_back(
56  static_cast<ccPolyline*>(entity->getChild(i)));
57  }
58  } catch (const std::bad_alloc&) {
60  }
61 
62  if (candidates.empty()) return CC_FERR_NO_SAVE;
63 
64  // open ASCII file for writing
65  QFile file(filename);
66  if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
67  return CC_FERR_WRITING;
68 
69  QTextStream outFile(&file);
70  const int c_precision = 12;
71 
73 
74  // for each polyline
75  for (size_t i = 0; i < candidates.size(); ++i) {
76  ccPolyline* poly = candidates[i];
77  unsigned vertCount = poly ? poly->size() : 0;
78  if (vertCount < 2) {
79  // invalid size
80  CVLog::Warning(QString("[Salome Hydro] Polyline '%1' does not have "
81  "enough vertices")
82  .arg(poly ? poly->getName()
83  : QStringLiteral("unnamed")));
84  continue;
85  }
86 
87  // a simple empty line is used as separator between each polyline!
88  if (i != 0) outFile << QtCompat::endl;
89 
90  for (unsigned j = 0; j < vertCount; ++j) {
91  const CCVector3* P = poly->getPoint(j);
92 
93  // convert to 'local' coordinate system
94  CCVector3d Pg = poly->toGlobal3d(*P);
95  outFile << QString::number(Pg.x, 'E', c_precision) << " ";
96  outFile << QString::number(Pg.y, 'E', c_precision) << " ";
97  outFile << QString::number(Pg.z, 'E', c_precision)
98  << QtCompat::endl;
99  }
100 
102  }
103 
104  file.close();
105 
106  return result;
107 }
108 
110  ccHObject& container,
111  LoadParameters& parameters) {
112  // we open the file (ASCII mode)
113  QFile file(filename);
114  if (!file.open(QFile::ReadOnly)) {
115  return CC_FERR_READING;
116  }
117  QTextStream stream(&file);
118 
120  CCVector3d Pshift(0, 0, 0);
121  bool preserveCoordinateShift = true;
122  bool firstPoint = true;
123 
124  ccPointCloud* currentVertices = nullptr;
125  unsigned index = 0;
126  while (true) {
127  QString currentLine = stream.readLine().trimmed();
128  if (currentLine.isNull() || currentLine.isEmpty()) {
129  // close any ongoing polyline
130  if (currentVertices) {
131  if (currentVertices->size() < 2) {
132  delete currentVertices;
133  currentVertices = nullptr;
135  "[Salome Hydro] An invalid polyline (single "
136  "vertex) will be ignored");
137  } else {
138  currentVertices->shrinkToFit();
139 
140  // create the corresponding polyline
141  ccPolyline* newPoly = new ccPolyline(currentVertices);
142  newPoly->setName(
143  QString(QString("Polyline #%1").arg(++index)));
144  newPoly->addChild(currentVertices);
145  newPoly->set2DMode(false);
146 
147  if (!newPoly->reserve(currentVertices->size())) {
148  delete newPoly;
150  break;
151  }
152  newPoly->addPointIndex(0, currentVertices->size());
153  currentVertices->setEnabled(false);
154  container.addChild(newPoly);
155  currentVertices = nullptr;
156  }
157  }
158 
159  if (currentLine.isNull()) {
160  // end of file
161  break;
162  }
163  } else {
164  if (!currentVertices) {
165  currentVertices = new ccPointCloud("vertices");
166  if (!firstPoint && preserveCoordinateShift) {
167  currentVertices->setGlobalShift(Pshift);
168  }
169  }
170 
171  QStringList parts = qtCompatSplitRegex(currentLine, "\\s+",
173  if (parts.size() == 3) {
174  //(X,Y,Z)
175  CCVector3d P(parts[0].toDouble(), parts[1].toDouble(),
176  parts[2].toDouble());
177 
178  // first point: check for 'big' coordinates
179  if (firstPoint) {
180  if (HandleGlobalShift(P, Pshift, preserveCoordinateShift,
181  parameters)) {
182  if (preserveCoordinateShift) {
183  currentVertices->setGlobalShift(Pshift);
184  }
186  "[Salome Hydro] Polylines will be recentered! "
187  "Translation: (%.2f ; %.2f ; %.2f)",
188  Pshift.x, Pshift.y, Pshift.z);
189  }
190  firstPoint = false;
191  }
192 
193  // add point
194  if (currentVertices->size() == currentVertices->capacity()) {
195  if (!currentVertices->reserve(currentVertices->size() +
196  64)) {
197  delete currentVertices;
198  currentVertices = 0;
200  break;
201  }
202  }
203  currentVertices->addPoint(CCVector3::fromArray((P + Pshift).u));
204  } else {
206  "[Salome Hydro] Malformed file: 3 values per line "
207  "expected");
209  break;
210  }
211  }
212  }
213 
214  delete currentVertices;
215  currentVertices = nullptr;
216 
217  return result;
218 }
int64_t CV_CLASS_ENUM
Type of object type flags (64 bits)
Definition: CVTypes.h:97
std::string filename
char type
CC_FILE_ERROR
Typical I/O filter errors.
Definition: FileIOFilter.h:20
@ CC_FERR_WRITING
Definition: FileIOFilter.h:25
@ CC_FERR_MALFORMED_FILE
Definition: FileIOFilter.h:32
@ CC_FERR_BAD_ARGUMENT
Definition: FileIOFilter.h:22
@ CC_FERR_NO_SAVE
Definition: FileIOFilter.h:27
@ CC_FERR_NO_ERROR
Definition: FileIOFilter.h:21
@ CC_FERR_READING
Definition: FileIOFilter.h:26
@ CC_FERR_NOT_ENOUGH_MEMORY
Definition: FileIOFilter.h:31
QStringList qtCompatSplitRegex(const QString &str, const QString &pattern, Qt::SplitBehavior behavior=Qt::KeepEmptyParts)
Definition: QtCompat.h:308
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
Generic file I/O filter.
Definition: FileIOFilter.h:46
static constexpr float DEFAULT_PRIORITY
Definition: FileIOFilter.h:313
static bool HandleGlobalShift(const CCVector3d &P, CCVector3d &Pshift, bool &preserveCoordinateShift, LoadParameters &loadParameters, bool useInputCoordinatesShiftIfPossible=false)
Shortcut to the ecvGlobalShiftManager mechanism specific for files.
virtual CC_FILE_ERROR loadFile(const QString &filename, ccHObject &container, LoadParameters &parameters) override
Loads one or more entities from a file.
virtual CC_FILE_ERROR saveToFile(ccHObject *entity, const QString &filename, const SaveParameters &parameters) override
Saves an entity (or a group of) to a file.
virtual bool canSave(CV_CLASS_ENUM type, bool &multiple, bool &exclusive) const override
Returns whether this I/O filter can save the specified type of entity.
Type y
Definition: CVGeom.h:137
Type x
Definition: CVGeom.h:137
Type z
Definition: CVGeom.h:137
static Vector3Tpl fromArray(const int a[3])
Constructor from an int array.
Definition: CVGeom.h:268
Hierarchical CLOUDVIEWER Object.
Definition: ecvHObject.h:25
unsigned getChildrenNumber() const
Returns the number of children.
Definition: ecvHObject.h:312
virtual bool addChild(ccHObject *child, int dependencyFlags=DP_PARENT_OF_OTHER, int insertIndex=-1)
Adds a child.
ccHObject * getChild(unsigned childPos) const
Returns the ith child.
Definition: ecvHObject.h:325
virtual QString getName() const
Returns object name.
Definition: ecvObject.h:72
bool isA(CV_CLASS_ENUM type) const
Definition: ecvObject.h:131
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
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
bool reserve(unsigned numberOfPoints) override
Reserves memory for all the active features.
void shrinkToFit()
Removes unused capacity.
Colored polyline.
Definition: ecvPolyline.h:24
void set2DMode(bool state)
Defines if the polyline is considered as 2D or 3D.
CCVector3d toGlobal3d(const Vector3Tpl< T > &Plocal) const
Returns the point back-projected into the original coordinates system.
virtual void setGlobalShift(double x, double y, double z)
Sets shift applied to original coordinates (information storage only)
void addPoint(const CCVector3 &P)
Adds a 3D point to the database.
unsigned size() const override
Definition: PointCloudTpl.h:38
unsigned capacity() const
Returns cloud capacity (i.e. reserved size)
virtual bool addPointIndex(unsigned globalIndex)
Point global index insertion mechanism.
unsigned size() const override
Returns the number of points.
virtual bool reserve(unsigned n)
Reserves some memory for hosting the point references.
const CCVector3 * getPoint(unsigned index) const override
Returns the ith point.
@ HIERARCHY_OBJECT
Definition: CVTypes.h:103
@ POLY_LINE
Definition: CVTypes.h:112
constexpr Qt::SplitBehavior SkipEmptyParts
Definition: QtCompat.h:302
QTextStream & endl(QTextStream &stream)
Definition: QtCompat.h:718
Generic loading parameters.
Definition: FileIOFilter.h:51
Generic saving parameters.
Definition: FileIOFilter.h:84