2020-11-27 11:47:21 +01:00
|
|
|
#include "flatpattern.hpp"
|
|
|
|
#include "trianglepatterngeometry.hpp"
|
|
|
|
#include <filesystem>
|
|
|
|
|
|
|
|
FlatPattern::FlatPattern() {}
|
|
|
|
|
2021-01-04 13:30:22 +01:00
|
|
|
FlatPattern::FlatPattern(const std::string &filename, bool addNormalsIfAbsent) {
|
2021-01-12 13:40:25 +01:00
|
|
|
if (!std::filesystem::exists(std::filesystem::path(filename))) {
|
|
|
|
assert(false);
|
|
|
|
std::cerr << "No flat pattern with name " << filename << std::endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!loadPly(filename)) {
|
|
|
|
assert(false);
|
|
|
|
std::cerr << "File could not be loaded " << filename << std::endl;
|
|
|
|
return;
|
|
|
|
}
|
2020-11-27 11:47:21 +01:00
|
|
|
if (addNormalsIfAbsent) {
|
|
|
|
bool normalsAreAbsent = vert[0].cN().Norm() < 0.000001;
|
|
|
|
if (normalsAreAbsent) {
|
|
|
|
for (auto &v : vert) {
|
|
|
|
v.N() = CoordType(0, 0, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
vcg::tri::UpdateTopology<FlatPattern>::VertexEdge(*this);
|
2021-01-04 13:30:22 +01:00
|
|
|
const double baseTriangleCentralEdgeSize =
|
|
|
|
(vert[0].cP() - vert[3].cP()).Norm();
|
2020-11-27 11:47:21 +01:00
|
|
|
|
2020-12-03 19:56:03 +01:00
|
|
|
updateEigenEdgeAndVertices();
|
2020-11-27 11:47:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
FlatPattern::FlatPattern(const std::vector<size_t> &numberOfNodesPerSlot,
|
|
|
|
const std::vector<vcg::Point2i> &edges) {
|
|
|
|
add(numberOfNodesPerSlot, edges);
|
|
|
|
// add normals
|
|
|
|
bool normalsAreAbsent = vert[0].cN().Norm() < 0.000001;
|
|
|
|
if (normalsAreAbsent) {
|
|
|
|
for (auto &v : vert) {
|
|
|
|
v.N() = CoordType(0, 0, 1);
|
|
|
|
}
|
|
|
|
}
|
2021-01-04 13:30:22 +01:00
|
|
|
baseTriangleHeight = (vert[0].cP() - vert[3].cP()).Norm();
|
2020-11-27 11:47:21 +01:00
|
|
|
updateEigenEdgeAndVertices();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool FlatPattern::createHoneycombAtom() {
|
|
|
|
VCGEdgeMesh honeycombQuarter;
|
|
|
|
const VCGEdgeMesh::CoordType n(0, 0, 1);
|
|
|
|
const double H = 0.2;
|
|
|
|
const double height = 1.5 * H;
|
|
|
|
const double width = 0.2;
|
|
|
|
const double theta = 70;
|
|
|
|
const double dy = tan(vcg::math::ToRad(90 - theta)) * width / 2;
|
|
|
|
vcg::tri::Allocator<VCGEdgeMesh>::AddVertex(
|
|
|
|
honeycombQuarter, VCGEdgeMesh::CoordType(0, height / 2, 0), n);
|
|
|
|
vcg::tri::Allocator<VCGEdgeMesh>::AddVertex(
|
|
|
|
honeycombQuarter, VCGEdgeMesh::CoordType(0, H / 2 - dy, 0), n);
|
|
|
|
vcg::tri::Allocator<VCGEdgeMesh>::AddVertex(
|
|
|
|
honeycombQuarter, VCGEdgeMesh::CoordType(width / 2, H / 2, 0), n);
|
|
|
|
vcg::tri::Allocator<VCGEdgeMesh>::AddVertex(
|
|
|
|
honeycombQuarter, VCGEdgeMesh::CoordType(width / 2, 0, 0), n);
|
|
|
|
vcg::tri::Allocator<VCGEdgeMesh>::AddEdge(honeycombQuarter, 0, 1);
|
|
|
|
vcg::tri::Allocator<VCGEdgeMesh>::AddEdge(honeycombQuarter, 1, 2);
|
|
|
|
vcg::tri::Allocator<VCGEdgeMesh>::AddEdge(honeycombQuarter, 2, 3);
|
|
|
|
|
|
|
|
VCGEdgeMesh honeycombAtom;
|
|
|
|
// Top right
|
|
|
|
vcg::tri::Append<VCGEdgeMesh, VCGEdgeMesh>::MeshCopy(honeycombAtom,
|
|
|
|
honeycombQuarter);
|
|
|
|
// Bottom right
|
|
|
|
vcg::Matrix44d rotM;
|
|
|
|
rotM.SetRotateDeg(180, vcg::Point3d(1, 0, 0));
|
|
|
|
vcg::tri::UpdatePosition<VCGEdgeMesh>::Matrix(honeycombQuarter, rotM);
|
|
|
|
vcg::tri::Append<VCGEdgeMesh, VCGEdgeMesh>::Mesh(honeycombAtom,
|
|
|
|
honeycombQuarter);
|
|
|
|
// Bottom left
|
|
|
|
rotM.SetRotateDeg(180, vcg::Point3d(0, 1, 0));
|
|
|
|
vcg::tri::UpdatePosition<VCGEdgeMesh>::Matrix(honeycombQuarter, rotM);
|
|
|
|
vcg::tri::Append<VCGEdgeMesh, VCGEdgeMesh>::Mesh(honeycombAtom,
|
|
|
|
honeycombQuarter);
|
|
|
|
// Top left
|
|
|
|
rotM.SetRotateDeg(180, vcg::Point3d(1, 0, 0));
|
|
|
|
vcg::tri::UpdatePosition<VCGEdgeMesh>::Matrix(honeycombQuarter, rotM);
|
|
|
|
vcg::tri::Append<VCGEdgeMesh, VCGEdgeMesh>::Mesh(honeycombAtom,
|
|
|
|
honeycombQuarter);
|
|
|
|
|
|
|
|
for (VertexType &v : honeycombAtom.vert) {
|
|
|
|
v.P()[2] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-01-04 13:30:22 +01:00
|
|
|
void FlatPattern::copy(FlatPattern &pattern) {
|
|
|
|
VCGEdgeMesh::copy(pattern);
|
|
|
|
baseTriangleHeight = pattern.getBaseTriangleHeight();
|
|
|
|
}
|
|
|
|
|
2020-11-27 11:47:21 +01:00
|
|
|
void FlatPattern::deleteDanglingEdges() {
|
|
|
|
for (VertexType &v : vert) {
|
|
|
|
std::vector<VCGEdgeMesh::EdgePointer> incidentElements;
|
|
|
|
vcg::edge::VEStarVE(&v, incidentElements);
|
|
|
|
if (incidentElements.size() == 1) {
|
|
|
|
vcg::tri::Allocator<VCGEdgeMesh>::DeleteEdge(*this, *incidentElements[0]);
|
|
|
|
}
|
|
|
|
if (incidentElements.size() == 1) {
|
|
|
|
vcg::tri::Allocator<VCGEdgeMesh>::DeleteVertex(*this, v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
vcg::tri::Clean<VCGEdgeMesh>::RemoveDegenerateVertex(*this);
|
|
|
|
vcg::tri::Clean<VCGEdgeMesh>::RemoveDegenerateEdge(*this);
|
|
|
|
vcg::tri::Allocator<VCGEdgeMesh>::CompactEveryVector(*this);
|
|
|
|
}
|
|
|
|
|
2021-01-04 13:30:22 +01:00
|
|
|
void FlatPattern::scale(const double &desiredBaseTriangleCentralEdgeSize) {
|
|
|
|
this->baseTriangleHeight = desiredBaseTriangleCentralEdgeSize;
|
2020-11-27 11:47:21 +01:00
|
|
|
const double baseTriangleCentralEdgeSize =
|
|
|
|
(vert[0].cP() - vert[3].cP()).Norm();
|
|
|
|
const double scaleRatio =
|
|
|
|
desiredBaseTriangleCentralEdgeSize / baseTriangleCentralEdgeSize;
|
|
|
|
|
|
|
|
vcg::tri::UpdatePosition<VCGEdgeMesh>::Scale(*this, scaleRatio);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FlatPattern::deleteDanglingVertices() {
|
|
|
|
vcg::tri::Allocator<FlatPattern>::PointerUpdater<VertexPointer> pu;
|
|
|
|
deleteDanglingVertices(pu);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FlatPattern::deleteDanglingVertices(
|
|
|
|
vcg::tri::Allocator<FlatPattern>::PointerUpdater<VertexPointer> &pu) {
|
|
|
|
for (VertexType &v : vert) {
|
|
|
|
std::vector<FlatPattern::EdgePointer> incidentElements;
|
|
|
|
vcg::edge::VEStarVE(&v, incidentElements);
|
|
|
|
if (incidentElements.size() == 0) {
|
|
|
|
vcg::tri::Allocator<FlatPattern>::DeleteVertex(*this, v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
vcg::tri::Allocator<FlatPattern>::CompactVertexVector(*this, pu);
|
|
|
|
vcg::tri::Allocator<FlatPattern>::CompactEdgeVector(*this);
|
|
|
|
|
|
|
|
updateEigenEdgeAndVertices();
|
|
|
|
}
|
|
|
|
|
|
|
|
void FlatPattern::tilePattern(VCGEdgeMesh &pattern, VCGPolyMesh &tileInto,
|
|
|
|
const bool &shouldDeleteDanglingEdges) {
|
|
|
|
const size_t middleIndex = 3;
|
|
|
|
double xOffset =
|
|
|
|
vcg::Distance(pattern.vert[0].cP(), pattern.vert[middleIndex].cP()) /
|
|
|
|
std::tan(M_PI / 3);
|
|
|
|
CoordType patternCoord0 = pattern.vert[0].cP();
|
|
|
|
CoordType patternBottomRight =
|
|
|
|
pattern.vert[middleIndex].cP() + CoordType(xOffset, 0, 0);
|
|
|
|
CoordType patternBottomLeft =
|
|
|
|
pattern.vert[middleIndex].cP() - CoordType(xOffset, 0, 0);
|
|
|
|
std::vector<vcg::Point3d> patternTrianglePoints{
|
|
|
|
patternCoord0, patternBottomRight, patternBottomLeft};
|
|
|
|
CoordType pointOnPattern =
|
|
|
|
patternCoord0 + (patternBottomLeft - patternCoord0) ^
|
|
|
|
(patternBottomRight - patternCoord0);
|
|
|
|
|
|
|
|
std::vector<CoordType> faceCenters(FN());
|
|
|
|
VCGTriMesh tileIntoEdgeMesh;
|
|
|
|
|
|
|
|
for (VCGPolyMesh::FaceType &f : tileInto.face) {
|
|
|
|
std::vector<VCGPolyMesh::VertexType *> incidentVertices;
|
|
|
|
vcg::face::VFIterator<PFace> vfi(
|
|
|
|
&f, 0); // initialize the iterator to the first face
|
|
|
|
// vcg::face::Pos p(vfi.F(), f.cV(0));
|
|
|
|
// vcg::face::VVOrderedStarFF(p, incidentVertices);
|
|
|
|
size_t numberOfNodes = 0;
|
|
|
|
CoordType centerOfFace(0, 0, 0);
|
|
|
|
for (size_t vi = 0; vi < f.VN(); vi++) {
|
|
|
|
numberOfNodes++;
|
|
|
|
centerOfFace = centerOfFace + f.cP(vi);
|
|
|
|
}
|
|
|
|
centerOfFace /= f.VN();
|
|
|
|
vcg::tri::Allocator<VCGTriMesh>::AddVertex(tileIntoEdgeMesh, centerOfFace,
|
|
|
|
vcg::Color4b::Yellow);
|
|
|
|
|
|
|
|
// const size_t vi = vcg::tri::Index<VCGPolyMesh>(tileInto, v);
|
|
|
|
// std::cout << "vertex " << vi << " has incident vertices:" <<
|
|
|
|
// std::endl;
|
|
|
|
for (size_t vi = 0; vi < f.VN(); vi++) {
|
|
|
|
// size_t f = 0;
|
|
|
|
// std::cout << vcg::tri::Index<VCGTriMesh>(tileInto,
|
|
|
|
// / incidentVertices[f]) / << std::endl;
|
|
|
|
|
|
|
|
// Compute transformation matrix M
|
|
|
|
// vcg::Matrix44d M;
|
|
|
|
std::vector<vcg::Point3d> meshTrianglePoints{
|
|
|
|
centerOfFace, f.cP(vi), vi + 1 == f.VN() ? f.cP(0) : f.cP(vi + 1)};
|
|
|
|
CoordType faceNormal = ((meshTrianglePoints[1] - meshTrianglePoints[0]) ^
|
|
|
|
(meshTrianglePoints[2] - meshTrianglePoints[0]))
|
|
|
|
.Normalize();
|
|
|
|
auto fit = vcg::tri::Allocator<VCGTriMesh>::AddFace(
|
|
|
|
tileIntoEdgeMesh, meshTrianglePoints[0], meshTrianglePoints[1],
|
|
|
|
meshTrianglePoints[2]);
|
|
|
|
fit->N() = faceNormal;
|
|
|
|
CoordType pointOnTriMesh =
|
|
|
|
meshTrianglePoints[0] +
|
|
|
|
(meshTrianglePoints[1] - meshTrianglePoints[0]) ^
|
|
|
|
(meshTrianglePoints[2] - meshTrianglePoints[0]);
|
|
|
|
vcg::Matrix44d M;
|
|
|
|
// vcg::ComputeRigidMatchMatrix(meshTrianglePoints,
|
|
|
|
// patternTrianglePoints,
|
|
|
|
// M);
|
|
|
|
vcg::Matrix44d A_prime;
|
|
|
|
A_prime[0][0] = meshTrianglePoints[0][0];
|
|
|
|
A_prime[1][0] = meshTrianglePoints[0][1];
|
|
|
|
A_prime[2][0] = meshTrianglePoints[0][2];
|
|
|
|
A_prime[3][0] = 1;
|
|
|
|
A_prime[0][1] = meshTrianglePoints[1][0];
|
|
|
|
A_prime[1][1] = meshTrianglePoints[1][1];
|
|
|
|
A_prime[2][1] = meshTrianglePoints[1][2];
|
|
|
|
A_prime[3][1] = 1;
|
|
|
|
A_prime[0][2] = meshTrianglePoints[2][0];
|
|
|
|
A_prime[1][2] = meshTrianglePoints[2][1];
|
|
|
|
A_prime[2][2] = meshTrianglePoints[2][2];
|
|
|
|
A_prime[3][2] = 1;
|
|
|
|
A_prime[0][3] = pointOnTriMesh[0];
|
|
|
|
A_prime[1][3] = pointOnTriMesh[1];
|
|
|
|
A_prime[2][3] = pointOnTriMesh[2];
|
|
|
|
A_prime[3][3] = 1;
|
|
|
|
vcg::Matrix44d A;
|
|
|
|
A[0][0] = patternTrianglePoints[0][0];
|
|
|
|
A[1][0] = patternTrianglePoints[0][1];
|
|
|
|
A[2][0] = patternTrianglePoints[0][2];
|
|
|
|
A[3][0] = 1;
|
|
|
|
A[0][1] = patternTrianglePoints[1][0];
|
|
|
|
A[1][1] = patternTrianglePoints[1][1];
|
|
|
|
A[2][1] = patternTrianglePoints[1][2];
|
|
|
|
A[3][1] = 1;
|
|
|
|
A[0][2] = patternTrianglePoints[2][0];
|
|
|
|
A[1][2] = patternTrianglePoints[2][1];
|
|
|
|
A[2][2] = patternTrianglePoints[2][2];
|
|
|
|
A[3][2] = 1;
|
|
|
|
A[0][3] = pointOnPattern[0];
|
|
|
|
A[1][3] = pointOnPattern[1];
|
|
|
|
A[2][3] = pointOnPattern[2];
|
|
|
|
A[3][3] = 1;
|
|
|
|
M = A_prime * vcg::Inverse(A);
|
|
|
|
|
|
|
|
VCGEdgeMesh transformedPattern;
|
|
|
|
vcg::tri::Append<VCGEdgeMesh, VCGEdgeMesh>::MeshCopy(transformedPattern,
|
|
|
|
pattern);
|
|
|
|
vcg::tri::UpdatePosition<VCGEdgeMesh>::Matrix(transformedPattern, M);
|
|
|
|
for (VertexType &v : transformedPattern.vert) {
|
|
|
|
v.N() = faceNormal;
|
|
|
|
}
|
|
|
|
|
|
|
|
vcg::tri::Append<VCGEdgeMesh, VCGEdgeMesh>::Mesh(*this,
|
|
|
|
transformedPattern);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// vcg::tri::Clean<VCGEdgeMesh>::MergeCloseVertex(*this, 0.0000000001);
|
|
|
|
// vcg::tri::Clean<VCGEdgeMesh>::RemoveDegenerateVertex(*this);
|
|
|
|
// vcg::tri::Clean<VCGEdgeMesh>::RemoveDegenerateEdge(*this);
|
|
|
|
// vcg::tri::Allocator<VCGEdgeMesh>::CompactEveryVector(*this);
|
|
|
|
|
|
|
|
vcg::tri::UpdateTopology<VCGEdgeMesh>::VertexEdge(*this);
|
|
|
|
|
|
|
|
vcg::tri::Clean<VCGEdgeMesh>::MergeCloseVertex(*this, 0.0000000001);
|
|
|
|
deleteDanglingVertices();
|
|
|
|
deleteDanglingEdges();
|
|
|
|
vcg::tri::Clean<VCGEdgeMesh>::RemoveDegenerateVertex(*this);
|
|
|
|
vcg::tri::Clean<VCGEdgeMesh>::RemoveDegenerateEdge(*this);
|
|
|
|
vcg::tri::Allocator<VCGEdgeMesh>::CompactEveryVector(*this);
|
|
|
|
updateEigenEdgeAndVertices();
|
|
|
|
savePly("tiledPattern.ply");
|
|
|
|
|
|
|
|
vcg::tri::Clean<VCGTriMesh>::MergeCloseVertex(tileIntoEdgeMesh, 0.0000000001);
|
|
|
|
vcg::tri::Clean<VCGTriMesh>::RemoveDegenerateVertex(tileIntoEdgeMesh);
|
|
|
|
vcg::tri::Clean<VCGTriMesh>::RemoveDegenerateEdge(tileIntoEdgeMesh);
|
|
|
|
tileIntoEdgeMesh.savePly("tileIntoTriMesh.ply");
|
|
|
|
}
|
|
|
|
|
|
|
|
void FlatPattern::createFan(const size_t &fanSize) {
|
|
|
|
FlatPattern rotatedPattern;
|
|
|
|
vcg::tri::Append<FlatPattern, FlatPattern>::MeshCopy(rotatedPattern, *this);
|
|
|
|
for (int rotationCounter = 1; rotationCounter < fanSize; rotationCounter++) {
|
|
|
|
vcg::Matrix44d R;
|
|
|
|
auto rotationAxis = vcg::Point3d(0, 0, 1);
|
|
|
|
R.SetRotateDeg(360 / fanSize, rotationAxis);
|
|
|
|
vcg::tri::UpdatePosition<FlatPattern>::Matrix(rotatedPattern, R);
|
|
|
|
vcg::tri::Append<FlatPattern, FlatPattern>::Mesh(*this, rotatedPattern);
|
|
|
|
}
|
|
|
|
|
|
|
|
removeDuplicateVertices();
|
2020-12-17 19:06:17 +01:00
|
|
|
// const double precision = 1e-4;
|
|
|
|
// for (size_t vi = 0; vi < VN(); vi++) {
|
|
|
|
// vert[vi].P()[0] = std::round(vert[vi].P()[0] * (1 / precision)) *
|
|
|
|
// precision; vert[vi].P()[1] = std::round(vert[vi].P()[1] * (1 /
|
|
|
|
// precision)) * precision; vert[vi].P()[2] = std::round(vert[vi].P()[2]
|
|
|
|
// * (1 / precision)) * precision;
|
|
|
|
// }
|
|
|
|
|
2020-11-27 11:47:21 +01:00
|
|
|
updateEigenEdgeAndVertices();
|
|
|
|
}
|
|
|
|
|
|
|
|
void FlatPattern::removeDuplicateVertices() {
|
|
|
|
vcg::tri::Clean<VCGEdgeMesh>::MergeCloseVertex(*this, 0.0000000001);
|
|
|
|
vcg::tri::Clean<VCGEdgeMesh>::RemoveDegenerateVertex(*this);
|
|
|
|
vcg::tri::Clean<VCGEdgeMesh>::RemoveDegenerateEdge(*this);
|
|
|
|
vcg::tri::Allocator<VCGEdgeMesh>::CompactEveryVector(*this);
|
|
|
|
vcg::tri::UpdateTopology<FlatPattern>::VertexEdge(*this);
|
|
|
|
}
|
|
|
|
|
2021-01-04 13:30:22 +01:00
|
|
|
double FlatPattern::getBaseTriangleHeight() const { return baseTriangleHeight; }
|
|
|
|
|
2020-11-27 11:47:21 +01:00
|
|
|
void FlatPattern::tilePattern(VCGEdgeMesh &pattern, VCGTriMesh &tileInto) {
|
|
|
|
|
|
|
|
const size_t middleIndex = 3;
|
|
|
|
double xOffset =
|
|
|
|
vcg::Distance(pattern.vert[0].cP(), pattern.vert[middleIndex].cP()) /
|
|
|
|
std::tan(M_PI / 3);
|
|
|
|
CoordType patternCoord0 = pattern.vert[0].cP();
|
|
|
|
CoordType patternBottomRight =
|
|
|
|
pattern.vert[middleIndex].cP() + CoordType(xOffset, 0, 0);
|
|
|
|
CoordType patternBottomLeft =
|
|
|
|
pattern.vert[middleIndex].cP() - CoordType(xOffset, 0, 0);
|
|
|
|
std::vector<vcg::Point3d> patternTrianglePoints{
|
|
|
|
patternCoord0, patternBottomRight, patternBottomLeft};
|
|
|
|
CoordType pointOnPattern =
|
|
|
|
patternCoord0 + (patternBottomLeft - patternCoord0) ^
|
|
|
|
(patternBottomRight - patternCoord0);
|
|
|
|
|
|
|
|
for (VCGTriMesh::VertexType &v : tileInto.vert) {
|
|
|
|
const auto centralNodeColor = vcg::Color4<unsigned char>(64, 64, 64, 255);
|
|
|
|
const bool isCentralNode = v.cC() == centralNodeColor;
|
|
|
|
if (isCentralNode) {
|
|
|
|
std::vector<VCGTriMesh::VertexType *> incidentVertices;
|
|
|
|
vcg::face::VFIterator<VCGTriMeshFace> vfi(
|
|
|
|
&v); // initialize the iterator tohe first face
|
|
|
|
vcg::face::Pos p(vfi.F(), &v);
|
|
|
|
vcg::face::VVOrderedStarFF(p, incidentVertices);
|
|
|
|
|
|
|
|
const size_t vi = vcg::tri::Index<VCGTriMesh>(tileInto, v);
|
|
|
|
std::cout << "vertex " << vi << " has incident vertices:" << std::endl;
|
|
|
|
for (size_t f = 0; f < incidentVertices.size(); f++) {
|
|
|
|
// size_t f = 0;
|
|
|
|
std::cout << vcg::tri::Index<VCGTriMesh>(tileInto, incidentVertices[f])
|
|
|
|
<< std::endl;
|
|
|
|
|
|
|
|
// Compute transformation matrix M
|
|
|
|
// vcg::Matrix44d M;
|
|
|
|
std::vector<vcg::Point3d> meshTrianglePoints{
|
|
|
|
v.cP(), incidentVertices[f]->cP(),
|
|
|
|
f + 1 == incidentVertices.size() ? incidentVertices[0]->cP()
|
|
|
|
: incidentVertices[f + 1]->cP()};
|
|
|
|
CoordType faceNormal =
|
|
|
|
((meshTrianglePoints[1] - meshTrianglePoints[0]) ^
|
|
|
|
(meshTrianglePoints[2] - meshTrianglePoints[0]))
|
|
|
|
.Normalize();
|
|
|
|
CoordType pointOnTriMesh =
|
|
|
|
meshTrianglePoints[0] +
|
|
|
|
(meshTrianglePoints[1] - meshTrianglePoints[0]) ^
|
|
|
|
(meshTrianglePoints[2] - meshTrianglePoints[0]);
|
|
|
|
vcg::Matrix44d M;
|
|
|
|
// vcg::ComputeRigidMatchMatrix(meshTrianglePoints,
|
|
|
|
// patternTrianglePoints,
|
|
|
|
// M);
|
|
|
|
vcg::Matrix44d A_prime;
|
|
|
|
A_prime[0][0] = meshTrianglePoints[0][0];
|
|
|
|
A_prime[1][0] = meshTrianglePoints[0][1];
|
|
|
|
A_prime[2][0] = meshTrianglePoints[0][2];
|
|
|
|
A_prime[3][0] = 1;
|
|
|
|
A_prime[0][1] = meshTrianglePoints[1][0];
|
|
|
|
A_prime[1][1] = meshTrianglePoints[1][1];
|
|
|
|
A_prime[2][1] = meshTrianglePoints[1][2];
|
|
|
|
A_prime[3][1] = 1;
|
|
|
|
A_prime[0][2] = meshTrianglePoints[2][0];
|
|
|
|
A_prime[1][2] = meshTrianglePoints[2][1];
|
|
|
|
A_prime[2][2] = meshTrianglePoints[2][2];
|
|
|
|
A_prime[3][2] = 1;
|
|
|
|
A_prime[0][3] = pointOnTriMesh[0];
|
|
|
|
A_prime[1][3] = pointOnTriMesh[1];
|
|
|
|
A_prime[2][3] = pointOnTriMesh[2];
|
|
|
|
A_prime[3][3] = 1;
|
|
|
|
vcg::Matrix44d A;
|
|
|
|
A[0][0] = patternTrianglePoints[0][0];
|
|
|
|
A[1][0] = patternTrianglePoints[0][1];
|
|
|
|
A[2][0] = patternTrianglePoints[0][2];
|
|
|
|
A[3][0] = 1;
|
|
|
|
A[0][1] = patternTrianglePoints[1][0];
|
|
|
|
A[1][1] = patternTrianglePoints[1][1];
|
|
|
|
A[2][1] = patternTrianglePoints[1][2];
|
|
|
|
A[3][1] = 1;
|
|
|
|
A[0][2] = patternTrianglePoints[2][0];
|
|
|
|
A[1][2] = patternTrianglePoints[2][1];
|
|
|
|
A[2][2] = patternTrianglePoints[2][2];
|
|
|
|
A[3][2] = 1;
|
|
|
|
A[0][3] = pointOnPattern[0];
|
|
|
|
A[1][3] = pointOnPattern[1];
|
|
|
|
A[2][3] = pointOnPattern[2];
|
|
|
|
A[3][3] = 1;
|
|
|
|
M = A_prime * vcg::Inverse(A);
|
|
|
|
|
|
|
|
VCGEdgeMesh transformedPattern;
|
|
|
|
vcg::tri::Append<VCGEdgeMesh, VCGEdgeMesh>::MeshCopy(transformedPattern,
|
|
|
|
pattern);
|
|
|
|
vcg::tri::UpdatePosition<VCGEdgeMesh>::Matrix(transformedPattern, M);
|
|
|
|
for (VertexType &v : transformedPattern.vert) {
|
|
|
|
v.N() = faceNormal;
|
|
|
|
}
|
|
|
|
|
|
|
|
vcg::tri::Append<VCGEdgeMesh, VCGEdgeMesh>::Mesh(*this,
|
|
|
|
transformedPattern);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
vcg::tri::UpdateTopology<VCGEdgeMesh>::VertexEdge(*this);
|
|
|
|
deleteDanglingVertices();
|
|
|
|
deleteDanglingEdges();
|
|
|
|
vcg::tri::Allocator<VCGEdgeMesh>::CompactEveryVector(*this);
|
|
|
|
|
|
|
|
updateEigenEdgeAndVertices();
|
|
|
|
}
|