PolyFEM
Loading...
Searching...
No Matches
Obstacle.cpp
Go to the documentation of this file.
2
7
8#include <igl/edges.h>
9#include <ipc/utils/eigen_ext.hpp>
10
11namespace polyfem
12{
13 using namespace utils;
14
15 namespace mesh
16 {
18 {
19 clear();
20 }
21
23 {
24 dim_ = 0;
25 v_.resize(0, 0);
26 f_.resize(0, 0);
27 e_.resize(0, 0);
28
29 in_f_.resize(0, 0);
30 in_e_.resize(0, 0);
31 in_v_.resize(0);
32
33 displacements_.clear();
34
35 endings_.clear();
36
37 planes_.clear();
38 }
39
41 const Eigen::MatrixXd &vertices,
42 const Eigen::VectorXi &codim_vertices,
43 const Eigen::MatrixXi &codim_edges,
44 const Eigen::MatrixXi &faces)
45 {
46 if (vertices.size() == 0)
47 return;
48
49 if (dim_ == 0)
50 dim_ = vertices.cols();
51 assert(dim_ == vertices.cols());
52
53 if (codim_vertices.size())
54 {
55 codim_v_.conservativeResize(codim_v_.size() + codim_vertices.size());
56 codim_v_.tail(codim_vertices.size()) = codim_vertices.array() + v_.rows();
57
58 in_v_.conservativeResize(in_v_.size() + codim_vertices.size());
59 in_v_.tail(codim_vertices.size()) = codim_vertices.array() + v_.rows();
60 }
61
62 if (codim_edges.size())
63 {
64 e_.conservativeResize(e_.rows() + codim_edges.rows(), 2);
65 e_.bottomRows(codim_edges.rows()) = codim_edges.array() + v_.rows();
66
67 in_e_.conservativeResize(in_e_.rows() + codim_edges.rows(), 2);
68 in_e_.bottomRows(codim_edges.rows()) = codim_edges.array() + v_.rows();
69 }
70
71 if (faces.size() && faces.cols() == 3)
72 {
73 f_.conservativeResize(f_.rows() + faces.rows(), 3);
74 f_.bottomRows(faces.rows()) = faces.array() + v_.rows();
75
76 in_f_.conservativeResize(in_f_.rows() + faces.rows(), 3);
77 in_f_.bottomRows(faces.rows()) = faces.array() + v_.rows();
78
79 Eigen::MatrixXi edges;
80 igl::edges(faces, edges);
81
82 e_.conservativeResize(e_.rows() + edges.rows(), 2);
83 e_.bottomRows(edges.rows()) = edges.array() + v_.rows();
84 }
85 else if (faces.size())
86 {
87 log_and_throw_error("Obstacle supports only segments and triangles!");
88 }
89
90 v_.conservativeResize(v_.rows() + vertices.rows(), dim_);
91 v_.bottomRows(vertices.rows()) = vertices;
92
93 endings_.push_back(v_.rows());
94 }
95
97 const Eigen::MatrixXd &vertices,
98 const Eigen::VectorXi &codim_vertices,
99 const Eigen::MatrixXi &codim_edges,
100 const Eigen::MatrixXi &faces,
101 const json &displacement,
102 const std::string &root_path)
103 {
104 append_mesh(vertices, codim_vertices, codim_edges, faces);
105
106 displacements_.emplace_back();
107 for (size_t d = 0; d < dim_; ++d)
108 {
109 assert(displacement["value"].is_array());
110 displacements_.back().value[d].init(displacement["value"][d], root_path);
111 }
112
113 if (displacement.contains("interpolation"))
114 {
115 if (displacement["interpolation"].is_array())
116 {
117 for (int ii = 0; ii < displacement["interpolation"].size(); ++ii)
118 displacements_.back().interpolation.emplace_back(Interpolation::build(displacement["interpolation"][ii]));
119 }
120 else
121 displacements_.back().interpolation.emplace_back(Interpolation::build(displacement["interpolation"]));
122 }
123 }
124
126 const std::vector<Eigen::MatrixXd> &vertices,
127 const Eigen::VectorXi &codim_vertices,
128 const Eigen::MatrixXi &codim_edges,
129 const Eigen::MatrixXi &faces,
130 const int fps)
131 {
132 if (vertices.size() == 0 || vertices[0].size() == 0)
133 return;
134
135 append_mesh(vertices[0], codim_vertices, codim_edges, faces);
136
137 std::array<std::vector<Eigen::MatrixXd>, 3> displacements_xyz;
138 for (size_t i = 0; i < vertices.size(); ++i)
139 {
140 Eigen::MatrixXd displacement = vertices[i] - vertices[0];
141 for (size_t d = 0; d < dim_; ++d)
142 displacements_xyz[d].push_back(displacement.col(d));
143 }
144
145 displacements_.emplace_back();
146 for (size_t d = 0; d < dim_; ++d)
147 {
148 const std::vector<Eigen::MatrixXd> displacements = displacements_xyz[d];
149 displacements_.back().value[d].init(
150 [displacements, fps](double x, double y, double z, double t, int index) -> double {
151 const double frame = t * fps;
152 const double interp = frame - floor(frame);
153 const int frame0 = (int)floor(frame);
154 const int frame1 = (int)ceil(frame);
155 if (frame1 >= displacements.size())
156 return displacements.back()(index);
157 const double u0 = displacements[frame0](index);
158 const double u1 = displacements[frame1](index);
159 return (u1 - u0) * interp + u0;
160 });
161 }
162 }
163
164 void Obstacle::append_plane(const VectorNd &origin, const VectorNd &normal)
165 {
166 if (dim_ == 0)
167 dim_ = origin.size();
168 assert(normal.size() >= dim_);
169 assert(origin.size() >= dim_);
170 planes_.emplace_back(origin.head(dim_), normal.head(dim_).normalized());
171 }
172
173 void Obstacle::change_displacement(const int oid, const Eigen::RowVector3d &val, const std::string &interp)
174 {
175 change_displacement(oid, val, interp.empty() ? std::make_shared<NoInterpolation>() : Interpolation::build(interp));
176 }
177 void Obstacle::change_displacement(const int oid, const std::function<Eigen::MatrixXd(double x, double y, double z, double t)> &func, const std::string &interp)
178 {
179 change_displacement(oid, func, interp.empty() ? std::make_shared<NoInterpolation>() : Interpolation::build(interp));
180 }
181 void Obstacle::change_displacement(const int oid, const json &val, const std::string &interp)
182 {
183 change_displacement(oid, val, "", interp);
184 }
185 void Obstacle::change_displacement(const int oid, const json &val, const std::string &root_path, const std::string &interp)
186 {
187 change_displacement(oid, val, interp.empty() ? std::make_shared<NoInterpolation>() : Interpolation::build(interp), root_path);
188 }
189
190 void Obstacle::change_displacement(const int oid, const Eigen::RowVector3d &val, const std::shared_ptr<Interpolation> &interp)
191 {
192 for (size_t k = 0; k < val.size(); ++k)
193 displacements_[oid].value[k].init(val[k]);
194
195 displacements_[oid].interpolation.clear();
196 displacements_[oid].interpolation.push_back(interp);
197 }
198
199 void Obstacle::change_displacement(const int oid, const std::function<Eigen::MatrixXd(double x, double y, double z, double t)> &func, const std::shared_ptr<Interpolation> &interp)
200 {
201 for (size_t k = 0; k < displacements_.back().value.size(); ++k)
202 displacements_[oid].value[k].init(func, k);
203
204 displacements_[oid].interpolation.clear();
205 displacements_[oid].interpolation.push_back(interp);
206 }
207
208 void Obstacle::change_displacement(const int oid, const json &val, const std::shared_ptr<Interpolation> &interp)
209 {
210 change_displacement(oid, val, interp, "");
211 }
212 void Obstacle::change_displacement(const int oid, const json &val, const std::shared_ptr<Interpolation> &interp, const std::string &root_path)
213 {
214 for (size_t k = 0; k < val.size(); ++k)
215 displacements_[oid].value[k].init(val[k], root_path);
216
217 displacements_[oid].interpolation.clear();
218 displacements_[oid].interpolation.push_back(interp);
219 }
220
221 void Obstacle::update_displacement(const double t, Eigen::MatrixXd &sol) const
222 {
223 // NOTE: assumes obstacle displacements is stored at the bottom of sol
224 const int offset = sol.rows() - v_.rows() * (sol.cols() == 1 ? dim_ : 1);
225
226 int start = 0;
227
228 for (int k = 0; k < endings_.size(); ++k)
229 {
230 const int to = endings_[k];
231 const auto &disp = displacements_[k];
232
233 for (int i = start; i < to; ++i)
234 {
235 for (int d = 0; d < dim_; ++d)
236 {
237 const int sol_row = sol.cols() == 1 ? (offset + i * dim_ + d) : (offset + i);
238 const int sol_col = sol.cols() == 1 ? 0 : d;
239 sol(sol_row, sol_col) = disp.eval(v_.row(i), d, t, i - start);
240 }
241 }
242
243 start = to;
244 }
245 assert(endings_.empty() || (start * (sol.cols() == 1 ? dim_ : 1) + offset) == sol.rows());
246 }
247
248 void Obstacle::set_zero(Eigen::MatrixXd &sol) const
249 {
250 // NOTE: assumes obstacle displacements is stored at the bottom of sol
251 sol.bottomRows(v_.rows() * (sol.cols() == 1 ? dim_ : 1)).setZero();
252 }
253
254 void Obstacle::set_units(const Units &units)
255 {
256 for (auto &d : displacements_)
257 {
258 d.set_unit_type(units.length());
259 }
260 }
261
263 {
264 constexpr int size_x = 10;
265 constexpr int size_y = 10;
266
267 if (dim_ == 2)
268 {
269 Eigen::Vector2d tangent(normal().y(), -normal().x());
270
271 vis_v_.resize(size_x + 1, 2);
272 for (int x = 0; x <= size_x; ++x)
273 {
274 vis_v_.row(x) = (x - size_x / 2.0) * tangent;
275 }
276
277 vis_e_.resize(size_x, 2);
278 for (int x = 0; x < size_x; ++x)
279 {
280 vis_e_.row(x) << x, x + 1;
281 }
282 }
283 else
284 {
285 assert(dim_ == 3);
286
287 const Eigen::Vector3d normal = this->normal();
288
289 const Eigen::Vector3d cross_x = Eigen::Vector3d::UnitX().cross(normal);
290 const Eigen::Vector3d cross_y = Eigen::Vector3d::UnitY().cross(normal);
291
292 Eigen::Vector3d tangent_x, tangent_y;
293 if (cross_x.squaredNorm() > cross_y.squaredNorm())
294 {
295 tangent_x = cross_x.normalized();
296 tangent_y = normal.cross(cross_x).normalized();
297 }
298 else
299 {
300 tangent_x = cross_y.normalized();
301 tangent_y = normal.cross(cross_y).normalized();
302 }
303
304 vis_v_.resize((size_x + 1) * (size_y + 1), 3);
305 for (int x = 0; x <= size_x; ++x)
306 {
307 for (int y = 0; y <= size_y; ++y)
308 {
309 vis_v_.row(x * size_y + y) = (x - size_x / 2.0) * tangent_x + (y - size_y / 2.0) * tangent_y;
310 }
311 }
312
313 vis_f_.resize(2 * size_x * size_y, 3);
314 for (int x = 0; x < size_x; ++x)
315 {
316 for (int y = 0; y < size_y; ++y)
317 {
318 vis_f_.row(2 * (x * size_x + y)) << x * size_x + y, x * size_x + y + 1, (x + 1) * size_x + y;
319 vis_f_.row(2 * (x * size_x + y) + 1) << x * size_x + y + 1, (x + 1) * size_x + (y + 1), (x + 1) * size_x + y;
320 }
321 }
322
323 igl::edges(vis_f_, vis_e_);
324 }
325 }
326
327 } // namespace mesh
328} // namespace polyfem
double val
Definition Assembler.cpp:86
std::vector< Eigen::VectorXi > faces
int y
int z
int x
const std::string & length() const
Definition Units.hpp:19
const VectorNd & normal() const
Definition Obstacle.hpp:112
std::vector< Plane > planes_
Definition Obstacle.hpp:96
void change_displacement(const int oid, const Eigen::RowVector3d &val, const std::shared_ptr< utils::Interpolation > &interp=std::make_shared< utils::NoInterpolation >())
Eigen::MatrixXi f_
Definition Obstacle.hpp:85
void append_mesh(const Eigen::MatrixXd &vertices, const Eigen::VectorXi &codim_vertices, const Eigen::MatrixXi &codim_edges, const Eigen::MatrixXi &faces, const json &displacement, const std::string &root_path)
Definition Obstacle.cpp:96
Eigen::MatrixXi e_
Definition Obstacle.hpp:86
void append_plane(const VectorNd &point, const VectorNd &normal)
Definition Obstacle.cpp:164
Eigen::MatrixXi in_f_
Definition Obstacle.hpp:89
Eigen::MatrixXd v_
Definition Obstacle.hpp:83
void set_zero(Eigen::MatrixXd &sol) const
Definition Obstacle.cpp:248
void append_mesh_sequence(const std::vector< Eigen::MatrixXd > &vertices, const Eigen::VectorXi &codim_vertices, const Eigen::MatrixXi &codim_edges, const Eigen::MatrixXi &faces, const int fps)
Definition Obstacle.cpp:125
Eigen::VectorXi codim_v_
Definition Obstacle.hpp:84
void update_displacement(const double t, Eigen::MatrixXd &sol) const
Definition Obstacle.cpp:221
void set_units(const Units &units)
Definition Obstacle.cpp:254
Eigen::MatrixXi in_e_
Definition Obstacle.hpp:90
Eigen::VectorXi in_v_
Definition Obstacle.hpp:88
std::vector< assembler::TensorBCValue > displacements_
Definition Obstacle.hpp:92
std::vector< int > endings_
Definition Obstacle.hpp:94
static std::shared_ptr< Interpolation > build(const json &params)
Eigen::Matrix< double, Eigen::Dynamic, 1, 0, 3, 1 > VectorNd
Definition Types.hpp:11
nlohmann::json json
Definition Common.hpp:9
void log_and_throw_error(const std::string &msg)
Definition Logger.cpp:73