#include "mainwindow.h" #include "ui_mainwindow.h" #include #include #include using namespace std; /* **** début de la partie à compléter **** */ void MainWindow::showSelections(MyMesh* _mesh) { // on réinitialise les couleurs de tout le maillage resetAllColorsAndThickness(_mesh); /* **** à compléter ! **** cette fonction utilise les variables de * sélection vertexSelection, edgeSelection et faceSelection qui * sont les ID des élements sélectionnés et qui sont égales à -1 * si la sélection est vide */ if (vertexSelection >= 0 && vertexSelection < _mesh->n_vertices() - 1) { VertexHandle vh = _mesh->vertex_handle(vertexSelection); _mesh->set_color(vh, MyMesh::Color(255, 0, 0)); _mesh->data(vh).thickness = 5; } if (edgeSelection >= 0 && edgeSelection < _mesh->n_edges() - 1) { EdgeHandle eh = _mesh->edge_handle(edgeSelection); _mesh->data(eh).thickness = 5; _mesh->set_color(eh, MyMesh::Color(255, 0, 0)); } if (faceSelection >= 0 && faceSelection < _mesh->n_faces() - 1) { _mesh->set_color(_mesh->face_handle(faceSelection), MyMesh::Color(255, 0, 0)); } // on affiche le nouveau maillage displayMesh(_mesh); } void MainWindow::showSelectionsNeighborhood(MyMesh* _mesh) { // on réinitialise les couleurs de tout le maillage resetAllColorsAndThickness(_mesh); /* **** à compléter ! **** cette fonction utilise les variables de * sélection vertexSelection, edgeSelection et faceSelection qui * sont les ID des élements sélectionnés et qui sont égales à -1 * si la sélection est vide et affiche en plus le voisinage de * chaque sélection : * - les faces voisines les faces * - les faces adjacentes pour les arêtes * - les arêtes incidentes pour les sommets */ if (vertexSelection >= 0 && vertexSelection < _mesh->n_vertices() - 1) { VertexHandle vh = _mesh->vertex_handle(vertexSelection); for (auto ve_it = _mesh->ve_iter(vh); ve_it.is_valid(); ++ve_it) { _mesh->set_color(*ve_it, MyMesh::Color(255, 0, 0)); _mesh->data(*ve_it).thickness = 5; } } if (edgeSelection >= 0 && edgeSelection < _mesh->n_edges() - 1) { EdgeHandle eh = _mesh->edge_handle(edgeSelection); HalfedgeHandle heh0 = _mesh->halfedge_handle(eh, 0); HalfedgeHandle heh1 = _mesh->halfedge_handle(eh, 1); FaceHandle fh0 = _mesh->face_handle(heh0); FaceHandle fh1 = _mesh->face_handle(heh1); _mesh->set_color(fh0, MyMesh::Color(255, 0, 0)); _mesh->set_color(fh1, MyMesh::Color(255, 0, 0)); } if (faceSelection >= 0 && faceSelection < _mesh->n_faces() - 1) { FaceHandle fh = _mesh->face_handle(faceSelection); for (auto ff_it = _mesh->ff_iter(fh); ff_it.is_valid(); ++ff_it) { _mesh->set_color(*ff_it, MyMesh::Color(255, 0, 0)); } } // on affiche le nouveau maillage displayMesh(_mesh); } void MainWindow::showBorder(MyMesh* _mesh) { // on réinitialise l'affichage resetAllColorsAndThickness(_mesh); /* **** à compléter ! **** */ for (auto heh_it = _mesh->halfedges_begin(); heh_it != _mesh->halfedges_end(); ++heh_it) { if (_mesh->is_boundary(*heh_it)) { EdgeHandle eh = _mesh->edge_handle(*heh_it); _mesh->set_color(eh, MyMesh::Color(255, 100, 150)); _mesh->data(eh).thickness = 5; } } // on affiche le nouveau maillage displayMesh(_mesh); } void MainWindow::showPath(MyMesh* _mesh, int v1, int v2) { // on réinitialise l'affichage resetAllColorsAndThickness(_mesh); if ((v1 >= 0 && v1 < _mesh->n_vertices() - 1) && (v2 >= 0 && v2 < _mesh->n_vertices() - 1)) { // point de départ et point d'arrivée en vert et en gros _mesh->set_color(_mesh->vertex_handle(v1), MyMesh::Color(0, 255, 0)); _mesh->set_color(_mesh->vertex_handle(v2), MyMesh::Color(0, 255, 0)); _mesh->data(_mesh->vertex_handle(v1)).thickness = 12; _mesh->data(_mesh->vertex_handle(v2)).thickness = 12; /* **** à compléter ! **** */ for (const int &edge_id : meinDijkstra(_mesh, v1, v2)) { _mesh->set_color(_mesh->edge_handle(edge_id), MyMesh::Color(0, 255, 0)); _mesh->data(_mesh->edge_handle(edge_id)).thickness = 12; } } // on affiche le nouveau maillage displayMesh(_mesh); } int minimal_new(vector dist, set visited) { long mini = LONG_MAX; int mini_id = -1; for (int i = 0; i < dist.size(); i++) { if (visited.count(i) == 0 && dist[i] < mini) { mini = dist[i]; mini_id = i; } } return mini_id; } vector meinDijkstra(MyMesh *_mesh, int v1, int v2) { set visited_nodes_id = {}; const int nb = _mesh->n_faces(); vector dist_min (nb, ULONG_MAX); vector prec_hf (nb); dist_min[v1] = 0; int current; VertexHandle current_node; uint distance; int following; while (visited_nodes_id.size() != nb) { current = minimal_new(dist_min, visited_nodes_id); visited_nodes_id.insert(current); if (current == v2) break; current_node = _mesh->vertex_handle(current); for (auto voh_it = _mesh->voh_iter(current_node); voh_it.is_valid(); ++voh_it) { distance = dist_min[current] + 1; following = _mesh->to_vertex_handle(*voh_it).idx(); if (distance < dist_min[following]) { dist_min[following] = distance; prec_hf[following] = _mesh->opposite_halfedge_handle(*voh_it); } } } vector path; current = v2; while (current != v1) { path.push_back(_mesh->edge_handle(prec_hf[current]).idx()); current = _mesh->to_vertex_handle(prec_hf[current]).idx(); } return path; } /* **** fin de la partie à compléter **** */ /* **** début de la partie boutons et IHM **** */ void MainWindow::on_pushButton_bordure_clicked() { showBorder(&mesh); } void MainWindow::on_pushButton_voisinage_clicked() { // changement de mode entre avec et sans voisinage if(modevoisinage) { ui->pushButton_voisinage->setText("Repasser en mode normal"); modevoisinage = false; } else { ui->pushButton_voisinage->setText("Passer en mode voisinage"); modevoisinage = true; } // on montre la nouvelle selection if(!modevoisinage) showSelections(&mesh); else showSelectionsNeighborhood(&mesh); } void MainWindow::on_pushButton_vertexMoins_clicked() { // mise à jour de l'interface vertexSelection = vertexSelection - 1; ui->labelVertex->setText(QString::number(vertexSelection)); // on montre la nouvelle selection if(!modevoisinage) showSelections(&mesh); else showSelectionsNeighborhood(&mesh); } void MainWindow::on_pushButton_vertexPlus_clicked() { // mise à jour de l'interface vertexSelection = vertexSelection + 1; ui->labelVertex->setText(QString::number(vertexSelection)); // on montre la nouvelle selection if(!modevoisinage) showSelections(&mesh); else showSelectionsNeighborhood(&mesh); } void MainWindow::on_pushButton_edgeMoins_clicked() { // mise à jour de l'interface edgeSelection = edgeSelection - 1; ui->labelEdge->setText(QString::number(edgeSelection)); // on montre la nouvelle selection if(!modevoisinage) showSelections(&mesh); else showSelectionsNeighborhood(&mesh); } void MainWindow::on_pushButton_edgePlus_clicked() { // mise à jour de l'interface edgeSelection = edgeSelection + 1; ui->labelEdge->setText(QString::number(edgeSelection)); // on montre la nouvelle selection if(!modevoisinage) showSelections(&mesh); else showSelectionsNeighborhood(&mesh); } void MainWindow::on_pushButton_faceMoins_clicked() { // mise à jour de l'interface faceSelection = faceSelection - 1; ui->labelFace->setText(QString::number(faceSelection)); // on montre la nouvelle selection if(!modevoisinage) showSelections(&mesh); else showSelectionsNeighborhood(&mesh); } void MainWindow::on_pushButton_facePlus_clicked() { // mise à jour de l'interface faceSelection = faceSelection + 1; ui->labelFace->setText(QString::number(faceSelection)); // on montre la nouvelle selection if(!modevoisinage) showSelections(&mesh); else showSelectionsNeighborhood(&mesh); } void MainWindow::on_pushButton_afficherChemin_clicked() { // on récupère les sommets de départ et d'arrivée int indexV1 = ui->spinBox_v1_chemin->value(); int indexV2 = ui->spinBox_v2_chemin->value(); showPath(&mesh, indexV1, indexV2); } void MainWindow::on_pushButton_chargement_clicked() { // fenêtre de sélection des fichiers QString fileName = QFileDialog::getOpenFileName(this, tr("Open Mesh"), "", tr("Mesh Files (*.obj)")); // chargement du fichier .obj dans la variable globale "mesh" OpenMesh::IO::read_mesh(mesh, fileName.toUtf8().constData()); // initialisation des couleurs et épaisseurs (sommets et arêtes) du mesh resetAllColorsAndThickness(&mesh); // on affiche le maillage displayMesh(&mesh); } /* **** fin de la partie boutons et IHM **** */ /* **** fonctions supplémentaires **** */ // permet d'initialiser les couleurs et les épaisseurs des élements du maillage void MainWindow::resetAllColorsAndThickness(MyMesh* _mesh) { for (MyMesh::VertexIter curVert = _mesh->vertices_begin(); curVert != _mesh->vertices_end(); curVert++) { _mesh->data(*curVert).thickness = 1; _mesh->set_color(*curVert, MyMesh::Color(0, 0, 0)); } for (MyMesh::FaceIter curFace = _mesh->faces_begin(); curFace != _mesh->faces_end(); curFace++) { _mesh->set_color(*curFace, MyMesh::Color(150, 150, 150)); } for (MyMesh::EdgeIter curEdge = _mesh->edges_begin(); curEdge != _mesh->edges_end(); curEdge++) { _mesh->data(*curEdge).thickness = 1; _mesh->set_color(*curEdge, MyMesh::Color(0, 0, 0)); } } // charge un objet MyMesh dans l'environnement OpenGL void MainWindow::displayMesh(MyMesh* _mesh, DisplayMode mode) { GLuint* triIndiceArray = new GLuint[_mesh->n_faces() * 3]; GLfloat* triCols = new GLfloat[_mesh->n_faces() * 3 * 3]; GLfloat* triVerts = new GLfloat[_mesh->n_faces() * 3 * 3]; int i = 0; if(mode == DisplayMode::TemperatureMap) { QVector values; for (MyMesh::VertexIter curVert = _mesh->vertices_begin(); curVert != _mesh->vertices_end(); curVert++) values.append(fabs(_mesh->data(*curVert).value)); qSort(values); float range = values.at(values.size()*0.8); MyMesh::ConstFaceIter fIt(_mesh->faces_begin()), fEnd(_mesh->faces_end()); MyMesh::ConstFaceVertexIter fvIt; for (; fIt!=fEnd; ++fIt) { fvIt = _mesh->cfv_iter(*fIt); if(_mesh->data(*fvIt).value > 0){triCols[3*i+0] = 255; triCols[3*i+1] = 255 - std::min((_mesh->data(*fvIt).value/range) * 255.0, 255.0); triCols[3*i+2] = 255 - std::min((_mesh->data(*fvIt).value/range) * 255.0, 255.0);} else{triCols[3*i+2] = 255; triCols[3*i+1] = 255 - std::min((-_mesh->data(*fvIt).value/range) * 255.0, 255.0); triCols[3*i+0] = 255 - std::min((-_mesh->data(*fvIt).value/range) * 255.0, 255.0);} triVerts[3*i+0] = _mesh->point(*fvIt)[0]; triVerts[3*i+1] = _mesh->point(*fvIt)[1]; triVerts[3*i+2] = _mesh->point(*fvIt)[2]; triIndiceArray[i] = i; i++; ++fvIt; if(_mesh->data(*fvIt).value > 0){triCols[3*i+0] = 255; triCols[3*i+1] = 255 - std::min((_mesh->data(*fvIt).value/range) * 255.0, 255.0); triCols[3*i+2] = 255 - std::min((_mesh->data(*fvIt).value/range) * 255.0, 255.0);} else{triCols[3*i+2] = 255; triCols[3*i+1] = 255 - std::min((-_mesh->data(*fvIt).value/range) * 255.0, 255.0); triCols[3*i+0] = 255 - std::min((-_mesh->data(*fvIt).value/range) * 255.0, 255.0);} triVerts[3*i+0] = _mesh->point(*fvIt)[0]; triVerts[3*i+1] = _mesh->point(*fvIt)[1]; triVerts[3*i+2] = _mesh->point(*fvIt)[2]; triIndiceArray[i] = i; i++; ++fvIt; if(_mesh->data(*fvIt).value > 0){triCols[3*i+0] = 255; triCols[3*i+1] = 255 - std::min((_mesh->data(*fvIt).value/range) * 255.0, 255.0); triCols[3*i+2] = 255 - std::min((_mesh->data(*fvIt).value/range) * 255.0, 255.0);} else{triCols[3*i+2] = 255; triCols[3*i+1] = 255 - std::min((-_mesh->data(*fvIt).value/range) * 255.0, 255.0); triCols[3*i+0] = 255 - std::min((-_mesh->data(*fvIt).value/range) * 255.0, 255.0);} triVerts[3*i+0] = _mesh->point(*fvIt)[0]; triVerts[3*i+1] = _mesh->point(*fvIt)[1]; triVerts[3*i+2] = _mesh->point(*fvIt)[2]; triIndiceArray[i] = i; i++; } } if(mode == DisplayMode::Normal) { MyMesh::ConstFaceIter fIt(_mesh->faces_begin()), fEnd(_mesh->faces_end()); MyMesh::ConstFaceVertexIter fvIt; for (; fIt!=fEnd; ++fIt) { fvIt = _mesh->cfv_iter(*fIt); triCols[3*i+0] = _mesh->color(*fIt)[0]; triCols[3*i+1] = _mesh->color(*fIt)[1]; triCols[3*i+2] = _mesh->color(*fIt)[2]; triVerts[3*i+0] = _mesh->point(*fvIt)[0]; triVerts[3*i+1] = _mesh->point(*fvIt)[1]; triVerts[3*i+2] = _mesh->point(*fvIt)[2]; triIndiceArray[i] = i; i++; ++fvIt; triCols[3*i+0] = _mesh->color(*fIt)[0]; triCols[3*i+1] = _mesh->color(*fIt)[1]; triCols[3*i+2] = _mesh->color(*fIt)[2]; triVerts[3*i+0] = _mesh->point(*fvIt)[0]; triVerts[3*i+1] = _mesh->point(*fvIt)[1]; triVerts[3*i+2] = _mesh->point(*fvIt)[2]; triIndiceArray[i] = i; i++; ++fvIt; triCols[3*i+0] = _mesh->color(*fIt)[0]; triCols[3*i+1] = _mesh->color(*fIt)[1]; triCols[3*i+2] = _mesh->color(*fIt)[2]; triVerts[3*i+0] = _mesh->point(*fvIt)[0]; triVerts[3*i+1] = _mesh->point(*fvIt)[1]; triVerts[3*i+2] = _mesh->point(*fvIt)[2]; triIndiceArray[i] = i; i++; } } if(mode == DisplayMode::ColorShading) { MyMesh::ConstFaceIter fIt(_mesh->faces_begin()), fEnd(_mesh->faces_end()); MyMesh::ConstFaceVertexIter fvIt; for (; fIt!=fEnd; ++fIt) { fvIt = _mesh->cfv_iter(*fIt); triCols[3*i+0] = _mesh->data(*fvIt).faceShadingColor[0]; triCols[3*i+1] = _mesh->data(*fvIt).faceShadingColor[1]; triCols[3*i+2] = _mesh->data(*fvIt).faceShadingColor[2]; triVerts[3*i+0] = _mesh->point(*fvIt)[0]; triVerts[3*i+1] = _mesh->point(*fvIt)[1]; triVerts[3*i+2] = _mesh->point(*fvIt)[2]; triIndiceArray[i] = i; i++; ++fvIt; triCols[3*i+0] = _mesh->data(*fvIt).faceShadingColor[0]; triCols[3*i+1] = _mesh->data(*fvIt).faceShadingColor[1]; triCols[3*i+2] = _mesh->data(*fvIt).faceShadingColor[2]; triVerts[3*i+0] = _mesh->point(*fvIt)[0]; triVerts[3*i+1] = _mesh->point(*fvIt)[1]; triVerts[3*i+2] = _mesh->point(*fvIt)[2]; triIndiceArray[i] = i; i++; ++fvIt; triCols[3*i+0] = _mesh->data(*fvIt).faceShadingColor[0]; triCols[3*i+1] = _mesh->data(*fvIt).faceShadingColor[1]; triCols[3*i+2] = _mesh->data(*fvIt).faceShadingColor[2]; triVerts[3*i+0] = _mesh->point(*fvIt)[0]; triVerts[3*i+1] = _mesh->point(*fvIt)[1]; triVerts[3*i+2] = _mesh->point(*fvIt)[2]; triIndiceArray[i] = i; i++; } } ui->displayWidget->loadMesh(triVerts, triCols, _mesh->n_faces() * 3 * 3, triIndiceArray, _mesh->n_faces() * 3); delete[] triIndiceArray; delete[] triCols; delete[] triVerts; GLuint* linesIndiceArray = new GLuint[_mesh->n_edges() * 2]; GLfloat* linesCols = new GLfloat[_mesh->n_edges() * 2 * 3]; GLfloat* linesVerts = new GLfloat[_mesh->n_edges() * 2 * 3]; i = 0; QHash > edgesIDbyThickness; for (MyMesh::EdgeIter eit = _mesh->edges_begin(); eit != _mesh->edges_end(); ++eit) { float t = _mesh->data(*eit).thickness; if(t > 0) { if(!edgesIDbyThickness.contains(t)) edgesIDbyThickness[t] = QList(); edgesIDbyThickness[t].append((*eit).idx()); } } QHashIterator > it(edgesIDbyThickness); QList > edgeSizes; while (it.hasNext()) { it.next(); for(int e = 0; e < it.value().size(); e++) { int eidx = it.value().at(e); MyMesh::VertexHandle vh1 = _mesh->to_vertex_handle(_mesh->halfedge_handle(_mesh->edge_handle(eidx), 0)); linesVerts[3*i+0] = _mesh->point(vh1)[0]; linesVerts[3*i+1] = _mesh->point(vh1)[1]; linesVerts[3*i+2] = _mesh->point(vh1)[2]; linesCols[3*i+0] = _mesh->color(_mesh->edge_handle(eidx))[0]; linesCols[3*i+1] = _mesh->color(_mesh->edge_handle(eidx))[1]; linesCols[3*i+2] = _mesh->color(_mesh->edge_handle(eidx))[2]; linesIndiceArray[i] = i; i++; MyMesh::VertexHandle vh2 = _mesh->from_vertex_handle(_mesh->halfedge_handle(_mesh->edge_handle(eidx), 0)); linesVerts[3*i+0] = _mesh->point(vh2)[0]; linesVerts[3*i+1] = _mesh->point(vh2)[1]; linesVerts[3*i+2] = _mesh->point(vh2)[2]; linesCols[3*i+0] = _mesh->color(_mesh->edge_handle(eidx))[0]; linesCols[3*i+1] = _mesh->color(_mesh->edge_handle(eidx))[1]; linesCols[3*i+2] = _mesh->color(_mesh->edge_handle(eidx))[2]; linesIndiceArray[i] = i; i++; } edgeSizes.append(qMakePair(it.key(), it.value().size())); } ui->displayWidget->loadLines(linesVerts, linesCols, i * 3, linesIndiceArray, i, edgeSizes); delete[] linesIndiceArray; delete[] linesCols; delete[] linesVerts; GLuint* pointsIndiceArray = new GLuint[_mesh->n_vertices()]; GLfloat* pointsCols = new GLfloat[_mesh->n_vertices() * 3]; GLfloat* pointsVerts = new GLfloat[_mesh->n_vertices() * 3]; i = 0; QHash > vertsIDbyThickness; for (MyMesh::VertexIter vit = _mesh->vertices_begin(); vit != _mesh->vertices_end(); ++vit) { float t = _mesh->data(*vit).thickness; if(t > 0) { if(!vertsIDbyThickness.contains(t)) vertsIDbyThickness[t] = QList(); vertsIDbyThickness[t].append((*vit).idx()); } } QHashIterator > vitt(vertsIDbyThickness); QList > vertsSizes; while (vitt.hasNext()) { vitt.next(); for(int v = 0; v < vitt.value().size(); v++) { int vidx = vitt.value().at(v); pointsVerts[3*i+0] = _mesh->point(_mesh->vertex_handle(vidx))[0]; pointsVerts[3*i+1] = _mesh->point(_mesh->vertex_handle(vidx))[1]; pointsVerts[3*i+2] = _mesh->point(_mesh->vertex_handle(vidx))[2]; pointsCols[3*i+0] = _mesh->color(_mesh->vertex_handle(vidx))[0]; pointsCols[3*i+1] = _mesh->color(_mesh->vertex_handle(vidx))[1]; pointsCols[3*i+2] = _mesh->color(_mesh->vertex_handle(vidx))[2]; pointsIndiceArray[i] = i; i++; } vertsSizes.append(qMakePair(vitt.key(), vitt.value().size())); } ui->displayWidget->loadPoints(pointsVerts, pointsCols, i * 3, pointsIndiceArray, i, vertsSizes); delete[] pointsIndiceArray; delete[] pointsCols; delete[] pointsVerts; } MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { vertexSelection = -1; edgeSelection = -1; faceSelection = -1; modevoisinage = false; ui->setupUi(this); } MainWindow::~MainWindow() { delete ui; }