Wildmeshing Toolkit
Loading...
Searching...
No Matches
to_points.cpp
Go to the documentation of this file.
1#include "to_points.hpp"
2#include <Eigen/Geometry>
3
4
5#include <bitset>
6
7#include <SimpleBVH/BVH.hpp>
8#include <wmtk/PointMesh.hpp>
10#include <wmtk/utils/Logger.hpp>
12
13namespace wmtk::components {
14
15using namespace simplex;
16
17std::shared_ptr<PointMesh> to_points(
18 const Mesh& mesh,
19 const attribute::MeshAttributeHandle& pts_attr,
20 const ToPtsOptions& options,
21 const std::string& output_pos_attr_name)
22{
23 const auto pts_acc = mesh.create_const_accessor<double>(pts_attr);
24 const auto vs = mesh.get_all(PrimitiveType::Vertex);
25
26 Eigen::AlignedBox<double, Eigen::Dynamic> bbox(pts_acc.dimension());
27
28 int64_t box_size = std::pow(2, pts_acc.dimension());
29
30 Eigen::MatrixXd pts(vs.size() + (options.add_box ? box_size : 0), pts_acc.dimension());
31
32 int64_t index = 0;
33 for (const auto& v : vs) {
34 pts.row(index) << pts_acc.const_vector_attribute(v).transpose();
35 bbox.extend(pts.row(index).transpose());
36 ++index;
37 }
38
39 wmtk::logger().info(
40 "Input bbox max {}, min {}, diag {}, potential target edge length: {}",
41 bbox.max(),
42 bbox.min(),
43 bbox.diagonal().norm(),
44 bbox.diagonal().norm() * options.box_scale);
45
46 if (options.add_box && !options.add_grid) {
47 auto center = bbox.center();
48 auto r = bbox.diagonal() / 2.;
49
50 bbox.min() = center - options.box_scale * r;
51 bbox.max() = center + options.box_scale * r;
52
53 for (int64_t d = 0; d < box_size; ++d) {
54 std::bitset<32> bits = d;
55 for (int64_t i = 0; i < pts.cols(); ++i) {
56 pts(index, i) = bits[i] == 0 ? bbox.min()[i] : bbox.max()[i];
57 }
58 ++index;
59 }
60 }
61
62 if (options.add_grid) {
63 const double bbox_diag = bbox.diagonal().norm();
64 const auto r = Eigen::VectorXd::Ones(pts_acc.dimension()) * bbox_diag;
65 const double grid_spacing = options.grid_spacing;
66
67
68 bbox.min() -= options.box_scale * r;
69 bbox.max() += options.box_scale * r;
70 // Eigen::VectorXi res = (diag / grid_spacing).cast<int>();
71
72 // // TODO: remove the hack
73 // // hack grid spacing as relative
74 const Eigen::VectorXi res = (bbox.diagonal() / (bbox_diag * grid_spacing)).cast<int>() +
75 Eigen::VectorXi::Ones(pts_acc.dimension());
76
77 Eigen::MatrixXd background_V;
78
79
80 if (pts.cols() == 3) {
81 auto v_index = [&res](int i, int j, int k) {
82 return k * (res[0] + 1) * (res[1] + 1) + j * (res[0] + 1) + i;
83 };
84
85 background_V.resize((res[0] + 1) * (res[1] + 1) * (res[2] + 1), 3);
86
87 for (int k = 0; k <= res[2]; ++k) {
88 for (int j = 0; j <= res[1]; ++j) {
89 for (int i = 0; i <= res[0]; ++i) {
90 const Eigen::Vector3d iii(i, j, k);
91 const Eigen::Vector3d ttmp = bbox.diagonal().array() * iii.array();
92 background_V.row(v_index(i, j, k)) =
93 bbox.min().array() + ttmp.array() / res.cast<double>().array();
94 }
95 }
96 }
97 }
98
99 wmtk::logger().info(
100 "Grid bbox max {}, min {}, diag {}, potential target edge length: {}",
101 bbox.max(),
102 bbox.min(),
103 bbox.diagonal().norm(),
104 bbox.diagonal().norm() * options.box_scale);
105 // else 2d and 1d
106
107 if (options.min_dist >= 0) {
108 int64_t count = 0;
109 int64_t findex = 0;
110
111 const std::vector<Tuple>& facest = mesh.get_all(mesh.top_simplex_type());
112 const int64_t dim = int64_t(mesh.top_simplex_type()) + 1;
113
114 Eigen::MatrixXd vertices(dim * facest.size(), pts_acc.dimension());
115 Eigen::MatrixXi faces(facest.size(), dim);
116
117 for (const auto& f : facest) {
119 mesh,
120 simplex::Simplex(mesh, mesh.top_simplex_type(), f),
122
123 assert(tmp.size() == dim);
124 for (int64_t j = 0; j < tmp.size(); ++j) {
125 auto p = pts_acc.const_vector_attribute(tmp[j]);
126 faces(findex, j) = count;
127 vertices.row(dim * findex + j) = p;
128
129 ++count;
130 }
131 ++findex;
132 }
133
134 SimpleBVH::BVH bvh;
135 bvh.init(vertices, faces, 1e-10);
136
137 const double min_dist =
138 options.min_dist > 0 ? (options.min_dist * options.min_dist * bbox_diag * bbox_diag)
139 : (bbox_diag * bbox_diag * grid_spacing * grid_spacing / 4);
140 std::vector<Eigen::VectorXd> good;
141 SimpleBVH::VectorMax3d nearest_point;
142 for (int64_t i = 0; i < background_V.rows(); ++i) {
143 double sq_dist;
144 bvh.nearest_facet(background_V.row(i), nearest_point, sq_dist);
145 if (sq_dist >= min_dist) good.emplace_back(background_V.row(i));
146 }
147 int64_t current_size = pts.rows();
148 pts.conservativeResize(current_size + good.size(), pts.cols());
149 for (const auto& v : good) {
150 pts.row(current_size) = v.transpose();
151 ++current_size;
152 }
153 } else {
154 // TODO
155 }
156 }
157
158 // remove duplicates
159 int64_t old_size = pts.rows();
160 auto remove_duplicated_vertices = [](Eigen::MatrixXd& P) -> Eigen::MatrixXd {
161 std::vector<Eigen::VectorXd> vec;
162 for (int64_t i = 0; i < P.rows(); ++i) vec.push_back(P.row(i));
163
164 std::sort(vec.begin(), vec.end(), [](Eigen::VectorXd const& p1, Eigen::VectorXd const& p2) {
165 return (p1(0) < p2(0)) || (p1(0) == p2(0) && p1(1) < p2(1)) ||
166 (p1(0) == p2(0) && p1(1) == p2(1) && p1(2) < p2(2));
167 });
168
169 auto it = std::unique(vec.begin(), vec.end());
170 vec.resize(std::distance(vec.begin(), it));
171
172 Eigen::MatrixXd new_P(vec.size(), P.cols());
173 for (int64_t i = 0; i < vec.size(); ++i) {
174 new_P.row(i) = vec[i];
175 }
176
177 return new_P;
178 };
179
180 if (options.remove_duplicates) {
181 pts = remove_duplicated_vertices(pts);
182 wmtk::logger().info("removed {} duplicated vertices", pts.rows() - old_size);
183 }
184
185 wmtk::logger().info("generated {} vertices", pts.rows());
186 std::shared_ptr<PointMesh> pts_mesh = std::make_shared<PointMesh>(pts.rows());
187
188 mesh_utils::set_matrix_attribute(pts, output_pos_attr_name, PrimitiveType::Vertex, *pts_mesh);
189
190 return pts_mesh;
191}
192
193} // namespace wmtk::components
const attribute::Accessor< T, Mesh, attribute::CachingAttribute< T >, D > create_const_accessor(const attribute::MeshAttributeHandle &handle) const
std::vector< Tuple > get_all(PrimitiveType type) const
Generate a vector of Tuples from global vertex/edge/triangle/tetrahedron index.
Definition Mesh.cpp:18
PrimitiveType top_simplex_type() const
Definition Mesh.hpp:980
std::shared_ptr< PointMesh > to_points(const Mesh &mesh, const attribute::MeshAttributeHandle &pts_attr, const ToPtsOptions &options, const std::string &output_pos_attr_name)
Definition to_points.cpp:17
attribute::MeshAttributeHandle set_matrix_attribute(const Mat &data, const std::string &name, const PrimitiveType &type, Mesh &mesh)
std::vector< Tuple > vertices(const Mesh &m, const Simplex &simplex)
std::vector< Tuple > faces_single_dimension_tuples(const Mesh &mesh, const Simplex &simplex, const PrimitiveType face_type)
SimplexCollection faces(const Mesh &mesh, const Simplex &simplex, const bool sort_and_clean)
Returns all faces of a simplex.
Definition faces.cpp:10
spdlog::logger & logger()
Retrieves the current logger.
Definition Logger.cpp:58