18 #include <QTextStream>
35 #include <riegl/rdb.hpp>
47 QStringList{
"rdbx",
"vxls",
"ptch",
"mtch"},
"RDB2",
48 QStringList{
"RDB Pointcloud file (*.rdbx)",
49 "RDB Voxelfile (*.vxls)",
50 "RDB Plane Patch file (*.ptch)",
51 "RDB Match file (*.mtch)"},
57 void updateTable(
RDBOpenDialog &openDlg, riegl::rdb::Pointcloud &rdb) {
58 static const QIcon xIcon(
59 QString::fromUtf8(
":/CC/images/typeXCoordinate.png"));
60 static const QIcon yIcon(
61 QString::fromUtf8(
":/CC/images/typeYCoordinate.png"));
62 static const QIcon zIcon(
63 QString::fromUtf8(
":/CC/images/typeZCoordinate.png"));
64 static const QIcon NormIcon(
65 QString::fromUtf8(
":/CC/images/typeNormal.png"));
66 static const QIcon RGBIcon(
67 QString::fromUtf8(
":/CC/images/typeRgbCcolor.png"));
68 static const QIcon GreyIcon(
69 QString::fromUtf8(
":/CC/images/typeGrayColor.png"));
70 static const QIcon ScalarIcon(QString::fromUtf8(
":/CC/images/typeSF.png"));
72 struct SpecialAttribute {
73 const std::string
name;
74 const std::string comboBoxEntry;
76 SpecialAttribute(
const std::string &arg_name,
77 const std::string &arg_comboBoxEntry,
78 const QIcon &arg_icon)
80 comboBoxEntry(arg_comboBoxEntry),
83 const std::vector<SpecialAttribute> known_special_attributes{
86 {
"riegl.surface_normal",
94 std::vector<std::string> attributes = rdb.pointAttribute().list();
95 openDlg.rdbTableWidget->setColumnCount(2);
96 openDlg.rdbTableWidget->setRowCount(
97 static_cast<int>(known_special_attributes.size()));
98 openDlg.rdbTableWidget->setColumnWidth(0, 200);
99 openDlg.rdbTableWidget->setEditTriggers(
100 QAbstractItemView::NoEditTriggers);
102 QStringList headerLabels;
103 headerLabels <<
"Name"
105 openDlg.rdbTableWidget->setHorizontalHeaderLabels(headerLabels);
108 auto list_known_attribute = [](
RDBOpenDialog &openDlg,
int &idx,
109 std::vector<std::string> &attributes,
110 const std::string &att,
111 const std::string &comboBoxEntry,
113 if (std::find(attributes.begin(), attributes.end(), att) !=
116 std::remove(attributes.begin(), attributes.end(), att),
119 openDlg.rdbTableWidget->setItem(
120 idx, 0,
new QTableWidgetItem(att.c_str()));
121 QComboBox *columnHeaderWidget =
new QComboBox();
122 columnHeaderWidget->addItem(comboBoxEntry.c_str());
123 columnHeaderWidget->setMaxVisibleItems(1);
124 columnHeaderWidget->setCurrentIndex(0);
125 columnHeaderWidget->setItemIcon(0, icon);
126 openDlg.rdbTableWidget->setCellWidget(idx, 1,
131 auto add_qcombobox_scalar = [](
RDBOpenDialog &openDlg,
int &idx,
132 const std::string &att,
bool active) {
133 openDlg.rdbTableWidget->setItem(idx, 0,
134 new QTableWidgetItem(att.c_str()));
137 QComboBox *columnHeaderWidget =
new QComboBox();
138 columnHeaderWidget->addItem(
140 columnHeaderWidget->addItem(
142 columnHeaderWidget->setMaxVisibleItems(2);
143 columnHeaderWidget->setItemIcon(1, ScalarIcon);
145 columnHeaderWidget->setCurrentIndex(1);
147 columnHeaderWidget->setCurrentIndex(0);
149 openDlg.rdbTableWidget->setCellWidget(idx, 1, columnHeaderWidget);
152 auto add_qcombobox_known_scalar =
154 std::vector<std::string> &attributes,
155 const std::string &att,
bool active) {
156 if (std::find(attributes.begin(), attributes.end(), att) !=
158 attributes.erase(std::remove(attributes.begin(),
159 attributes.end(), att),
161 add_qcombobox_scalar(openDlg, idx, att, active);
167 for (
const SpecialAttribute &att : known_special_attributes) {
168 list_known_attribute(openDlg, idx, attributes, att.name,
169 att.comboBoxEntry, att.icon);
175 const size_t total_rows = std::accumulate(
176 attributes.cbegin(), attributes.cend(),
size_t(idx),
177 [&rdb](
const size_t running_sum,
178 const std::string &att) ->
size_t {
179 uint32_t att_length = rdb.pointAttribute().get(att).length;
180 return running_sum + static_cast<size_t>(att_length);
183 openDlg.rdbTableWidget->setRowCount(
static_cast<int>(total_rows));
187 add_qcombobox_known_scalar(openDlg, idx, attributes,
"riegl.id",
false);
188 add_qcombobox_known_scalar(openDlg, idx, attributes,
189 "riegl.reflectance",
true);
190 add_qcombobox_known_scalar(openDlg, idx, attributes,
"riegl.amplitude",
192 add_qcombobox_known_scalar(openDlg, idx, attributes,
"riegl.deviation",
195 CVLog::Print(QString(
"unknown attributes: %1").arg(attributes.size()));
198 for (
const std::string &att : attributes) {
199 const riegl::rdb::pointcloud::PointAttribute rdb_attribute =
200 rdb.pointAttribute().get(att);
201 const uint32_t attribute_length = rdb_attribute.length;
202 if (attribute_length == 1) {
203 add_qcombobox_scalar(openDlg, idx, att,
false);
207 for (uint32_t att_idx = 0; att_idx < attribute_length;
209 add_qcombobox_scalar(
229 bool rdb_hasRGBA =
false;
230 bool rdb_hasNormals =
false;
231 bool rdb_has_pca_axis_min =
false;
235 bool rdb_has_plane_up =
false;
236 bool rdb_has_plane_width =
false;
237 bool rdb_has_plane_height =
false;
241 riegl::rdb::Pointcloud rdb(
context);
242 riegl::rdb::pointcloud::OpenSettings settings(
context);
243 rdb.open(
filename.toStdString(), settings);
246 updateTable(openDlg, rdb);
249 riegl::rdb::pointcloud::QueryStat stat = rdb.stat();
250 riegl::rdb::pointcloud::GraphNode root = stat.index();
251 openDlg.rdbPointsNumber->setText(
252 QString(
"%1").arg(root.pointCountTotal));
256 std::vector<std::string> attributes = rdb.pointAttribute().list();
259 auto listContains = [](std::vector<std::string> &attributes,
261 return std::find(attributes.begin(), attributes.end(), att) !=
265 rdb_hasRGBA = listContains(attributes,
"riegl.rgba");
266 rdb_hasNormals = listContains(attributes,
"riegl.surface_normal");
267 rdb_has_pca_axis_min =
268 listContains(attributes,
"riegl.pca_axis_min");
269 rdb_has_plane_up = listContains(attributes,
"riegl.plane_up");
270 rdb_has_plane_width = listContains(attributes,
"riegl.plane_width");
271 rdb_has_plane_height =
272 listContains(attributes,
"riegl.plane_height");
274 if (rdb_hasNormals && rdb_has_pca_axis_min) {
276 rdb_has_pca_axis_min =
false;
282 if (!openDlg.exec()) {
293 std::vector<float> buffer;
297 const size_t BUFFER_SIZE = 100000;
304 bool create_planes =
false;
306 if (rdb_hasNormals && rdb_has_plane_up && rdb_has_plane_width &&
307 rdb_has_plane_height) {
308 create_planes =
true;
309 cloud->
setName(
"Plane Centers");
314 std::vector<std::string> scalars2load;
315 for (
int i = 0; i < openDlg.rdbTableWidget->rowCount(); ++i) {
316 QComboBox *cbox =
static_cast<QComboBox *
>(
317 openDlg.rdbTableWidget->cellWidget(i, 1));
318 if (cbox->currentText() ==
320 QString att = openDlg.rdbTableWidget->item(i, 0)->text();
321 scalars2load.push_back(att.toStdString());
327 std::vector<Conversion> conversions;
328 for (std::string &att : scalars2load) {
333 conv.buffer.resize(BUFFER_SIZE);
335 conversions.push_back(conv);
343 if (rdb_hasNormals || rdb_has_pca_axis_min) {
346 if (conversions.size() > 0) {
352 riegl::rdb::Pointcloud rdb(
context);
353 riegl::rdb::pointcloud::OpenSettings settings(
context);
354 rdb.open(
filename.toStdString(), settings);
356 riegl::rdb::pointcloud::QueryStat stat = rdb.stat();
357 riegl::rdb::pointcloud::GraphNode root = stat.index();
362 &pdlg, root.pointCountTotal / BUFFER_SIZE);
364 std::stringstream ss;
365 ss <<
"Loading RDB file [" <<
filename.toStdString().c_str() <<
"]";
367 pdlg.
setInfo(
"Points loaded: 0");
372 std::vector<std::array<float, 3>> buffer_xyz(BUFFER_SIZE);
373 std::vector<std::array<float, 3>> buffer_normals;
374 std::vector<std::array<uint8_t, 4>> buffer_rgba;
375 std::vector<std::array<float, 3>> buffer_plane_up;
376 std::vector<float> buffer_plane_width;
377 std::vector<float> buffer_plane_height;
379 if (rdb_hasNormals) buffer_normals.resize(BUFFER_SIZE);
380 if (rdb_hasRGBA) buffer_rgba.resize(BUFFER_SIZE);
381 if (rdb_has_plane_up) buffer_plane_up.resize(BUFFER_SIZE);
382 if (rdb_has_plane_width) buffer_plane_width.resize(BUFFER_SIZE);
383 if (rdb_has_plane_height) buffer_plane_height.resize(BUFFER_SIZE);
386 riegl::rdb::pointcloud::QuerySelect select = rdb.select();
389 select.bind(
"riegl.xyz", riegl::rdb::pointcloud::DataType::SINGLE,
392 select.bind(
"riegl.rgba", riegl::rdb::pointcloud::DataType::UINT8,
395 select.bind(
"riegl.surface_normal",
396 riegl::rdb::pointcloud::DataType::SINGLE,
397 buffer_normals.data());
398 if (rdb_has_pca_axis_min)
399 select.bind(
"riegl.pca_axis_min",
400 riegl::rdb::pointcloud::DataType::SINGLE,
401 buffer_normals.data());
402 if (rdb_has_plane_up)
403 select.bind(
"riegl.plane_up",
404 riegl::rdb::pointcloud::DataType::SINGLE,
405 buffer_plane_up.data());
407 riegl::rdb::pointcloud::DataType ScalarTypeRiegl =
408 (
sizeof(ScalarType) == 4
409 ? riegl::rdb::pointcloud::DataType::SINGLE
410 : riegl::rdb::pointcloud::DataType::DOUBLE);
411 if (rdb_has_plane_width)
412 select.bind(
"riegl.plane_width", ScalarTypeRiegl,
413 buffer_plane_width.data());
414 if (rdb_has_plane_height)
415 select.bind(
"riegl.plane_height", ScalarTypeRiegl,
416 buffer_plane_height.data());
417 for (Conversion &conv : conversions) {
418 select.bind(conv.att, ScalarTypeRiegl, conv.buffer.data());
422 unsigned total_entries = 0;
424 riegl::rdb::pointcloud::QuerySelect count_select = rdb.select();
425 while (
const uint32_t
count = count_select.next(BUFFER_SIZE)) {
426 total_entries +=
count;
428 if (cloud->
reserve(total_entries)) {
430 CVLog::Print(QString(
"[RDBFilter] Not enough memory to "
431 "reserve RGB table for points. Try to "
432 "load as many as possible. Total: %1")
433 .arg(total_entries));
436 if ((rdb_hasNormals || rdb_has_pca_axis_min) &&
439 QString(
"[RDBFilter] Not enough memory to reserve "
440 "normal table for points. Try to load as "
441 "many as possible. Total: %1")
442 .arg(total_entries));
447 CVLog::Print(QString(
"[RDBFilter] Not enough memory to load "
448 "all points. Try to load as many as "
449 "possible. Total: %1")
450 .arg(total_entries));
456 while (
const uint32_t
count = select.next(BUFFER_SIZE)) {
469 if ((rdb_hasNormals || rdb_has_pca_axis_min) &&
478 for (uint32_t i = 0; i <
count; ++i) {
483 col.
r =
static_cast<unsigned char>(buffer_rgba[i][0]);
484 col.
g =
static_cast<unsigned char>(buffer_rgba[i][1]);
485 col.
b =
static_cast<unsigned char>(buffer_rgba[i][2]);
489 if (rdb_hasNormals || rdb_has_pca_axis_min) {
494 for (Conversion &conv : conversions) {
495 conv.sf->addElement(conv.buffer[i]);
510 static_cast<float>(buffer_xyz[i][1]),
511 static_cast<float>(buffer_xyz[i][2]));
516 buffer_plane_width[i]),
518 buffer_plane_height[i]),
521 col.
r =
static_cast<unsigned char>(buffer_rgba[i][0]);
522 col.
g =
static_cast<unsigned char>(buffer_rgba[i][1]);
523 col.
b =
static_cast<unsigned char>(buffer_rgba[i][2]);
535 pdlg.
setInfo(QString(
"Points loaded: %1").arg(total));
546 CVLog::Print(QString(
"[RDBFilter] Number of points: %1").arg(total));
549 for (Conversion &conv : conversions) {
550 conv.sf->computeMinAndMax();
564 bool &exclusive)
const {
float PointCoordinateType
Type of the coordinates of a (N-D) point.
int64_t CV_CLASS_ENUM
Type of object type flags (64 bits)
CC_FILE_ERROR
Typical I/O filter errors.
@ CC_FERR_CANCELED_BY_USER
@ CC_FERR_NOT_ENOUGH_MEMORY
const char RDB_OPEN_DLG_TYPES_NAMES[RDB_OPEN_DLG_TYPES_NUMBER][24]
static bool Print(const char *format,...)
Prints out a formatted message in console.
static constexpr float DEFAULT_PRIORITY
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.
CC_FILE_ERROR loadFile(const QString &fileName, ccHObject &container, LoadParameters ¶meters) override
Loads one or more entities from a file.
Vector3Tpl cross(const Vector3Tpl &v) const
Cross product.
static Vector3Tpl fromArray(const int a[3])
Constructor from an int array.
virtual void setVisible(bool state)
Sets entity visibility.
virtual void showNormals(bool state)
Sets normals visibility.
virtual void showColors(bool state)
Sets colors visibility.
virtual void showSF(bool state)
Sets active scalarfield visibility.
Float version of ccGLMatrixTpl.
virtual void setColor(const ecvColor::Rgb &col)
Sets primitive color (shortcut)
Hierarchical CLOUDVIEWER Object.
virtual bool addChild(ccHObject *child, int dependencyFlags=DP_PARENT_OF_OTHER, int insertIndex=-1)
Adds a child.
virtual void setName(const QString &name)
Sets object name.
void showNormalVector(bool state)
Show normal vector.
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
void setCurrentDisplayedScalarField(int index)
Sets the currently displayed scalar field.
void addNorm(const CCVector3 &N)
Pushes a normal vector on stack (shortcut)
int addScalarField(const char *uniqueName) override
Creates a new scalar field and registers it.
bool reserve(unsigned numberOfPoints) override
Reserves memory for all the active features.
bool reserveTheNormsTable()
Reserves memory to store the compressed normals.
bool reserveTheRGBTable()
Reserves memory to store the RGB colors.
void addRGBColor(const ecvColor::Rgb &C)
Pushes an RGB color on stack.
A scalar field associated to display-related parameters.
bool oneStep()
Increments total progress value of a single unit.
void addPoint(const CCVector3 &P)
Adds a 3D point to the database.
unsigned size() const override
Graphical progress indicator (thread-safe)
virtual void start() override
virtual void setInfo(const char *infoStr) override
Notifies some information about the ongoing process.
virtual void setMethodTitle(const char *methodTitle) override
Notifies the algorithm title.
std::string to_string(const T &n)
Generic loading parameters.
QWidget * parentWidget
Parent widget (if any)