Я сейчас пользуюсь libigl манипулировать / деформировать простой (2D) квадрат, манипулируя его углами (см. начальное состояние ниже):
После наложения смещения u (1,1) в нижний левый угол и обновления местоположений неугловых вершин с использованием бигармонической деформации я получаю следующее состояние (вдохновлено Бигармоническая деформация учебник ):
Проблемы:
Тогда идеальным решением было бы что-то близкое к изображению ниже, без необходимости управлять каждой граничной вершиной:
Вопросы:
ПРИМЕЧАНИЕ: полная реализация:
#include <iostream>
#include <Eigen/Core>
#include <igl/colon.h>
#include <igl/harmonic.h>
#include <igl/viewer/Viewer.h>
#include <igl/triangle/triangulate.h>
#include "tutorial_shared_path.h"
using namespace Eigen;
using namespace std;
double step = 0.1;
// Input polygon
MatrixXd V; // corners location
MatrixXi E; // boundary edges
MatrixXd H; // 2D positions of points contained in holes of the triangulation
// Triangulated interior
MatrixXd D_bc; // displacements / corner
MatrixXd V2; // all vertexes location
MatrixXd U; // deformed vertexes
MatrixXi F2;
Eigen::VectorXi b; // index of corner vertices
int selected = 0; // index of currently selected corner
void update(igl::viewer::Viewer &viewer) {
cout << "D_bc " <<endl
<< D_bc <<endl;
// compute displacements
MatrixXd D;
igl::harmonic(V2,F2,b,D_bc,2.,D);
// compute solution as init state + displacements
U = V2+D;
viewer.data.set_vertices(U);
// display current selection
Eigen::MatrixXd points(1,3);
points << V(selected, 0) + D_bc(selected, 0), V(selected, 1) + D_bc(selected, 1), 0;
viewer.data.set_points(points,Eigen::RowVector3d(1,0,0));
}
bool key_down(igl::viewer::Viewer &viewer, unsigned char key, int mods) {
switch((int)key)
{
case 32: // space
selected = (selected + 1) % 4;
break;
case 6: // right
D_bc(selected, 0) += step;
break;
case 7: // left
D_bc(selected, 0) -= step;
break;
case 8: // down
D_bc(selected, 1) -= step;
break;
case 9: // top
D_bc(selected, 1) += step;
break;
default:
return false;
}
update(viewer);
return true;
}
int main(int argc, char *argv[])
{
// Create the boundary of a square
V.resize(4,2);
V << -1,-1, 1,-1, 1,1, -1,1;
E.resize(4,2);
E << 0,1, 1,2, 2,3, 3,0;
H.resize(0,2);
// Triangulate the interior
igl::triangle::triangulate(V,E,H,"a0.01q",V2,F2);
igl::colon<int>(0,V.rows()-1,b);
// Plot the generated mesh
igl::viewer::Viewer viewer;
viewer.data.set_mesh(V2,F2);
// set initial displacements / solution
D_bc = MatrixXd::Zero(V.rows(), V.cols());
U=V2;
viewer.callback_key_down = &key_down;
update(viewer);
// display legend
cout<<
"Press [space] to switch point."<<endl<<
"Use arrows to move current point."<<endl;
viewer.launch();
}
Задача ещё не решена.
Других решений пока нет …