Commit 75789509 authored by Pierre Kraemer's avatar Pierre Kraemer

add schnapps plugin surface_lsm (least square meshes)

parent 1729eb93
......@@ -10,3 +10,6 @@ target_link_libraries( bench_remesh ${CGoGN_LIBS} ${CGoGN_EXT_LIBS} )
add_executable(bench_compact bench_compact.cpp )
target_link_libraries( bench_compact ${CGoGN_LIBS} ${CGoGN_EXT_LIBS} )
add_executable(bench_import_trav bench_import_trav.cpp )
target_link_libraries( bench_import_trav ${CGoGN_LIBS} ${CGoGN_EXT_LIBS} )
......@@ -62,7 +62,7 @@ class MeshTablesSurface
public:
typedef typename PFP::MAP MAP ;
typedef typename PFP::VEC3 VEC3 ;
typedef typename VEC3::DATA_TYPE DATA_TYPE ;
typedef typename VEC3::DATA_TYPE DATA_TYPE ;
typedef typename PFP::REAL REAL ;
protected:
......
......@@ -23,6 +23,7 @@ ADD_SUBDIRECTORY(surface_differentialProperties)
ADD_SUBDIRECTORY(surface_subdivision)
ADD_SUBDIRECTORY(surface_selection)
ADD_SUBDIRECTORY(surface_deformation)
ADD_SUBDIRECTORY(surface_lsm)
ADD_SUBDIRECTORY(surface_modelisation)
#ADD_SUBDIRECTORY(surface_tilings)
ADD_SUBDIRECTORY(surface_distance)
......
cmake_minimum_required(VERSION 2.8)
SET( PLUGIN_NAME Surface_LSM )
SET( PLUGIN_ROOT_DIR ${SCHNApps_ROOT_DIR}/Plugins/surface_lsm )
INCLUDE_DIRECTORIES(
${PLUGIN_ROOT_DIR}/include
${CMAKE_CURRENT_BINARY_DIR}
)
file(
GLOB_RECURSE
PLUGIN_FILES
${PLUGIN_ROOT_DIR}/src/*.cpp
${PLUGIN_ROOT_DIR}/include/*.h
${PLUGIN_ROOT_DIR}/include/*.hpp
)
file(
GLOB_RECURSE
PLUGIN_UI_FILES
${PLUGIN_ROOT_DIR}/forms/*.ui
)
SET(
PLUGIN_QOBJECT_FILES
${PLUGIN_ROOT_DIR}/include/surface_deformation.h
${PLUGIN_ROOT_DIR}/include/surface_deformation_dockTab.h
)
include( ${SCHNApps_ROOT_DIR}/Plugins/plugins_cmake.txt )
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Surface_Deformation_TabWidget</class>
<widget class="QWidget" name="Surface_Deformation_TabWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>207</width>
<height>545</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="6" column="0" colspan="2">
<widget class="QComboBox" name="combo_freeSelector">
<item>
<property name="text">
<string>- select selector -</string>
</property>
</item>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Position :</string>
</property>
</widget>
</item>
<item row="5" column="0" colspan="2">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Free vertices selector :</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="combo_positionAttribute">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>- select attribute -</string>
</property>
</item>
</widget>
</item>
<item row="9" column="0" colspan="2">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="10" column="0" colspan="2">
<widget class="QPushButton" name="button_start_stop">
<property name="text">
<string>Start</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="QComboBox" name="combo_handleSelector">
<item>
<property name="text">
<string>- select selector -</string>
</property>
</item>
</widget>
</item>
<item row="11" column="0" colspan="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>156</width>
<height>161</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="0" colspan="2">
<widget class="QLabel" name="label">
<property name="text">
<string>Handle vertices selector :</string>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>combo_positionAttribute</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>
#ifndef _SURFACE_DEFORMATION_PLUGIN_H_
#define _SURFACE_DEFORMATION_PLUGIN_H_
#include "plugin_interaction.h"
#include "surface_deformation_dockTab.h"
#include "mapHandler.h"
#include "Container/fakeAttribute.h"
#include "NL/nl.h"
#include "Algo/LinearSolving/basic.h"
#include "Eigen/Dense"
namespace CGoGN
{
namespace SCHNApps
{
typedef NoTypeNameAttribute<Eigen::Matrix3f> Eigen_Matrix3f;
struct MapParameters
{
MapParameters();
~MapParameters();
void start(MapHandlerGen* mh);
void stop(MapHandlerGen* mh);
VertexAttribute<PFP2::VEC3, PFP2::MAP> positionAttribute;
CellSelector<PFP2::MAP, VERTEX>* handleSelector;
CellSelector<PFP2::MAP, VERTEX>* freeSelector;
bool initialized;
VertexAttribute<PFP2::VEC3, PFP2::MAP> positionInit;
VertexAttribute<unsigned int, PFP2::MAP> vIndex;
unsigned int nb_vertices;
NLContext nlContext;
};
class Surface_Deformation_Plugin : public PluginInteraction
{
Q_OBJECT
Q_INTERFACES(CGoGN::SCHNApps::Plugin)
#if CGOGN_QT_DESIRED_VERSION == 5
Q_PLUGIN_METADATA(IID "CGoGN.SCHNapps.Plugin")
#endif
friend class Surface_Deformation_DockTab;
public:
Surface_Deformation_Plugin() :
m_draginit(false),
m_dragging(false)
{}
~Surface_Deformation_Plugin()
{}
virtual bool enable();
virtual void disable();
virtual void draw(View *view);
virtual void drawMap(View* view, MapHandlerGen* map) {}
virtual void keyPress(View* view, QKeyEvent* event);
virtual void keyRelease(View* , QKeyEvent* ) {}
virtual void mousePress(View* , QMouseEvent* ) {}
virtual void mouseRelease(View* , QMouseEvent* ) {}
virtual void mouseMove(View* view, QMouseEvent* event);
virtual void wheelEvent(View* , QWheelEvent* ) {}
virtual void viewLinked(View *view) {}
virtual void viewUnlinked(View *view) {}
private slots:
// slots called from SCHNApps signals
void selectedMapChanged(MapHandlerGen* prev, MapHandlerGen* cur);
void mapAdded(MapHandlerGen* map);
void mapRemoved(MapHandlerGen* map);
// slots called from MapHandler signals
void attributeAdded(unsigned int orbit, const QString& name);
void cellSelectorAdded(unsigned int orbit, const QString& name);
void cellSelectorRemoved(unsigned int orbit, const QString& name);
void selectedCellsChanged(CellSelectorGen *cs);
public slots:
// slots for Python calls
void changePositionAttribute(const QString& map, const QString& name);
void changeHandleSelector(const QString& map, const QString& name);
void changeFreeSelector(const QString& map, const QString& name);
protected:
void toggleMapDeformation(MapHandlerGen* map);
void lsm(MapHandlerGen* map);
protected:
Surface_Deformation_DockTab* m_dockTab;
QHash<MapHandlerGen*, MapParameters> h_parameterSet;
bool m_draginit;
bool m_dragging;
PFP2::REAL m_dragZ;
qglviewer::Vec m_dragPrevious;
};
} // namespace SCHNApps
} // namespace CGoGN
#endif
#ifndef _SURFACE_DEFORMATION_DOCK_TAB_H_
#define _SURFACE_DEFORMATION_DOCK_TAB_H_
#include "ui_surface_deformation.h"
namespace CGoGN
{
namespace SCHNApps
{
class SCHNApps;
class Surface_Deformation_Plugin;
struct MapParameters;
class Surface_Deformation_DockTab : public QWidget, public Ui::Surface_Deformation_TabWidget
{
Q_OBJECT
friend class Surface_Deformation_Plugin;
public:
Surface_Deformation_DockTab(SCHNApps* s, Surface_Deformation_Plugin* p);
private:
SCHNApps* m_schnapps;
Surface_Deformation_Plugin* m_plugin;
bool b_updatingUI;
private slots:
void positionAttributeChanged(int index);
void handleSelectorChanged(int index);
void freeSelectorChanged(int index);
void startStopButtonClicked();
private:
void addVertexAttribute(const QString& nameAttr);
void addVertexSelector(const QString& name);
void removeVertexSelector(const QString& name);
void mapParametersInitialized(bool b);
void updateMapParameters();
};
} // namespace SCHNApps
} // namespace CGoGN
#endif
#include "surface_deformation.h"
#include "Algo/Geometry/normal.h"
#include "Algo/Geometry/laplacian.h"
#include "Algo/LinearSolving/basic.h"
#include "Algo/Topo/basic.h"
#include "camera.h"
#include <QKeyEvent>
#include <QMouseEvent>
namespace CGoGN
{
namespace SCHNApps
{
MapParameters::MapParameters() :
handleSelector(NULL),
freeSelector(NULL),
initialized(false),
nlContext(NULL)
{}
MapParameters::~MapParameters()
{
if(nlContext)
nlDeleteContext(nlContext);
}
void MapParameters::start(MapHandlerGen* mhg)
{
if(!initialized)
{
if(positionAttribute.isValid() && handleSelector && freeSelector)
{
MapHandler<PFP2>* mh = static_cast<MapHandler<PFP2>*>(mhg);
positionInit = mh->getAttribute<PFP2::VEC3, VERTEX>("positionInit");
if(!positionInit.isValid())
positionInit = mh->addAttribute<PFP2::VEC3, VERTEX>("positionInit");
vIndex = mh->getAttribute<unsigned int, VERTEX>("vIndex");
if(!vIndex.isValid())
vIndex = mh->addAttribute<unsigned int, VERTEX>("vIndex");
PFP2::MAP* map = static_cast<MapHandler<PFP2>*>(mh)->getMap();
map->copyAttribute(positionInit, positionAttribute);
nb_vertices = Algo::Topo::computeIndexCells<VERTEX>(*map, vIndex);
if(nlContext)
nlDeleteContext(nlContext);
nlContext = nlNewContext();
nlSolverParameteri(NL_NB_VARIABLES, nb_vertices);
nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE);
nlSolverParameteri(NL_SOLVER, NL_CHOLMOD_EXT);
initialized = true;
}
}
}
void MapParameters::stop(MapHandlerGen* mh)
{
if(initialized)
{
// if(positionInit.isValid())
// mh->removeAttribute(positionInit);
// if(vIndex.isValid())
// mh->removeAttribute(vIndex);
if(nlContext)
nlDeleteContext(nlContext);
initialized = false;
}
}
bool Surface_Deformation_Plugin::enable()
{
// magic line that init static variables of GenericMap in the plugins
GenericMap::copyAllStatics(m_schnapps->getStaticPointers());
m_dockTab = new Surface_Deformation_DockTab(m_schnapps, this);
m_schnapps->addPluginDockTab(this, m_dockTab, "Surface_Deformation");
connect(m_schnapps, SIGNAL(selectedMapChanged(MapHandlerGen*, MapHandlerGen*)), this, SLOT(selectedMapChanged(MapHandlerGen*, MapHandlerGen*)));
connect(m_schnapps, SIGNAL(mapAdded(MapHandlerGen*)), this, SLOT(mapAdded(MapHandlerGen*)));
connect(m_schnapps, SIGNAL(mapRemoved(MapHandlerGen*)), this, SLOT(mapRemoved(MapHandlerGen*)));
foreach(MapHandlerGen* map, m_schnapps->getMapSet().values())
mapAdded(map);
m_dockTab->updateMapParameters();
return true;
}
void Surface_Deformation_Plugin::disable()
{
disconnect(m_schnapps, SIGNAL(selectedMapChanged(MapHandlerGen*, MapHandlerGen*)), this, SLOT(selectedMapChanged(MapHandlerGen*, MapHandlerGen*)));
}
void Surface_Deformation_Plugin::draw(View *view)
{
}
void Surface_Deformation_Plugin::keyPress(View* view, QKeyEvent* event)
{
switch(event->key())
{
case Qt::Key_D : {
MapHandlerGen* mh = m_schnapps->getSelectedMap();
if(mh)
{
const MapParameters& p = h_parameterSet[mh];
if(!m_dragging)
{
if(p.handleSelector && !p.handleSelector->getSelectedCells().empty())
{
m_dragging = true;
m_draginit = false;
view->setMouseTracking(true);
view->getCurrentCamera()->disableViewsBoundingBoxFitting();
}
}
else
{
m_dragging = false;
m_draginit = false;
view->setMouseTracking(false);
view->getCurrentCamera()->enableViewsBoundingBoxFitting();
}
}
break;
}
case Qt::Key_R : {
MapHandlerGen* mh = m_schnapps->getSelectedMap();
if(mh)
{
const MapParameters& p = h_parameterSet[mh];
if(p.initialized)
{
lsm(mh);
mh->notifyAttributeModification(p.positionAttribute);
view->updateGL();
}
}
break;
}
}
}
void Surface_Deformation_Plugin::mouseMove(View* view, QMouseEvent* event)
{
if (m_dragging)
{
MapHandlerGen* mh = m_schnapps->getSelectedMap();
MapParameters& p = h_parameterSet[mh];
const std::vector<Vertex>& handle = p.handleSelector->getSelectedCells();
if (!m_draginit)
{
m_dragZ = 0;
for (std::vector<Vertex>::const_iterator it = handle.begin(); it != handle.end(); ++it)
{
const PFP2::VEC3& pp = p.positionAttribute[*it];
qglviewer::Vec q = view->camera()->projectedCoordinatesOf(qglviewer::Vec(pp[0],pp[1],pp[2]));
m_dragZ += q.z;
}
m_dragZ /= handle.size();
qglviewer::Vec pp(event->x(), event->y(), m_dragZ);
m_dragPrevious = view->camera()->unprojectedCoordinatesOf(pp);
m_draginit = true;
}
else
{
qglviewer::Vec pp(event->x(), event->y(), m_dragZ);
qglviewer::Vec qq = view->camera()->unprojectedCoordinatesOf(pp);
qglviewer::Vec vec = qq - m_dragPrevious;
PFP2::VEC3 t(vec.x, vec.y, vec.z);
for (std::vector<Vertex>::const_iterator it = handle.begin(); it != handle.end(); ++it)
p.positionAttribute[*it] += t;
m_dragPrevious = qq;
if (p.initialized)
{
lsm(mh);
mh->notifyAttributeModification(p.positionAttribute);
}
}
view->updateGL();
}
}
void Surface_Deformation_Plugin::selectedMapChanged(MapHandlerGen *prev, MapHandlerGen *cur)
{
m_dockTab->updateMapParameters();
if (cur==NULL)
m_dockTab->setDisabled(true);
else
m_dockTab->setDisabled(false);
}
void Surface_Deformation_Plugin::mapAdded(MapHandlerGen* map)
{
connect(map, SIGNAL(attributeAdded(unsigned int, const QString&)), this, SLOT(attributeAdded(unsigned int, const QString&)));
connect(map, SIGNAL(cellSelectorAdded(unsigned int, const QString&)), this, SLOT(cellSelectorAdded(unsigned int, const QString&)));
connect(map, SIGNAL(cellSelectorRemoved(unsigned int, const QString&)), this, SLOT(cellSelectorRemoved(unsigned int, const QString&)));
connect(map, SIGNAL(selectedCellsChanged(CellSelectorGen*)), this, SLOT(selectedCellsChanged(CellSelectorGen*)));
}
void Surface_Deformation_Plugin::mapRemoved(MapHandlerGen* map)
{
disconnect(map, SIGNAL(attributeAdded(unsigned int, const QString&)), this, SLOT(attributeAdded(unsigned int, const QString&)));
disconnect(map, SIGNAL(cellSelectorAdded(unsigned int, const QString&)), this, SLOT(cellSelectorAdded(unsigned int, const QString&)));
disconnect(map, SIGNAL(cellSelectorRemoved(unsigned int, const QString&)), this, SLOT(cellSelectorRemoved(unsigned int, const QString&)));
disconnect(map, SIGNAL(selectedCellsChanged(CellSelectorGen*)), this, SLOT(selectedCellsChanged(CellSelectorGen*)));
}
void Surface_Deformation_Plugin::attributeAdded(unsigned int orbit, const QString& name)
{
MapHandlerGen* map = static_cast<MapHandlerGen*>(QObject::sender());
if(orbit == VERTEX && map->isSelectedMap())
m_dockTab->addVertexAttribute(name);
}
void Surface_Deformation_Plugin::cellSelectorAdded(unsigned int orbit, const QString& name)
{
MapHandlerGen* map = static_cast<MapHandlerGen*>(QObject::sender());
if(orbit == VERTEX && map->isSelectedMap())
m_dockTab->addVertexSelector(name);
}
void Surface_Deformation_Plugin::cellSelectorRemoved(unsigned int orbit, const QString& name)
{
MapHandlerGen* map = static_cast<MapHandlerGen*>(QObject::sender());
if(orbit == VERTEX && map->isSelectedMap())
m_dockTab->removeVertexSelector(name);
MapParameters& p = h_parameterSet[map];
if(p.handleSelector->getName() == name)
{
p.stop(map);
if(!p.initialized && map->isSelectedMap())
m_dockTab->mapParametersInitialized(false);
p.handleSelector = NULL;
}
if(p.freeSelector->getName() == name)
{
p.stop(map);
if(!p.initialized && map->isSelectedMap())
m_dockTab->mapParametersInitialized(false);
p.freeSelector = NULL;
}
}
void Surface_Deformation_Plugin::selectedCellsChanged(CellSelectorGen* cs)
{
MapHandlerGen* map = static_cast<MapHandlerGen*>(QObject::sender());
MapParameters& p = h_parameterSet[map];
if(p.initialized && (p.handleSelector == cs || p.freeSelector == cs))
{
nlMakeCurrent(p.nlContext) ;
nlReset(NL_FALSE) ;
}
}
void Surface_Deformation_Plugin::changePositionAttribute(const QString& map, const QString& name)
{
MapHandlerGen* m = m_schnapps->getMap(map);
if(m)
{
MapParameters& p = h_parameterSet[m];
if(!p.initialized)
{
MapHandler<PFP2>* mh = static_cast<MapHandler<PFP2>*>(m);
p.positionAttribute = mh->getAttribute<PFP2::VEC3, VERTEX>(name);
if(m->isSelectedMap())
m_dockTab->updateMapParameters();
}
}
}
void Surface_Deformation_Plugin::changeHandleSelector(const QString& map, const QString& name)
{
MapHandlerGen* m = m_schnapps->getMap(map);
if(m)
{
MapParameters& p = h_parameterSet[m];
if(!p.initialized)
{
MapHandler<PFP2>* mh = static_cast<MapHandler<PFP2>*>(m);
p.handleSelector = mh->getCellSelector<VERTEX>(name);
if(m->isSelectedMap())
m_dockTab->updateMapParameters();
}
}
}
void Surface_Deformation_Plugin::changeFreeSelector(const QString& map, const QString& name)
{
MapHandlerGen* m = m_schnapps->getMap(map);
if(m)
{
MapParameters& p = h_parameterSet[m];
if(!p.initialized)
{
MapHandler<PFP2>* mh = static_cast<MapHandler<PFP2>*>(m);
p.freeSelector = mh->getCellSelector<VERTEX>(name);
if(m->isSelectedMap())
m_dockTab->updateMapParameters();
}
}
}
void Surface_Deformation_Plugin::toggleMapDeformation(MapHandlerGen* map)
{
if(map)
{
MapParameters& p = h_parameterSet[map];
if (!p.initialized)
{
p.start(map);
if (p.initialized && map->isSelectedMap())
m_dockTab->mapParametersInitialized(true);
}
else
{
p.stop(map);
if (!p.initialized && map->isSelectedMap())
m_dockTab->mapParametersInitialized(false);
}
}
}