9#include <ipc/utils/eigen_ext.hpp>
13 using namespace utils;
43 const Eigen::MatrixXd &vertices,
44 const Eigen::VectorXi &codim_vertices,
45 const Eigen::MatrixXi &codim_edges,
46 const Eigen::MatrixXi &
faces,
47 const Eigen::MatrixXi &tets)
49 if (vertices.size() == 0)
52 if (
tets.size() && (
tets.cols() == 3 ||
tets.cols() == 4))
54 const int tc =
tets.cols();
63 log_and_throw_error(
"Obstacle volumetric cells must be triangles (2D) or tetrahedra (3D)!");
67 dim_ = vertices.cols();
68 assert(
dim_ == vertices.cols());
70 if (codim_vertices.size())
73 codim_v_.tail(codim_vertices.size()) = codim_vertices.array() +
v_.rows();
75 in_v_.conservativeResize(
in_v_.size() + codim_vertices.size());
76 in_v_.tail(codim_vertices.size()) = codim_vertices.array() +
v_.rows();
79 if (codim_edges.size())
81 e_.conservativeResize(
e_.rows() + codim_edges.rows(), 2);
82 e_.bottomRows(codim_edges.rows()) = codim_edges.array() +
v_.rows();
84 in_e_.conservativeResize(
in_e_.rows() + codim_edges.rows(), 2);
85 in_e_.bottomRows(codim_edges.rows()) = codim_edges.array() +
v_.rows();
90 f_.conservativeResize(
f_.rows() +
faces.rows(), 3);
96 Eigen::MatrixXi edges;
97 igl::edges(
faces, edges);
99 e_.conservativeResize(
e_.rows() + edges.rows(), 2);
100 e_.bottomRows(edges.rows()) = edges.array() +
v_.rows();
102 else if (
faces.size())
107 v_.conservativeResize(
v_.rows() + vertices.rows(),
dim_);
108 v_.bottomRows(vertices.rows()) = vertices;
114 const Eigen::MatrixXd &vertices,
115 const Eigen::VectorXi &codim_vertices,
116 const Eigen::MatrixXi &codim_edges,
117 const Eigen::MatrixXi &
faces,
118 const json &displacement,
120 const Eigen::MatrixXi &tets)
125 for (
size_t d = 0; d <
dim_; ++d)
127 assert(displacement[
"value"].is_array());
128 displacements_.back().value[d].init(displacement[
"value"][d], resources);
131 if (displacement.contains(
"interpolation"))
133 if (displacement[
"interpolation"].is_array())
135 for (
int ii = 0; ii < displacement[
"interpolation"].size(); ++ii)
144 const std::vector<Eigen::MatrixXd> &vertices,
145 const Eigen::VectorXi &codim_vertices,
146 const Eigen::MatrixXi &codim_edges,
147 const Eigen::MatrixXi &
faces,
149 const Eigen::MatrixXi &tets)
151 if (vertices.size() == 0 || vertices[0].size() == 0)
156 std::array<std::vector<Eigen::MatrixXd>, 3> displacements_xyz;
157 for (
size_t i = 0; i < vertices.size(); ++i)
159 Eigen::MatrixXd displacement = vertices[i] - vertices[0];
160 for (
size_t d = 0; d <
dim_; ++d)
161 displacements_xyz[d].push_back(displacement.col(d));
165 for (
size_t d = 0; d <
dim_; ++d)
167 const std::vector<Eigen::MatrixXd> displacements = displacements_xyz[d];
169 [displacements, fps](
double x,
double y,
double z,
double t,
int index) ->
double {
170 const double frame = t * fps;
171 const double interp = frame - floor(frame);
172 const int frame0 = (int)floor(frame);
173 const int frame1 = (int)ceil(frame);
174 if (frame1 >= displacements.size())
175 return displacements.back()(index);
176 const double u0 = displacements[frame0](index);
177 const double u1 = displacements[frame1](index);
178 return (u1 - u0) * interp + u0;
186 dim_ = origin.size();
187 assert(normal.size() >=
dim_);
188 assert(origin.size() >=
dim_);
189 planes_.emplace_back(origin.head(
dim_), normal.head(
dim_).normalized());
207 for (
size_t k = 0; k <
val.size(); ++k)
214 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)
229 for (
size_t k = 0; k <
val.size(); ++k)
239 const int offset = sol.rows() -
v_.rows() * (sol.cols() == 1 ?
dim_ : 1);
243 for (
int k = 0; k <
endings_.size(); ++k)
248 for (
int i = start; i < to; ++i)
250 for (
int d = 0; d <
dim_; ++d)
252 const int sol_row = sol.cols() == 1 ? (offset + i *
dim_ + d) : (offset + i);
253 const int sol_col = sol.cols() == 1 ? 0 : d;
254 sol(sol_row, sol_col) = disp.eval(
v_.row(i), d, t, i - start);
260 assert(
endings_.empty() || (start * (sol.cols() == 1 ?
dim_ : 1) + offset) == sol.rows());
266 sol.bottomRows(
v_.rows() * (sol.cols() == 1 ?
dim_ : 1)).setZero();
273 d.set_unit_type(units.
length());
279 constexpr int size_x = 10;
280 constexpr int size_y = 10;
286 vis_v_.resize(size_x + 1, 2);
287 for (
int x = 0;
x <= size_x; ++
x)
289 vis_v_.row(
x) = (
x - size_x / 2.0) * tangent;
293 for (
int x = 0;
x < size_x; ++
x)
304 const Eigen::Vector3d cross_x = Eigen::Vector3d::UnitX().cross(
normal);
305 const Eigen::Vector3d cross_y = Eigen::Vector3d::UnitY().cross(
normal);
307 Eigen::Vector3d tangent_x, tangent_y;
308 if (cross_x.squaredNorm() > cross_y.squaredNorm())
310 tangent_x = cross_x.normalized();
311 tangent_y =
normal.cross(cross_x).normalized();
315 tangent_x = cross_y.normalized();
316 tangent_y =
normal.cross(cross_y).normalized();
319 vis_v_.resize((size_x + 1) * (size_y + 1), 3);
320 for (
int x = 0;
x <= size_x; ++
x)
322 for (
int y = 0;
y <= size_y; ++
y)
324 vis_v_.row(
x * size_y +
y) = (
x - size_x / 2.0) * tangent_x + (
y - size_y / 2.0) * tangent_y;
328 vis_f_.resize(2 * size_x * size_y, 3);
329 for (
int x = 0;
x < size_x; ++
x)
331 for (
int y = 0;
y < size_y; ++
y)
333 vis_f_.row(2 * (
x * size_x +
y)) <<
x * size_x +
y,
x * size_x +
y + 1, (
x + 1) * size_x +
y;
334 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;
std::vector< Eigen::VectorXi > faces
const std::string & length() const
Read-only interface to a hierarchical collection of simulation resources.
void construct_vis_mesh()
const VectorNd & normal() const
std::vector< Plane > planes_
void change_displacement(const int oid, const Eigen::RowVector3d &val, const std::shared_ptr< utils::Interpolation > &interp=std::make_shared< utils::NoInterpolation >())
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 io::ResourceIO &resources, const Eigen::MatrixXi &tets=Eigen::MatrixXi())
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, const Eigen::MatrixXi &tets=Eigen::MatrixXi())
const Eigen::MatrixXi & tets() const
void append_plane(const VectorNd &point, const VectorNd &normal)
void set_zero(Eigen::MatrixXd &sol) const
void update_displacement(const double t, Eigen::MatrixXd &sol) const
void set_units(const Units &units)
std::vector< assembler::TensorBCValue > displacements_
std::vector< int > endings_
static std::shared_ptr< Interpolation > build(const json ¶ms)
Eigen::Matrix< double, Eigen::Dynamic, 1, 0, 3, 1 > VectorNd
void log_and_throw_error(const std::string &msg)