我目前正在使用libigl通过操纵角来操纵/变形一个简单的(2D)正方形(参见下面的初始状态):
在将位移 u(1,1) 施加到左下角并使用双调和变形更新非角顶点位置后,我最终得到以下状态(受双调和变形教程的启发):
问题是:
- 三角形不是均匀分布的
- 变形改变了不再是直线的边
一个理想的解决方案将是接近下图的东西,而不必管理每个边界顶点:
问题是:
- 我应该使用哪种变形之王来达到这样的效果?
- libigl 是此类操作的正确工具吗?
注意:完整的实现是:
#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();
}