174 lines
4.1 KiB
C++
174 lines
4.1 KiB
C++
#include "my_mesh.h"
|
||
|
||
#include <ctgmath>
|
||
#include <iostream>
|
||
#include <fstream>
|
||
|
||
#define PI 3.14159265
|
||
|
||
|
||
bool check_faces_are_triangles(MyMesh &mesh) {
|
||
for (auto f_it = mesh.faces_begin(); f_it != mesh.faces_end(); ++f_it) {
|
||
size_t n_edges = 0;
|
||
for (auto fe_it = mesh.fe_iter(*f_it); fe_it.is_valid(); ++fe_it) {
|
||
n_edges++;
|
||
}
|
||
if (n_edges != 3) {
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
|
||
bool check_faces_arent_lonely(MyMesh &mesh) {
|
||
for (auto f_it = mesh.faces_begin(); f_it != mesh.faces_end(); ++f_it) {
|
||
auto ff_it = mesh.ff_iter(*f_it);
|
||
if (!ff_it.is_valid()) {
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
|
||
bool check_vertices_arent_lonely(MyMesh &mesh) {
|
||
for (auto v_it = mesh.vertices_begin(); v_it != mesh.vertices_end(); ++v_it) {
|
||
auto ve_it = mesh.ve_iter(*v_it);
|
||
if (!ve_it.is_valid()) {
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
|
||
bool check_edges_arent_lonely(const char *path) {
|
||
using namespace std;
|
||
ifstream f(path);
|
||
string line;
|
||
while (getline(f, line)) {
|
||
istringstream iss(line);
|
||
char first;
|
||
iss >> first;
|
||
if (first == 'l') return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
|
||
float face_area(MyMesh &mesh, const MyMesh::FaceHandle &face) {
|
||
MyMesh::Point p0, p1, p2;
|
||
auto fv_it = mesh.fv_iter(face);
|
||
p0 = mesh.point(*fv_it++);
|
||
p1 = mesh.point(*fv_it++);
|
||
p2 = mesh.point(*fv_it);
|
||
return ((p1 - p0) % (p2 - p0)).norm() / 2;
|
||
}
|
||
|
||
|
||
float total_area(MyMesh &mesh) {
|
||
if (!check_faces_are_triangles(mesh)) {
|
||
std::cerr << "Le calcul de l’aire ne peu se faire que sur un maillage triangulaire." << std::endl;
|
||
return -1;
|
||
}
|
||
float ret = 0;
|
||
for (const MyMesh::FaceHandle &face : mesh.faces()) {
|
||
ret += face_area(mesh, face);
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
|
||
void stats_surface_area(MyMesh &mesh) {
|
||
if (!check_faces_are_triangles(mesh)) {
|
||
std::cerr << "Le calcul de l’aire ne peu se faire que sur un maillage triangulaire." << std::endl;
|
||
return;
|
||
}
|
||
for (const MyMesh::FaceHandle &face : mesh.faces()) {
|
||
std::cout << face_area(mesh, face) << " ";
|
||
}
|
||
std::cout << std::endl;
|
||
}
|
||
|
||
|
||
void stats_n_neighbors(MyMesh &mesh) {
|
||
for (const VertexHandle &vh : mesh.vertices()) {
|
||
unsigned count = 0;
|
||
for (auto vv_it = mesh.vv_iter(vh); vv_it.is_valid(); ++vv_it) {
|
||
count++;
|
||
}
|
||
std::cout << count << " ";
|
||
}
|
||
std::cout << std::endl;
|
||
}
|
||
|
||
|
||
void stats_normal_deviation(MyMesh &mesh) {
|
||
mesh.update_normals();
|
||
for (const VertexHandle &vh : mesh.vertices()) {
|
||
MyMesh::Normal normal = mesh.normal(vh);
|
||
float max = 0;
|
||
for (auto vf_it = mesh.vf_iter(vh); vf_it.is_valid(); ++vf_it) {
|
||
float angle = acos(OpenMesh::dot(mesh.normal(*vf_it), normal)) * 180.0 / PI;
|
||
if (angle > max)
|
||
max = angle;
|
||
}
|
||
std::cout << max << " ";
|
||
}
|
||
std::cout << std::endl;
|
||
}
|
||
|
||
|
||
void stats_dihedral_angles(MyMesh &mesh) {
|
||
mesh.update_normals();
|
||
for (size_t i = 0; i < mesh.n_halfedges(); i++) {
|
||
MyMesh::HalfedgeHandle heh = mesh.halfedge_handle(i);
|
||
std::cout << mesh.calc_dihedral_angle_fast(heh) * 180.0 / PI + 180 << " ";
|
||
}
|
||
std::cout << std::endl;
|
||
}
|
||
|
||
|
||
int main(int argc, char *argv[]) {
|
||
using namespace std;
|
||
|
||
if (argc != 2 && argc != 3) {
|
||
cerr << "Utilisation : " << argv[0] << " fichier.obj [surface|valence|deviation|dièdre]" << endl;
|
||
return 1;
|
||
}
|
||
MyMesh mesh;
|
||
OpenMesh::IO::read_mesh(mesh, argv[1]);
|
||
cerr << "Les faces sont des triangles : "
|
||
<< (check_faces_are_triangles(mesh) ? "oui" : "non")
|
||
<< endl;
|
||
cerr << "Les faces ont des voisines : "
|
||
<< (check_faces_arent_lonely(mesh) ? "oui" : "non")
|
||
<< endl;
|
||
cerr << "Les sommets sont sur une arête : "
|
||
<< (check_vertices_arent_lonely(mesh) ? "oui" : "non")
|
||
<< endl;
|
||
cerr << "Les arêtes sont sur une face : "
|
||
<< (check_edges_arent_lonely(argv[1]) ? "oui" : "non")
|
||
<< endl;
|
||
float area = total_area(mesh);
|
||
cerr << "Aire totale : " << area << endl;
|
||
cerr << "Aire moyenne : " << area / mesh.n_faces() << endl;
|
||
if (argc == 3) {
|
||
string cmd = argv[2];
|
||
if (cmd == "surface")
|
||
stats_surface_area(mesh);
|
||
else if (cmd == "valence")
|
||
stats_n_neighbors(mesh);
|
||
else if (cmd == "deviation")
|
||
stats_normal_deviation(mesh);
|
||
else if (cmd == "dièdre")
|
||
stats_dihedral_angles(mesh);
|
||
else {
|
||
cerr << "Commande inconnue : " << cmd << endl;
|
||
return 1;
|
||
}
|
||
}
|
||
return 0;
|
||
}
|