Commit 126b6f4f authored by Emmanuel Promayon's avatar Emmanuel Promayon
Browse files

FIXED clean vtkmesh code (finished!)

At last vtkmesh contains only what it should...
parent ef5549d0
......@@ -31,25 +31,33 @@
#include <QTextStream>
#include <Application.h>
#include <QFileDialog>
#include <VtkMeshComponent.h>
#include <MeshComponent.h>
#include <QPushButton>
#include <QLayout>
// CamiTK includes
#include <ActionWidget.h>
// Vtk includes
#include <vtkGeometryFilter.h>
#include <vtkTriangleFilter.h>
#include <vtkCleanPolyData.h>
#include <vtkPointData.h>
#include <vtkPolyDataNormals.h>
#include <vtkCell.h>
using namespace camitk;
// --------------- Constructor -------------------
ExportAsMDL::ExportAsMDL(ActionExtension* extension) : Action(extension) {
ExportAsMDL::ExportAsMDL ( ActionExtension* extension ) : Action ( extension ) {
// Setting name, description and input component
setName("Export As MDL");
setDescription(tr("Export As MDL"));
setComponent("VtkMeshComponent");
setName ( "Export As MDL" );
setDescription ( tr ( "Export As MDL (an old legacy file format from early CAMI devices). This is kept for historical reason only." ) );
setComponent ( "MeshComponent" );
// Setting classification family and tags
setFamily("Mesh Processing");
setFamily ( "Mesh Processing" );
// DO NOT Put any GUI instanciation here,
// If you need, do it in getWidget() method, using lazy instanciation
......@@ -62,79 +70,176 @@ ExportAsMDL::~ExportAsMDL() {
// (except if you use smart pointers of course !!)
}
// --------------- getWidget -------------------
QWidget* ExportAsMDL::getWidget() {
// Use lazy instanciation (instanciate only once and when needed)
// We will return the default action widget with an additionnal button
// build or update the widget
if ( !actionWidget ) {
// Setting the widget containing the parameters, using the default widget
actionWidget = new ActionWidget ( this );
QPushButton* outputbutton = new QPushButton ( "Output file" );
outputfile = new QLineEdit();
actionWidget->layout()->addWidget ( outputbutton );
actionWidget->layout()->addWidget ( outputfile );
QObject::connect ( outputbutton, SIGNAL ( released() ), SLOT ( outputMDL() ) );
QObject::connect ( outputfile, SIGNAL ( textChanged ( const QString& ) ), this, SLOT ( outputFileChanged ( const QString& ) ) );
}
else {
// make sure the widget has updated targets
dynamic_cast<ActionWidget*> ( actionWidget )->updateTargets();
}
return actionWidget;
}
// --------------- outputMDL -------------------
void ExportAsMDL::outputMDL() {
QString ofile = QFileDialog::getSaveFileName(NULL, tr("Save As MDL..."), QString(), tr("MDL format(*.mdl)"));
QString ofile = QFileDialog::getSaveFileName ( NULL, tr ( "Save As MDL..." ), QString(), tr ( "MDL format(*.mdl)" ) );
if (!ofile.isEmpty()) {
outputfile->setText(ofile);
if ( !ofile.isEmpty() ) {
outputfile->setText ( ofile );
}
}
// --------------- outputFileChanged -------------------
void ExportAsMDL::outputFileChanged(const QString& ofile) {
fn = ofile;
void ExportAsMDL::outputFileChanged ( const QString& ofile ) {
filename = ofile;
}
// --------------- apply -------------------
Action::ApplyStatus ExportAsMDL::apply() {
foreach (Component * comp, getTargets()) {
VtkMeshComponent* input = dynamic_cast<VtkMeshComponent*> (comp);
process(input);
Action::ApplyStatus returnStatus = SUCCESS;
foreach ( Component* comp, getTargets() ) {
MeshComponent* input = dynamic_cast<MeshComponent*> ( comp );
if ( input ) {
process ( input );
}
else {
CAMITK_ERROR ( "ExportAsMDL", "apply", "Target component \"" << comp->getName().toUtf8().constData() << "\" is of type \"" << comp->getHierarchy().value(0).toStdString() << "\", expecting MeshComponent" );
returnStatus = ERROR; // Bad input (should not be possible)
}
}
return SUCCESS;
return returnStatus;
}
// --------------- process -------------------
void ExportAsMDL::process(MeshComponent* comp) {
if (!fn.isEmpty()) {
VtkMeshComponent* input = dynamic_cast<VtkMeshComponent*> (comp);
if (input) {
// if the filename does not have the ".mdl" extension, add it
QString extension = fn.right(4);
QString txt(".mdl");
if (extension.compare(txt) != 0) {
// add the extension to the filename
fn += txt;
}
input->exportMDL(fn.toStdString());
}
void ExportAsMDL::process ( MeshComponent* comp ) {
if ( !filename.isEmpty() ) {
// if the filename does not have the ".mdl" extension, add it
QFileInfo fileinfo(filename);
if (fileinfo.suffix() != ".mdl")
filename += ".mdl";
saveMeshComponentToMDL ( comp );
}
else {
CAMITK_WARNING("ExportAsMDL", "process", "Output file is missing, please provide one. ");
CAMITK_WARNING ( "ExportAsMDL", "process", "Output file is missing, please provide one. " );
}
}
// --------------- getWidget -------------------
QWidget* ExportAsMDL::getWidget() {
// Use lazy instanciation (instanciate only once and when needed)
// We will return the default action widget with an additionnal button
// --------------- saveMeshComponentToMDL -------------------
void ExportAsMDL::saveMeshComponentToMDL( MeshComponent* comp ) {
// build or update the widget
if ( !actionWidget ) {
// Setting the widget containing the parameters, using the default widget
actionWidget = new ActionWidget ( this );
int i;
// MDL format supports only triangles. Hence, this dataset triangularized before
// being exported (this operation is then NOT reversible).
// if the dataset is a volumetric mesh (e.g. hexahedrons), only the external surface is exported.
QPushButton* outputbutton = new QPushButton("Output file");
outputfile = new QLineEdit();
//extract external surface
vtkSmartPointer<vtkGeometryFilter> geomF = vtkSmartPointer<vtkGeometryFilter>::New();
geomF->SetInputData ( comp->getPointSet() );
// triangles
vtkSmartPointer<vtkTriangleFilter> triangleF = vtkSmartPointer<vtkTriangleFilter>::New();
triangleF->SetInputData ( geomF->GetOutput() );
// clean unused
vtkSmartPointer<vtkCleanPolyData> cleaner = vtkSmartPointer<vtkCleanPolyData>::New();
cleaner->SetInputData ( triangleF->GetOutput() );
cleaner->Update();
vtkSmartPointer<vtkPolyData> ds = cleaner->GetOutput();
//--- write as .mdl file (Registration format)
std::ofstream o ( filename.toUtf8().constData() );
//--- name
o << "[Name, STRING]" << std::endl;
o << comp->getName().toStdString() << std::endl;
o << std::endl;
double pt[3];
actionWidget->layout()->addWidget(outputbutton);
actionWidget->layout()->addWidget(outputfile);
//--- vertices
o << "[Vertices, ARRAY1<POINT3D>]" << std::endl;
if (ds->GetPoints() != nullptr) {
o << ds->GetPoints()->GetNumberOfPoints() << std::endl;
QObject::connect(outputbutton, SIGNAL(released()), SLOT(outputMDL()));
QObject::connect(outputfile, SIGNAL(textChanged(const QString&)), this, SLOT(outputFileChanged(const QString&)));
for ( i = 0; i < ds->GetPoints()->GetNumberOfPoints(); i++ ) {
ds->GetPoints()->GetPoint ( i, pt );
o << pt[0] << " " << pt[1] << " " << pt[2] << std::endl;
}
}
o << std::endl;
//--- normals
o << "[Normals, ARRAY1<VECTOR3D>]" << std::endl;
if ( ds->GetPointData() && ds->GetPointData()->GetNormals() ) {
// save existing normals
o << ds->GetPointData()->GetNormals()->GetNumberOfTuples() << std::endl;
for ( i = 0; i < ds->GetPointData()->GetNormals()->GetNumberOfTuples(); i++ ) {
ds->GetPointData()->GetNormals()->GetTuple ( i, pt );
o << pt[0] << " " << pt[1] << " " << pt[2] << std::endl;
}
}
else {
// make sure the widget has updated targets
dynamic_cast<ActionWidget*> ( actionWidget )->updateTargets();
// compute the normals
vtkSmartPointer<vtkPolyDataNormals> pNormals = vtkSmartPointer<vtkPolyDataNormals>::New();
pNormals->SetInputData ( ds );
pNormals->Update();
if (pNormals->GetOutput()->GetPointData() != nullptr && pNormals->GetOutput()->GetPointData()->GetNormals() != nullptr) {
o << pNormals->GetOutput()->GetPointData()->GetNormals()->GetNumberOfTuples() << std::endl;
for ( i = 0; i < pNormals->GetOutput()->GetPointData()->GetNormals()->GetNumberOfTuples(); i++ ) {
pNormals->GetOutput()->GetPointData()->GetNormals()->GetTuple ( i, pt );
o << pt[0] << " " << pt[1] << " " << pt[2] << std::endl;
}
}
}
return actionWidget;
}
o << std::endl;
//--- triangles
int j;
o << "[Triangles, ARRAY1<STRING>]" << std::endl;
o << ds->GetNumberOfCells() << std::endl;
for ( i = 0; i < ds->GetNumberOfCells(); i++ ) {
// write it twice
for ( j = 0; j < ds->GetCell ( i )->GetNumberOfPoints(); j++ ) {
o << ds->GetCell ( i )->GetPointId ( j ) << " ";
}
for ( j = 0; j < ds->GetCell ( i )->GetNumberOfPoints(); j++ ) {
o << ds->GetCell ( i )->GetPointId ( j ) << " ";
}
o << std::endl;
}
}
......@@ -60,13 +60,16 @@ public slots:
private:
/// helper method to simplify the target component processing
virtual void process(camitk::MeshComponent*);
void process ( camitk::MeshComponent* );
/// output file
QString fn;
QString filename;
/// output file editor
QLineEdit* outputfile;
/// export MeshComponent in MDL format
void saveMeshComponentToMDL( camitk::MeshComponent* );
};
......
......@@ -26,22 +26,11 @@
#include "VtkMeshComponent.h"
// -- CamiTK stuff
#include <Application.h>
#include <MeshComponent.h>
#include <Geometry.h>
#include <InteractiveViewer.h>
#include <Property.h>
// -- vtk stuff
#include <vtkPolyData.h>
#include <vtkCleanPolyData.h>
#include <vtkPointData.h>
#include <vtkCell.h>
#include <vtkCellData.h>
#include <vtkTriangleFilter.h>
#include <vtkGeometryFilter.h>
#include <vtkPolyDataNormals.h>
#include <vtkDoubleArray.h>
#include <vtkProperty.h>
using namespace camitk;
......@@ -90,110 +79,6 @@ void VtkMeshComponent::initPointData() {
setActiveData(MeshDataModel::CELLS,NULL);
}
// -------------------- exportMDL --------------------
bool VtkMeshComponent::exportMDL ( std::string filename ) {
if ( myGeometry ) {
int i;
// MDL format supports only triangles. Hence, this dataset triangularized before
// being exported (this operation is then NOT reversible).
// if the dataset is a volumetric mesh (e.g. hexahedrons), only the external surface is exported.
//extract external surface
vtkSmartPointer<vtkGeometryFilter> geomF = vtkSmartPointer<vtkGeometryFilter>::New();
geomF->SetInputData(getPointSet());
// triangles
vtkSmartPointer<vtkTriangleFilter> triangleF = vtkSmartPointer<vtkTriangleFilter>::New();
triangleF->SetInputData(geomF->GetOutput());
// clean unused
vtkSmartPointer<vtkCleanPolyData> cleaner = vtkSmartPointer<vtkCleanPolyData>::New();
cleaner->SetInputData(triangleF->GetOutput());
cleaner->Update();
vtkSmartPointer<vtkPolyData> ds = cleaner->GetOutput();
//--- write as .mdl file (Registration format)
std::ofstream o ( filename.c_str() );
//--- name
o << "[Name, STRING]" << std::endl;
o << getName().toStdString() << std::endl;
o << std::endl;
//--- vertices
o << "[Vertices, ARRAY1<POINT3D>]" << std::endl;
o << ds->GetPoints()->GetNumberOfPoints() << std::endl;
double pt[3];
for ( i = 0; i < ds->GetPoints()->GetNumberOfPoints(); i++ ) {
ds->GetPoints()->GetPoint ( i, pt );
o << pt[0] << " " << pt[1] << " " << pt[2] << std::endl;
}
o << std::endl;
//--- normals
o << "[Normals, ARRAY1<VECTOR3D>]" << std::endl;
if ( ds->GetPointData() && ds->GetPointData()->GetNormals() ) {
// save existing normals
o << ds->GetPointData()->GetNormals()->GetNumberOfTuples() << std::endl;
for ( i = 0; i < ds->GetPointData()->GetNormals()->GetNumberOfTuples(); i++ ) {
ds->GetPointData()->GetNormals()->GetTuple ( i, pt );
o << pt[0] << " " << pt[1] << " " << pt[2] << std::endl;
}
}
else {
// compute the normals
vtkSmartPointer<vtkPolyDataNormals> pNormals = vtkSmartPointer<vtkPolyDataNormals>::New();
pNormals->SetInputData( ds );
pNormals->Update();
o << pNormals->GetOutput()->GetPointData()->GetNormals()->GetNumberOfTuples() << std::endl;
for ( i = 0; i < pNormals->GetOutput()->GetPointData()->GetNormals()->GetNumberOfTuples(); i++ ) {
pNormals->GetOutput()->GetPointData()->GetNormals()->GetTuple ( i, pt );
o << pt[0] << " " << pt[1] << " " << pt[2] << std::endl;
}
}
o << std::endl;
//--- triangles
int j;
o << "[Triangles, ARRAY1<STRING>]" << std::endl;
o << ds->GetNumberOfCells() << std::endl;
for ( i = 0; i < ds->GetNumberOfCells(); i++ ) {
// write it twice
for ( j = 0; j < ds->GetCell ( i )->GetNumberOfPoints(); j++ ) {
o << ds->GetCell ( i )->GetPointId ( j ) << " ";
}
for ( j = 0; j < ds->GetCell ( i )->GetNumberOfPoints(); j++ ) {
o << ds->GetCell ( i )->GetPointId ( j ) << " ";
}
o << std::endl;
}
return true;
}
else {
return false;
}
}
//------------------------ getPixmap ---------------------
#include "vtklogo_20x20.xpm"
QPixmap* VtkMeshComponent::myPixmap = NULL;
......
......@@ -31,8 +31,6 @@
#include "VtkMeshComponentAPI.h"
#include "VtkMeshUtil.h"
#include <vtkSmartPointer.h>
class VtkMeshComponentProperties;
class vtkDoubleArray;
class vtkPointData;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment