ReUseX
0.0.5
3D Point Cloud Processing for Building Reuse
Toggle main menu visibility
Loading...
Searching...
No Matches
CellComplexFaceCoverage.hpp
Go to the documentation of this file.
1
// SPDX-FileCopyrightText: 2025 Povl Filip Sonne-Frederiksen
2
//
3
// SPDX-License-Identifier: GPL-3.0-or-later
4
5
#pragma once
6
#include "reusex/core/logging.hpp"
7
#include "reusex/core/processing_observer.hpp"
8
#include "reusex/geometry/CellComplex.hpp"
9
#include "reusex/geometry/utils.hpp"
10
11
#include <CGAL/Boolean_set_operations_2.h>
12
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
13
#include <CGAL/Polygon_2.h>
14
#include <CGAL/Polygon_2_algorithms.h>
15
#include <CGAL/circulator.h>
16
17
#include <range/v3/range/concepts.hpp>
18
#include <range/v3/to_container.hpp>
19
#include <range/v3/view/filter.hpp>
20
#include <range/v3/view/transform.hpp>
21
#include <range/v3/view/zip.hpp>
22
23
template
<
class
Kernel>
24
static
double
25
compute_grid_coverage
(
typename
CGAL::Polygon_2<Kernel>
const
&polygon,
26
std::vector<typename Kernel::Point_2>
const
&points,
27
const
double
cell_size = 0.2) {
28
// Bounding box (seeded from first vertex, expanded over all)
29
double
min_x = polygon[0].x(), max_x = min_x;
30
double
min_y = polygon[0].y(), max_y = min_y;
31
for
(
auto
&p : polygon) {
32
min_x = std::min(min_x, p.x());
33
max_x = std::max(max_x, p.x());
34
min_y = std::min(min_y, p.y());
35
max_y = std::max(max_y, p.y());
36
}
37
38
int
nx =
static_cast<
int
>
(std::ceil((max_x - min_x) / cell_size));
39
int
ny =
static_cast<
int
>
(std::ceil((max_y - min_y) / cell_size));
40
41
int
covered_cells = 0;
42
int
total_cells = 0;
43
44
for
(
int
i = 0; i < nx; ++i) {
45
for
(
int
j = 0; j < ny; ++j) {
46
const
double
cx = min_x + (i + 0.5) * cell_size;
47
const
double
cy = min_y + (j + 0.5) * cell_size;
48
typename
Kernel::Point_2 cell_center(cx, cy);
49
if
(polygon.bounded_side(cell_center) == CGAL::ON_UNBOUNDED_SIDE)
50
continue
;
51
52
++total_cells;
53
for
(
auto
&pt : points) {
54
if
(std::abs(pt.x() - cx) <= cell_size / 2 &&
55
std::abs(pt.y() - cy) <= cell_size / 2) {
56
++covered_cells;
57
break
;
58
}
59
}
60
}
61
}
62
if
(total_cells == 0)
63
return
0.0;
64
65
return
static_cast<
double
>
(covered_cells) / total_cells;
66
}
67
namespace
reusex::geometry
{
68
template
<
typename
Po
int
T>
69
auto
CellComplex::compute_face_coverage
(pcl::PointCloud<PointT>::ConstPtr cloud,
70
EigenVectorContainer<double, 4>
&planes,
71
std::vector<pcl::IndicesPtr> &inliers,
72
const
double
grid_size) ->
void
{
73
74
using
EPICK = CGAL::Exact_predicates_inexact_constructions_kernel;
75
76
using
Point_3 = EPICK::Point_3;
77
using
Plane_3 = EPICK::Plane_3;
78
79
using
Polygon_2 = CGAL::Polygon_2<EPICK>;
80
using
Point_2 = Polygon_2::Point_2;
81
82
// INFO: Compute face probabilities
83
reusex::trace
(
"calling compute_face_coverage"
);
84
auto
f_sp =
85
this->
add_property_map<Vertex, double>
(
"f:support_probability"
).first;
86
87
{
88
auto
observer =
reusex::core::ProgressObserver
(
89
reusex::core::Stage::computing_face_coverage
, this->
num_faces
());
90
91
std::vector<reusex::geometry::CellComplex::Vertex> face_list;
92
face_list.reserve(this->
num_faces
());
93
for
(
auto
fit = this->
faces_begin
(); fit != this->
faces_end
(); ++fit)
94
face_list.push_back(*fit);
95
96
#pragma omp parallel for schedule(dynamic)
97
for
(
size_t
face_idx = 0; face_idx < face_list.size(); ++face_idx) {
98
auto
fit = face_list[face_idx];
99
100
// for (size_t face_idx = 0; face_idx < this->num_faces(); ++face_idx) {
101
// auto fit = this->faces_begin();
102
103
const
int
plane_id = std::get<FaceData>((*
this
)[fit].data).plane_id;
104
105
auto
get_comverage = [&](
const
int
id) {
106
// if (id < 0) {
107
// reusex::warn("Face {} has no associated plane",
108
// (*this)[*fit].id); f_sp[*fit] = -1.0;
109
// ++observer;
110
// continue;
111
// }
112
113
const
auto
plane_vec = planes[id];
114
const
auto
indices = inliers[id];
115
116
const
Plane_3
plane
(plane_vec[0], plane_vec[1], plane_vec[2],
117
plane_vec[3]);
118
119
if
(indices->empty())
120
return
0.0;
121
122
Polygon_2 polygon{};
123
std::transform(this->
vertices_of_face_begin
(fit),
124
this->
vertices_of_face_end
(fit),
125
std::back_inserter(polygon), [&](
Vertex
v) {
126
const
auto
pos = (*this)[v].pos;
127
return
plane
.to_2d(Point_3(pos[0], pos[1], pos[2]));
128
});
129
130
// if (!polygon.is_simple()) {
131
// reusex::warn("Face {} polygon not is simple",
132
// (*this)[fit].id); f_sp[fit] = -1.0;
133
// ++observer;
134
// continue;
135
// }
136
137
const
auto
inliers = *indices | ranges::views::transform([&](
int
idx) {
138
const
PointT
&p = cloud->points[idx];
139
return
plane
.to_2d(Point_3(p.x, p.y, p.z));
140
}) | ranges::views::filter([&](
const
Point_2 &p) {
141
return
polygon.bounded_side(p) == CGAL::ON_BOUNDED_SIDE;
142
}) | ranges::to<std::vector>();
143
144
if
(inliers.empty())
145
return
0.0;
146
147
return
compute_grid_coverage<EPICK>
(polygon, inliers, grid_size);
148
};
149
150
auto
val = get_comverage(plane_id);
151
152
#pragma omp critical
153
f_sp[fit] = val;
154
155
++observer;
156
}
157
}
158
}
159
}
// namespace reusex::geometry
compute_grid_coverage
static double compute_grid_coverage(typename CGAL::Polygon_2< Kernel > const &polygon, std::vector< typename Kernel::Point_2 > const &points, const double cell_size=0.2)
Definition
CellComplexFaceCoverage.hpp:25
reusex::core::ProgressObserver
Definition
processing_observer.hpp:34
reusex::geometry::CellComplex::compute_face_coverage
auto compute_face_coverage(pcl::PointCloud< PointT >::ConstPtr cloud, EigenVectorContainer< double, 4 > &planes, std::vector< pcl::IndicesPtr > &inliers, const double grid_size=0.2) -> void
Definition
CellComplexFaceCoverage.hpp:69
reusex::geometry::CellComplex::faces_end
auto faces_end() const -> FaceIterator
reusex::geometry::CellComplex::Vertex
boost::graph_traits< Graph >::vertex_descriptor Vertex
Definition
CellComplex.hpp:70
reusex::geometry::CellComplex::vertices_of_face_end
auto vertices_of_face_end(Vertex f) const -> VertexOnFaceIterator
reusex::geometry::CellComplex::faces_begin
auto faces_begin() const -> FaceIterator
reusex::geometry::CellComplex::vertices_of_face_begin
auto vertices_of_face_begin(Vertex f) const -> VertexOnFaceIterator
reusex::geometry::CellComplex::num_faces
size_t num_faces() const
reusex::geometry::Registry::add_property_map
std::pair< boost::associative_property_map< std::map< Key, T > >, bool > add_property_map(const std::string &name)
Definition
Registry.hpp:27
reusex::core::Stage::computing_face_coverage
@ computing_face_coverage
Definition
stages.hpp:14
reusex::geometry
Definition
processing_observer.hpp:19
reusex::geometry::SceneNodeType::plane
@ plane
Definition
SceneGraph.hpp:31
reusex::PointT
pcl::PointXYZRGB PointT
Definition
types.hpp:17
reusex::trace
void trace(fmt::format_string< Args... > format, Args &&...args)
Definition
logging.hpp:72
reusex::EigenVectorContainer
std::vector< Eigen::Matrix< Scalar, Rows, 1 >, Eigen::aligned_allocator< Eigen::Matrix< Scalar, Rows, 1 > > > EigenVectorContainer
Definition
types.hpp:43
libs
reusex
include
geometry
CellComplexFaceCoverage.hpp
Generated by
1.17.0