Revision ad8e9d4f15917a78050e26fb7a846e17f90636e6 authored by Merve Asiler on 03 July 2024, 20:45:15 UTC, committed by GitHub on 03 July 2024, 20:45:15 UTC
1 parent ba0ff13
MeshTools.cpp
// @author Merve Asiler
#include "Mesh.h"
#include "BasicGeometricElements.h"
#include "BaseGeoOpUtils.h"
bool Mesh::isManifold() {
// Check edge sharing between triangles
for (int i = 0; i < edges.size(); i++)
if (edges[i].triList.size() != 2)
return false;
/*
// Check normals
// for the first triangle
bool invalid = false;
double* diff1 = diffVects(verts[tris[0].corners[1]].coords, verts[tris[0].corners[0]].coords);
double* diff2 = diffVects(verts[tris[0].corners[2]].coords, verts[tris[0].corners[0]].coords);
double* normal_dir1 = crossProduct(diff1, diff2);
delete[] diff1;
delete[] diff2;
if (computeLength(normal_dir1) < EPSILON) {
delete[] normal_dir1;
return false;
}
// the other triangles
for (int i = 1; i < tris.size(); i++) {
bool invalid = false;
double* diff3 = diffVects(verts[tris[i].corners[1]].coords, verts[tris[i].corners[0]].coords);
double* diff4 = diffVects(verts[tris[i].corners[2]].coords, verts[tris[i].corners[0]].coords);
double* normal_dir2 = crossProduct(diff3, diff4);
// check normal length
if (computeLength(normal_dir2) < EPSILON)
invalid = true;
// check clocwkise - counterclockwise ordering
if (dotProduct(normal_dir1, normal_dir2) < 0)
invalid = true;
delete[] diff3;
delete[] diff4;
delete[] normal_dir1;
normal_dir1 = normal_dir2;
if (invalid || i == tris.size() - 1)
delete[] normal_dir2;
if (invalid)
return false;
}
*/
return true;
}
void Mesh::computeTrisAngles() {
for (unsigned int i = 0; i < tris.size(); i++) {
Triangle& triangle = tris[i];
Edge& a = edges[triangle.edgeList[0]];
Edge& b = edges[triangle.edgeList[1]];
Edge& c = edges[triangle.edgeList[2]];
// law of cosines
double cos_a = (pow((b.length), 2) + pow((c.length), 2) - pow((a.length), 2)) / (2 * b.length * c.length);
double cos_b = (pow((a.length), 2) + pow((c.length), 2) - pow((b.length), 2)) / (2 * a.length * c.length);
double cos_c = (pow((a.length), 2) + pow((b.length), 2) - pow((c.length), 2)) / (2 * a.length * b.length);
triangle.angleList.push_back(acos(cos_a));
triangle.angleList.push_back(acos(cos_b));
triangle.angleList.push_back(acos(cos_c));
}
}
void Mesh::tetrahedralizeSurface() {
// find each triangle's surface tetrahedron
for (int i = 0; i < tris.size(); i++) {
//compute the peak point of the tetrahedron (the fourth point)
Triangle& triangle = tris[i];
double* peakCoords = new double[3];
// get the pointers for the triangle corners
Vertex corners[3];
for (int j = 0; j < 3; j++)
corners[j] = verts[triangle.corners[j]];
// find the center of the triangle
double* center = triangle.computeCenter(&corners[0], &corners[1], &corners[2]);
// find the vector in the direction of the normal which will point to the peak point
double edgeVector1[3], edgeVector2[3];
for (int j = 0; j < 3; j++) {
edgeVector1[j] = corners[1].coords[j] - corners[0].coords[j];
edgeVector2[j] = corners[2].coords[j] - corners[1].coords[j];
}
double* dirVect = crossProduct(edgeVector1, edgeVector2);
double scaleFactor = sqrt(computeLength(dirVect));
for (int j = 0; j < 3; j++)
dirVect[j] /= scaleFactor;
// find the peak point
for (int j = 0; j < 3; j++)
peakCoords[j] = center[j] + dirVect[j];
delete[] dirVect;
Vertex* peak = new Vertex(i, peakCoords);
//Tetrahedron* tetrahedron = new Tetrahedron(i, peak);
//tets.push_back(tetrahedron);
}
}
double Mesh::computeVolume() {
double volume = 0;
for (int i = 0; i < tris.size(); i++) {
Triangle triangle = tris[i];
Vertex corners[3];
for (int j = 0; j < 3; j++)
corners[j] = verts[triangle.corners[j]];
double* a_cross_b = crossProduct(corners[0].coords, corners[1].coords);
double a_cross_b_dot_c = dotProduct(a_cross_b, corners[2].coords);
delete[] a_cross_b;
volume += a_cross_b_dot_c / 6.0;
}
return abs(volume);
}
vector<double> Mesh::computeCurvaturePerVertex() {
vector<double> curvatures;
vector< vector <double> > aroundAngles; // for each vertex it holds the angles around it
aroundAngles.resize(verts.size());
for (int i = 0; i < tris.size(); i++) {
Triangle& t = tris[i];
for (int c = 0; c < 3; c++) {
Edge& e1 = edges[t.edgeList[c]];
Edge& e2 = edges[t.edgeList[(c+1)%3]];
double* vect1 = diffVects(verts[e1.endVerts[0]].coords, verts[e1.endVerts[1]].coords);
double* vect2 = diffVects(verts[e2.endVerts[1]].coords, verts[e2.endVerts[0]].coords);
normalize(vect1);
normalize(vect2);
if (e1.endVerts[1] == e2.endVerts[0])
aroundAngles[e1.endVerts[1]].push_back( acos(dotProduct(vect1, vect2)) );
else if (e1.endVerts[1] == e2.endVerts[1])
aroundAngles[e1.endVerts[1]].push_back( PI - acos(dotProduct(vect1, vect2)) );
else if (e1.endVerts[0] == e2.endVerts[1])
aroundAngles[e1.endVerts[0]].push_back( acos(dotProduct(vect1, vect2)) );
else // (e1->endVerts[0] == e2->endVerts[0])
aroundAngles[e1.endVerts[0]].push_back( PI - acos(dotProduct(vect1, vect2)) );
}
}
for (int i = 0; i < verts.size(); i++) {
double angleSum = 0;
for (int j = 0; j < aroundAngles[i].size(); j++)
angleSum += aroundAngles[i][j];
curvatures.push_back(2*PI - angleSum);
}
return curvatures;
}
int findDistinctEnd(int* c1, int* c2) {
int i, j;
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++)
if (c1[i] == c2[j])
break;
if (j == 3)
return i;
}
return -1;
}
bool isEdgeConvex(Triangle* t1, Triangle* t2, vector<Vertex> vertexSet) {
// check whether they are on the same plane
bool theSame = true;
for (int i=0; i<3; i++)
if (abs(t1->normal[i] - t2->normal[i]) > EPSILON) {
theSame = false;
break;
}
if (theSame)
return true;
/*
theSame = true;
for (int i = 0; i < 3; i++)
if (abs(t1->normal[i] + t2->normal[i]) > EPSILON) {
theSame = false;
break;
}
if (theSame)
return true;
*/
// find the distinct vertex on t1
int p_id = findDistinctEnd(t1->corners, t2->corners);
Vertex& p = vertexSet[t1->corners[p_id]];
Line* t1_line;
Plane* t2_plane;
// check for perpendicular planes:
double cosAngle = findCosAngleBetween(t1->normal, t2->normal); // then the cos of angle between the planes is -cosAngle.
if (abs(cosAngle) < EPSILON) { // if they are perpendicular
double plane_normal[3];
for (int i = 0; i < 3; i++)
plane_normal[i] = (t1->normal[i] + t2->normal[i]) / 2;
normalize(plane_normal);
Vertex& q = vertexSet[t1->corners[(p_id+1)%3]];
t2_plane = new Plane(q.coords, plane_normal);
}
else // if they are not perpendicular
t2_plane = new Plane(vertexSet[t2->corners[0]].coords, t2->normal);
// find the intersection
t1_line = new Line(p.coords, t1->normal);
double parameter = findLinePlaneIntersection(*t1_line, *t2_plane);
delete t1_line;
delete t2_plane;
if (abs(cosAngle) < EPSILON && parameter < 0)
return false;
if (abs(cosAngle) < EPSILON && parameter > 0)
return true;
if (cosAngle < 0 && parameter > 0)
return false;
if (cosAngle > 0 && parameter < 0)
return false;
return true;
}
void Mesh::makeConvex() {
bool need_to_check = true;
int counter = 0;
while (need_to_check) {
if (counter == 0)
break;
counter++;
need_to_check = false;
for (int i = 0; i < edges.size(); i++) {
Triangle& t1 = tris[edges[i].triList[0]];
Triangle& t2 = tris[edges[i].triList[1]];
if (isEdgeConvex(&t1, &t2, verts))
continue;
// concave
need_to_check = true; // after all the edges are handled, we will re-check in one more loop
double n[3];
for (int j = 0; j < 3; j++)
n[j] = ((double)t1.normal[j] + t2.normal[j]) / 2.0;
normalize(n);
int ind = findDistinctEnd(t1.corners, t2.corners);
Vertex& p = verts[t1.corners[ind]];
Plane* plane = new Plane(p.coords, n);
Vertex& v1 = verts[t1.corners[(ind + 1) % 3]];
double* new_v1_coords = projectVertexOnPlane(plane, v1.coords);
Vertex& v2 = verts[t1.corners[(ind + 2) % 3]];
double* new_v2_coords = projectVertexOnPlane(plane, v2.coords);
for (int j = 0; j < 3; j++) {
v1.coords[j] = new_v1_coords[j];
v2.coords[j] = new_v2_coords[j];
}
delete[] new_v1_coords;
delete[] new_v2_coords;
delete plane;
}
}
}
void Mesh::removeAbnormalTris() {
int initial_num_of_edges = edges.size();
for (int i = 0, removed = 0; i < initial_num_of_edges; i++) {
Edge& edge = edges[i - removed];
if (edge.triList.size() == 1) {
cout << "1-neighbor-triangle" << endl;
edges.erase(edges.begin() + (i - removed));
removed++;
}
else if (edge.triList.size() > 2)
cout << "more than 2-neighbor-triangle" << endl;
}
}
void Mesh::rotate(double angles[3]) {
double Rx[3][3] = { {1, 0, 0},
{0, cos(angles[0]), -sin(angles[0])},
{0, sin(angles[0]), cos(angles[0])} };
double Ry[3][3] = { {cos(angles[1]), 0, sin(angles[1])},
{0, 1, 0},
{-sin(angles[1]), 0, cos(angles[1])} };
double Rz[3][3] = { {cos(angles[2]), -sin(angles[2]), 0},
{sin(angles[2]), cos(angles[2]), 0},
{0, 0, 1} };
double R[3][3], temp[3][3];
for (int r = 0; r < 3; r++) {
for (int c = 0; c < 3; c++) {
double value = 0;
for (int k = 0; k < 3; k++)
value += Rx[r][k] * Ry[k][c];
temp[r][c] = value;
}
}
for (int r = 0; r < 3; r++) {
for (int c = 0; c < 3; c++) {
double value = 0;
for (int k = 0; k < 3; k++)
value += temp[r][k] * Rz[k][c];
R[r][c] = value;
}
}
double center[3] = { 0, 0, 0 };
for (int i = 0; i < verts.size(); i++)
for (int d = 0; d < 3; d++)
center[d] += verts[i].coords[d];
for (int d = 0; d < 3; d++)
center[d] /= verts.size();
for (int i = 0; i < verts.size(); i++)
for (int d = 0; d < 3; d++)
verts[i].coords[d] -= center[d];
for (int i = 0; i < verts.size(); i++) {
for (int r = 0; r < 3; r++) {
double value = 0;
for (int c = 0; c < 3; c++)
value += R[r][c] * verts[i].coords[c];
verts[i].coords[r] = value;
}
}
}
void Mesh::setKernelAABB(double initialCorner[3], double finalCorner[3]) {
aabb_corners.push_back({ initialCorner[0], initialCorner[1], initialCorner[2], 1.0 });
aabb_corners.push_back({ finalCorner[0], initialCorner[1], initialCorner[2], 1.0 });
aabb_corners.push_back({ finalCorner[0], initialCorner[1], finalCorner[2], 1.0 });
aabb_corners.push_back({ initialCorner[0], initialCorner[1], finalCorner[2], 1.0 });
aabb_corners.push_back({ initialCorner[0], finalCorner[1], initialCorner[2], 1.0 });
aabb_corners.push_back({ finalCorner[0], finalCorner[1], initialCorner[2], 1.0 });
aabb_corners.push_back({ finalCorner[0], finalCorner[1], finalCorner[2], 1.0 });
aabb_corners.push_back({ initialCorner[0], finalCorner[1], finalCorner[2], 1.0 });
}
Computing file changes ...