Commit ec3256e2 authored by lealv's avatar lealv
Browse files

FIXED - Frame : resolve some frame robustness issues

Usecase1: when a frame is defined as its own parent, it must get the World frame as parent. -> this situation wasn't correctly managed (checkedparent is a pointer on a Component not a Frame). Manage the frames with the names resolves the issue.
Usecase2: when a child frame of a frame is defined as the new parent of the frame, the new parent frame must have the world frame as parent. This a complex management of the frame items.

+ spaces replace tabs, remove trim trailing spaces
 

git-svn-id: svn+ssh://scm.forge.imag.fr/var/lib/gforge/chroot/scmrepos/svn/camitk/trunk/camitk@1826 ec899d31-69d1-42ba-9299-647d76f65fb3
parent 0848ec4b
......@@ -758,7 +758,7 @@ public:
* All the implemented InterfaceFrame methods
*/
///@{
delegateGet0(myFrame, getFrameName, QString)
delegateGet0(myFrame, getFrameName, const QString & )
delegate1(myFrame, setFrameName, QString)
......@@ -802,6 +802,8 @@ public:
delegateGet0(myFrame, getDescendantsFrame, QVector<InterfaceFrame *> *)
delegateGet0(myFrame, getDescendantsFrameName, QVector<QString*> *)
///@}
protected:
/// myGeometry is the 3d representation of this Component, the Component delegates all InterfaceGeometry activity to myGeometry (delegation pattern)
......
......@@ -37,18 +37,18 @@ int Frame::nbTotalFrames = 0;
Frame::Frame(vtkSmartPointer<vtkTransform> transform, Frame *parentFrame)
{
initAttributes();
if (transform != NULL) {
if (transform != NULL) {
setTransformFromParent(transform);
}
}
// setParentFrame(parentFrame);
this->parentFrame = parentFrame;
this->transformWorldToMe->Identity();
this->transformWorldToMe->PostMultiply();
this->transformWorldToMe->Concatenate(transformParentToMe);
this->transformWorldToMe->Update();
if (this->parentFrame != NULL)
{
this->transformWorldToMe->Concatenate(this->parentFrame->getTransformFromWorld());
......@@ -62,13 +62,13 @@ Frame::Frame(vtkSmartPointer<vtkTransform> transform, Frame *parentFrame)
void Frame::initAttributes() {
frameName = "Frame" + QString::number(nbTotalFrames);
nbTotalFrames ++;
this->axes = NULL;
this->parentFrame = NULL;
this->parentFrame = NULL;
this->transformParentToMe = vtkSmartPointer<vtkTransform>::New();
this->transformParentToMe->Identity();
this->transformWorldToMe = vtkSmartPointer<vtkTransform>::New();
this->transformWorldToMe->Identity();
this->transformWorldToMe->PostMultiply();
......@@ -76,7 +76,7 @@ void Frame::initAttributes() {
this->representationTransformFilter = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
this->representationTransformFilter->SetTransform(transformWorldToMe);
this->representationTransformFilter->GlobalWarningDisplayOff();
this->childrenFrame.clear();
}
......@@ -84,23 +84,23 @@ void Frame::initAttributes() {
// ------------------- Default Destructor ----------------------------------
Frame::~Frame() {
if (parentFrame != NULL) {
parentFrame->removeFrameChild(this);
}
if (parentFrame != NULL) {
parentFrame->removeFrameChild(this);
}
// Declare my children as orpheans
foreach (InterfaceFrame * f, childrenFrame) {
f->setParentFrame(NULL);
}
this->childrenFrame.clear();
this->frameViewers.clear();
}
// -----------------* Hierarchy accessors / Modifyers *-----------------
// ------------------- getFrameName ----------------------------------
QString Frame::getFrameName()
const QString & Frame::getFrameName()
{
return frameName;
}
......@@ -123,30 +123,53 @@ const QVector<InterfaceFrame *> * Frame::getChildrenFrame()
}
// ------------------- getDescendantsFrame ----------------------------------
QVector<InterfaceFrame *> * Frame::getDescendantsFrame() {
QVector<InterfaceFrame *> * result = new QVector<InterfaceFrame *>();
foreach(InterfaceFrame * child, childrenFrame) {
result->append(child);
QVector<InterfaceFrame *> * grandChildren = child->getDescendantsFrame();
foreach(InterfaceFrame * grandChild, *grandChildren) {
result->append(grandChild);
}
delete grandChildren;
}
return result;
QVector<InterfaceFrame *> * result = new QVector<InterfaceFrame *>();
foreach(InterfaceFrame * child, childrenFrame) {
result->append(child);
QVector<InterfaceFrame *> * grandChildren = child->getDescendantsFrame();
foreach(InterfaceFrame * grandChild, *grandChildren) {
result->append(grandChild);
}
delete grandChildren;
}
return result;
}
QVector<QString *> * Frame::getDescendantsFrameName() {
QVector<QString *> * result = new QVector<QString *>();
QVector<InterfaceFrame *> * frames = getDescendantsFrame();
foreach(InterfaceFrame * child, *frames) {
result->append((QString * const &)(child->getFrameName()));
}
delete frames;
return result;
}
// ------------------- setParentFrame ----------------------------------
void Frame::setParentFrame(InterfaceFrame *parent, bool keepTransform)
{
InterfaceFrame * checkedParent = parent;
// setParentFrame(this) should not be possible...
// Neither should be setParentFrame from one of my child
QVector<InterfaceFrame *> * descendants = getDescendantsFrame();
if ((checkedParent == this) || (descendants->indexOf(checkedParent) != -1)) {
checkedParent = NULL;
InterfaceFrame * checkedParent = parent;
if (checkedParent)
{
// setParentFrame(this) should not be possible...
// Neither should be setParentFrame from one of my child
QVector<QString *> * descendants = getDescendantsFrameName();
if(checkedParent->getFrameName() == getFrameName()) {
checkedParent = NULL;
}
else if(descendants->indexOf((QString * const &)(checkedParent->getFrameName())) != -1){
//remove the new parent in the list of children
removeFrameChild(checkedParent);
//In this usecase, the former descendant is attached to the world frame
checkedParent->setParentFrame(NULL);
}
delete descendants;
}
delete descendants;
// If we don't keep transform => update it in order for the frame not to move during parent transition
if(!keepTransform)
......@@ -157,10 +180,10 @@ void Frame::setParentFrame(InterfaceFrame *parent, bool keepTransform)
}
// tell my former parent that I am no more its child
if (parentFrame != NULL) {
if (parentFrame != NULL) {
parentFrame->removeFrameChild(this);
}
this->parentFrame = checkedParent;
}
this->parentFrame = checkedParent;
this->transformWorldToMe->Identity();
this->transformWorldToMe->PostMultiply();
this->transformWorldToMe->Concatenate(transformParentToMe);
......@@ -175,7 +198,7 @@ void Frame::setParentFrame(InterfaceFrame *parent, bool keepTransform)
}
// ------------------- setParentFrame ----------------------------------
// ------------------- addFrameChild ----------------------------------
void Frame::addFrameChild(InterfaceFrame * frame)
{
if (! childrenFrame.contains(frame))
......@@ -185,9 +208,9 @@ void Frame::addFrameChild(InterfaceFrame * frame)
}
void Frame::removeFrameChild(InterfaceFrame * frame) {
if (childrenFrame.indexOf(frame) != -1) {
childrenFrame.remove(childrenFrame.indexOf(frame));
}
if (childrenFrame.indexOf(frame) != -1) {
childrenFrame.remove(childrenFrame.indexOf(frame));
}
}
// -----------------* Transforms accessors / Modifyers *-----------------
// ------------------- getTransformFromWorld ----------------------------------
......@@ -204,7 +227,7 @@ const vtkSmartPointer<vtkTransform> Frame::getTransformFromParent() {
vtkSmartPointer<vtkTransform> Frame::getTransformFromFrame(InterfaceFrame * frame) {
// World -> Me
vtkSmartPointer<vtkMatrix4x4> worldToMeMatrix = transformWorldToMe->GetMatrix();
// World -> Frame
vtkSmartPointer<vtkMatrix4x4> worldToFrameMatrix;
if (frame == NULL) { // Frame IS the world Frame !
......@@ -215,17 +238,17 @@ vtkSmartPointer<vtkTransform> Frame::getTransformFromFrame(InterfaceFrame * fram
worldToFrameMatrix = frame->getTransformFromWorld()->GetMatrix();
//frame->getTransformFromParent()->GetConcatenatedTransform(frame->getTransformFromParent()->GetNumberOfConcatenatedTransforms())->GetMatrix();
}
// Frame -> World
vtkSmartPointer<vtkMatrix4x4> frameToWorldMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
vtkMatrix4x4::Invert(worldToFrameMatrix, frameToWorldMatrix);
vtkMatrix4x4::Invert(worldToFrameMatrix, frameToWorldMatrix);
// Frame -> Me = Frame -> World -> Me
vtkSmartPointer<vtkMatrix4x4> frameToMeMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
vtkMatrix4x4::Multiply4x4(frameToWorldMatrix, worldToMeMatrix, frameToMeMatrix);
vtkMatrix4x4::Multiply4x4(frameToWorldMatrix, worldToMeMatrix, frameToMeMatrix);
vtkSmartPointer<vtkTransform> result = vtkSmartPointer<vtkTransform>::New();
result->SetMatrix(frameToMeMatrix);
vtkSmartPointer<vtkTransform> result = vtkSmartPointer<vtkTransform>::New();
result->SetMatrix(frameToMeMatrix);
return result;
}
......@@ -307,7 +330,7 @@ void Frame::setRotation(double aroundX, double aroundY, double aroundZ) {
// ------------------- getFrameActor ----------------------------------
vtkSmartPointer<vtkAxesActor> Frame::getFrameAxisActor() {
if (axes == NULL) {
axes = vtkSmartPointer<vtkAxesActor>::New();
axes->SetShaftTypeToCylinder();
......@@ -328,50 +351,50 @@ vtkSmartPointer<vtkAxesActor> Frame::getFrameAxisActor() {
axes->GetXAxisCaptionActor2D()->GetCaptionTextProperty()->SetColor(0.9, 0.4, 0.4);
// make sure the label can be hidden by any geometry, like the axes
axes->GetXAxisCaptionActor2D()->GetProperty()->SetDisplayLocationToBackground();
vtkSmartPointer<vtkTextProperty> axeYTextProp = vtkSmartPointer<vtkTextProperty>::New();
axeYTextProp->ShallowCopy(axeXTextProp);
axes->GetYAxisCaptionActor2D()->SetCaptionTextProperty(axeYTextProp);
axes->GetYAxisCaptionActor2D()->GetTextActor()->SetTextScaleModeToNone();
axes->GetYAxisCaptionActor2D()->GetCaptionTextProperty()->SetColor(0.4, 0.9, 0.4);
axes->GetYAxisCaptionActor2D()->GetProperty()->SetDisplayLocationToBackground();
vtkSmartPointer<vtkTextProperty> axeZTextProp = vtkSmartPointer<vtkTextProperty>::New();
axeZTextProp->ShallowCopy(axeXTextProp);
axes->GetZAxisCaptionActor2D()->SetCaptionTextProperty(axeZTextProp);
axes->GetZAxisCaptionActor2D()->GetTextActor()->SetTextScaleModeToNone();
axes->GetZAxisCaptionActor2D()->GetCaptionTextProperty()->SetColor(0.4, 0.4, 0.9);
axes->GetZAxisCaptionActor2D()->GetProperty()->SetDisplayLocationToBackground();
axes->SetUserTransform(transformWorldToMe);
}
return axes;
}
void Frame::setFrameVisibility(Viewer * viewer, bool visible) {
QMap<Viewer *, bool>::iterator it = this->frameViewers.find(viewer);
if (it == frameViewers.end()) {
frameViewers.insert(viewer, visible);
}
else {
it.value() = visible;
}
}
bool Frame::getFrameVisibility(Viewer * viewer) {
QMap<Viewer *, bool>::iterator it = this->frameViewers.find(viewer);
if (it == frameViewers.end()) {
return false;
}
else {
return it.value();
}
}
......@@ -15,48 +15,48 @@ namespace camitk
/**
* Represents a hierarchy of frames.
* Each frame is represented by its parent frame (by default the World frame) and
* a linear transformation from its parent frame ; i.e.
* a linear transformation from its parent frame ; i.e.
* the transformation to represents my points (expressed in my frame) in my parent's frame.
*
* Frames are in a tree hierarchy, in a top down way.
*
* The frame hierarchy only changes the REPRESENTATION of Components, not Components themselves
* To obtain the real point position of child components, one should apply getWorldTransformation to them.
*
* To obtain the real point position of child components, one should apply getWorldTransformation to them.
*
* When a frame moves, it should move from its parent, not from the world frame
* (except if its parent frame is the world frame).
*
*/
class CAMITK_API Frame : public InterfaceFrame {
public:
/** Default constructor with transformation
* @name is the name of the frame
* @transform is the vtk transformtation to express the current frame coordinates into its parent frame.
* If no transform is givent the default transform is set to the identity matrix.
* @parentFrame is the base frame in the begin of the hierarchical system.
* If no parent is given, the default parent is set to NULL and considered as the World frame.
*/
Frame(vtkSmartPointer<vtkTransform> transform = NULL, Frame *parentFrame = NULL);
/// Default Destructor
/** Default constructor with transformation
* @name is the name of the frame
* @transform is the vtk transformtation to express the current frame coordinates into its parent frame.
* If no transform is givent the default transform is set to the identity matrix.
* @parentFrame is the base frame in the begin of the hierarchical system.
* If no parent is given, the default parent is set to NULL and considered as the World frame.
*/
Frame(vtkSmartPointer<vtkTransform> transform = NULL, Frame *parentFrame = NULL);
/// Default Destructor
virtual ~Frame();
/**
* Hierarchy accessors / Modifyers
* @{
*/
/// Get the Frame Unique identifyer (can be set by user)
virtual QString getFrameName();
virtual const QString & getFrameName();
/// Set the Frame Unique identifyer
virtual void setFrameName(QString name);
/// Get the parent frame
virtual InterfaceFrame * getParentFrame();
/**
* Set the parent frame to the parameter frame.
* During the parent transition you have the choice to keep or not the frame transform.
......@@ -64,9 +64,9 @@ public:
* its transform's target frame changes.
* If you decide not to keep the initial frame's transfor, this one is updated during the parent transition in order
* to keep the original frame position (in the world frame).
*
*
* Caution: if the parent frame in parameter is either the current frame
* or one of its descendant, the parent frame is set to the world frame.
* or one of its descendant, the parent frame is set to the world frame.
*/
virtual void setParentFrame(InterfaceFrame * parent, bool keepTransform = true);
......@@ -75,13 +75,19 @@ public:
* The Frame hierarchy may not be the same as the Component Hierarchy.
*/
virtual const QVector<InterfaceFrame *> * getChildrenFrame();
/// Returns a vector containing the children and the children of children and etc.
/// of the current frame.
virtual QVector<InterfaceFrame *> * getDescendantsFrame();
/// Returns a vector containing the children and the children of children and etc.
/// of the current frame.
virtual QVector<InterfaceFrame *> * getDescendantsFrame();
/// Returns a vector containing names of the children and the children of children and etc.
/// of the current frame.
/// Note: as InterfaceFrame * are manipulated as different types(Frame*, even Component *) it is not
/// possible to compare objects with their pointer value. The frame name is something "more stable".
virtual QVector<QString *> * getDescendantsFrameName();
/** @} */
/**
* Transforms accessors / Modifyers
......@@ -95,18 +101,18 @@ public:
/// Get a COPY of the transformation with respect to another frame
virtual vtkSmartPointer<vtkTransform> getTransformFromFrame(InterfaceFrame * frame);
/**
* Sets the current frame position with respect to its parent Frame to
* Sets the current frame position with respect to its parent Frame to
* @transform parameter no matter its previous position.
*/
virtual void setTransformFromParent(vtkSmartPointer<vtkTransform> transform);
/**
/**
* Sets the current frame position equal to its parent position (to the world position if no parent.
*/
virtual void setTransformFromParentToIdentity();
/**
* Apply a translation relative to the current position
*/
......@@ -126,9 +132,9 @@ public:
* Apply an absolute rotation (the current rotation is replaced by the new rotation).
*/
virtual void setRotation(double aroundX, double aroundY, double aroundZ);
/** @} */
/**
* Gives the 3D representation of the frame (based on xyd arrows)
*/
......@@ -138,71 +144,71 @@ public:
* Set the Component Frame visible for a given viewer
*/
virtual void setFrameVisibility(Viewer * viewer, bool visible);
/**
* Get the Component Frame visibility for a given viewer
*/
virtual bool getFrameVisibility(Viewer * viewer);
/// When the current Frame is set to parent, it must update its children list
virtual void addFrameChild(InterfaceFrame * frame);
/**
* If the parent frame keeps track of its children, when a child is deleted
* it should warn its parent
*/
virtual void removeFrameChild(InterfaceFrame * frame);
///@{ Constructors helpers
/// When the current Frame is set to parent, it must update its children list
virtual void addFrameChild(InterfaceFrame * frame);
/**
* If the parent frame keeps track of its children, when a child is deleted
* it should warn its parent
*/
virtual void removeFrameChild(InterfaceFrame * frame);
///@{ Constructors helpers
/// Private method to initialize private attributes (called only in constrctors but in all constructors)
void initAttributes();
///@}
protected:
/**
/**
* Frame unique identifier
*/
QString frameName;
/**
/**
* The Parent Frame.
* If it is NULL, then the parent is the World Frame.
*/
InterfaceFrame * parentFrame;
InterfaceFrame * parentFrame;
/**
* Transformation to represent my points (expressed in my frame) in my parent's frame.
* Transformation to apply to this (and children) data to place them in my parent's frame.
*/
vtkSmartPointer<vtkTransform> transformParentToMe;
vtkSmartPointer<vtkTransform> transformParentToMe;
/**
* Transformation to represent my points (expressed in my frame) in the world's frame.
* i.e. Transformation to apply to this (and children) data to place them in the world's frame.
*
*
* This transformation is always re-calculated and stored only for convenience purpose.
* It can not be set by a user.
*/
vtkSmartPointer<vtkTransform> transformWorldToMe;
/**
* Transform Filter to store the transformation for the Frame's 3D representation.
*/
vtkSmartPointer<vtkTransformPolyDataFilter> representationTransformFilter;
/**
* List of children Frames to keep track of Frame hierarchy
*/
QVector<InterfaceFrame *> childrenFrame;
private:
/// To be able to give a default unique identyfier to each created frame
static int nbTotalFrames;
/// Geometric representation of the frame (vtkAxes)
vtkSmartPointer<vtkAxesActor> axes;
/// List of Viewers in which the frame is visible
QMap<Viewer *, bool> frameViewers;
......
......@@ -44,20 +44,20 @@ namespace camitk
{
class Viewer;
/**
* @ingroup group_sdk_libraries_core_component
*
* @brief
*
* @brief
* This class describe what are the methods to implement in order to manage a Component position in space.
*
*
* The Frame hierarchy is inspired from IGSTK hierarchy:
* - Each Frame knows its parent frame
* - Each Frame knows the transormation to its parent frame
*
* For hierachy display convenience, each Frame also knows its children frames.
*
*
*
* Ecah Component has a Frame, and each Frame belongs to only one Component.
* However, the Frame hierarchy may be different from the Component hierarchy (InterfaceNode).
*
......@@ -67,47 +67,54 @@ class InterfaceFrame {
public:
/// empty virtual destructor, to avoid memory leak
virtual ~InterfaceFrame() {};
/**
* Hierarchy accessors / Modifyers
* @{
*/
/// Get the Frame Unique identifyer (can be set by user)
virtual QString getFrameName() = 0;
virtual const QString & getFrameName() = 0;
/// Set the Frame Unique identifyer
virtual void setFrameName(QString name) = 0;
/// Get the parent frame
virtual InterfaceFrame * getParentFrame() = 0;
/// Set the parent frame and update or not its transform during the parent transition
virtual void setParentFrame(InterfaceFrame * parent, bool keepTransform = true) = 0;
/**
* Get the Children Frames from the current Frame in the Frame Hierarchy
* The Frame hierarchy may not be the same as the Component Hierarchy.
*/
virtual const QVector<InterfaceFrame *> * getChildrenFrame() = 0;
/// Returns a vector containing the children and the children of children and etc.
/// of the current frame.
virtual QVector<InterfaceFrame *> * getDescendantsFrame() = 0;
/// Returns a vector containing the children and the children of children and etc.
/// of the current frame.
virtual QVector<InterfaceFrame *> * getDescendantsFrame() = 0;
/// Returns a vector containing names of the children and the children of children and etc.
/// of the current frame.
/// Note: as InterfaceFrame * are manipulated as different types(Frame*, even Component *) it is not
/// possible to compare objects with their pointer value. The frame name is something "more stable".
virtual QVector<QString *> * getDescendantsFrameName() = 0;
/** @} */
/**
* Transforms accessors / Modifyers
* @{
*/
/// Get a the transformation with respect to the world frame
virtual const vtkSmartPointer<vtkTransform> getTransformFromWorld() = 0;
/// Get a the transformation with respect to the parent frame
virtual const vtkSmartPointer<vtkTransform> getTransformFromParent() = 0;