Commit work of previous days (week-end, yesterday and this morning):

The surface mesher Qt4 demo can now deal with labellized images.
This commit is contained in:
Laurent Rineau 2008-10-07 13:00:59 +00:00
parent e23bac61be
commit 43cc745311
23 changed files with 861 additions and 223 deletions

5
.gitattributes vendored
View File

@ -3862,12 +3862,13 @@ Surface_mesher/demo/Surface_mesher/qt4-demo/icons/surface.png -text svneol=unset
Surface_mesher/demo/Surface_mesher/qt4-demo/icons/surface.svg -text svneol=unset#image/svg%2Bxml
Surface_mesher/demo/Surface_mesher/qt4-demo/icons/twosides.png -text svneol=unset#image/png
Surface_mesher/demo/Surface_mesher/qt4-demo/icons/twosides.svg -text svneol=unset#image/svg%2Bxml
Surface_mesher/demo/Surface_mesher/qt4-demo/isovalues_list.qrc -text
Surface_mesher/demo/Surface_mesher/qt4-demo/surface_mesher.qrc -text
Surface_mesher/demo/Surface_mesher/qt4-demo/ui/isovalues_list.ui -text
Surface_mesher/demo/Surface_mesher/qt4-demo/ui/mainwindow.ui -text
Surface_mesher/demo/Surface_mesher/qt4-demo/ui/meshing_bar.ui -text
Surface_mesher/demo/Surface_mesher/qt4-demo/ui/optionsdialog.ui -text
Surface_mesher/demo/Surface_mesher/qt4-demo/ui/raw_image.ui -text
Surface_mesher/demo/Surface_mesher/qt4-demo/ui/values_list.ui -text
Surface_mesher/demo/Surface_mesher/qt4-demo/values_list.qrc -text
Surface_mesher/demo/Surface_mesher/replay-tangle -text
Surface_mesher/demo/Surface_mesher/windows/Mesh.sln eol=crlf
Surface_mesher/demo/Surface_mesher/windows/Mesh.suo -text

3
.gitignore vendored
View File

@ -23,6 +23,7 @@ Boolean_set_operations_2/demo/Boolean_set_operations_2/*.vcproj
Boolean_set_operations_2/demo/Boolean_set_operations_2/Makefile
Boolean_set_operations_2/demo/Boolean_set_operations_2/boolean_operations_2
CGALimageIO/demo/CGALimageIO/Makefile
CGALimageIO/demo/CGALimageIO/cgal_test_with_cmake
CGALimageIO/demo/CGALimageIO/cmake_install.cmake
CGALimageIO/demo/CGALimageIO/image_to_vtk_viewer
CGALimageIO/examples/CGALimageIO/*.exe
@ -30,6 +31,7 @@ CGALimageIO/examples/CGALimageIO/Makefile
CGALimageIO/examples/CGALimageIO/convert_raw_image_to_inr
CGALimageIO/examples/CGALimageIO/makefile
CGALimageIO/examples/CGALimageIO/test_imageio
CGALimageIO/src/CGALimageIO/Makefile
Distance_3/include
GraphicsView/TAGS
GraphicsView/demo/Alpha_shapes_3/*.exe
@ -411,6 +413,7 @@ Surface_mesher/demo/Surface_mesher/qt4-demo/.qglviewer.xml
Surface_mesher/demo/Surface_mesher/qt4-demo/CMakeCache.txt
Surface_mesher/demo/Surface_mesher/qt4-demo/CMakeFiles
Surface_mesher/demo/Surface_mesher/qt4-demo/Makefile
Surface_mesher/demo/Surface_mesher/qt4-demo/Surface_mesher
Surface_mesher/demo/Surface_mesher/qt4-demo/Surface_mesher_Qt4_Demo
Surface_mesher/demo/Surface_mesher/qt4-demo/cgal.prf
Surface_mesher/demo/Surface_mesher/qt4-demo/cmake_install.cmake

View File

@ -382,7 +382,8 @@ _image* _readImage_raw(const char *name,
const unsigned int rz,
const double vx = 1.,
const double vy = 1.,
const double vz = 1.);
const double vz = 1.,
const unsigned int offset = 0);
/** Writes given image in file 'name'.<br>

View File

@ -113,11 +113,12 @@ public:
const unsigned int rz,
const double vx = 1,
const double vy = 1,
const double vz = 1)
const double vz = 1,
const unsigned int offset = 0)
{
return private_read(::_readImage_raw(file,
rx,ry,rz,
vx,vy,vz));
vx,vy,vz,offset));
}
#ifdef CGAL_USE_VTK

View File

@ -1 +1 @@
cgal-develop
Laurent Rineau <Laurent.Rineau@geometryfactory.com>

View File

@ -560,7 +560,8 @@ _image* _readImage_raw(const char *name,
const unsigned int rz,
const double vx,
const double vy,
const double vz)
const double vz,
const unsigned int offset)
{
_image *im = NULL;
im = (_image *) ImageIO_alloc(sizeof(_image));
@ -610,8 +611,14 @@ _image* _readImage_raw(const char *name,
return NULL;
}
// read offset
if(offset > 0) {
im->data = ImageIO_alloc(offset+1);
ImageIO_read(im, im->data, offset);
ImageIO_free(im->data);
}
// allocate memory
im->data = (void *)new unsigned char[rx*ry*rz];
im->data = ImageIO_alloc(rx*ry*rz);
if(im->data == NULL)
return NULL;

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 2.4.5)
set ( prj Surface_mesher_Qt4_Demo )
set ( prj Surface_mesher )
project ( ${prj} )
@ -29,7 +29,7 @@ set( QT_USE_QTOPENGL TRUE )
set( QT_USE_QTXML TRUE )
set( QT_USE_QTMAIN TRUE )
find_package(CGAL REQUIRED )
find_package(CGAL REQUIRED COMPONENTS ImageIO Qt4)
if ( CGAL_FOUND )
include( ${CGAL_USE_FILE} )
@ -38,7 +38,7 @@ if ( CGAL_FOUND )
find_package(QGLViewer REQUIRED )
find_package(OpenGL REQUIRED )
find_package(ZLIB REQUIRED )
# find_package(VTK QUIET)
find_package(VTK QUIET)
find_path(bimap_DIR boost/bimap/bimap.hpp ${Boost_INCLUDE_DIRS} DOC "The directory containing the bimap subdirectory.")
@ -50,7 +50,7 @@ if ( CGAL_FOUND )
endif()
endif(EXISTS ${bimap_DIR}/boost/bimap/bimap.hpp)
if( VTK_FOUND )
if( VTK_FOUND AND EXISTS ${VTK_USE_FILE})
# if( ${VTK_MAJOR_VERSION} STRGREATER "5")
message(STATUS "VTK-${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION}.${VTK_BUILD_VERSION} found in ${VTK_DIR}.")
set(VTK_BUILD_SETTINGS_FILE "")
@ -58,9 +58,9 @@ if ( CGAL_FOUND )
add_definitions(-DCGAL_USE_VTK)
# endif( ${VTK_MAJOR_VERSION} GREATER 5)
SET(PRJ_VTK_LIBS vtkImaging vtkIO)
else( VTK_FOUND)
else( VTK_FOUND AND EXISTS ${VTK_USE_FILE})
message(STATUS "VTK not found.")
endif( VTK_FOUND )
endif( VTK_FOUND AND EXISTS ${VTK_USE_FILE})
add_definitions(-DCGAL_USE_ZLIB)
@ -80,7 +80,7 @@ if ( CGAL_FOUND )
include_directories( ${QGLVIEWER_INCLUDE_DIR} )
set( sources colorlisteditor.cpp isovalues_list.cpp mainwindow.cpp surface_mesher.cpp viewer.cpp volume.cpp ${PACKAGE_ROOT}/../Marching_cube/src/mc/ply.c)
set( sources colorlisteditor.cpp values_list.cpp mainwindow.cpp Surface_mesher.cpp viewer.cpp volume.cpp polyhedral_surface.cpp ${PACKAGE_ROOT}/../Marching_cube/src/mc/ply.c)
qt4_automoc( ${sources} )
@ -88,18 +88,16 @@ if ( CGAL_FOUND )
set( sources ${sources} moc_surface.cpp)
qt4_wrap_ui( uis ui/isovalues_list.ui ui/mainwindow.ui ui/meshing_bar.ui ui/optionsdialog.ui )
qt4_wrap_ui( uis ui/values_list.ui ui/mainwindow.ui ui/meshing_bar.ui ui/optionsdialog.ui ui/raw_image.ui )
qt4_add_resources( qrc_sources isovalues_list.qrc surface_mesher.qrc )
qt4_add_resources( qrc_sources values_list.qrc surface_mesher.qrc )
add_executable ( ${prj} ${sources} ${uis} ${qrc_sources} )
# Link the executable to CGAL and third-party libraries
if ( NOT AUTO_LINK_ENABLED )
target_link_libraries( ${prj} CGAL CGAL-ImageIO ${CGAL_3RD_PARTY_LIBRARIES})
endif()
target_link_libraries( ${prj} ${CGAL_LIBRARIES} ${CGAL_3RD_PARTY_LIBRARIES})
target_link_libraries( ${prj} CGAL-Qt4 ${QT_LIBRARIES} ${QGLVIEWER_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} ) # ${PRJ_VTK_LIBS}
target_link_libraries( ${prj} ${QT_LIBRARIES} ${QGLVIEWER_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} ${PRJ_VTK_LIBS} )
endif()
endif(CGAL_FOUND)

View File

@ -0,0 +1,9 @@
#include "ui_raw_image.h"
struct Raw_image_dialog : public QDialog, public Ui::Raw_image_dialog {
Raw_image_dialog(QWidget* parent = 0) : QDialog(parent)
{
setupUi(this);
}
};

View File

@ -31,6 +31,8 @@
template <typename FT_, typename Point>
class CBinary_image_3 : public CGAL::Image_3
{
bool interpolate_;
public:
float min_value;
float max_value;
@ -38,11 +40,12 @@ public:
typedef FT_ FT;
public:
CBinary_image_3() : Image_3()
CBinary_image_3() : Image_3(), interpolate_(true)
{
}
CBinary_image_3(const CBinary_image_3& bi) : Image_3(bi)
CBinary_image_3(const CBinary_image_3& bi)
: Image_3(bi), interpolate_(bi.interpolate_)
{
std::cerr << "CBinary_image_3::copy_constructor\n";
min_value = bi.min_value;
@ -151,16 +154,55 @@ public:
float rand_y() { return (float)rand() / (float)RAND_MAX * ymax(); }
float rand_z() { return (float)rand() / (float)RAND_MAX * zmax(); }
void set_interpolation(const bool b)
{
interpolate_ = b;
}
bool interpolation() const {
return interpolate_;
}
FT operator()(Point p) const
{
const float x = static_cast<float>(CGAL::to_double(p.x()));
const float y = static_cast<float>(CGAL::to_double(p.y()));
const float z = static_cast<float>(CGAL::to_double(p.z()));
if(inside(x,y,z))
return FT(::trilinear_interpolation(image_ptr.get(),x,y,z));
else
return 0;
if(interpolation()) {
std::cerr << "interpolation\n";
if(inside(x,y,z))
return FT(::trilinear_interpolation(image_ptr.get(),x,y,z));
else
return 0;
}
else {
const int i = static_cast<int>(x/image()->vx + 0.5f);
const int j = static_cast<int>(y/image()->vy + 0.5f);
const int k = static_cast<int>(z/image()->vz + 0.5f);
if( i < 0 ||
j < 0 ||
k < 0 )
{
return 0;
}
else
{
const unsigned int ui = static_cast<unsigned int>(i);
const unsigned int uj = static_cast<unsigned int>(j);
const unsigned int uk = static_cast<unsigned int>(k);
if( ui >= image()->xdim ||
uj >= image()->ydim ||
uk >= image()->zdim )
{
return 0;
}
else
{
return this->value(ui, uj, uk);
}
}
}
}
}; // end CBinary_image_3

View File

@ -24,6 +24,7 @@
#include "ui_mainwindow.h"
#include "volume.h"
#include "polyhedral_surface.h"
MainWindow::MainWindow(MainWindow* other_window /* = 0 */) :
CGAL::Qt::DemosMainWindow(),
@ -42,6 +43,7 @@ MainWindow::MainWindow(MainWindow* other_window /* = 0 */) :
QToolBar* tb_meshing = qFindChild<QToolBar*>(this, "toolBar_meshing");
// tb_meshing->setVisible(false);
QAction* action_mc = qFindChild<QAction*>(this, "actionMarching_cubes");
if(tb_meshing && action_mc) {
@ -51,10 +53,11 @@ MainWindow::MainWindow(MainWindow* other_window /* = 0 */) :
tb_meshing->insertWidget(action_mc,
meshing_bar);
tb_meshing->insertSeparator(action_mc);
meshing_bar->setProperty("show_only_in", QStringList() << "volume");
}
show_only("");
surface = new Volume(this);
// surface = new Volume(this);
addAboutCGAL();
this->addRecentFiles(this->menu_File,
@ -78,8 +81,17 @@ void MainWindow::dropEvent(QDropEvent *event)
void MainWindow::surface_open(const QString& filename)
{
surface->open(filename);
this->addToRecentFiles(filename);
surface = new Polyhedral_surface(this);
if(surface->open(filename)) {
this->addToRecentFiles(filename);
}
else {
delete surface;
surface = new Volume(this);
if(surface->open(filename)) {
this->addToRecentFiles(filename);
}
}
}
void MainWindow::show_only(QString tag)
@ -98,9 +110,12 @@ void MainWindow::show_only(QString tag)
err << s << " ";
const bool visible = show_only_in.contains(tag);
err << (visible ? "(enabled)\n" : "(disabled)\n");
object->setProperty("visible", QVariant::fromValue<bool>(visible));
if(QMenu* menu = qobject_cast<QMenu*>(object))
if(QMenu* menu = qobject_cast<QMenu*>(object)) {
menu->menuAction()->setVisible(visible);
}
else {
object->setProperty("visible", QVariant::fromValue<bool>(visible));
}
}
}
}

View File

@ -2,6 +2,7 @@
#include "get_polyhedral_surface.h"
#include <QMainWindow>
#include <QString>
#include <QStatusBar>
#include <QApplication>
#include <QAction>
@ -123,8 +124,11 @@ void Polyhedral_surface::connect_actions()
this, it->second.second);
}
MainWindow* mw = qobject_cast<MainWindow *>(parent);
if(mw)
mw->fix_menus_visibility();
if(mw) {
// mw->fix_menus_visibility();
mw->show_only("polyhedral");
}
connect(this, SIGNAL(changed()), this, SLOT(display_nb_elements_in_status_bar()));
}
@ -241,7 +245,7 @@ void Polyhedral_surface::make_one_subdivision_step()
if(surface_ptr)
{
Polyhedron output;
CSubdivider_loop<Polyhedron , Kernel> pw_loop_subdiviser;
CSubdivider_loop<Polyhedron , Poly_kernel> pw_loop_subdiviser;
pw_loop_subdiviser.subdivide(*surface_ptr, output);
static_cast<Polyhedron&>(*surface_ptr) = output;
@ -252,14 +256,15 @@ void Polyhedral_surface::make_one_subdivision_step()
}
}
void Polyhedral_surface::open(const QString& filename)
bool Polyhedral_surface::open(const QString& filename)
{
clear();
std::cerr << "Opening file \"" << filename.toLocal8Bit() << "\"...";
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
std::cerr << "Opening file \"" << qPrintable(filename) << "\"...";
std::ifstream in(filename.toUtf8());
if(!in) return;
if(!in) return false;
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
if(surface_ptr)
delete surface_ptr;
@ -268,6 +273,10 @@ void Polyhedral_surface::open(const QString& filename)
sharp_edges_angle_upper_bound,
false /*do not construct
octree*/);
if(!in) {
QApplication::restoreOverrideCursor();
return false;
}
is_octree_initialized = false;
selected_facet = selected_edge = -1;
update_data_structures();
@ -299,6 +308,7 @@ void Polyhedral_surface::open(const QString& filename)
QAction* actionInverse_normals = qFindChild<QAction*>(this, "actionInverse_normals");
if(actionInverse_normals) actionInverse_normals->setChecked(false);
emit set_dirty();
return true;
}
void Polyhedral_surface::close()

View File

@ -25,15 +25,14 @@ typedef std::map<const char*, Signal_slot_pair> Connection_map;
// piece-wise loop subdivision
#include <CGAL/pws_loop_subdivision.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel Poly_kernel;
typedef Poly_kernel::FT FT;
typedef Poly_kernel::Point_3 Poly_point;
typedef Poly_kernel::Sphere_3 Sphere;
typedef Poly_kernel::Vector_3 Vector;
typedef Poly_kernel::Triangle_3 Triangle_3;
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef Kernel::FT FT;
typedef Kernel::Point_3 Point;
typedef Kernel::Sphere_3 Sphere;
typedef Kernel::Vector_3 Vector;
typedef Kernel::Triangle_3 Triangle_3;
typedef CGAL::Polyhedral_surface_3<Kernel,
typedef CGAL::Polyhedral_surface_3<Poly_kernel,
CGAL::Surface_mesher::Has_edges> CGAL_polyhedral_surface;
@ -43,8 +42,8 @@ class Polyhedral_surface : public Surface
public:
Polyhedral_surface(QObject* parent,
double sharp_edges_angle_lower_bound,
double sharp_edges_angle_upper_bound);
double sharp_edges_angle_lower_bound = 90,
double sharp_edges_angle_upper_bound = 120);
~Polyhedral_surface();
public slots:
@ -67,7 +66,7 @@ public slots:
void on_action_Options_triggered();
public:
void open(const QString& filename);
bool open(const QString& filename);
void close();
void draw();
void drawWithNames();

View File

@ -19,7 +19,7 @@ protected:
viewer->set_surface(this);
}
public slots:
virtual void open(const QString& filename) = 0;
virtual bool open(const QString& filename) = 0;
virtual void close() = 0;
virtual void draw() = 0;
virtual void get_bbox(float&, float&, float&,

View File

@ -5,18 +5,19 @@
<rect>
<x>0</x>
<y>0</y>
<width>1090</width>
<height>570</height>
<width>1100</width>
<height>595</height>
</rect>
</property>
<property name="windowTitle" >
<string>Surface mesher demo</string>
</property>
<property name="windowIcon" >
<iconset resource="../surface_mesher.qrc" >:/icons/cgal_logo.xpm</iconset>
<iconset resource="../surface_mesher.qrc" >
<normaloff>:/icons/cgal_logo.xpm</normaloff>:/icons/cgal_logo.xpm</iconset>
</property>
<widget class="QWidget" name="centralwidget" >
<layout class="QGridLayout" >
<layout class="QGridLayout" name="gridLayout" >
<item row="0" column="0" >
<widget class="QSplitter" name="splitter" >
<property name="orientation" >
@ -30,12 +31,107 @@
</sizepolicy>
</property>
</widget>
<widget class="Isovalues_list" native="1" name="isovalues" >
<property name="show_only_in" stdset="0" >
<stringlist>
<string>volume</string>
</stringlist>
</property>
<widget class="QWidget" name="layoutWidget" >
<layout class="QVBoxLayout" name="optionsLayout" >
<item>
<widget class="QGroupBox" name="groupBoxImageType" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Expanding" hsizetype="Preferred" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title" >
<string>Image type</string>
</property>
<property name="show_only_in" stdset="0" >
<stringlist>
<string>volume</string>
</stringlist>
</property>
<layout class="QVBoxLayout" name="verticalLayout" >
<item>
<widget class="QRadioButton" name="grayLevelRadioButton" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Preferred" hsizetype="Minimum" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text" >
<string>Grayscale image</string>
</property>
<property name="checked" >
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="labellizedRadioButton" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Preferred" hsizetype="Minimum" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text" >
<string>Segmented image</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBoxCriteria" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Minimum" hsizetype="Preferred" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title" >
<string>Criteria</string>
</property>
<property name="show_only_in" stdset="0" >
<stringlist>
<string>volume</string>
</stringlist>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2" >
<item>
<widget class="QCheckBox" name="manifoldCheckBox" >
<property name="text" >
<string>Manifold</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="sameIndexCheckBox" >
<property name="text" >
<string>Facets vertices have same index</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="Values_list" native="1" name="values" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Expanding" hsizetype="Preferred" >
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="show_only_in" stdset="0" >
<stringlist>
<string>volume</string>
</stringlist>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
@ -46,7 +142,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>1090</width>
<width>1100</width>
<height>29</height>
</rect>
</property>
@ -66,7 +162,7 @@
<property name="show_only_in" stdset="0" >
<stringlist>
<string>volume</string>
<string>polyhedra</string>
<string>polyhedral</string>
</stringlist>
</property>
<addaction name="actionInverse_normals" />
@ -113,7 +209,6 @@
</attribute>
<addaction name="action_Open" />
<addaction name="actionExport_surface_mesh_to_OFF" />
<addaction name="action_Clone" />
<addaction name="separator" />
<addaction name="actionAuto_resize" />
<addaction name="actionDisplay_front_and_back" />
@ -141,7 +236,8 @@
</widget>
<action name="action_Open" >
<property name="icon" >
<iconset resource="../surface_mesher.qrc" >:/icons/fileopen.png</iconset>
<iconset resource="../surface_mesher.qrc" >
<normaloff>:/icons/fileopen.png</normaloff>:/icons/fileopen.png</iconset>
</property>
<property name="text" >
<string>&amp;Open...</string>
@ -166,7 +262,8 @@
<bool>true</bool>
</property>
<property name="icon" >
<iconset resource="../surface_mesher.qrc" >:/icons/flip.png</iconset>
<iconset resource="../surface_mesher.qrc" >
<normaloff>:/icons/flip.png</normaloff>:/icons/flip.png</iconset>
</property>
<property name="text" >
<string>&amp;Inverse normals</string>
@ -189,7 +286,8 @@
<bool>true</bool>
</property>
<property name="icon" >
<iconset resource="../surface_mesher.qrc" >:/icons/bbox.png</iconset>
<iconset resource="../surface_mesher.qrc" >
<normaloff>:/icons/bbox.png</normaloff>:/icons/bbox.png</iconset>
</property>
<property name="text" >
<string>Display oc&amp;tree</string>
@ -211,7 +309,8 @@
<bool>true</bool>
</property>
<property name="icon" >
<iconset resource="../surface_mesher.qrc" >:/icons/surface.png</iconset>
<iconset resource="../surface_mesher.qrc" >
<normaloff>:/icons/surface.png</normaloff>:/icons/surface.png</iconset>
</property>
<property name="text" >
<string>Display &amp;surface</string>
@ -288,7 +387,8 @@
<bool>true</bool>
</property>
<property name="icon" >
<iconset resource="../surface_mesher.qrc" >:/icons/bbox-red.png</iconset>
<iconset resource="../surface_mesher.qrc" >
<normaloff>:/icons/bbox-red.png</normaloff>:/icons/bbox-red.png</iconset>
</property>
<property name="text" >
<string>Display edges octree</string>
@ -333,7 +433,8 @@
<bool>true</bool>
</property>
<property name="icon" >
<iconset resource="../surface_mesher.qrc" >:/icons/twosides.png</iconset>
<iconset resource="../surface_mesher.qrc" >
<normaloff>:/icons/twosides.png</normaloff>:/icons/twosides.png</iconset>
</property>
<property name="text" >
<string>Display facets with &amp;front and back</string>
@ -347,7 +448,7 @@
<property name="show_only_in" stdset="0" >
<stringlist>
<string>volume</string>
<string>surface</string>
<string>polyhedral</string>
</stringlist>
</property>
</action>
@ -364,7 +465,8 @@
<bool>false</bool>
</property>
<property name="icon" >
<iconset resource="../surface_mesher.qrc" >:/icons/resize.png</iconset>
<iconset resource="../surface_mesher.qrc" >
<normaloff>:/icons/resize.png</normaloff>:/icons/resize.png</iconset>
</property>
<property name="text" >
<string>Auto-&amp;resize</string>
@ -460,7 +562,8 @@
</action>
<action name="actionExport_surface_mesh_to_OFF" >
<property name="icon" >
<iconset resource="../surface_mesher.qrc" >:/icons/filesave.png</iconset>
<iconset resource="../surface_mesher.qrc" >
<normaloff>:/icons/filesave.png</normaloff>:/icons/filesave.png</iconset>
</property>
<property name="text" >
<string>Export surface mesh to OFF...</string>
@ -479,9 +582,9 @@
<header>viewer.h</header>
</customwidget>
<customwidget>
<class>Isovalues_list</class>
<class>Values_list</class>
<extends>QWidget</extends>
<header>isovalues_list.h</header>
<header>values_list.h</header>
<container>1</container>
</customwidget>
</customwidgets>

View File

@ -0,0 +1,282 @@
<ui version="4.0" >
<class>Raw_image_dialog</class>
<widget class="QDialog" name="Raw_image_dialog" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>479</width>
<height>316</height>
</rect>
</property>
<property name="windowTitle" >
<string>Open raw image</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout" >
<item>
<widget class="QGroupBox" name="groupBox_2" >
<property name="title" >
<string>Image &amp;value type</string>
</property>
<layout class="QGridLayout" name="gridLayout" >
<item row="2" column="0" >
<widget class="QRadioButton" name="short_bt" >
<property name="text" >
<string>Short (16 bits)</string>
</property>
</widget>
</item>
<item row="3" column="0" >
<widget class="QRadioButton" name="float_bt" >
<property name="text" >
<string>Float</string>
</property>
</widget>
</item>
<item row="0" column="1" >
<widget class="QRadioButton" name="int_bt" >
<property name="text" >
<string>Int (32 bits)</string>
</property>
</widget>
</item>
<item row="3" column="1" >
<widget class="QRadioButton" name="radioButton_6" >
<property name="text" >
<string>Double</string>
</property>
</widget>
</item>
<item row="2" column="1" >
<widget class="QCheckBox" name="signed_bt" >
<property name="text" >
<string>Signed</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox" >
<property name="title" >
<string>Image dimensions</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2" >
<item>
<layout class="QGridLayout" >
<item row="0" column="0" >
<widget class="QLabel" name="label_dim" >
<property name="text" >
<string>&amp;Dimensions:</string>
</property>
<property name="alignment" >
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy" >
<cstring>dim_x</cstring>
</property>
</widget>
</item>
<item row="1" column="0" >
<widget class="QLabel" name="label_spacing" >
<property name="text" >
<string>&amp;Spacing:</string>
</property>
<property name="alignment" >
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy" >
<cstring>spacing_x</cstring>
</property>
</widget>
</item>
<item row="0" column="1" >
<widget class="QSpinBox" name="dim_x" >
<property name="prefix" >
<string>x: </string>
</property>
<property name="maximum" >
<number>100000000</number>
</property>
</widget>
</item>
<item row="0" column="2" >
<widget class="QSpinBox" name="dim_y" >
<property name="prefix" >
<string>y: </string>
</property>
<property name="maximum" >
<number>100000000</number>
</property>
</widget>
</item>
<item row="0" column="3" >
<widget class="QSpinBox" name="dim_z" >
<property name="prefix" >
<string>z: </string>
</property>
<property name="maximum" >
<number>100000000</number>
</property>
</widget>
</item>
<item row="1" column="1" >
<widget class="QDoubleSpinBox" name="spacing_x" >
<property name="prefix" >
<string>vx: </string>
</property>
<property name="decimals" >
<number>3</number>
</property>
<property name="value" >
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item row="1" column="2" >
<widget class="QDoubleSpinBox" name="spacing_y" >
<property name="prefix" >
<string>vy: </string>
</property>
<property name="decimals" >
<number>3</number>
</property>
<property name="value" >
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item row="1" column="3" >
<widget class="QDoubleSpinBox" name="spacing_z" >
<property name="prefix" >
<string>vz: </string>
</property>
<property name="decimals" >
<number>3</number>
</property>
<property name="value" >
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item row="2" column="0" >
<widget class="QLabel" name="offset_label" >
<property name="text" >
<string>&amp;Offset:</string>
</property>
<property name="alignment" >
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy" >
<cstring>offset</cstring>
</property>
</widget>
</item>
<item row="2" column="1" >
<widget class="QSpinBox" name="offset" >
<property name="suffix" >
<string> bytes</string>
</property>
<property name="maximum" >
<number>999999999</number>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox" >
<property name="standardButtons" >
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Open</set>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>int_bt</tabstop>
<tabstop>short_bt</tabstop>
<tabstop>signed_bt</tabstop>
<tabstop>float_bt</tabstop>
<tabstop>radioButton_6</tabstop>
<tabstop>dim_x</tabstop>
<tabstop>dim_y</tabstop>
<tabstop>dim_z</tabstop>
<tabstop>spacing_x</tabstop>
<tabstop>spacing_y</tabstop>
<tabstop>spacing_z</tabstop>
<tabstop>offset</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>float_bt</sender>
<signal>toggled(bool)</signal>
<receiver>signed_bt</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>47</x>
<y>112</y>
</hint>
<hint type="destinationlabel" >
<x>257</x>
<y>83</y>
</hint>
</hints>
</connection>
<connection>
<sender>radioButton_6</sender>
<signal>toggled(bool)</signal>
<receiver>signed_bt</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>281</x>
<y>113</y>
</hint>
<hint type="destinationlabel" >
<x>290</x>
<y>82</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Raw_image_dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel" >
<x>191</x>
<y>290</y>
</hint>
<hint type="destinationlabel" >
<x>183</x>
<y>313</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Raw_image_dialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel" >
<x>253</x>
<y>293</y>
</hint>
<hint type="destinationlabel" >
<x>252</x>
<y>312</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -1,6 +1,6 @@
<ui version="4.0" >
<class>Isovalues_list</class>
<widget class="QWidget" name="Isovalues_list" >
<class>Values_list</class>
<widget class="QWidget" name="Values_list" >
<property name="geometry" >
<rect>
<x>0</x>
@ -76,7 +76,7 @@
<string>...</string>
</property>
<property name="icon" >
<iconset resource="../isovalues_list.qrc" >:/isovalues/plus.png</iconset>
<iconset resource="../values_list.qrc" >:/values/plus.png</iconset>
</property>
</widget>
</item>
@ -86,7 +86,7 @@
<string>...</string>
</property>
<property name="icon" >
<iconset resource="../isovalues_list.qrc" >:/isovalues/minus.png</iconset>
<iconset resource="../values_list.qrc" >:/values/minus.png</iconset>
</property>
<property name="shortcut" >
<string>Del</string>
@ -112,7 +112,7 @@
</widget>
<resources>
<include location="../surface_mesher.qrc" />
<include location="../isovalues_list.qrc" />
<include location="../values_list.qrc" />
</resources>
<connections/>
</ui>

View File

@ -1,6 +1,7 @@
#include "isovalues_list.h"
#include "ui_isovalues_list.h"
#include "values_list.h"
#include "ui_values_list.h"
#include "colorlisteditor.h"
#include <iostream>
#include <QTreeWidget>
#include <QTreeWidgetItem>
@ -20,12 +21,12 @@
#include <QLineEdit>
#include <QDoubleValidator>
Isovalues_delegate::Isovalues_delegate(QWidget* parent) : QItemDelegate(parent) {}
void Isovalues_delegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const
Values_delegate::Values_delegate(QWidget* parent) : QItemDelegate(parent) {}
void Values_delegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const
{
switch(index.column())
{
case Isovalues_list::Color: {
case Values_list::Color: {
painter->fillRect(option.rect, index.data().value<QColor>());
drawFocus(painter, option, option.rect);
break;
@ -35,15 +36,15 @@ void Isovalues_delegate::paint(QPainter * painter, const QStyleOptionViewItem &
}
}
QWidget *Isovalues_delegate::createEditor(QWidget *parent,
QWidget *Values_delegate::createEditor(QWidget *parent,
const QStyleOptionViewItem & option,
const QModelIndex & index) const
{
if(index.column() == Isovalues_list::Color)
if(index.column() == Values_list::Color)
{
return new ColorListEditor(parent);
}
else if(index.column() == Isovalues_list::Isovalue)
else if(index.column() == Values_list::Value)
{
QLineEdit* lineedit = new QLineEdit(parent);
lineedit->setAutoFillBackground(true);
@ -53,16 +54,16 @@ QWidget *Isovalues_delegate::createEditor(QWidget *parent,
else return QItemDelegate::createEditor(parent, option, index);
}
void Isovalues_delegate::setEditorData(QWidget *editor,
void Values_delegate::setEditorData(QWidget *editor,
const QModelIndex &index) const
{
if(index.column() == Isovalues_list::Color)
if(index.column() == Values_list::Color)
{
ColorListEditor* coloreditor = qobject_cast<ColorListEditor*>(editor);
if(coloreditor)
coloreditor->setColor(index.data().value<QColor>());
}
else if(index.column() == Isovalues_list::Isovalue)
else if(index.column() == Values_list::Value)
{
QLineEdit* lineedit = qobject_cast<QLineEdit*>(editor);
if(lineedit)
@ -70,10 +71,10 @@ void Isovalues_delegate::setEditorData(QWidget *editor,
}
else QItemDelegate::setEditorData(editor, index);
}
void Isovalues_delegate::setModelData(QWidget *editor, QAbstractItemModel *model,
void Values_delegate::setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const
{
if(index.column() == Isovalues_list::Color)
if(index.column() == Values_list::Color)
{
ColorListEditor* coloreditor = qobject_cast<ColorListEditor*>(editor);
if(coloreditor)
@ -82,44 +83,47 @@ void Isovalues_delegate::setModelData(QWidget *editor, QAbstractItemModel *model
emit new_color(index);
}
}
else if(index.column() == Isovalues_list::Isovalue)
else if(index.column() == Values_list::Value)
{
QLineEdit* lineedit = qobject_cast<QLineEdit*>(editor);
if(lineedit)
{
model->setData(index, lineedit->text().toDouble());
emit new_isovalue(index);
emit new_value(index);
}
}
else QItemDelegate::setModelData(editor, model, index);
}
const double Isovalues_list::default_isovalue = 0.0;
const double Values_list::default_value = 0.0;
Isovalues_list::Isovalues_list(QWidget* parent):
Values_list::Values_list(QWidget* parent):
QWidget(parent)
{
Ui::Isovalues_list().setupUi(this);
Ui::Values_list().setupUi(this);
treeWidget = parent->findChild<QTreeWidget*>("treeWidget");
Q_ASSERT_X(treeWidget, "Isovalues_list constructor", "cannot find widget \"treeWidget\"");
Q_ASSERT_X(treeWidget, "Values_list constructor", "cannot find widget \"treeWidget\"");
treeWidget->sortByColumn(Isovalue, Qt::AscendingOrder);
treeWidget->sortByColumn(Value, Qt::AscendingOrder);
treeWidget->header()->setClickable(false);
Isovalues_delegate* isovalues_delegate = new Isovalues_delegate(parent);
Values_delegate* values_delegate = new Values_delegate(parent);
treeWidget->setItemDelegate(isovalues_delegate);
connect(isovalues_delegate, SIGNAL(new_isovalue(const QModelIndex&)),
this, SIGNAL(isovalues_changed()));
connect(isovalues_delegate, SIGNAL(new_color(const QModelIndex&)),
treeWidget->setItemDelegate(values_delegate);
connect(values_delegate, SIGNAL(new_value(const QModelIndex&)),
this, SIGNAL(values_changed()));
connect(values_delegate, SIGNAL(new_color(const QModelIndex&)),
this, SIGNAL(colors_changed()));
connect(this->treeWidget->model(),
SIGNAL(dataChanged (const QModelIndex &, const QModelIndex &)),
this, SIGNAL(changed()));
connect(this, SIGNAL(changed()),
this, SLOT(update_items_cache()));
}
QColor Isovalues_list::color(const int i) const
QColor Values_list::color(const int i) const
{
if(i < 0 || i > treeWidget->topLevelItemCount())
return QColor();
@ -127,25 +131,25 @@ QColor Isovalues_list::color(const int i) const
return treeWidget->topLevelItem(i)->data(Color, Qt::DisplayRole).value<QColor>();
}
QColor Isovalues_list::color(const QTreeWidgetItem* item) const
QColor Values_list::color(const QTreeWidgetItem* item) const
{
return item->data(Color, Qt::DisplayRole).value<QColor>();
}
int Isovalues_list::numberOfIsoValues() const
int Values_list::numberOfValues() const
{
return treeWidget->topLevelItemCount();
}
double Isovalues_list::isovalue(const int i) const
double Values_list::value(const int i) const
{
if(i < 0 || i > numberOfIsoValues())
if(i < 0 || i > numberOfValues())
return 0.;
else
return treeWidget->topLevelItem(i)->data(Isovalue, Qt::DisplayRole).toDouble();
return treeWidget->topLevelItem(i)->data(Value, Qt::DisplayRole).toDouble();
}
QString Isovalues_list::name(const int i) const
QString Values_list::name(const int i) const
{
if(i < 0 || i > treeWidget->topLevelItemCount())
return QString();
@ -153,20 +157,20 @@ QString Isovalues_list::name(const int i) const
return treeWidget->topLevelItem(i)->data(Name, Qt::DisplayRole).toString();
}
bool Isovalues_list::enabled(const int i) const
bool Values_list::enabled(const int i) const
{
if(i < 0 || i > treeWidget->topLevelItemCount())
return 0.;
else
return treeWidget->topLevelItem(i)->data(Isovalue, Qt::CheckStateRole).toDouble();
return treeWidget->topLevelItem(i)->data(Value, Qt::CheckStateRole).toDouble();
}
bool Isovalues_list::enabled(const QTreeWidgetItem* item) const
bool Values_list::enabled(const QTreeWidgetItem* item) const
{
return item->data(Isovalue, Qt::CheckStateRole).toDouble();
return item->data(Value, Qt::CheckStateRole).toDouble();
}
const QTreeWidgetItem* Isovalues_list::item(const int i) const
const QTreeWidgetItem* Values_list::item(const int i) const
{
if(i < 0 || i > treeWidget->topLevelItemCount())
return 0;
@ -174,15 +178,15 @@ const QTreeWidgetItem* Isovalues_list::item(const int i) const
return treeWidget->topLevelItem(i);
}
void Isovalues_list::save_values(QString filename) const
void Values_list::save_values(QString filename) const
{
QSettings settings;
settings.beginGroup(QUrl::toPercentEncoding(filename));
settings.beginWriteArray("isovalues");
for (int i = 0; i < numberOfIsoValues(); ++i) {
settings.beginWriteArray("values");
for (int i = 0; i < numberOfValues(); ++i) {
settings.setArrayIndex(i);
settings.setValue("isovalue", isovalue(i));
settings.setValue("value", value(i));
settings.setValue("color", color(i));
settings.setValue("name", name(i));
settings.setValue("enabled", enabled(i));
@ -191,18 +195,18 @@ void Isovalues_list::save_values(QString filename) const
settings.endGroup();
}
void Isovalues_list::load_values(QString filename)
void Values_list::load_values(QString filename)
{
QSettings settings;
settings.beginGroup(QUrl::toPercentEncoding(filename));
int nb = settings.beginReadArray("isovalues");
int nb = settings.beginReadArray("values");
for (int i = 0; i < nb; ++i) {
settings.setArrayIndex(i);
QTreeWidgetItem *newItem = new QTreeWidgetItem(treeWidget);
newItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
newItem->setData(Isovalue, Qt::CheckStateRole, settings.value("enabled").toBool() ? Qt::Checked : Qt::Unchecked);
newItem->setData(Isovalue, Qt::DisplayRole, settings.value("isovalue").toDouble());
newItem->setData(Value, Qt::CheckStateRole, settings.value("enabled").toBool() ? Qt::Checked : Qt::Unchecked);
newItem->setData(Value, Qt::DisplayRole, settings.value("value").toDouble());
newItem->setData(Color, Qt::DisplayRole, settings.value("color").value<QColor>());
newItem->setData(Name, Qt::DisplayRole, settings.value("name").toString());
}
@ -210,28 +214,51 @@ void Isovalues_list::load_values(QString filename)
settings.endGroup();
}
void Isovalues_list::on_minusButton_clicked()
void Values_list::on_minusButton_clicked()
{
Q_FOREACH(QTreeWidgetItem* item, treeWidget->selectedItems())
{
treeWidget->invisibleRootItem()->removeChild(item);
delete item;
}
emit isovalues_changed();
emit values_changed();
}
void Isovalues_list::on_plusButton_clicked()
void Values_list::on_plusButton_clicked()
{
addValue();
}
void Values_list::addValue(const double i)
{
QTreeWidgetItem *newItem = new QTreeWidgetItem(treeWidget);
newItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
newItem->setData(Isovalue, Qt::CheckStateRole, Qt::Checked);
newItem->setData(Isovalue, Qt::DisplayRole, default_isovalue);
newItem->setData(Value, Qt::CheckStateRole, Qt::Checked);
newItem->setData(Value, Qt::DisplayRole, i);
QStringList colors = QColor::colorNames();
const int color_index = qrand() % colors.size();
QColor color = QColor(colors[color_index]);
newItem->setData(Color, Qt::DisplayRole, color);
newItem->setData(Name, Qt::DisplayRole, "");
emit isovalues_changed();
emit values_changed();
}
#include "isovalues_list.moc"
void Values_list::update_items_cache() {
items_cache.clear();
for(int i = 0, nb = numberOfValues(); i < nb; ++i) {
items_cache.insert(std::make_pair(value(i), item(i)));
}
}
const QTreeWidgetItem* Values_list::search(const double value) const
{
Items_cache::const_iterator it = items_cache.find(value);
if(it != items_cache.end()) {
return it->second;
}
else {
return 0;
}
}
#include "values_list.moc"

View File

@ -1,5 +1,5 @@
#ifndef _ISOVALUES_LIST_H
#define _ISOVALUES_LIST_H
#ifndef _VALUES_LIST_H
#define _VALUES_LIST_H
#include <QWidget>
#include <QString>
@ -10,15 +10,15 @@
class QTreeWidget;
class QTreeWidgetItem;
class Isovalues_delegate : public QItemDelegate
class Values_delegate : public QItemDelegate
{
Q_OBJECT
public:
Isovalues_delegate(QWidget* parent);
Values_delegate(QWidget* parent);
signals:
void new_color(const QModelIndex&) const;
void new_isovalue(const QModelIndex&) const;
void new_value(const QModelIndex&) const;
protected:
void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const;
@ -31,21 +31,23 @@ protected:
const QModelIndex &index) const;
};
class Isovalues_list : public QWidget
class Values_list : public QWidget
{
Q_OBJECT
public:
enum Field { Isovalue = 0 , Color = 1, Name = 2};
Isovalues_list(QWidget* parent);
int numberOfIsoValues() const;
enum Field { Value = 0 , Color = 1, Name = 2};
Values_list(QWidget* parent);
// const accessors
int numberOfValues() const;
QColor color(const int i) const;
QColor color(const QTreeWidgetItem* i) const;
double isovalue(const int i) const;
double value(const int i) const;
QString name(const int i) const;
bool enabled(const int i) const;
bool enabled(const QTreeWidgetItem* i) const;
const QTreeWidgetItem* item(const int i) const;
const QTreeWidgetItem* search(const double value) const;
public slots:
void save_values(QString) const;
@ -53,15 +55,23 @@ public slots:
void on_plusButton_clicked();
void on_minusButton_clicked();
// setters
void addValue(const double v = Values_list::default_value);
private slots:
void update_items_cache();
signals:
void changed();
void colors_changed();
void isovalues_changed();
void values_changed();
private:
QTreeWidget* treeWidget;
typedef std::map<double, const QTreeWidgetItem*> Items_cache;
Items_cache items_cache;
static const double default_isovalue;
static const double default_value;
};
#endif // _ISOVALUES_LIST_H
#endif // _VALUES_LIST_H

View File

@ -1,5 +1,5 @@
<RCC>
<qresource prefix="/isovalues" >
<qresource prefix="/values" >
<file alias="minus.png">icons/minus.png</file>
<file alias="plus.png">icons/plus.png</file>
</qresource>

View File

@ -9,7 +9,7 @@
#include "volume.h"
#include "viewer.h"
#include "mainwindow.h"
#include "isovalues_list.h"
#include "values_list.h"
#include "File_XT.h" // format XT from Total/ELF
@ -23,6 +23,9 @@
#include <QTime>
#include <QColor>
#include <QColorDialog>
#include <QSettings>
#include <QUrl>
#include "Raw_image_dialog.h"
#include <GL/glu.h>
@ -35,12 +38,15 @@
struct Threshold : public std::unary_function<FT, unsigned char> {
double isovalue;
bool is_identity;
Threshold(double isovalue) : isovalue(isovalue) {}
Threshold(double isovalue) : isovalue(isovalue), is_identity(false) {}
result_type operator()(FT value)
{
if(value >= isovalue)
if(is_identity)
return static_cast<unsigned char>(value);
else if(value >= isovalue)
return 1;
else
return 0;
@ -53,6 +59,7 @@ class Classify_from_isovalue_list :
typedef std::pair<FT, result_type> Isovalue;
typedef std::vector<Isovalue> Isovalues;
boost::shared_ptr<Isovalues> isovalues;
bool is_identity;
struct Sort_isovalues : std::binary_function<Isovalue, Isovalue, bool>
{
@ -62,16 +69,24 @@ class Classify_from_isovalue_list :
}
};
public:
Classify_from_isovalue_list(Isovalues_list * list)
Classify_from_isovalue_list(Values_list * list)
: is_identity(false)
{
isovalues = boost::shared_ptr<Isovalues>(new Isovalues(list->numberOfIsoValues()));
for(int i = 0, nbs = list->numberOfIsoValues(); i < nbs; ++i )
(*isovalues)[i] = std::make_pair(list->isovalue(i), i);
isovalues = boost::shared_ptr<Isovalues>(new Isovalues(list->numberOfValues()));
for(int i = 0, nbs = list->numberOfValues(); i < nbs; ++i )
(*isovalues)[i] = std::make_pair(list->value(i), i);
std::sort(isovalues->begin(), isovalues->end(), Sort_isovalues());
}
void set_identity(bool b) {
is_identity = b;
}
result_type operator()(FT value)
{
if(is_identity) {
return static_cast<unsigned char>(value);
}
result_type result = 0;
// std::cerr << "isovalues: ";
for(int i = 1, end = isovalues->size(); i <= end; ++i)
@ -84,7 +99,7 @@ public:
}
}
// if(result>1)
// std::cerr << "result = " << (int)result << "/" << list->numberOfIsoValues() << std::endl;
// std::cerr << "result = " << (int)result << "/" << list->numberOfValues() << std::endl;
// else
// std::cerr << std::endl;
if(result>0)
@ -99,14 +114,25 @@ class Generate_surface_identifiers :
Classify_from_isovalue_list::result_type,
const QTreeWidgetItem*>
{
Isovalues_list* list;
Values_list* list;
bool labellized;
public:
Generate_surface_identifiers(Isovalues_list* list) : list(list) {};
Generate_surface_identifiers(Values_list* list)
: list(list), labellized(false) {};
void set_labellized_image(bool b)
{
labellized = b;
}
result_type operator()(const Classify_from_isovalue_list::result_type& a,
const Classify_from_isovalue_list::result_type& b)
{
return list->item((std::min)(a, b));
if(labellized)
return list->search((std::max)(a, b));
else
return list->item((std::min)(a, b));
}
};
@ -179,7 +205,7 @@ Volume::Volume(MainWindow* mw) :
Q_ASSERT_X(spinBox_radius_bound && spinBox_distance_bound,
"Volume::Volume()", "Cannot find spinboxes!");
isovalues_list = mw->isovalues;
values_list = mw->values;
connect(spinBox_radius_bound, SIGNAL(valueChanged(double)),
this, SLOT(set_radius_bound(double)));
@ -217,9 +243,9 @@ Volume::Volume(MainWindow* mw) :
connect(this, SIGNAL(new_bounding_box(double, double, double, double, double, double)),
mw->viewer, SLOT(interpolateToFitBoundingBox(double, double, double, double, double, double)));
connect(isovalues_list, SIGNAL(isovalues_changed()),
connect(values_list, SIGNAL(values_changed()),
this, SLOT(changed_parameters()));
connect(isovalues_list, SIGNAL(changed()),
connect(values_list, SIGNAL(changed()),
mw->viewer, SLOT(updateGL()));
connect(this, SIGNAL(changed()),
this, SLOT(check_can_export_off()));
@ -273,13 +299,15 @@ void Volume::set_use_gouraud(const bool b) {
#include <vtkImageReader.h>
#include <vtkImageGaussianSmooth.h>
void Volume::opendir(const QString& dirname)
bool Volume::opendir(const QString& dirname)
{
bool result = true;
if(!fileinfo.isReadable())
{
QMessageBox::warning(mw, mw->windowTitle(),
tr("Cannot read directory <tt>%1</tt>!").arg(dirname));
status_message(tr("Opening of directory %1 failed!").arg(dirname));
result = false;
}
else
{
@ -298,18 +326,21 @@ void Volume::opendir(const QString& dirname)
QMessageBox::warning(mw, mw->windowTitle(),
tr("Error with file <tt>%1/</tt>:\nunknown file format!").arg(dirname));
status_message(tr("Opening of file %1/ failed!").arg(dirname));
result = false;
}
else
{
status_message(tr("File %1/ successfully opened.").arg(dirname));
finish_open();
result = true;
}
dicom_reader->Delete();
// smoother->Delete();
}
return result;
}
void Volume::open_vtk(const QString& filename)
bool Volume::open_vtk(const QString& filename)
{
mw->show_only("volume");
@ -317,8 +348,7 @@ void Volume::open_vtk(const QString& filename)
if(fileinfo.isDir())
{
opendir(filename);
return;
return opendir(filename);
}
if(!fileinfo.isReadable())
@ -326,6 +356,7 @@ void Volume::open_vtk(const QString& filename)
QMessageBox::warning(mw, mw->windowTitle(),
tr("Cannot read file <tt>%1</tt>!").arg(filename));
status_message(tr("Opening of file %1 failed!").arg(filename));
return false;
}
else
{
@ -344,11 +375,13 @@ void Volume::open_vtk(const QString& filename)
QMessageBox::warning(mw, mw->windowTitle(),
tr("Error with file <tt>%1</tt>:\nunknown file format!").arg(filename));
status_message(tr("Opening of file %1 failed!").arg(filename));
return false;
}
else
{
status_message(tr("File %1 successfully opened.").arg(filename));
finish_open();
return true;
}
}
}
@ -421,14 +454,18 @@ bool Volume::open_xt(const QString& filename)
}
#else // CGAL_USE_VTK
void Volume::opendir(const QString&) {}
bool Volume::opendir(const QString&)
{
return false;
}
bool Volume::open_xt(const QString&)
{
return false;
}
#endif // CGAL_USE_VTK
void Volume::open(const QString& filename)
bool Volume::open(const QString& filename)
{
mw->show_only("volume");
@ -436,15 +473,13 @@ void Volume::open(const QString& filename)
if(fileinfo.isDir())
{
opendir(filename);
return;
return opendir(filename);
}
if(!fileinfo.isReadable())
{
QMessageBox::warning(mw, mw->windowTitle(),
tr("Cannot read file <tt>%1</tt>!").arg(filename));
status_message(tr("Opening of file %1 failed!").arg(filename));
}
else
{
@ -452,13 +487,63 @@ void Volume::open(const QString& filename)
{
status_message(tr("File %1 successfully opened.").arg(filename));
finish_open();
return true;
}
else if(!open_xt(filename)) {
QMessageBox::warning(mw, mw->windowTitle(),
tr("Error with file <tt>%1</tt>:\nunknown file format!").arg(filename));
status_message(tr("Opening of file %1 failed!").arg(filename));
QSettings settings;
settings.beginGroup(QUrl::toPercentEncoding(fileinfo.absoluteFilePath()));
if( settings.value("is_raw").toBool() &&
m_image.read_raw(filename.toStdString().c_str(),
settings.value("dim_x").toInt(),
settings.value("dim_y").toInt(),
settings.value("dim_z").toInt(),
settings.value("spacing_x").toDouble(),
settings.value("spacing_y").toDouble(),
settings.value("spacing_z").toDouble(),
settings.value("offset").toInt()) )
{
status_message(tr("File %1 successfully opened.").arg(filename));
finish_open();
return true;
}
else if(QMessageBox::warning(mw, mw->windowTitle(),
tr("Error with file <tt>%1</tt>:\n"
"unknown file format!\n"
"\n"
"Open it as a raw image?").arg(filename),
QMessageBox::Yes|QMessageBox::No) == QMessageBox::Yes)
{
Raw_image_dialog raw_dialog;
if( raw_dialog.exec() &&
m_image.read_raw(filename.toStdString().c_str(),
raw_dialog.dim_x->value(),
raw_dialog.dim_y->value(),
raw_dialog.dim_z->value(),
raw_dialog.spacing_x->value(),
raw_dialog.spacing_y->value(),
raw_dialog.spacing_z->value(),
raw_dialog.offset->value()) )
{
status_message(tr("File %1 successfully opened.").arg(filename));
QSettings settings;
settings.beginGroup(QUrl::toPercentEncoding(fileinfo.absoluteFilePath()));
settings.setValue("is_raw", true);
settings.setValue("dim_x", raw_dialog.dim_x->value());
settings.setValue("dim_y", raw_dialog.dim_y->value());
settings.setValue("dim_z", raw_dialog.dim_z->value());
settings.setValue("spacing_x", raw_dialog.spacing_x->value());
settings.setValue("spacing_y", raw_dialog.spacing_y->value());
settings.setValue("spacing_z", raw_dialog.spacing_z->value());
settings.setValue("offset", raw_dialog.offset->value());
settings.endGroup();
finish_open();
return true;
}
}
}
}
status_message(tr("Opening of file %1 failed!").arg(filename));
return false;
}
void Volume::finish_open()
@ -469,7 +554,7 @@ void Volume::finish_open()
m_image.zmax()));
mw->viewer->showEntireScene();
isovalues_list->load_values(fileinfo.absoluteFilePath());
values_list->load_values(fileinfo.absoluteFilePath());
changed_parameters();
emit changed();
}
@ -531,7 +616,7 @@ void Volume::display_marchin_cube()
QTime total_time;
total_time.start();
isovalues_list->save_values(fileinfo.absoluteFilePath());
values_list->save_values(fileinfo.absoluteFilePath());
unsigned int nx = m_image.xdim();
unsigned int ny = m_image.ydim();
@ -555,13 +640,13 @@ void Volume::display_marchin_cube()
mc.init_all();
mc.set_ext_data(static_cast<unsigned char*>(m_image.image()->data));
nbs_of_mc_triangles.resize(isovalues_list->numberOfIsoValues());
nbs_of_mc_triangles.resize(values_list->numberOfValues());
for(int isovalue_id = 0;
isovalue_id < isovalues_list->numberOfIsoValues();
++isovalue_id)
for(int value_id = 0;
value_id < values_list->numberOfValues();
++value_id)
{
status_message(tr("Marching cubes, isovalue #%1...").arg(isovalue_id));
status_message(tr("Marching cubes, isovalue #%1...").arg(value_id));
// set data
// for(unsigned int i=0;i<nx;i++)
@ -572,9 +657,9 @@ void Volume::display_marchin_cube()
// mc.set_data(value,i,j,k);
// }
// compute scaling ratio
if(isovalue_id > 0)
if(value_id > 0)
mc.init_temps();
mc.run(isovalues_list->isovalue(isovalue_id),
mc.run(values_list->value(value_id),
m_image.vx(),
m_image.vy(),
m_image.vz());
@ -584,7 +669,7 @@ void Volume::display_marchin_cube()
mc.get_facets(facets);
mc_timer.stop();
const unsigned int begin = isovalue_id == 0 ? 0 : nbs_of_mc_triangles[isovalue_id-1];
const unsigned int begin = value_id == 0 ? 0 : nbs_of_mc_triangles[value_id-1];
const unsigned int nbt = facets.size() / 9;
for(unsigned int i=begin;i<nbt;i++)
{
@ -596,9 +681,9 @@ void Volume::display_marchin_cube()
const Vector v = t[2] - t[0];
Vector n = CGAL::cross_product(u,v);
n = n / std::sqrt(n*n);
m_surface_mc.push_back(Facet(t,n,isovalues_list->item(isovalue_id)));
m_surface_mc.push_back(Facet(t,n,values_list->item(value_id)));
}
nbs_of_mc_triangles[isovalue_id]=m_surface_mc.size();
nbs_of_mc_triangles[value_id]=m_surface_mc.size();
mc_timer.start();
}
mc_timer.stop();
@ -644,7 +729,7 @@ void Volume::display_surface_mesher_result()
QTime total_time;
total_time.start();
isovalues_list->save_values(fileinfo.absoluteFilePath());
values_list->save_values(fileinfo.absoluteFilePath());
unsigned int nx = m_image.xdim();
unsigned int ny = m_image.ydim();
@ -667,15 +752,34 @@ void Volume::display_surface_mesher_result()
del.clear();
Sphere bounding_sphere(m_image.center(),m_image.radius()*m_image.radius());
m_image.set_interpolation(mw->grayLevelRadioButton->isChecked());
// definition of the surface
Surface_3 surface(m_image, bounding_sphere, m_relative_precision);
// Threshold threshold(m_image.isovalue());
Classify_from_isovalue_list classify(isovalues_list);
Generate_surface_identifiers generate_ids(isovalues_list);
Classify_from_isovalue_list classify(values_list);
Generate_surface_identifiers generate_ids(values_list);
classify.set_identity(mw->labellizedRadioButton->isChecked());
generate_ids.set_labellized_image(mw->labellizedRadioButton->isChecked());
std::vector<Point> seeds;
search_for_connected_components(std::back_inserter(seeds), classify);
{
std::set<unsigned char> domains;
search_for_connected_components(std::back_inserter(seeds),
CGAL::inserter(domains),
classify);
if(mw->labellizedRadioButton->isChecked() &&
values_list->numberOfValues() == 0)
{
Q_FOREACH(unsigned char label, domains) {
if(label != 0) {
values_list->addValue(label);
}
}
}
}
// surface mesh traits class
typedef CGAL::Surface_mesher::Implicit_surface_oracle_3<Kernel,
// typedef CGAL::Surface_mesher::Image_surface_oracle_3<Kernel,
@ -722,16 +826,25 @@ void Volume::display_surface_mesher_result()
criterion_vector.push_back(&aspect_ratio_criterion);
criterion_vector.push_back(&uniform_size_criterion);
criterion_vector.push_back(&curvature_size_criterion);
criterion_vector.push_back(&vertices_on_the_same_psc_element_criterion);
if(mw->sameIndexCheckBox->isChecked()) {
criterion_vector.push_back(&vertices_on_the_same_psc_element_criterion);
std::cerr << "vertices_on_the_same_psc_element_criterion is activated.\n";
}
CGAL::Surface_mesher::Standard_criteria<Criterion> criteria(criterion_vector);
std::cerr << "Surface_mesher... angle=" << m_sm_angle << ", radius= " << m_sm_radius
<< ", distance=" << m_sm_distance << "\n";
// meshing surface
make_surface_mesh(c2t3, surface, oracle, criteria,
// CGAL::Non_manifold_tag(), 0);
CGAL::Manifold_tag(), 0);
if(mw->manifoldCheckBox->isChecked()) {
// meshing surface
std::cerr << "manifold criteria is activated.\n";
make_surface_mesh(c2t3, surface, oracle, criteria,
CGAL::Manifold_tag(), 0);
}
else {
make_surface_mesh(c2t3, surface, oracle, criteria,
CGAL::Non_manifold_tag(), 0);
}
sm_timer.stop();
not_busy();
@ -909,19 +1022,19 @@ void Volume::gl_draw_surface_mc()
if(lists_draw_surface_mc_is_valid)
{
for(int i = 0, nbs = isovalues_list->numberOfIsoValues(); i < nbs; ++i )
for(int i = 0, nbs = values_list->numberOfValues(); i < nbs; ++i )
{
if(isovalues_list->enabled(i))
if(values_list->enabled(i))
{
mw->viewer->qglColor(isovalues_list->color(i));
mw->viewer->qglColor(values_list->color(i));
::glCallList(lists_draw_surface_mc[i]);
}
}
}
else
{
lists_draw_surface_mc.resize(isovalues_list->numberOfIsoValues(), 0);
for(int i = 0, nbs = isovalues_list->numberOfIsoValues(); i < nbs; ++i )
lists_draw_surface_mc.resize(values_list->numberOfValues(), 0);
for(int i = 0, nbs = values_list->numberOfValues(); i < nbs; ++i )
{
if(!lists_draw_surface_mc[i])
{
@ -933,18 +1046,18 @@ void Volume::gl_draw_surface_mc()
% lists_draw_surface_mc[i]
% i;
mw->viewer->qglColor(isovalues_list->color(i));
mw->viewer->qglColor(values_list->color(i));
if(lists_draw_surface_mc[i]) // If
::glNewList(lists_draw_surface_mc[i], // lists_draw_surface[i]==0 then something
isovalues_list->enabled(i) // got wrong in the list generation.
values_list->enabled(i) // got wrong in the list generation.
? GL_COMPILE_AND_EXECUTE
: GL_COMPILE);
gl_draw_surface(m_surface_mc.begin(),
m_surface_mc.end(),
isovalues_list->item(i));
values_list->item(i));
if(lists_draw_surface_mc[i]) // If lists_draw_surface[i]==0 then
{ // something got wrong in the list
@ -957,21 +1070,28 @@ void Volume::gl_draw_surface_mc()
void Volume::gl_draw_surface()
{
// if(mw->labellizedRadioButton->isChecked()) {
// mw->viewer->qglColor(::Qt::blue);
// gl_draw_surface(m_surface.begin(),
// m_surface.end(),
// 0);
// }
// else
if(lists_draw_surface_is_valid)
{
for(int i = 0, nbs = isovalues_list->numberOfIsoValues(); i < nbs; ++i )
for(int i = 0, nbs = values_list->numberOfValues(); i < nbs; ++i )
{
if(isovalues_list->enabled(i))
if(values_list->enabled(i))
{
mw->viewer->qglColor(isovalues_list->color(i));
mw->viewer->qglColor(values_list->color(i));
::glCallList(lists_draw_surface[i]);
}
}
}
else
{
lists_draw_surface.resize(isovalues_list->numberOfIsoValues(), 0);
for(int i = 0, nbs = isovalues_list->numberOfIsoValues(); i < nbs; ++i )
lists_draw_surface.resize(values_list->numberOfValues(), 0);
for(int i = 0, nbs = values_list->numberOfValues(); i < nbs; ++i )
{
if(!lists_draw_surface[i])
{
@ -983,17 +1103,17 @@ void Volume::gl_draw_surface()
% lists_draw_surface[i]
% i;
mw->viewer->qglColor(isovalues_list->color(i));
mw->viewer->qglColor(values_list->color(i));
if(lists_draw_surface[i]) // If
::glNewList(lists_draw_surface[i], // lists_draw_surface[i]==0
isovalues_list->enabled(i) // then something got wrong
values_list->enabled(i) // then something got wrong
? GL_COMPILE_AND_EXECUTE // in the list generation.
: GL_COMPILE);
gl_draw_surface(m_surface.begin(),
m_surface.end(),
isovalues_list->item(i));
values_list->item(i));
if(lists_draw_surface[i]) // If lists_draw_surface[i]==0 then
{ // something got wrong in the list
@ -1086,11 +1206,11 @@ void Volume::gl_draw_marchingcube()
if(!m_inverse_normals)
::glEnableClientState(GL_NORMAL_ARRAY);
for(int i = 0, nbs = isovalues_list->numberOfIsoValues(); i < nbs; ++i)
for(int i = 0, nbs = values_list->numberOfValues(); i < nbs; ++i)
{
const int begin = i == 0 ? 0 : nbs_of_mc_triangles[i-1];
const int end = nbs_of_mc_triangles[i];
mw->viewer->qglColor(isovalues_list->color(i));
mw->viewer->qglColor(values_list->color(i));
::glBegin(GL_TRIANGLES);
for(int i = begin; i < end; ++i)
{

View File

@ -72,7 +72,7 @@ typedef CGAL::Implicit_surface_3<Kernel, Binary_image> Surface_3;
class MainWindow;
class QDoubleSpinBox;
class Viewer;
class Isovalues_list;
class Values_list;
class Volume : public Surface
{
@ -109,7 +109,7 @@ private:
MainWindow* mw;
QFileInfo fileinfo;
Isovalues_list* isovalues_list;
Values_list* values_list;
QDoubleSpinBox* spinBox_radius_bound;
QDoubleSpinBox* spinBox_distance_bound;
@ -128,8 +128,12 @@ private:
template <typename Iterator>
void gl_draw_surface(Iterator begin, Iterator end, const QTreeWidgetItem* = 0);
template <typename PointsOutputIterator, typename TransformOperator>
void search_for_connected_components(PointsOutputIterator, TransformOperator);
template <typename PointsOutputIterator,
typename DomainsOutputIterator,
typename TransformOperator>
void search_for_connected_components(PointsOutputIterator,
DomainsOutputIterator,
TransformOperator);
public:
void gl_draw_surface();
@ -148,12 +152,12 @@ public slots:
void set_triangulation_edges_color();
void set_draw_triangulation(const bool);
void set_use_gouraud(const bool);
void open(const QString& filename);
bool open(const QString& filename);
#ifdef CGAL_USE_VTK
void open_vtk(const QString& filename);
bool open_vtk(const QString& filename);
#endif
bool open_xt(const QString& filename);
void opendir(const QString& dirname);
bool opendir(const QString& dirname);
void finish_open();
void export_off();
void check_can_export_off();
@ -172,8 +176,12 @@ private:
void not_busy() const;
};
template <typename PointsOutputIterator, typename TransformOperator>
void Volume::search_for_connected_components(PointsOutputIterator it, TransformOperator transform)
template <typename PointsOutputIterator,
typename DomainsOutputIterator,
typename TransformOperator>
void Volume::search_for_connected_components(PointsOutputIterator it,
DomainsOutputIterator dom_it,
TransformOperator transform)
{
const unsigned int nx = m_image.xdim();
const unsigned int ny = m_image.ydim();
@ -195,6 +203,7 @@ void Volume::search_for_connected_components(PointsOutputIterator it, TransformO
if(visited[i][j][k]>0)
continue;
const Label current_label = transform(m_image.value(i, j, k));
*dom_it++ = current_label;
if(current_label == Label()) {
visited[i][j][k] = 3;
continue;

View File

@ -338,7 +338,8 @@ public:
timer.start();
#endif // CGAL_SURFACE_MESHER_DEBUG_POLYHEDRAL_SURFACE_CONSTRUCTION
CGAL::scan_OFF(input_file, *this, true);
CGAL_assertion(input_file);
if(!input_file)
return;
this->compute_bounding_box();
this->compute_normals();