Commit 396f4184 authored by promayon's avatar promayon
Browse files

FIXED missing files, sorry...

git-svn-id: svn+ssh://scm.forge.imag.fr/var/lib/gforge/chroot/scmrepos/svn/camitk/trunk/camitk@210 ec899d31-69d1-42ba-9299-647d76f65fb3
parent 66697d5e
/*****************************************************************************
* $CAMITK_LICENCE_BEGIN$
*
* CamiTK - Computer Assisted Medical Intervention ToolKit
* (c) 2001-2012 UJF-Grenoble 1, CNRS, TIMC-IMAG UMR 5525 (GMCAO)
*
* Visit http://camitk.imag.fr for more information
*
* This file is part of CamiTK.
*
* CamiTK is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* CamiTK is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with CamiTK. If not, see <http://www.gnu.org/licenses/>.
*
* $CAMITK_LICENCE_END$
****************************************************************************/
#include "CenterMesh.h"
#include <MeshComponent.h>
#include <Application.h>
#include <Log.h>
#include <vtkUnstructuredGrid.h>
#include <vtkPolyData.h>
//For Vtk 5.10 #include <vtkCenterOfMass.h>
#include <vtkTransform.h>
#include <vtkTransformFilter.h>
// --------------- constructor -------------------
CenterMesh::CenterMesh(ActionExtension* extension) : Action(extension) {
setName("Center Mesh");
setEmbedded(false);
setDescription("Center current mesh component (at the end the barycenter of the mesh is in (0,0,0)");
setComponent("MeshComponent");
setFamily("Basic Mesh");
addTag("Transform");
addTag("Translate");
}
// --------------- apply -------------------
Action::ApplyStatus CenterMesh::apply() {
// set waiting cursor and status bar
QApplication::setOverrideCursor ( QCursor ( Qt::WaitCursor ) );
Application::showStatusBarMessage("Centering...");
Application::resetProgressBar();
// apply the transformation
MeshComponent *targetMesh;
for (unsigned int i=0; i<getTargets().size(); i++) {
targetMesh = dynamic_cast<MeshComponent*>(getTargets().at(i));
CAMITK_INFO("CenterMesh", "apply", "Centering " << targetMesh->getName().toStdString());
//-- compute barycenter
double barycenter[3] = {0.0, 0.0, 0.0};
for (vtkIdType j=0; j<targetMesh->getPointSet()->GetNumberOfPoints(); j++) {
double *position = targetMesh->getPointSet()->GetPoints()->GetPoint(j);
for (unsigned int k = 0; k < 3; k++) {
barycenter[k] += position[k];
}
}
for (unsigned int k = 0; k < 3; k++) {
barycenter[k] /= targetMesh->getPointSet()->GetNumberOfPoints();
}
//-- create the transformation to center the barycenter
vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
transform->Translate(-barycenter[0], -barycenter[1], -barycenter[2]);
//-- transform the mesh using the filter
vtkSmartPointer<vtkTransformFilter> filter = vtkSmartPointer<vtkTransformFilter>::New();
filter->SetInputConnection(targetMesh->getDataPort());
filter->SetTransform(transform);
filter->Update();
//-- get the resulting mesh
vtkSmartPointer<vtkPointSet> result = vtkPointSet::SafeDownCast(filter->GetOutputDataObject(0));
if (result) {
targetMesh->setPointSet(result);
targetMesh->setModified();
}
else {
CAMITK_INFO("CenterMesh", "apply transformation", "Error: filter output is of type: " << filter->GetOutputDataObject(0)->GetClassName());
return ERROR;
}
Application::setProgressBarValue(100.0*(i+1.0)/((double)getTargets().size()));
}
// restore the normal cursor and progress bar
Application::refresh();
Application::resetProgressBar();
QApplication::restoreOverrideCursor();
return SUCCESS;
}
/*****************************************************************************
* $CAMITK_LICENCE_BEGIN$
*
* CamiTK - Computer Assisted Medical Intervention ToolKit
* (c) 2001-2012 UJF-Grenoble 1, CNRS, TIMC-IMAG UMR 5525 (GMCAO)
*
* Visit http://camitk.imag.fr for more information
*
* This file is part of CamiTK.
*
* CamiTK is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* CamiTK is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with CamiTK. If not, see <http://www.gnu.org/licenses/>.
*
* $CAMITK_LICENCE_END$
****************************************************************************/
#ifndef CENTERMESH_H
#define CENTERMESH_H
#include "Action.h"
using namespace camitk;
/** Center current mesh component (at the end the barycenter of the mesh is in (0,0,0)
*/
class CenterMesh : public Action {
Q_OBJECT
public:
/// the constructor
CenterMesh(ActionExtension*);
/// Destructor
virtual ~CenterMesh() {};
/// no widget, just apply the action
QWidget * getWidget() { return NULL; };
public slots:
/// method called when the action is applied
virtual ApplyStatus apply();
};
#endif // CENTERMESH_H
/*****************************************************************************
* $CAMITK_LICENCE_BEGIN$
*
* CamiTK - Computer Assisted Medical Intervention ToolKit
* (c) 2001-2012 UJF-Grenoble 1, CNRS, TIMC-IMAG UMR 5525 (GMCAO)
*
* Visit http://camitk.imag.fr for more information
*
* This file is part of CamiTK.
*
* CamiTK is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* CamiTK is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with CamiTK. If not, see <http://www.gnu.org/licenses/>.
*
* $CAMITK_LICENCE_END$
****************************************************************************/
// because of namespace problems with Component, put these include first
#include "MeshQuality.h"
#include <MeshComponent.h>
#include <Log.h>
#include <Application.h>
#include <InteractiveViewer.h>
#include <vtkMeshQuality.h>
#include <vtkDoubleArray.h>
#include <vtkCellData.h>
// Qt
#include <QPushButton>
#include <QVBoxLayout>
#include <QHeaderView>
// -------------------- MeshQuality --------------------
MeshQuality::MeshQuality(ActionExtension *extension) : Action(extension) {
setName("Mesh Quality");
setDescription("Display basic mesh quality information");
setComponent("MeshComponent");
setFamily("Basic Mesh");
addTag("Quality");
addTag("Distort");
addTag("Degenerated");
//-- widget lazy instanciation
informationFrame = NULL;
// TODO add the management of a property for selecting a quality measure (enum ?)
}
// --------------- getWidget -------------------
QWidget* MeshQuality::getWidget() {
if (!informationFrame) {
//-- the frame
informationFrame = new QFrame();
informationFrame->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
informationFrame->setLineWidth(3);
//-- Create the specific widgets
informationLabel = new QLabel();
qualityInfo = new QTableWidget();
//-- the vertical layout, put every GUI elements in it
QVBoxLayout * informationFrameLayout = new QVBoxLayout();
//-- add the widgets
informationFrameLayout->addWidget(informationLabel);
informationFrameLayout->addWidget(qualityInfo);
//-- set the layout for the action widget
informationFrame->setLayout(informationFrameLayout);
}
apply();
return informationFrame;
}
// --------------- apply -------------------
Action::ApplyStatus MeshQuality::apply() {
// set waiting cursor (not really needed here as the action is very fast, but after all this is a demo)
QApplication::setOverrideCursor ( QCursor ( Qt::WaitCursor ) );
// get the last selected image component
MeshComponent * meshComponent = dynamic_cast<MeshComponent *>(getTargets().last());
// the information message (in rich text, i.e., html)
QString message = "<b>Selected Component:</b> " + meshComponent->getName() + "<br/>";
message += "Number of Cells: " + QString("%1").arg(meshComponent->getPointSet()->GetNumberOfCells(),6) + "<br/>";
//-- compute quality
vtkSmartPointer<vtkMeshQuality> qualityFilter = vtkSmartPointer<vtkMeshQuality>::New();
qualityFilter->SetInputConnection(meshComponent->getDataPort());
qualityFilter->SetHexQualityMeasureToDistortion(); //SetHexQualityMeasureToMedAspectFrobenius(); // SetHexQualityMeasureToJacobian(); //SetTriangleQualityMeasureToArea();
qualityFilter->Update();
vtkDataSet* qualityMesh = qualityFilter->GetOutput();
vtkSmartPointer<vtkDoubleArray> qualityArray = vtkDoubleArray::SafeDownCast(qualityMesh->GetCellData()->GetArray("Quality"));
message += "Number of Hex Jacobian values:" + QString("%1").arg(qualityArray->GetNumberOfTuples(),6) + "<br/>";
// resize the table
qualityInfo->setRowCount(qualityArray->GetNumberOfTuples());
qualityInfo->setColumnCount(2);
qualityInfo->setSortingEnabled(false); // temporarily for insertion!
QStringList headerTitles;
headerTitles << "Cell Id" << "Quality";
qualityInfo->setHorizontalHeaderLabels(headerTitles);
/* qualityInfo->horizontalHeader()->setStretchLastSection(false);
qualityInfo->horizontalHeader()->setResizeMode(0, QHeaderView::Stretch); // First column stretch to what is needed
qualityInfo->horizontalHeader()->setResizeMode(1, QHeaderView::Fixed); // Last column never resize
*/
qualityInfo->horizontalHeader()->setVisible(true);
qualityInfo->verticalHeader()->setVisible(false);
double min = VTK_DOUBLE_MAX, max = VTK_DOUBLE_MIN, avg = 0.0;
for(vtkIdType i = 0; i < qualityArray->GetNumberOfTuples(); i++) {
double val = qualityArray->GetValue(i);
qualityInfo->setItem(i, 0, new QTableWidgetItem(tr("%1").arg(i)));
qualityInfo->setItem(i, 1, new QTableWidgetItem(tr("%1").arg(val)));
avg += val;
if (val<min)
min = val;
if (val>max)
max = val;
}
qualityInfo->resizeColumnsToContents();
qualityInfo->resizeRowsToContents();
qualityInfo->setSortingEnabled(true);
qualityInfo->sortByColumn(1, Qt::AscendingOrder);
avg /= qualityArray->GetNumberOfTuples();
message += "Min " + QString("%1").arg(min,6) + ", Max " + QString("%1").arg(max,6)+ ", Avg " + QString("%1").arg(avg,6)+"<br/>";
//-- update the information label
informationLabel->setText(message);
// restore the normal cursor
QApplication::restoreOverrideCursor();
return SUCCESS;
}
/*****************************************************************************
* $CAMITK_LICENCE_BEGIN$
*
* CamiTK - Computer Assisted Medical Intervention ToolKit
* (c) 2001-2012 UJF-Grenoble 1, CNRS, TIMC-IMAG UMR 5525 (GMCAO)
*
* Visit http://camitk.imag.fr for more information
*
* This file is part of CamiTK.
*
* CamiTK is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* CamiTK is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with CamiTK. If not, see <http://www.gnu.org/licenses/>.
*
* $CAMITK_LICENCE_END$
****************************************************************************/
#ifndef MESH_QUALITY_H
#define MESH_QUALITY_H
#include <Action.h>
using namespace camitk;
#include <QFrame>
#include <QLabel>
#include <QTableWidget>
/**
* (very simple) Display of mesh quality
*/
class MeshQuality : public Action {
public:
/// the constructor
MeshQuality(ActionExtension *);
/// the destructor
virtual ~MeshQuality() {};
/// method called when the action when the action is triggered (i.e. started)
virtual QWidget * getWidget();
public slots:
/// method called when the action is applied
virtual ApplyStatus apply();
private:
/// this action widget (to simplify, it is just a label that gives mesh quality information)
QFrame *informationFrame;
/// the information label (needed as an attributes to update the displayed text)
QLabel *informationLabel;
/// the list of quality informations
QTableWidget *qualityInfo;
};
#endif // MESH_QUALITY_H
\ No newline at end of file
/*****************************************************************************
* $CAMITK_LICENCE_BEGIN$
*
* CamiTK - Computer Assisted Medical Intervention ToolKit
* (c) 2001-2012 UJF-Grenoble 1, CNRS, TIMC-IMAG UMR 5525 (GMCAO)
*
* Visit http://camitk.imag.fr for more information
*
* This file is part of CamiTK.
*
* CamiTK is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* CamiTK is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with CamiTK. If not, see <http://www.gnu.org/licenses/>.
*
* $CAMITK_LICENCE_END$
****************************************************************************/
#include "WarpOut.h"
#include <Application.h>
#include <MeshComponent.h>
#include <Log.h>
using namespace camitk;
#include <QMessageBox>
#include <set>
#include <complex>
#include <vtkPointSet.h>
#include <vtkPolyDataNormals.h>
#include <vtkDataSetSurfaceFilter.h>
#include <vtkPointData.h>
#include <vtkIdTypeArray.h>
#include <vtkCellLocator.h>
#include <vtkPolyDataConnectivityFilter.h>
#include <vtkUnstructuredGrid.h>
//#include <vtkFeatureEdges.h>
// -------------------- WarpOut --------------------
WarpOut::WarpOut(ActionExtension* extension) : Action(extension) {
// Setting name, description and input component
setName("Warp Out");
setDescription("Move the outside points along the normal in order to thicken a volumic mesh (works only with closed- centered- mesh).");
setComponent("MeshComponent");
// Setting classification family and tags
setFamily("Mesh Processing");
addTag("Grow");
addTag("Thicken");
setProperty("Displacement", QVariant(1.0)); // Total displacement to use the nodes
}
// --------------- apply -------------------
Action::ApplyStatus WarpOut::apply() {
CAMITK_INFO("WarpOut", "apply", "Warping out " << getTargets().last()->getName().toStdString());
// set waiting cursor and status bar
QApplication::setOverrideCursor ( QCursor ( Qt::WaitCursor ) );
Application::showStatusBarMessage("Warping out...");
Application::resetProgressBar();
// use the last target
MeshComponent *targetMesh = dynamic_cast<MeshComponent*>(getTargets().last());
vtkSmartPointer<vtkPointSet> resultPointSet;
if ( vtkUnstructuredGrid::SafeDownCast ( targetMesh->getPointSet() ) ) {
resultPointSet = vtkSmartPointer<vtkUnstructuredGrid>::New();
}
else
if ( vtkPolyData::SafeDownCast ( targetMesh->getPointSet() ) ) {
resultPointSet = vtkSmartPointer<vtkPolyData>::New();
}
else {
QMessageBox::warning(NULL, "Warp Out", "Invalid mesh: the selected component (\"" + targetMesh->getName() + "\") is not an unstructured grid nor a polydata.", QMessageBox::Abort);
return ABORTED;
}
resultPointSet->DeepCopy(targetMesh->getPointSet());
//-- add the id as point data in order to match normal to the points
vtkSmartPointer<vtkIdTypeArray> pointId = vtkSmartPointer<vtkIdTypeArray>::New();
pointId->SetNumberOfComponents(1);
pointId->SetName("PointId");
for (vtkIdType id=0; id<resultPointSet->GetNumberOfPoints(); id++) {
pointId->InsertNextValue(id);
}
resultPointSet->GetPointData()->AddArray(pointId);
//-- extract the surface
vtkSmartPointer<vtkDataSetSurfaceFilter> surfaceFilter = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
surfaceFilter->SetInput(resultPointSet);
surfaceFilter->Update();
//-- generate the normals
vtkSmartPointer<vtkPolyDataNormals> normalGenerator = vtkSmartPointer<vtkPolyDataNormals>::New();
normalGenerator->SetInputConnection(surfaceFilter->GetOutputPort());
normalGenerator->ComputePointNormalsOn();
normalGenerator->ComputeCellNormalsOff();
normalGenerator->SplittingOff();
normalGenerator->Update();
//-- Find the outer surface (see ExtractOutsideSurface Cxx example)
vtkSmartPointer<vtkCellLocator> cellLocator = vtkSmartPointer<vtkCellLocator>::New();
cellLocator->SetDataSet(normalGenerator->GetOutput());
cellLocator->BuildLocator();
// computer center and bounds
double center[3], bounds[6];
normalGenerator->GetOutput()->GetCenter(center);
normalGenerator->GetOutput()->GetPoints()->GetBounds(bounds);
// Now fire a ray from outside the bounds to the center and find a
// cell. This cell should be on the outside surface
double rayStart[3];
for (unsigned int i = 0; i < 3; i++) {
rayStart[i] = bounds[2 * i + 1] * 1.1;
}
vtkIdType cellId = -1;
double xyz[3], t, pcoords[3];
int subId;
cellLocator->IntersectWithLine(rayStart, center, 0.0001, t, xyz, pcoords, subId,cellId);
// use the connectivity filter to select only the outer surface
vtkSmartPointer<vtkPolyDataConnectivityFilter> connectivityFilter = vtkSmartPointer<vtkPolyDataConnectivityFilter>::New();
connectivityFilter->SetInputConnection(normalGenerator->GetOutputPort());
connectivityFilter->SetExtractionModeToCellSeededRegions();
connectivityFilter->InitializeSeedList();
connectivityFilter->AddSeed(cellId);
connectivityFilter->Update();
/*
// Check if selected surface is closed or not
vtkSmartPointer<vtkFeatureEdges> featureEdges = vtkSmartPointer<vtkFeatureEdges>::New();
featureEdges->FeatureEdgesOff();
featureEdges->BoundaryEdgesOn();
featureEdges->NonManifoldEdgesOn();
featureEdges->SetInputConnection(connectivityFilter->GetOutputPort());
featureEdges->Update();
int numberOfOpenEdges = featureEdges->GetOutput()->GetNumberOfCells();
if(numberOfOpenEdges > 0) {
std::cout << "Surface is not closed" << std::endl;
}
else {
std::cout << "Surface is closed" << std::endl;
}
*/
//-- get the original point id
pointId = vtkIdTypeArray::SafeDownCast(connectivityFilter->GetOutput()->GetPointData()->GetArray("PointId"));
//-- move along the normal (warp it)
vtkSmartPointer<vtkDataArray> pointNormals = vtkDataArray::SafeDownCast(connectivityFilter->GetOutput()->GetPointData()->GetNormals());
vtkIdType id;
double pos[3];
double normal[3];
double displacement=property("Displacement").toDouble();
for(vtkIdType i = 0; i<connectivityFilter->GetOutput()->GetNumberOfPoints(); i++) {
// get the id of the point in the original point set
pointId->GetTupleValue(i,&id);
// get the initial point position
resultPointSet->GetPoint(id,pos);
// get the normal
pointNormals->GetTuple(i, normal);
// move point
for (unsigned int j=0; j<3; j++)
pos[j] += displacement*normal[j];
resultPointSet->GetPoints()->SetPoint(id,pos);
}
// Create a mesh Component
MeshComponent * result = new MeshComponent(resultPointSet, targetMesh->getName() + " warped");
Application::refresh();
// restore the normal cursor and progress bar
Application::resetProgressBar();
QApplication::restoreOverrideCursor();
return SUCCESS;
}
/*****************************************************************************
* $CAMITK_LICENCE_BEGIN$
*
* CamiTK - Computer Assisted Medical Intervention ToolKit
* (c) 2001-2012 UJF-Grenoble 1, CNRS, TIMC-IMAG UMR 5525 (GMCAO)
*
* Visit http://camitk.imag.fr for more information
*
* This file is part of CamiTK.
*
* CamiTK is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* CamiTK is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details.
*
* You should have received a copy of the GNU Lesser General Public License