This repository has been archived on 2020-10-03. You can view files and clone it, but cannot push or open issues or pull requests.
pgai_tp1/src/main.cpp

174 lines
4.1 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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 laire 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 laire 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;
}