Add an operation to add triangle faces from vertex selection

This commit is contained in:
Mael Rouxel-Labbé 2024-06-19 16:00:23 +02:00
parent 4b71b12443
commit 363df4c424
2 changed files with 79 additions and 1 deletions

View File

@ -236,7 +236,8 @@ public:
"Select Edges Incident to Selected Facets" , "Select Edges Incident to Selected Facets" ,
"Select Vertices Incident to Selected Edges" , "Select Vertices Incident to Selected Edges" ,
"Select Edges on the Boundary of Regions of Selected Facets", "Select Edges on the Boundary of Regions of Selected Facets",
"Select Vertices of Selected Facets" "Select Vertices of Selected Facets",
"Add Triangle Face from Selected Vertices"
}; };
operations_map[operations_strings[0]] = 0; operations_map[operations_strings[0]] = 0;
@ -249,6 +250,7 @@ public:
operations_map[operations_strings[7]] = 7; operations_map[operations_strings[7]] = 7;
operations_map[operations_strings[8]] = 8; operations_map[operations_strings[8]] = 8;
operations_map[operations_strings[9]] = 9; operations_map[operations_strings[9]] = 9;
operations_map[operations_strings[10]] = 10;
} }
virtual void closure() override virtual void closure() override
{ {
@ -904,6 +906,20 @@ public Q_SLOTS:
selection_item->itemChanged(); selection_item->itemChanged();
break; break;
} }
//Add Triangle Face to FaceGraph
case 10:
{
Scene_polyhedron_selection_item* selection_item = getSelectedItem<Scene_polyhedron_selection_item>();
if(!selection_item) {
print_message("Error: there is no selected polyhedron selection item!");
return;
}
if(selection_item->selected_vertices.size() != 3) {
print_message("Error: there is not exactly 3 vertices selected!");
return;
}
selection_item->add_facet_from_selected_vertices();
}
default : default :
break; break;
} }
@ -1173,6 +1189,8 @@ void filter_operations()
if(has_v) if(has_v)
{ {
ui_widget.operationsBox->addItem(operations_strings[0]); ui_widget.operationsBox->addItem(operations_strings[0]);
if(selection_item->selected_vertices.size() == 3)
ui_widget.operationsBox->addItem(operations_strings[10]);
} }
if(has_e) if(has_e)
{ {

View File

@ -781,6 +781,66 @@ public:
return num_vertices(*out) > 0; return num_vertices(*out) > 0;
} }
fg_face_descriptor add_facet_from_selected_vertices()
{
fg_face_descriptor null_face = boost::graph_traits<Face_graph>::null_face();
if(selected_vertices.size() != 3) // NYI
return null_face;
// since the selected vertices are a set, we lost order in the process,
// so find back the correct orientation
std::array<fg_vertex_descriptor, 3> vs;
for(std::size_t i=0; i<3; ++i)
vs[i] = *(std::next(selected_vertices.begin(), i));
int pos_counter = 0, neg_counter = 0;
for(std::size_t i=0; i<3; ++i)
{
auto res = halfedge(vs[i], vs[(i+1)%3], *polyhedron());
if(res.second && !is_border(res.first, *polyhedron()))
{
// the halfedge 'vs[i] - vs[i+1]' already exists in the graph and is not border,
// so vote for orienting the facet the other way
++neg_counter;
}
res = halfedge(vs[(i+1)%3], vs[i], *polyhedron());
if(res.second && !is_border(res.first, *polyhedron()))
{
// the halfedge 'vs[i+1] - vs[i]' already exists in the graph and is not border,
// so vote for keeping the current orientationorientation
++pos_counter;
}
}
if(pos_counter > 0 && neg_counter > 0)
{
// disagreement, can't insert the face (@todo duplicate and insert?)
std::cerr << "Failed to find a valid orientation (" << pos_counter << " VS " << neg_counter << ")!" << std::endl;
return null_face;
}
else if(neg_counter > 0)
{
std::swap(vs[0], vs[1]);
}
fg_face_descriptor new_f = CGAL::Euler::add_face(vs, *polyhedron());
const bool successful_insertion = (new_f != null_face);
if(successful_insertion)
{
selected_vertices.clear();
invalidateOpenGLBuffers();
changed_with_poly_item();
}
else
{
std::cerr << "Failed to insert face!" << std::endl;
}
return new_f;
}
void select_sharp_edges(const double angle) void select_sharp_edges(const double angle)
{ {
CGAL::detect_sharp_edges(polyhedron(), angle); CGAL::detect_sharp_edges(polyhedron(), angle);