Demo updates,

(I added a "paint-like smoothing" feature but I am going to remove it since real-time smoothing is not efficient due to AABB reconstruction.
This commit is contained in:
iyaz 2013-05-26 16:04:36 +03:00
parent 056ecaa477
commit 6f5122c4a1
5 changed files with 304 additions and 135 deletions

View File

@ -39,6 +39,7 @@ public slots:
void on_Create_polyline_item_button();
void on_Fill_and_update_button();
void on_Fill_all_holes_button();
private:
QMainWindow* mw;
Scene_interface* scene;
@ -158,15 +159,23 @@ void Polyhedron_demo_hole_filling_plugin::on_Fill_all_holes_button() {
if(it->is_border()){
any_changes = true;
if(ui_widget->Scale_dependent_weight_radio_button->isChecked())
CGAL::fill(poly, it, refine, alpha, fair,
CGAL::internal::Fairing_weight_selector<Polyhedron, CGAL::SCALE_DEPENDENT_WEIGHTING>::weight_calculator());
if(ui_widget->Uniform_weight_radio_button->isChecked())
CGAL::fill(poly, it, refine, alpha, fair,
CGAL::internal::Fairing_weight_selector<Polyhedron, CGAL::UNIFORM_WEIGHTING>::weight_calculator());
else
CGAL::fill(poly, it, refine, alpha, fair,
CGAL::internal::Fairing_weight_selector<Polyhedron, CGAL::COTANGENT_WEIGHTING>::weight_calculator());
if(!fair && !refine) {
CGAL::triangulate_hole(poly, it);
}
else if(!fair) {
CGAL::triangulate_and_refine_hole(poly, it, NULL, alpha);
}
else {
if(ui_widget->Scale_dependent_weight_radio_button->isChecked())
CGAL::triangulate_refine_and_fair_hole(poly, it, NULL, alpha,
CGAL::Fairing_scale_dependent_weight<Polyhedron>());
if(ui_widget->Uniform_weight_radio_button->isChecked())
CGAL::triangulate_refine_and_fair_hole(poly, it, NULL, alpha,
CGAL::Fairing_uniform_weight<Polyhedron>());
else
CGAL::triangulate_refine_and_fair_hole(poly, it, NULL, alpha,
CGAL::Fairing_cotangent_weight<Polyhedron>());
}
it = poly.halfedges_begin();
continue;
@ -220,8 +229,8 @@ void Polyhedron_demo_hole_filling_plugin::on_Fill_and_update_button() {
// new_item->setName(tr("%1-Filled-%2-(alpha:%3)").arg(poly_item->name()).arg(param_exp).arg(alpha));
//}
CGAL::fill(*poly_item->polyhedron(), it->second.second, refine, alpha, fair);
scene->itemChanged(poly_item);
//CGAL::fill(*poly_item->polyhedron(), it->second.second, refine, alpha, fair);
// scene->itemChanged(poly_item);
//if(create_new) {
// using std::swap;
// swap(*poly_item->polyhedron(), *new_item->polyhedron());

View File

@ -8,6 +8,7 @@
//#include <CGAL/Fill_hole.h>
#include <CGAL/Fill_hole_Polyhedron_3.h>
#include <CGAL/internal/Smooth.h>
#include <QTime>
#include <QAction>
@ -17,11 +18,14 @@
#include <QEvent>
#include <QKeyEvent>
#include <QMouseEvent>
#include <QFileDialog>
#include <vector>
#include <algorithm>
#include <queue>
#include <boost/iterator/transform_iterator.hpp>
#include <QGLViewer/qglviewer.h>
#include "opengl_tools.h"
@ -39,6 +43,12 @@ public:
QGLViewer* viewer = *QGLViewer::QGLViewerPool().begin();
viewer->installEventFilter(this);
// assign id's to vertices (save roi, load roi)
std::size_t idx = 0;
for(Polyhedron::Vertex_iterator it = polyhedron()->vertices_begin();
it != polyhedron()->vertices_end(); ++it, ++idx) {
it->id() = idx;
}
}
void draw_edges() const {
@ -48,7 +58,7 @@ public:
}
}
void draw() const {
poly_item->draw();
poly_item->direct_draw();
draw_ROI();
}
void draw_ROI() const {
@ -70,6 +80,44 @@ public:
}
}
void save_roi(const char* file_name) const {
std::ofstream out(file_name);
// save roi
for(std::set<Vertex_handle>::iterator it = selected_vertices.begin();
it != selected_vertices.end(); ++it) {
out << (*it)->id() << " ";
}
out.close();
}
void load_roi(const char* file_name) {
// put vertices to vector
std::vector<Polyhedron::Vertex_handle> all_vertices;
all_vertices.reserve(polyhedron()->size_of_vertices());
Polyhedron::Vertex_iterator vb(polyhedron()->vertices_begin()), ve(polyhedron()->vertices_end());
for( ;vb != ve; ++vb) {
all_vertices.push_back(vb);
}
// read roi
std::ifstream in(file_name);
std::size_t idx;
while(in >> idx) {
selected_vertices.insert(all_vertices[idx]);
}
in.close();
}
void changed_with_poly_item() {
poly_item->changed();
emit itemChanged();
}
private:
// for transform iterator
struct Get_key {
typedef Vertex_handle result_type;
Vertex_handle operator()(const std::pair<Vertex_handle, int>& map_pair) const
{ return map_pair.first; }
};
public slots:
void changed() {
// do not use decorator function, which calls changed on poly_item which cause deletion of AABB
@ -79,23 +127,33 @@ public slots:
// get vertex descriptor
Get_vertex_handle get_vertex_handle;
get_vertex_handle.vertex_ptr = static_cast<Polyhedron::Vertex*>(void_ptr);
poly_item->polyhedron()->delegate(get_vertex_handle);
polyhedron()->delegate(get_vertex_handle);
Vertex_handle clicked_vertex = get_vertex_handle.vh;
// use clicked_vertex, do what you want
bool is_insert = ui_widget->Insertion_radio_button->isChecked();
bool is_paint_like_smooth = ui_widget->Paint_like_smooth_radio_button->isChecked();
int k_ring = ui_widget->Brush_size_spin_box->value();
std::map<Vertex_handle, int> selection = extract_k_ring(*poly_item->polyhedron(), clicked_vertex, k_ring);
bool any_change = false;
if(is_insert) {
for(std::map<Vertex_handle, int>::iterator it = selection.begin(); it != selection.end(); ++it) {
any_change |= selected_vertices.insert(it->first).second;
}
}else {
for(std::map<Vertex_handle, int>::iterator it = selection.begin(); it != selection.end(); ++it) {
any_change |= selected_vertices.erase(it->first) != 0;
std::map<Vertex_handle, int> selection = extract_k_ring(*polyhedron(), clicked_vertex, k_ring);
if(!is_paint_like_smooth)
{
bool any_change = false;
if(is_insert) {
for(std::map<Vertex_handle, int>::iterator it = selection.begin(); it != selection.end(); ++it) {
any_change |= selected_vertices.insert(it->first).second;
}
}else {
for(std::map<Vertex_handle, int>::iterator it = selection.begin(); it != selection.end(); ++it) {
any_change |= selected_vertices.erase(it->first) != 0;
}
}
if(any_change) { emit itemChanged(); }
}
else {
CGAL::smooth(*polyhedron(), boost::make_transform_iterator(selection.begin(), Get_key()),
boost::make_transform_iterator(selection.end(), Get_key()));
changed_with_poly_item();
}
if(any_change) { emit itemChanged(); }
}
protected:
@ -164,11 +222,8 @@ protected:
// structs
struct Mouse_keyboard_state
{
bool shift_pressing;
bool left_button_pressing;
Mouse_keyboard_state()
: shift_pressing(false), left_button_pressing(false) { }
bool shift_pressing, left_button_pressing;
Mouse_keyboard_state() : shift_pressing(false), left_button_pressing(false) { }
};
struct Get_vertex_handle : public CGAL::Modifier_base<Polyhedron::HDS>
@ -198,18 +253,32 @@ public:
bool applicable() const { return qobject_cast<Scene_polyhedron_item*>(scene->item(scene->mainSelectionIndex())); }
void print_message(QString message) { messages->information(message);}
QList<QAction*> actions() const { return QList<QAction*>() << actionSmoothingFairing; }
Scene_polyhedron_selectable_item* get_selected_item() {
int item_id = scene->mainSelectionIndex();
Scene_polyhedron_selectable_item* selectable_item = qobject_cast<Scene_polyhedron_selectable_item*>(scene->item(item_id));
if(!selectable_item) {
print_message("Error: there is no selected polyhedron item!");
return NULL;
}
return selectable_item;
}
void init(QMainWindow* mainWindow, Scene_interface* scene_interface, Messages_interface* m);
Scene_polyhedron_selectable_item* convert_to_selectable_polyhedron(Scene_interface::Item_id i, Scene_polyhedron_item* poly_item);
Scene_polyhedron_item* convert_to_plain_polyhedron(Scene_interface::Item_id i, Scene_polyhedron_selectable_item* selectable_poly);
public slots:
void smoothing_fairing_action();
void dock_widget_visibility_changed(bool visible);
void on_Fair_button_clicked();
void on_Smooth_button_clicked();
void on_Set_all_vertices_button_clicked();
void on_Clear_ROI_button_clicked();
void on_Show_ROI_check_box_stateChanged(int state);
void on_Save_ROI_button_clicked();
void on_Load_ROI_button_clicked();
void new_item_created(int item_id);
private:
typedef Scene_interface::Item_id Item_id;
@ -243,9 +312,15 @@ void Polyhedron_demo_smoothing_fairing_plugin::init(QMainWindow* mw,
connect(dock_widget, SIGNAL(visibilityChanged(bool)), this, SLOT(dock_widget_visibility_changed(bool)) );
connect(ui_widget->Fair_button, SIGNAL(clicked()), this, SLOT(on_Fair_button_clicked()));
connect(ui_widget->Smooth_button, SIGNAL(clicked()), this, SLOT(on_Smooth_button_clicked()));
connect(ui_widget->Set_all_vertices_button, SIGNAL(clicked()), this, SLOT(on_Set_all_vertices_button_clicked()));
connect(ui_widget->Clear_ROI_button, SIGNAL(clicked()), this, SLOT(on_Clear_ROI_button_clicked()));
connect(ui_widget->Show_ROI_check_box, SIGNAL(stateChanged(int)), this, SLOT(on_Show_ROI_check_box_stateChanged(int)));
connect(ui_widget->Save_ROI_button, SIGNAL(clicked()), this, SLOT(on_Save_ROI_button_clicked()));
connect(ui_widget->Load_ROI_button, SIGNAL(clicked()), this, SLOT(on_Load_ROI_button_clicked()));
QObject* scene = dynamic_cast<QObject*>(scene_interface);
if(scene) { connect(scene, SIGNAL(newItem(int)), this, SLOT(new_item_created(int))); }
}
void Polyhedron_demo_smoothing_fairing_plugin::smoothing_fairing_action(){
@ -254,58 +329,94 @@ void Polyhedron_demo_smoothing_fairing_plugin::smoothing_fairing_action(){
}
}
void Polyhedron_demo_smoothing_fairing_plugin::on_Set_all_vertices_button_clicked() {
int item_id = scene->mainSelectionIndex();
Scene_polyhedron_selectable_item* poly_item = qobject_cast<Scene_polyhedron_selectable_item*>(scene->item(item_id));
if(!poly_item) {
print_message("Error: there is no selected polyhedron item!");
return;
}
Polyhedron::Vertex_iterator vb(poly_item->polyhedron()->vertices_begin()), ve(poly_item->polyhedron()->vertices_end());
Scene_polyhedron_selectable_item* selectable_item = get_selected_item();
if(!selectable_item) { return; }
Polyhedron::Vertex_iterator vb(selectable_item->polyhedron()->vertices_begin()), ve(selectable_item->polyhedron()->vertices_end());
for( ;vb != ve; ++vb) {
poly_item->selected_vertices.insert(vb);
selectable_item->selected_vertices.insert(vb);
}
scene->itemChanged(selectable_item);
}
void Polyhedron_demo_smoothing_fairing_plugin::on_Clear_ROI_button_clicked() {
int item_id = scene->mainSelectionIndex();
Scene_polyhedron_selectable_item* poly_item = qobject_cast<Scene_polyhedron_selectable_item*>(scene->item(item_id));
if(!poly_item) {
print_message("Error: there is no selected polyhedron item!");
return;
}
poly_item->selected_vertices.clear();
Scene_polyhedron_selectable_item* selectable_item = get_selected_item();
if(!selectable_item) { return; }
selectable_item->selected_vertices.clear();
scene->itemChanged(selectable_item);
}
void Polyhedron_demo_smoothing_fairing_plugin::on_Show_ROI_check_box_stateChanged(int /*state*/)
{
for(Scene_interface::Item_id i = 0, end = scene->numberOfEntries(); i < end; ++i)
{
Scene_polyhedron_selectable_item* poly_item = qobject_cast<Scene_polyhedron_selectable_item*>(scene->item(i));
if(!poly_item) { continue; }
Scene_polyhedron_selectable_item* selectable_item = qobject_cast<Scene_polyhedron_selectable_item*>(scene->item(i));
if(!selectable_item) { continue; }
scene->itemChanged(poly_item); // just for redraw
scene->itemChanged(selectable_item); // just for redraw
}
}
void Polyhedron_demo_smoothing_fairing_plugin::on_Save_ROI_button_clicked()
{
Scene_polyhedron_selectable_item* selectable_item = get_selected_item();
if(!selectable_item) { return; }
void Polyhedron_demo_smoothing_fairing_plugin::on_Fair_button_clicked() {
QString fileName = QFileDialog::getSaveFileName(mw, "Save",
selectable_item->name() + ".txt", "Text (*.txt)");
if(fileName.isNull()) { return; }
int item_id = scene->mainSelectionIndex();
Scene_polyhedron_selectable_item* poly_item = qobject_cast<Scene_polyhedron_selectable_item*>(scene->item(item_id));
if(!poly_item) {
print_message("Error: there is no selected polyhedron item!");
return;
selectable_item->save_roi(fileName.toLocal8Bit().data());
}
void Polyhedron_demo_smoothing_fairing_plugin::on_Load_ROI_button_clicked()
{
Scene_polyhedron_selectable_item* selectable_item = get_selected_item();
if(!selectable_item) { return; }
QString fileName = QFileDialog::getOpenFileName(mw, "Read",
selectable_item->name() + ".txt", "Text (*.txt)");
if(fileName.isNull()) { return; }
selectable_item->load_roi(fileName.toLocal8Bit().data());
scene->itemChanged(selectable_item);
}
void Polyhedron_demo_smoothing_fairing_plugin::new_item_created(int item_id)
{
if(dock_widget->isVisible()) {
Scene_polyhedron_item* poly_item =
qobject_cast<Scene_polyhedron_item*>(scene->item(item_id));
if(poly_item) {
convert_to_selectable_polyhedron(item_id, poly_item);
}
}
if(ui_widget->Scale_dependent_weight_radio_button->isChecked())
CGAL::fair(*poly_item->polyhedron(), poly_item->selected_vertices,
CGAL::internal::Fairing_weight_selector<Polyhedron, CGAL::SCALE_DEPENDENT_WEIGHTING>::weight_calculator());
if(ui_widget->Uniform_weight_radio_button->isChecked())
CGAL::fair(*poly_item->polyhedron(), poly_item->selected_vertices,
CGAL::internal::Fairing_weight_selector<Polyhedron, CGAL::UNIFORM_WEIGHTING>::weight_calculator());
else
CGAL::fair(*poly_item->polyhedron(), poly_item->selected_vertices,
CGAL::internal::Fairing_weight_selector<Polyhedron, CGAL::COTANGENT_WEIGHTING>::weight_calculator());
poly_item->changed();
}
void Polyhedron_demo_smoothing_fairing_plugin::on_Fair_button_clicked()
{
Scene_polyhedron_selectable_item* selectable_item = get_selected_item();
if(!selectable_item) { return; }
if(ui_widget->Scale_dependent_weight_radio_button->isChecked())
CGAL::fair(*selectable_item->polyhedron(), selectable_item->selected_vertices,
CGAL::Fairing_scale_dependent_weight<Polyhedron>());
if(ui_widget->Uniform_weight_radio_button->isChecked())
CGAL::fair(*selectable_item->polyhedron(), selectable_item->selected_vertices,
CGAL::Fairing_uniform_weight<Polyhedron>());
else
CGAL::fair(*selectable_item->polyhedron(), selectable_item->selected_vertices,
CGAL::Fairing_cotangent_weight<Polyhedron>());
selectable_item->changed_with_poly_item();
}
void Polyhedron_demo_smoothing_fairing_plugin::on_Smooth_button_clicked()
{
Scene_polyhedron_selectable_item* selectable_item = get_selected_item();
if(!selectable_item) { return; }
CGAL::smooth(*selectable_item->polyhedron(),
selectable_item->selected_vertices.begin(),
selectable_item->selected_vertices.end());
selectable_item->changed_with_poly_item();
}
Scene_polyhedron_selectable_item*
Polyhedron_demo_smoothing_fairing_plugin::convert_to_selectable_polyhedron(Item_id i,
Scene_polyhedron_item* poly_item)

View File

@ -6,7 +6,7 @@ Scene_polyhedron_item_decorator::Scene_polyhedron_item_decorator(Scene_polyhedro
{ }
Scene_polyhedron_item_decorator::~Scene_polyhedron_item_decorator()
{ }
{ delete poly_item; }
Scene_polyhedron_item_decorator*
Scene_polyhedron_item_decorator::clone() const {
@ -88,8 +88,10 @@ Scene_polyhedron_item_decorator::select(double orig_x,
dir_z);
}
Scene_polyhedron_item* Scene_polyhedron_item_decorator::to_polyhedron_item() const {
return poly_item;
Scene_polyhedron_item* Scene_polyhedron_item_decorator::to_polyhedron_item() {
Scene_polyhedron_item* tmp = poly_item;
poly_item = NULL;
return tmp;
}
#include "Scene_polyhedron_item_decorator.moc"

View File

@ -38,9 +38,9 @@ public:
const Polyhedron* polyhedron() const;
/// Returns a Scene_polyhedron_item from the decorator item
/// Transfers the ownership of Scene_polyhedron_item, and sets NULL
/// The item 'this' must be destroy just after a call to this function.
Scene_polyhedron_item* to_polyhedron_item() const;
Scene_polyhedron_item* to_polyhedron_item();
// Get dimensions
bool isFinite() const { return true; }

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>237</width>
<height>320</height>
<width>274</width>
<height>407</height>
</rect>
</property>
<property name="toolTip">
@ -28,76 +28,105 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QRadioButton" name="Insertion_radio_button">
<property name="text">
<string>Insertion</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="Removal_radio_button">
<property name="text">
<string>Removal</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Brush size:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="Brush_size_spin_box"/>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QPushButton" name="Set_all_vertices_button">
<property name="text">
<string>Set All Vertices as ROI</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="Clear_ROI_button">
<property name="text">
<string>Clear ROI</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="Show_ROI_check_box">
<property name="text">
<string>Show ROI</string>
</property>
<property name="checked">
<bool>true</bool>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>ROI Parameters</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QRadioButton" name="Insertion_radio_button">
<property name="text">
<string>Insertion</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="Removal_radio_button">
<property name="text">
<string>Removal</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="Paint_like_smooth_radio_button">
<property name="text">
<string>Paint-like smooth</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Brush size:</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QSpinBox" name="Brush_size_spin_box"/>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QPushButton" name="Set_all_vertices_button">
<property name="text">
<string>Set All Vertices as ROI</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="Clear_ROI_button">
<property name="text">
<string>Clear ROI</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="Show_ROI_check_box">
<property name="text">
<string>Show ROI</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Fair Parameters</string>
<string>Weighting Parameters</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
@ -130,6 +159,24 @@
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="Save_ROI_button">
<property name="text">
<string>Save ROI</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="Load_ROI_button">
<property name="text">
<string>Load ROI</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>