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 {
103 append_mesh(vertices, codim_vertices, codim_edges, faces);
104
105 displacements_.emplace_back();
106 for (size_t d = 0; d < dim_; ++d)
107 {
108 assert(displacement["value"].is_array());
109 displacements_.back().value[d].init(displacement["value"][d]);
110 }
111
112 if (displacement.contains("interpolation"))
113 {
114 if (displacement["interpolation"].is_array())
115 {
116 for (int ii = 0; ii < displacement["interpolation"].size(); ++ii)
117 displacements_.back().interpolation.emplace_back(Interpolation::build(displacement["interpolation"][ii]));
118 }
119 else
120 displacements_.back().interpolation.emplace_back(Interpolation::build(displacement["interpolation"]));
121 }
122 }
123
125 const std::vector<Eigen::MatrixXd> &vertices,
126 const Eigen::VectorXi &codim_vertices,
127 const Eigen::MatrixXi &codim_edges,
128 const Eigen::MatrixXi &faces,
129 const int fps)
130 {
131 if (vertices.size() == 0 || vertices[0].size() == 0)
132 return;
133
134 append_mesh(vertices[0], codim_vertices, codim_edges, faces);
135
136 std::array<std::vector<Eigen::MatrixXd>, 3> displacements_xyz;
137 for (size_t i = 0; i < vertices.size(); ++i)
138 {
139 Eigen::MatrixXd displacement = vertices[i] - vertices[0];
140 for (size_t d = 0; d < dim_; ++d)
141 displacements_xyz[d].push_back(displacement.col(d));
142 }
143
144 displacements_.emplace_back();
145 for (size_t d = 0; d < dim_; ++d)
146 {
147 const std::vector<Eigen::MatrixXd> displacements = displacements_xyz[d];
148 displacements_.back().value[d].init(
149 [displacements, fps](double x, double y, double z, double t, int index) -> double {
150 const double frame = t * fps;
151 const double interp = frame - floor(frame);
152 const int frame0 = (int)floor(frame);
153 const int frame1 = (int)ceil(frame);
154 if (frame1 >= displacements.size())
155 return displacements.back()(index);
156 const double u0 = displacements[frame0](index);
157 const double u1 = displacements[frame1](index);
158 return (u1 - u0) * interp + u0;
159 });
160 }
161 }
162
163 void Obstacle::append_plane(const VectorNd &origin, const VectorNd &normal)
164 {
165 if (dim_ == 0)
166 dim_ = origin.size();
167 assert(normal.size() >= dim_);
168 assert(origin.size() >= dim_);
169 planes_.emplace_back(origin.head(dim_), normal.head(dim_).normalized());
170 }
171
172 void Obstacle::change_displacement(const int oid, const Eigen::RowVector3d &val, const std::string &interp)
173 {
174 change_displacement(oid, val, interp.empty() ? std::make_shared<NoInterpolation>() : Interpolation::build(interp));
175 }
176 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)
177 {
178 change_displacement(oid, func, interp.empty() ? std::make_shared<NoInterpolation>() : Interpolation::build(interp));
179 }
180 void Obstacle::change_displacement(const int oid, const json &val, const std::string &interp)
181 {
182 change_displacement(oid, val, interp.empty() ? std::make_shared<NoInterpolation>() : Interpolation::build(interp));
183 }
184
185 void Obstacle::change_displacement(const int oid, const Eigen::RowVector3d &val, const std::shared_ptr<Interpolation> &interp)
186 {
187 for (size_t k = 0; k < val.size(); ++k)
188 displacements_[oid].value[k].init(val[k]);
189
190 displacements_[oid].interpolation.clear();
191 displacements_[oid].interpolation.push_back(interp);
192 }
193
194 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)
195 {
196 for (size_t k = 0; k < displacements_.back().value.size(); ++k)
197 displacements_[oid].value[k].init(func, k);
198
199 displacements_[oid].interpolation.clear();
200 displacements_[oid].interpolation.push_back(interp);
201 }
202
203 void Obstacle::change_displacement(const int oid, const json &val, const std::shared_ptr<Interpolation> &interp)
204 {
205 for (size_t k = 0; k < val.size(); ++k)
206 displacements_[oid].value[k].init(val[k]);
207
208 displacements_[oid].interpolation.clear();
209 displacements_[oid].interpolation.push_back(interp);
210 }
211
212 void Obstacle::update_displacement(const double t, Eigen::MatrixXd &sol) const
213 {
214 // NOTE: assumes obstacle displacements is stored at the bottom of sol
215 const int offset = sol.rows() - v_.rows() * (sol.cols() == 1 ? dim_ : 1);
216
217 int start = 0;
218
219 for (int k = 0; k < endings_.size(); ++k)
220 {
221 const int to = endings_[k];
222 const auto &disp = displacements_[k];
223
224 for (int i = start; i < to; ++i)
225 {
226 for (int d = 0; d < dim_; ++d)
227 {
228 const int sol_row = sol.cols() == 1 ? (offset + i * dim_ + d) : (offset + i);
229 const int sol_col = sol.cols() == 1 ? 0 : d;
230 sol(sol_row, sol_col) = disp.eval(v_.row(i), d, t, i - start);
231 }
232 }
233
234 start = to;
235 }
236 assert(endings_.empty() || (start * (sol.cols() == 1 ? dim_ : 1) + offset) == sol.rows());
237 }
238
239 void Obstacle::set_zero(Eigen::MatrixXd &sol) const
240 {
241 // NOTE: assumes obstacle displacements is stored at the bottom of sol
242 sol.bottomRows(v_.rows() * (sol.cols() == 1 ? dim_ : 1)).setZero();
243 }
244
245 void Obstacle::set_units(const Units &units)
246 {
247 for (auto &d : displacements_)
248 {
249 d.set_unit_type(units.length());
250 }
251 }
252
254 {
255 constexpr int size_x = 10;
256 constexpr int size_y = 10;
257
258 if (dim_ == 2)
259 {
260 Eigen::Vector2d tangent(normal().y(), -normal().x());
261
262 vis_v_.resize(size_x + 1, 2);
263 for (int x = 0; x <= size_x; ++x)
264 {
265 vis_v_.row(x) = (x - size_x / 2.0) * tangent;
266 }
267
268 vis_e_.resize(size_x, 2);
269 for (int x = 0; x < size_x; ++x)
270 {
271 vis_e_.row(x) << x, x + 1;
272 }
273 }
274 else
275 {
276 assert(dim_ == 3);
277
278 const Eigen::Vector3d normal = this->normal();
279
280 const Eigen::Vector3d cross_x = Eigen::Vector3d::UnitX().cross(normal);
281 const Eigen::Vector3d cross_y = Eigen::Vector3d::UnitY().cross(normal);
282
283 Eigen::Vector3d tangent_x, tangent_y;
284 if (cross_x.squaredNorm() > cross_y.squaredNorm())
285 {
286 tangent_x = cross_x.normalized();
287 tangent_y = normal.cross(cross_x).normalized();
288 }
289 else
290 {
291 tangent_x = cross_y.normalized();
292 tangent_y = normal.cross(cross_y).normalized();
293 }
294
295 vis_v_.resize((size_x + 1) * (size_y + 1), 3);
296 for (int x = 0; x <= size_x; ++x)
297 {
298 for (int y = 0; y <= size_y; ++y)
299 {
300 vis_v_.row(x * size_y + y) = (x - size_x / 2.0) * tangent_x + (y - size_y / 2.0) * tangent_y;
301 }
302 }
303
304 vis_f_.resize(2 * size_x * size_y, 3);
305 for (int x = 0; x < size_x; ++x)
306 {
307 for (int y = 0; y < size_y; ++y)
308 {
309 vis_f_.row(2 * (x * size_x + y)) << x * size_x + y, x * size_x + y + 1, (x + 1) * size_x + y;
310 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;
311 }
312 }
313
314 igl::edges(vis_f_, vis_e_);
315 }
316 }
317
318 } // namespace mesh
319} // 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:105
std::vector< Plane > planes_
Definition Obstacle.hpp:89
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:78
Eigen::MatrixXi e_
Definition Obstacle.hpp:79
void append_plane(const VectorNd &point, const VectorNd &normal)
Definition Obstacle.cpp:163
Eigen::MatrixXi in_f_
Definition Obstacle.hpp:82
Eigen::MatrixXd v_
Definition Obstacle.hpp:76
void set_zero(Eigen::MatrixXd &sol) const
Definition Obstacle.cpp:239
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:124
Eigen::VectorXi codim_v_
Definition Obstacle.hpp:77
void update_displacement(const double t, Eigen::MatrixXd &sol) const
Definition Obstacle.cpp:212
void append_mesh(const Eigen::MatrixXd &vertices, const Eigen::VectorXi &codim_vertices, const Eigen::MatrixXi &codim_edges, const Eigen::MatrixXi &faces, const json &displacement)
Definition Obstacle.cpp:96
void set_units(const Units &units)
Definition Obstacle.cpp:245
Eigen::MatrixXi in_e_
Definition Obstacle.hpp:83
Eigen::VectorXi in_v_
Definition Obstacle.hpp:81
std::vector< assembler::TensorBCValue > displacements_
Definition Obstacle.hpp:85
std::vector< int > endings_
Definition Obstacle.hpp:87
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:71