Commit f9ad9e73 authored by promayon's avatar promayon
Browse files

NEW PML library using xsdcxx (no more libxml2 needed in camitk opensource)

NEW complete rewrite of the physical model component, now called
    PMLComponent (based on Nicolas's great work in the incubator)
                Way much faster than CamiTK 3.4.0 for PML!
NEW PMLExplorer action: explore all data (based on Nicolas's great work)
NEW CreateSC action: create a new PML StructuralComponent based on
    the current selection
NEW scalar data array can now be displayed at will
FIXED action viewer can now be reduced horizontally even after an action
      widget had set it to a fixed size
FIXED ActionWidget looks better (well let me know if you think the opposite)
      by opposite) by using a QToolBox for the description 
      and targets (this leave more space for the parameters object controller)
FIXED picking was calling the method twice (2x faster now!)
FIXED Action documentation (to explain how to take the user interaction
      immediately using Qt event catching)
FIXED crash due to MeshComponent in getSelection(QString) method with unknown
      name
FIXED various code cleaning
FIXED remove data array now (partially) implemented
FIXED removed coreschema (obsolet, use cepcoreschema)
FIXED vector graphics screenshots now back working (note: transparency is not
      well handle, due to vtk limitation, Vtk 6 has a much better support with vtkGL2PSExporter...)
FIXED viewer gradient background can now be turn off/on again
FIXED debian packaging bug due to the use of cmake 3.2.2-2 and missing path to ITKConfig.cmake
FIXED remove timestamp for doxygen generation (fix reproducibility building in
      debian)
FIXED ObjectController can now be used for editing class that have an
      Q_INVOKABLE getProperty(..) method but that are declared outside the
                        camitk namespace!
FIXED renamed "ctr" prefixed local variable
FIXED crash in MeshComponent when constructor is aborted by an exception


git-svn-id: svn+ssh://scm.forge.imag.fr/var/lib/gforge/chroot/scmrepos/svn/camitk/trunk/camitk@2072 ec899d31-69d1-42ba-9299-647d76f65fb3
parent 32410790
......@@ -102,17 +102,17 @@ QList<DicomSerie*> DicomParser::parseDirectory(const QString & directory) {
// build a DicomSerie object corresponding to what we have found
if(serieFileNames.size() > 0) {
DicomSerie* crtSerie = new DicomSerie();
crtSerie->setAcquisitionDate(DicomParser::getAcquisitionDate(serieFileNames));
crtSerie->setAcquisitionTime(DicomParser::getAcquisitionTime(serieFileNames));
crtSerie->setStudyName(DicomParser::getStudyName(serieFileNames));
crtSerie->setSerieName(DicomParser::getSerieName(serieFileNames));
crtSerie->setSerieDescription(DicomParser::getSerieDescription(serieFileNames));
crtSerie->setPatientName(DicomParser::getPatientName(serieFileNames));
crtSerie->setStdFileNames(serieFileNames);
crtSerie->setFileNames(stdListOfStringToQt(serieFileNames));
dicomSeries.append(crtSerie);
DicomSerie* dicomSerie = new DicomSerie();
dicomSerie->setAcquisitionDate(DicomParser::getAcquisitionDate(serieFileNames));
dicomSerie->setAcquisitionTime(DicomParser::getAcquisitionTime(serieFileNames));
dicomSerie->setStudyName(DicomParser::getStudyName(serieFileNames));
dicomSerie->setSerieName(DicomParser::getSerieName(serieFileNames));
dicomSerie->setSerieDescription(DicomParser::getSerieDescription(serieFileNames));
dicomSerie->setPatientName(DicomParser::getPatientName(serieFileNames));
dicomSerie->setStdFileNames(serieFileNames);
dicomSerie->setFileNames(stdListOfStringToQt(serieFileNames));
dicomSeries.append(dicomSerie);
}
}
}
......
camitk_extension(ACTION_EXTENSION
NEEDS_LIBXML2
NEEDS_XSD
NEEDS_CEP_LIBRARIES pml lml lmlschema monitoring monitoringgui mmlschema
NEEDS_COMPONENT_EXTENSION physicalmodel mmlcomponent vtkmesh physicalmodel msh
NEEDS_CEP_LIBRARIES pml pmlschema lml lmlschema monitoring monitoringgui mmlschema
NEEDS_COMPONENT_EXTENSION pmlcomponent mmlcomponent vtkmesh msh
CEP_NAME CEP_MODELING
DESCRIPTION "Action MML features algorithms applicable on MML components."
TEST_APPLICATION ${APPLICATION_TEST_ACTION}
# TEST_FILES BigEndian.hdr
)
\ No newline at end of file
......@@ -24,7 +24,6 @@
****************************************************************************/
#include "MMLActionExtension.h"
#include "CreateSC.h"
#include "GenerateModel.h"
#include "SimulationDialog.h"
......@@ -34,6 +33,5 @@ Q_EXPORT_PLUGIN2(mmlactionextension, MMLActionExtension)
// -------------------- init --------------------
void MMLActionExtension::init() {
registerNewAction(GenerateModel);
registerNewAction(CreateSC);
registerNewAction(SimulationDialog);
}
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ui_AddNewPropertyWidget</class>
<widget class="QDialog" name="ui_AddNewPropertyWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>407</width>
<height>125</height>
</rect>
</property>
<property name="windowTitle">
<string>Add New Property</string>
</property>
<property name="sizeGripEnabled">
<bool>false</bool>
</property>
<property name="modal">
<bool>true</bool>
</property>
<layout class="QFormLayout" name="formLayout">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<property name="labelAlignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<item row="0" column="0">
<widget class="QLabel" name="nameLabel">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="nameLineEdit"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="valueLabel">
<property name="text">
<string>Value</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="valueLineEdit"/>
</item>
<item row="4" column="1">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="4" column="0">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>ui_AddNewPropertyWidget</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>ui_AddNewPropertyWidget</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>
# Call CamiTK CMake Macro to define the action
camitk_extension( ACTION_EXTENSION
NEEDS_COMPONENT_EXTENSION pmlcomponent
NEEDS_CEP_LIBRARIES pml pmlschema
NEEDS_XSD
DESCRIPTION "Feature PML actions which aims at displaying and manipulating structural information about a PML component."
)
......@@ -22,39 +22,31 @@
*
* $CAMITK_LICENCE_END$
****************************************************************************/
#include "CamiTKPropertyList.h"
#include "PhysicalModelIO.h"
#include "CellProperties.h"
//--------------- Constructor -------------
void CellProperties::init() {
myCustomProperty1 = 0.0;
myCustomProperty2 = 0;
using namespace camitk;
// ---------------------- getProperty ----------------------------
Property* CamiTKPropertyList::getProperty(QString name) {
return propertyMap.value(name);
}
//--------------- destructor --------------
CellProperties::~CellProperties() {
Property* CamiTKPropertyList::getProperty ( unsigned int index) {
return getProperty(QString(dynamicPropertyNames().at(index)));
}
// --------------- xmlPrint ---------------
void CellProperties::xmlPrint(std::ostream &o) {
// beginning of the atom properties
beginXML(o);
// ---------------------- addProperty ----------------------------
bool CamiTKPropertyList::addProperty(Property * prop) {
// add a dynamic Qt Meta Object property with the same name
bool returnStatus = setProperty(prop->getName().toStdString().c_str(), prop->getInitialValue() );
// add to the map
propertyMap.insert(prop->getName(),prop);
for(std::map<std::string, std::string>::iterator it = fields.begin(); it!=fields.end() ; it++)
o << " "<<(*it).first<<"=\"" <<(*it).second<< "\"";
// print the custom properties only if different than default value
if (myCustomProperty1 != 0.0) {
o << " myCustomProperty1=\"" << myCustomProperty1 << "\"";
}
if (myCustomProperty2 != 0) {
o << " myCustomProperty2=\"" << myCustomProperty2 << "\"";
}
return returnStatus;
}
// end of the properties
endXML(o);
// ---------------------- getNumberOfProperties ----------------------------
unsigned int CamiTKPropertyList::getNumberOfProperties() const {
return dynamicPropertyNames().size();
}
......@@ -22,29 +22,47 @@
*
* $CAMITK_LICENCE_END$
****************************************************************************/
#include <QObject>
#include <QMap>
#include <Property.h>
#include "MMLComponentPopup.h"
#ifndef PMLITEMPROPERTY_H
#define PMLITEMPROPERTY_H
#include "MMLComponent.h"
#include "Component.h"
#include <Application.h>
// ---------------------- constructor ----------------------------
MMLComponentPopup::MMLComponentPopup(camitk::Component* comp, QWidget* parent):camitk::ComponentPopupMenu(comp, parent) {
showTabs=addAction("show monitoring tabs", SLOT(monitoringTabs()), true);
showTabs->setCheckable(true);
showTabs->setChecked(dynamic_cast<MMLComponent*>(myComponent)->isDockVisible());
}
// ---------------------- destructor ----------------------------
MMLComponentPopup::~MMLComponentPopup() {}
// ---------------------- monitoringTabs ----------------------------
void MMLComponentPopup::monitoringTabs() {
dynamic_cast<MMLComponent*>(myComponent)->setDockVisible(!dynamic_cast<MMLComponent*>(myComponent)->isDockVisible());
showTabs->setChecked(dynamic_cast<MMLComponent*>(myComponent)->isDockVisible());
}
/** This class holds a list of CamiTK Properties and can be used as an editable QObject
* for the ObjectControler widget
*/
class CamiTKPropertyList : public QObject {
Q_OBJECT
public:
/** Get a Property given its name
* @param name the property name
* @return NULL if the name does not match any property name
*
* @see Property
*/
Q_INVOKABLE virtual camitk::Property * getProperty(QString name);
/** Add a new CamiTK property to the component.
* If the property already exist, it will just change its value.
*
* \note
* The component takes ownership of the Property instance.
*
* @return false if the Qt Meta Object property was added by this method (otherwise the property was already defined and true is returned if it was successfully updated)
*/
virtual bool addProperty(camitk::Property*);
/// get the number of properties
virtual unsigned int getNumberOfProperties() const;
/// get the property stored at the given index
virtual camitk::Property* getProperty(unsigned int);
private:
/// list of CamiTK property decorating the dynamic properties
QMap<QString, camitk::Property*> propertyMap;
};
#endif // PMLITEMPROPERTY_H
\ No newline at end of file
......@@ -23,32 +23,62 @@
* $CAMITK_LICENCE_END$
****************************************************************************/
#include <PMManagerDC.h>
#include <PMLComponent.h>
#include <PhysicalModel.h>
#include <StructuralComponentDC.h>
#include <MultiComponentDC.h>
#include <MultiComponent.h>
#include "CreateSC.h"
#include <QVector3D>
#include <Log.h>
#include <Application.h>
#include <vtkIdTypeArray.h>
using namespace camitk;
// -------------------- CreateSC --------------------
CreateSC::CreateSC(ActionExtension* extension) : Action(extension) {
this->setName("CreateSC");
this->setDescription("Generates a Structural Component from a given box selection");
this->setComponent("PMManagerDC");
this->setFamily("Mesh Processing");
CreateSC::CreateSC(ActionExtension * extension) : Action(extension) {
checkEvents = false;
this->setName("Create Structural Component From Selection");
this->setDescription("Generates a Structural Component from a given bounding box or current PML explorer selection");
this->setComponent("PMLComponent");
this->setFamily("Physical Model");
this->addTag("CreateSC");
this->addTag("Select");
setProperty("Name Of The New Component", "selection");
//TODO setProperty("Select Only On Surface", (bool) false);
setProperty("Bottom Corner", QVector3D(0.0,0.0,0.0));
setProperty("Top Corner", QVector3D(0.0,0.0,0.0));
setProperty("Use PML Selection", (bool) false);
setProperty("Use Picking Selection", (bool) false);
setProperty("Bottom Corner", QVector3D(0.0, 0.0, 0.0));
setProperty("Top Corner", QVector3D(0.0, 0.0, 0.0));
// every time a property is changed, the action will be informed, see method event(..)
setAutoUpdateProperties(true);
}
// ---------------------- event ----------------------------
bool CreateSC::event(QEvent * e) {
if (checkEvents && e->type() == QEvent::DynamicPropertyChange) {
e->accept();
QDynamicPropertyChangeEvent * changeEvent = dynamic_cast<QDynamicPropertyChangeEvent *>(e);
if (!changeEvent) {
return false;
}
// if the user change the boolean properties, update bounds
PMLComponent * pmlComponent = dynamic_cast<PMLComponent *>(getTargets().last());
if (pmlComponent != NULL && changeEvent->propertyName() == "Use PML Selection" || changeEvent->propertyName() == "Use Picking Selection") {
updateCorners(pmlComponent);
}
return true;
}
return QObject::event(e);
}
// --------------- getWidget -------------------
......@@ -56,62 +86,194 @@ QWidget * CreateSC::getWidget() {
//-- init the property values using the selection state
if (getTargets().size() == 1) {
PMManagerDC *pmlDC = dynamic_cast<PMManagerDC*>(getTargets().last());
PMLComponent * pmlComponent = dynamic_cast<PMLComponent *>(getTargets().last());
//-- check if name exists, generate new if it does
QString selectionName = property("Name Of The New Component").toString();
while (pmlDC->getPhysicalModel()->getComponentByName(selectionName.toStdString())!=NULL) {
while (pmlComponent->getPhysicalModel()->getComponentByName(selectionName.toStdString()) != NULL) {
// If the name contains a number then increment it
QRegExp numSearch( "(^|[^\\d])(\\d+)" ); // we want to match as far left as possible, and when the number is at the start of the name
QRegExp numSearch("(^|[^\\d])(\\d+)"); // we want to match as far left as possible, and when the number is at the start of the name
// Does it have a number?
int start = numSearch.lastIndexIn( selectionName );
int start = numSearch.lastIndexIn(selectionName);
if (start != -1) {
// It has a number, increment it
start = numSearch.pos( 2 ); // we are only interested in the second group
start = numSearch.pos(2); // we are only interested in the second group
QString numAsStr = numSearch.capturedTexts()[ 2 ];
QString number = QString::number( numAsStr.toInt() + 1 );
number = number.rightJustified( numAsStr.length(), '0' );
selectionName.replace( start, numAsStr.length(), number );
} else {
QString number = QString::number(numAsStr.toInt() + 1);
number = number.rightJustified(numAsStr.length(), '0');
selectionName.replace(start, numAsStr.length(), number);
}
else {
// no number
start = selectionName.lastIndexOf('.');
if (start != -1) {
// has a . somewhere, e.g. it has an extension
selectionName.insert(start, '1');
} else {
}
else {
// no extension, just tack it on to the end
selectionName += '1';
}
}
}
setProperty("Name Of The New Component",selectionName);
double bounds[6]; // [xmin,xmax, ymin,ymax, zmin,zmax]
pmlDC->getBounds(bounds);
setProperty("Name Of The New Component", selectionName);
setProperty("Bottom Corner", QVector3D(bounds[0],bounds[2],bounds[4]));
setProperty("Top Corner", QVector3D(bounds[1],bounds[3],bounds[5]));
// update corner values depending on the selection (if this is what the user wants)
updateCorners(pmlComponent);
// now that we have a widget, consider all events
checkEvents = true;
}
return Action::getWidget();
}
// --------------- computeBoundsOfPointIds -------------------
void CreateSC::computeBoundsOfPointIds(PMLComponent * comp, vtkSmartPointer< vtkIdTypeArray > selectedIds, double bounds[6]) {
// compute the bounds of the selected atoms only
Atom * a;
double pos[3];
PhysicalModel * pml = comp->getPhysicalModel();
// bounds = [xmin,xmax, ymin,ymax, zmin,zmax]
bounds[0] = bounds[2] = bounds[4] = VTK_DOUBLE_MAX;
bounds[1] = bounds[3] = bounds[5] = -VTK_DOUBLE_MAX;
for (vtkIdType i = 0; i < selectedIds->GetNumberOfTuples(); i++) {
a = pml->getAtom(selectedIds->GetValue(i));
if (a) {
a->getPosition(pos);
for (int j = 0; j < 3; j++) {
if (pos[j] < bounds[2 * j]) {
bounds[2 * j] = pos[j];
}
if (pos[j] > bounds[2 * j + 1]) {
bounds[2 * j + 1] = pos[j];
}
}
}
}
}
// --------------- computeBoundsOfCellIds -------------------
void CreateSC::computeBoundsOfCellIds(PMLComponent * comp, vtkSmartPointer< vtkIdTypeArray > selectedCellIds, double bounds[6]) {
vtkSmartPointer< vtkIdTypeArray > selectedIds = vtkSmartPointer<vtkIdTypeArray>::New();
Cell * c;
PhysicalModel * pml = comp->getPhysicalModel();
for (vtkIdType i = 0; i < selectedCellIds->GetNumberOfTuples(); i++) {
c = pml->getCell(selectedCellIds->GetValue(i));
// insert all the cell atoms
for (int j = 0; j < c->getNumberOfStructures(); j++) {
selectedIds->InsertNextValue(c->getStructure(j)->getIndex());
}
}
computeBoundsOfPointIds(comp, selectedIds, bounds);
}
// --------------- mergeBounds -------------------
void CreateSC::mergeBounds(double bounds1[6], double bounds2[6]) {
// [xmin,xmax, ymin,ymax, zmin,zmax]
for (int j = 0; j < 3; j++) {
if (bounds1[2 * j] < bounds2[2 * j]) {
// negative expansion
bounds2[2 * j] = bounds1[2 * j];
}
if (bounds1[2 * j + 1] > bounds2[2 * j + 1]) {
// position expansion
bounds2[2 * j + 1] = bounds1[2 * j + 1];
}
}
}
// --------------- computeBoundsOfSelection -------------------
bool CreateSC::computeBoundsOfSelection(PMLComponent * pmlComponent, QString selectionName, double bounds[6]) {
// get the point selection
vtkSmartPointer<vtkSelectionNode> selectionNode = pmlComponent->getSelection(selectionName);
if (selectionNode) {
vtkSmartPointer<vtkIdTypeArray> indices = vtkIdTypeArray::SafeDownCast(selectionNode->GetSelectionList());
if (indices->GetNumberOfTuples() > 0) {
if (selectionNode->GetFieldType() == vtkSelectionNode::POINT) {
computeBoundsOfPointIds(pmlComponent, indices, bounds);
return true;
}
else
if (selectionNode->GetFieldType() == vtkSelectionNode::CELL) {
computeBoundsOfCellIds(pmlComponent, vtkIdTypeArray::SafeDownCast(selectionNode->GetSelectionList()), bounds);
return true;
}
}
}
return false;
}
// --------------- updateCorners -------------------
void CreateSC::updateCorners(PMLComponent * pmlComponent) {
double bounds[6];
// bounds = [xmin,xmax, ymin,ymax, zmin,zmax]
bounds[0] = bounds[2] = bounds[4] = VTK_DOUBLE_MAX;
bounds[1] = bounds[3] = bounds[5] = -VTK_DOUBLE_MAX;
bool usePMLSelection = property("Use PML Selection").toBool();
bool usePickingSelection = property("Use Picking Selection").toBool();
bool boundsInitialized = false;
// restrain to the selection
if (usePMLSelection) {
// get the point selection
boundsInitialized = computeBoundsOfSelection(pmlComponent, "Selected Atoms", bounds);
// get the cell selection
double cellBounds[6];
bool cellBoundsIsNotEmpty = computeBoundsOfSelection(pmlComponent, "Selected Cells", cellBounds);
boundsInitialized = boundsInitialized || cellBoundsIsNotEmpty;
if (cellBoundsIsNotEmpty)
mergeBounds(cellBounds, bounds);
}
else
if (usePickingSelection) {
// get the point selection
boundsInitialized = computeBoundsOfSelection(pmlComponent, "Picked Selection", bounds);
}
if (!boundsInitialized) {
pmlComponent->getBounds(bounds);
}
setProperty("Bottom Corner", QVector3D(bounds[0], bounds[2], bounds[4]));
setProperty("Top Corner", QVector3D(bounds[1], bounds[3], bounds[5]));
}
// --------------- apply -------------------
Action::ApplyStatus CreateSC::apply() {
CAMITK_INFO("CreateSC", "apply", "Create Structural Component in " << getTargets().last()->getName().toStdString());
// set waiting cursor and status bar
QApplication::setOverrideCursor ( QCursor ( Qt::WaitCursor ) );
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
Application::showStatusBarMessage("Creating New Structural Component...");
Application::resetProgressBar();
// use the last target
PMManagerDC *pmlDC = dynamic_cast<PMManagerDC*>(getTargets().last());
PhysicalModel *pm=pmlDC->getPhysicalModel();
PMLComponent * pmlComponent = dynamic_cast<PMLComponent *>(getTargets().last());
PhysicalModel * pm = pmlComponent->getPhysicalModel();
// update corner and selection settings
updateCorners(pmlComponent);