diff --git a/Modules/PlanarFigure/DataManagement/mitkPlanarFigure.cpp b/Modules/PlanarFigure/DataManagement/mitkPlanarFigure.cpp index a72e4c8176..a154ddedc7 100644 --- a/Modules/PlanarFigure/DataManagement/mitkPlanarFigure.cpp +++ b/Modules/PlanarFigure/DataManagement/mitkPlanarFigure.cpp @@ -1,596 +1,705 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2009-07-08 11:04:08 +0200 (Mi, 08 Jul 2009) $ Version: $Revision: 18029 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkPlanarFigure.h" #include "mitkGeometry2D.h" #include "mitkProperties.h" #include "algorithm" mitk::PlanarFigure::PlanarFigure() : m_FigurePlaced( false ), m_HoveringControlPointVisible( false ), m_SelectedControlPoint( -1 ), m_Geometry2D( NULL ), + m_PolyLineUpToDate(false), + m_HelperLinesUpToDate(false), + m_FeaturesUpToDate(false), m_FeaturesMTime( 0 ) { m_ControlPoints = VertexContainerType::New(); m_HoveringControlPoint = VertexContainerType::New(); m_PolyLines = VertexContainerVectorType::New(); m_HelperPolyLines = VertexContainerVectorType::New(); m_HelperPolyLinesToBePainted = BoolContainerType::New(); this->SetProperty( "closed", mitk::BoolProperty::New( false ) ); // Currently only single-time-step geometries are supported this->InitializeTimeSlicedGeometry( 1 ); } mitk::PlanarFigure::~PlanarFigure() { } void mitk::PlanarFigure::SetGeometry2D( mitk::Geometry2D *geometry ) { this->SetGeometry( geometry ); m_Geometry2D = geometry; } const mitk::Geometry2D *mitk::PlanarFigure::GetGeometry2D() const { return m_Geometry2D; } bool mitk::PlanarFigure::IsClosed() const { mitk::BoolProperty* closed = dynamic_cast< mitk::BoolProperty* >( this->GetProperty( "closed" ).GetPointer() ); if ( closed != NULL ) { return closed->GetValue(); } return false; } void mitk::PlanarFigure::PlaceFigure( const mitk::Point2D& point ) { for ( unsigned int i = 0; i < this->GetNumberOfControlPoints(); ++i ) { m_ControlPoints->InsertElement( i, this->ApplyControlPointConstraints( i, point ) ); m_NewControlPoints.push_back( point ); } m_FigurePlaced = true; m_SelectedControlPoint = 1; } bool mitk::PlanarFigure::AddControlPoint( const mitk::Point2D& point ) { if ( m_NumberOfControlPoints < this->GetMaximumNumberOfControlPoints() ) { m_ControlPoints->InsertElement( m_NumberOfControlPoints, this->ApplyControlPointConstraints( m_NumberOfControlPoints, point ) ); m_NewControlPoints.push_back( point ); ++m_NumberOfControlPoints; ++m_SelectedControlPoint; return true; } else { return false; } } bool mitk::PlanarFigure::SetControlPoint( unsigned int index, const Point2D& point, bool createIfDoesNotExist ) { + bool controlPointSetCorrectly = false; if (createIfDoesNotExist) { m_ControlPoints->InsertElement( index, this->ApplyControlPointConstraints( index, point ) ); if ( m_NumberOfControlPoints <= index ) { m_NewControlPoints.push_back( point ); m_NumberOfControlPoints = index + 1; } else { m_NewControlPoints.at( index ) = point; } - return true; + controlPointSetCorrectly = true; } else if ( index < m_NumberOfControlPoints ) { - m_NewControlPoints.at( index ) = point; m_ControlPoints->InsertElement( index, this->ApplyControlPointConstraints( index, point ) ); - return true; + m_NewControlPoints.at( index ) = point; + controlPointSetCorrectly = true; } - else + //else + //{ + // return false; + //} + + if ( controlPointSetCorrectly ) { - return false; + m_PolyLineUpToDate = false; + m_HelperLinesUpToDate = false; + m_FeaturesUpToDate = false; } + + return controlPointSetCorrectly; } bool mitk::PlanarFigure::SetCurrentControlPoint( const Point2D& point ) { if ( (m_SelectedControlPoint < 0) || (m_SelectedControlPoint >= (int)m_NumberOfControlPoints) ) { return false; } return this->SetControlPoint(m_SelectedControlPoint, point, false); } unsigned int mitk::PlanarFigure::GetNumberOfControlPoints() const { return m_NumberOfControlPoints; } bool mitk::PlanarFigure::SelectControlPoint( unsigned int index ) { if ( index < this->GetNumberOfControlPoints() ) { m_SelectedControlPoint = index; return true; } else { return false; } } void mitk::PlanarFigure::DeselectControlPoint() { m_SelectedControlPoint = -1; } void mitk::PlanarFigure::SetHoveringControlPoint( const Point2D& point ) { if ( m_HoveringControlPoint->Size() == 0 ) { m_HoveringControlPoint->InsertElement( 0, point ); } else { m_HoveringControlPoint->SetElement( 0, point ); } m_HoveringControlPointVisible = true; } void mitk::PlanarFigure::ResetHoveringContolPoint() { if ( m_HoveringControlPoint->Size() > 0 ) { m_HoveringControlPointVisible = false; m_HoveringControlPoint->DeleteIndex( 0 ); } } mitk::PlanarFigure::VertexContainerType::Pointer mitk::PlanarFigure::GetHoveringControlPoint() { return m_HoveringControlPoint; } bool mitk::PlanarFigure::IsHoveringControlPointVisible() { return m_HoveringControlPointVisible; } const mitk::PlanarFigure::VertexContainerType * mitk::PlanarFigure::GetControlPoints() const { return m_ControlPoints; } mitk::PlanarFigure::VertexContainerType * mitk::PlanarFigure::GetControlPoints() { return m_ControlPoints; } -mitk::Point2D& mitk::PlanarFigure::GetControlPoint( unsigned int index ) const +mitk::Point2D mitk::PlanarFigure::GetControlPoint( unsigned int index ) const { if ( index < m_NumberOfControlPoints ) { - return m_ControlPoints->ElementAt( index ); + //return m_ControlPoints->ElementAt( index ); + return m_NewControlPoints.at( index ); } itkExceptionMacro( << "GetControlPoint(): Invalid index!" ); } mitk::Point3D mitk::PlanarFigure::GetWorldControlPoint( unsigned int index ) const { Point3D point3D; if ( (m_Geometry2D != NULL) && (index < m_NumberOfControlPoints) ) { - m_Geometry2D->Map( m_ControlPoints->ElementAt( index ), point3D ); + //m_Geometry2D->Map( m_ControlPoints->ElementAt( index ), point3D ); + m_Geometry2D->Map( m_NewControlPoints.at( index ), point3D ); return point3D; } itkExceptionMacro( << "GetWorldControlPoint(): Invalid index!" ); } -mitk::PlanarFigure::VertexContainerType * +mitk::PlanarFigure::PolyLineType mitk::PlanarFigure::GetPolyLine(unsigned int index) { - if ( !m_PolyLines->IndexExists( index ) || (m_PolyLines->ElementAt( index )->GetMTime() < m_ControlPoints->GetMTime()) ) + mitk::PlanarFigure::PolyLineType polyLine; + if ( m_NewPolyLines.size() > index ) { - this->GeneratePolyLine(); + if ( !m_PolyLineUpToDate ) + { + this->GeneratePolyLine(); + m_PolyLineUpToDate = true; + } + + polyLine = m_NewPolyLines.at( index ); } - return m_PolyLines->ElementAt( index ); + return polyLine; + + //if ( !m_PolyLines->IndexExists( index ) || !m_PolyLineUpToDate ) // (m_PolyLines->ElementAt( index )->GetMTime() < m_ControlPoints->GetMTime()) ) + //{ + // this->GeneratePolyLine(); + // m_PolyLineUpToDate = true; + //} + + //return m_PolyLines->ElementAt( index ); } -const mitk::PlanarFigure::VertexContainerType * +const mitk::PlanarFigure::PolyLineType mitk::PlanarFigure::GetPolyLine(unsigned int index) const { - return m_PolyLines->ElementAt( index ); + return m_NewPolyLines.at( index ); + //return m_PolyLines->ElementAt( index ); } -const mitk::PlanarFigure::VertexContainerType * -mitk::PlanarFigure::GetHelperPolyLine(unsigned int index, double mmPerDisplayUnit, unsigned int displayHeight) +//const mitk::PlanarFigure::VertexContainerType * +//mitk::PlanarFigure::GetHelperPolyLine(unsigned int index, double mmPerDisplayUnit, unsigned int displayHeight) +//{ +// if ((m_HelperPolyLines->ElementAt( index )) && !m_HelperLinesUpToDate ) //(m_HelperPolyLines->ElementAt( index )->GetMTime() < m_ControlPoints->GetMTime()) ) +// { +// this->GenerateHelperPolyLine(mmPerDisplayUnit, displayHeight); +// m_HelperLinesUpToDate = true; +// } +// +// return m_HelperPolyLines->ElementAt( index ); +//} + +const mitk::PlanarFigure::PolyLineType mitk::PlanarFigure::GetHelperPolyLine( unsigned int index, double mmPerDisplayUnit, unsigned int displayHeight ) { - if ((m_HelperPolyLines->ElementAt( index )) && (m_HelperPolyLines->ElementAt( index )->GetMTime() < m_ControlPoints->GetMTime()) ) + mitk::PlanarFigure::PolyLineType helperPolyLine; + if ( index < m_NewHelperPolyLines.size() ) { - this->GenerateHelperPolyLine(mmPerDisplayUnit, displayHeight); + if ( !m_HelperLinesUpToDate ) + { + this->GenerateHelperPolyLine(mmPerDisplayUnit, displayHeight); + m_HelperLinesUpToDate = true; + } + + helperPolyLine = m_NewHelperPolyLines.at(index); } - return m_HelperPolyLines->ElementAt( index ); + return helperPolyLine; + + //if ((m_HelperPolyLines->ElementAt( index )) && !m_HelperLinesUpToDate ) //(m_HelperPolyLines->ElementAt( index )->GetMTime() < m_ControlPoints->GetMTime()) ) + //{ + // this->GenerateHelperPolyLine(mmPerDisplayUnit, displayHeight); + // m_HelperLinesUpToDate = true; + //} + + //return m_HelperPolyLines->ElementAt( index ); + } /** \brief Returns the number of features available for this PlanarFigure * (such as, radius, area, ...). */ unsigned int mitk::PlanarFigure::GetNumberOfFeatures() const { return m_Features.size(); } const char *mitk::PlanarFigure::GetFeatureName( unsigned int index ) const { if ( index < m_Features.size() ) { return m_Features[index].Name.c_str(); } else { return NULL; } } const char *mitk::PlanarFigure::GetFeatureUnit( unsigned int index ) const { if ( index < m_Features.size() ) { return m_Features[index].Unit.c_str(); } else { return NULL; } } double mitk::PlanarFigure::GetQuantity( unsigned int index ) const { if ( index < m_Features.size() ) { return m_Features[index].Quantity; } else { return 0.0; } } bool mitk::PlanarFigure::IsFeatureActive( unsigned int index ) const { if ( index < m_Features.size() ) { return m_Features[index].Active; } else { return false; } } void mitk::PlanarFigure::EvaluateFeatures() { - if ( m_FeaturesMTime < m_ControlPoints->GetMTime() ) + if ( !m_FeaturesUpToDate ) //m_FeaturesMTime < m_ControlPoints->GetMTime() ) { this->EvaluateFeaturesInternal(); - - m_FeaturesMTime = m_ControlPoints->GetMTime(); + + m_FeaturesUpToDate = true; + //m_FeaturesMTime = m_ControlPoints->GetMTime(); } } void mitk::PlanarFigure::UpdateOutputInformation() { // Bounds are NOT calculated here, since the Geometry2D defines a fixed // frame (= bounds) for the planar figure. Superclass::UpdateOutputInformation(); this->GetTimeSlicedGeometry()->UpdateInformation(); } void mitk::PlanarFigure::SetRequestedRegionToLargestPossibleRegion() { } bool mitk::PlanarFigure::RequestedRegionIsOutsideOfTheBufferedRegion() { return false; } bool mitk::PlanarFigure::VerifyRequestedRegion() { return true; } void mitk::PlanarFigure::SetRequestedRegion( itk::DataObject * /*data*/ ) { } void mitk::PlanarFigure::ResetNumberOfControlPoints( int numberOfControlPoints ) { m_NumberOfControlPoints = numberOfControlPoints; } mitk::Point2D mitk::PlanarFigure::ApplyControlPointConstraints( unsigned int /*index*/, const Point2D& point ) { if ( m_Geometry2D == NULL ) { return point; } Point2D indexPoint; m_Geometry2D->WorldToIndex( point, indexPoint ); BoundingBox::BoundsArrayType bounds = m_Geometry2D->GetBounds(); if ( indexPoint[0] < bounds[0] ) { indexPoint[0] = bounds[0]; } if ( indexPoint[0] > bounds[1] ) { indexPoint[0] = bounds[1]; } if ( indexPoint[1] < bounds[2] ) { indexPoint[1] = bounds[2]; } if ( indexPoint[1] > bounds[3] ) { indexPoint[1] = bounds[3]; } Point2D constrainedPoint; m_Geometry2D->IndexToWorld( indexPoint, constrainedPoint ); return constrainedPoint; } unsigned int mitk::PlanarFigure::AddFeature( const char *featureName, const char *unitName ) { unsigned int index = m_Features.size(); Feature newFeature( featureName, unitName ); m_Features.push_back( newFeature ); return index; } void mitk::PlanarFigure::SetFeatureName( unsigned int index, const char *featureName ) { if ( index < m_Features.size() ) { m_Features[index].Name = featureName; } } void mitk::PlanarFigure::SetFeatureUnit( unsigned int index, const char *unitName ) { if ( index < m_Features.size() ) { m_Features[index].Unit = unitName; } } void mitk::PlanarFigure::SetQuantity( unsigned int index, double quantity ) { if ( index < m_Features.size() ) { m_Features[index].Quantity = quantity; } } void mitk::PlanarFigure::ActivateFeature( unsigned int index ) { if ( index < m_Features.size() ) { m_Features[index].Active = true; } } void mitk::PlanarFigure::DeactivateFeature( unsigned int index ) { if ( index < m_Features.size() ) { m_Features[index].Active = false; } } void mitk::PlanarFigure::InitializeTimeSlicedGeometry( unsigned int timeSteps ) { mitk::TimeSlicedGeometry::Pointer timeGeometry = this->GetTimeSlicedGeometry(); mitk::Geometry2D::Pointer geometry2D = mitk::Geometry2D::New(); geometry2D->Initialize(); if ( timeSteps > 1 ) { mitk::ScalarType timeBounds[] = {0.0, 1.0}; geometry2D->SetTimeBounds( timeBounds ); } // The geometry is propagated automatically to all time steps, // if EvenlyTimed is true... timeGeometry->InitializeEvenlyTimed( geometry2D, timeSteps ); } void mitk::PlanarFigure::PrintSelf( std::ostream& os, itk::Indent indent) const { Superclass::PrintSelf( os, indent ); os << indent << this->GetNameOfClass() << ":\n"; if (this->IsClosed()) os << indent << "This figure is closed\n"; else os << indent << "This figure is not closed\n"; os << indent << "Minimum number of control points: " << this->GetMinimumNumberOfControlPoints() << std::endl; os << indent << "Maximum number of control points: " << this->GetMaximumNumberOfControlPoints() << std::endl; os << indent << "Current number of control points: " << this->GetNumberOfControlPoints() << std::endl; os << indent << "Control points:" << std::endl; mitk::PlanarFigure::VertexContainerType::ConstIterator it; for ( unsigned int i = 0; i < this->GetNumberOfControlPoints(); ++i ) { os << indent.GetNextIndent() << i << ": " << m_ControlPoints->ElementAt( i ) << std::endl; + os << indent.GetNextIndent() << i << ": " << m_NewControlPoints.at( i ) << std::endl; } os << indent << "Geometry:\n"; this->GetGeometry2D()->Print(os, indent.GetNextIndent()); } unsigned short mitk::PlanarFigure::GetPolyLinesSize() { - if ( m_PolyLines->GetMTime() < m_ControlPoints->GetMTime() ) + if ( !m_PolyLineUpToDate ) //m_PolyLines->GetMTime() < m_ControlPoints->GetMTime() ) { this->GeneratePolyLine(); + m_PolyLineUpToDate = true; } - return m_PolyLines->size(); + return m_NewPolyLines.size(); + //return m_PolyLines->size(); } unsigned short mitk::PlanarFigure::GetHelperPolyLinesSize() { - return m_HelperPolyLines->size(); + return m_NewHelperPolyLines.size(); + //return m_HelperPolyLines->size(); } bool mitk::PlanarFigure::IsHelperToBePainted(unsigned int index) { return m_HelperPolyLinesToBePainted->GetElement( index ); } bool mitk::PlanarFigure::ResetOnPointSelect() { return false; } void mitk::PlanarFigure::RemoveControlPoint( unsigned int index ) { - if ( index > m_NumberOfControlPoints ) + if ( index > m_NewControlPoints.size() ) return; - if ( (m_NumberOfControlPoints -1) < this->GetMinimumNumberOfControlPoints() ) + if ( (m_NewControlPoints.size() -1) < this->GetMinimumNumberOfControlPoints() ) return; - typedef std::vector vectortype; - vectortype vector = m_ControlPoints->CastToSTLContainer(); - vectortype::iterator iter; + ControlPointListType::iterator iter; + iter = m_NewControlPoints.begin() + index; - iter = std::find( vector.begin(), vector.end(), vector.at(index) ); - //vector.erase( iter ); + m_NewControlPoints.erase( iter ); - if ( iter != vector.end() ) - { - m_ControlPoints->erase( iter ); - m_NumberOfControlPoints--; - } + m_PolyLineUpToDate = false; + m_HelperLinesUpToDate = false; + m_FeaturesUpToDate = false; + + //if ( iter != vector.end() ) + //{ + // m_ControlPoints->erase( iter ); + // m_NumberOfControlPoints--; + //} //if ( m_ControlPoints->Size() < m_NumberOfControlPoints ) //{ //} } void mitk::PlanarFigure::RemoveLastControlPoint() { - m_ControlPoints->DeleteIndex( this->GetNumberOfControlPoints()-1 ); - this->ResetNumberOfControlPoints( this->GetNumberOfControlPoints()-1 ); - this->GeneratePolyLine(); + RemoveControlPoint( m_NewControlPoints.size()-1 ); + + //m_ControlPoints->DeleteIndex( this->GetNumberOfControlPoints()-1 ); + //this->ResetNumberOfControlPoints( this->GetNumberOfControlPoints()-1 ); + //this->GeneratePolyLine(); } void mitk::PlanarFigure::DeepCopy(Self::Pointer oldFigure) { //DeepCopy only same types of planar figures //Notice to get typeid polymorph you have to use the *operator if(typeid(*oldFigure) != typeid(*this)) { itkExceptionMacro( << "DeepCopy(): Inconsistent type of source and destination figure!" ); return; } // clone base data members SetPropertyList(oldFigure->GetPropertyList()->Clone()); /// deep copy members m_FigurePlaced = oldFigure->m_FigurePlaced; m_SelectedControlPoint = oldFigure->m_SelectedControlPoint; m_FeaturesMTime = oldFigure->m_FeaturesMTime; m_Features = oldFigure->m_Features; m_NumberOfControlPoints = oldFigure->m_NumberOfControlPoints; //copy geometry 2D of planar figure SetGeometry2D((mitk::Geometry2D*)oldFigure->m_Geometry2D->Clone().GetPointer()); m_ControlPoints = VertexContainerType::New(); for(unsigned long index=0; index < oldFigure->m_ControlPoints->Size(); index++) { m_ControlPoints->InsertElement(index, oldFigure->m_ControlPoints->ElementAt( index )); } //After setting the control points we can generate the polylines this->GeneratePolyLine(); } + +void mitk::PlanarFigure::SetNumberOfPolyLines( unsigned int numberOfPolyLines ) +{ + m_NewPolyLines.resize(numberOfPolyLines); +} + +void mitk::PlanarFigure::SetNumberOfHelperPolyLines( unsigned int numberOfHerlperPolyLines ) +{ + m_NewHelperPolyLines.resize(numberOfHerlperPolyLines); +} + + +void mitk::PlanarFigure::AppendPointToPolyLine( unsigned int index, PolyLineElement element ) +{ + m_NewPolyLines.at( index ).push_back( element ); +} + +void mitk::PlanarFigure::AppendPointToHelperPolyLine( unsigned int index, PolyLineElement element ) +{ + m_NewHelperPolyLines.at( index ).push_back( element ); +} + + +mitk::PlanarFigure::PolyLineType::const_iterator mitk::PlanarFigure::GetFirstElementOfPolyLine( unsigned int index ) const +{ + return m_NewPolyLines.at( index ).begin(); +} + +mitk::PlanarFigure::PolyLineType::const_iterator mitk::PlanarFigure::GetLastElementOfPolyLine( unsigned int index ) const +{ + return m_NewPolyLines.at( index ).end(); +} + +const mitk::PlanarFigure::PolyLineType mitk::PlanarFigure::GetPolyline( int index ) const +{ + return m_NewPolyLines.at( index ); +} + +//ControlPointListType::const_iterator mitk::PlanarFigure::GetSelectedControlPoint() const +//{ +// return m_NewControlPoints.begin(); +//} \ No newline at end of file diff --git a/Modules/PlanarFigure/DataManagement/mitkPlanarFigure.h b/Modules/PlanarFigure/DataManagement/mitkPlanarFigure.h index e143321a98..8362a52461 100644 --- a/Modules/PlanarFigure/DataManagement/mitkPlanarFigure.h +++ b/Modules/PlanarFigure/DataManagement/mitkPlanarFigure.h @@ -1,360 +1,385 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2009-05-13 18:06:46 +0200 (Mi, 13 Mai 2009) $ Version: $Revision: 17258 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef _MITK_PLANAR_FIGURE_H_ #define _MITK_PLANAR_FIGURE_H_ #include "PlanarFigureExports.h" #include "mitkBaseData.h" #include "mitkCommon.h" #include namespace mitk { class Geometry2D; /** * \brief Base-class for geometric planar (2D) figures, such as * lines, circles, rectangles, polygons, etc. * * \warning Currently does not support time-resolved data handling * * Behavior and appearance of PlanarFigures are controlled by various properties; for a detailed * list of appearance properties see mitk::PlanarFigureMapper2D * * The following properties control general PlanarFigure behavior: * * * * * TODO: Implement local 2D transform (including center of rotation...) * */ class PlanarFigure_EXPORT PlanarFigure : public BaseData { public: mitkClassMacro( PlanarFigure, BaseData ); struct PolyLineElement { PolyLineElement( Point2D point, int index ) : Point( point ), Index( index ) { }; Point2D Point; int Index; bool IsToBePainted; }; typedef itk::VectorContainer< unsigned long, mitk::Point2D > VertexContainerType; typedef itk::VectorContainer< unsigned long, VertexContainerType::Pointer> VertexContainerVectorType; typedef itk::VectorContainer< unsigned long, bool> BoolContainerType; typedef std::deque< Point2D > ControlPointListType; typedef std::list< PolyLineElement > PolyLineType; /** \brief Sets the 2D geometry on which this figure will be placed. * * In most cases, this is a Geometry already owned by another object, e.g. * describing the slice of the image on which measurements will be * performed. */ virtual void SetGeometry2D( mitk::Geometry2D *geometry ); /** \brief Returns (previously set) 2D geometry of this figure. */ virtual const Geometry2D *GetGeometry2D() const; /** \brief True if the planar figure is closed. * * Default is false. The "closed" boolean property must be set in sub-classes. */ virtual bool IsClosed() const; /** \brief True if the planar figure has been placed (and can be * displayed/interacted with). */ virtual bool IsPlaced() const { return m_FigurePlaced; }; /** \brief Place figure at the given point (in 2D index coordinates) onto * the given 2D geometry. * * By default, the first two control points of the figure are set to the * passed point. Further points can be set via AddControlPoint(), if the * current number of control points is below the maximum number of control * points. * * Can be re-implemented in sub-classes as needed. */ virtual void PlaceFigure( const Point2D& point ); virtual bool AddControlPoint( const Point2D& point ); virtual bool SetControlPoint( unsigned int index, const Point2D& point, bool createIfDoesNotExist = false); virtual bool SetCurrentControlPoint( const Point2D& point ); /** \brief Returns the current number of 2D control points defining this figure. */ unsigned int GetNumberOfControlPoints() const; /** \brief Returns the minimum number of control points needed to represent * this figure. * * Must be implemented in sub-classes. */ virtual unsigned int GetMinimumNumberOfControlPoints() const = 0; /** \brief Returns the maximum number of control points allowed for * this figure (e.g. 3 for triangles). * * Must be implemented in sub-classes. */ virtual unsigned int GetMaximumNumberOfControlPoints() const = 0; /** \brief Selects currently active control points. */ virtual bool SelectControlPoint( unsigned int index ); /** \brief Deselect control point; no control point active. */ virtual void DeselectControlPoint(); /** \brief Return currently selected control point. */ virtual int GetSelectedControlPoint() const { return m_SelectedControlPoint; } + //ControlPointListType::const_iterator GetSelectedControlPoint() const; /** \brief Returns 2D control points vector. */ const VertexContainerType *GetControlPoints() const; /** \brief Returns 2D control points vector. */ VertexContainerType *GetControlPoints(); /** \brief Returns specified control point in 2D world coordinates. */ - Point2D& GetControlPoint( unsigned int index ) const; + Point2D GetControlPoint( unsigned int index ) const; /** \brief Returns specified control point in world coordinates. */ Point3D GetWorldControlPoint( unsigned int index ) const; + void SetNumberOfPolyLines( unsigned int numberOfPolyLines ); + void SetNumberOfHelperPolyLines( unsigned int numberOfHelperPolyLines ); + + void AppendPointToPolyLine( unsigned int index, PolyLineElement element ); + void AppendPointToHelperPolyLine( unsigned int index, PolyLineElement element ); + + const PolyLineType GetPolyline( int index ) const; + + PolyLineType::const_iterator GetFirstElementOfPolyLine( unsigned int index ) const; + PolyLineType::const_iterator GetLastElementOfPolyLine( unsigned int index ) const; + /** \brief Returns the polyline representing the planar figure * (for rendering, measurements, etc.). */ - VertexContainerType *GetPolyLine(unsigned int index); + PolyLineType GetPolyLine(unsigned int index); /** \brief Returns the polyline representing the planar figure - * (for rendering, measurements, etc.). */ - const VertexContainerType *GetPolyLine(unsigned int index) const; + * (for rendering, measurments, etc.). */ + const PolyLineType GetPolyLine(unsigned int index) const; /** \brief Returns the polyline that should be drawn the same size at every scale * (for text, angles, etc.). */ - const VertexContainerType *GetHelperPolyLine(unsigned int index, double mmPerDisplayUnit, unsigned int displayHeight); + //const VertexContainerType *GetHelperPolyLine(unsigned int index, double mmPerDisplayUnit, unsigned int displayHeight); + const mitk::PlanarFigure::PolyLineType GetHelperPolyLine( unsigned int index, double mmPerDisplayUnit, unsigned int displayHeight ); + + /** \brief Returns the number of features available for this PlanarFigure * (such as, radius, area, ...). */ virtual unsigned int GetNumberOfFeatures() const; /** \brief Returns the name (identifier) of the specified features. */ const char *GetFeatureName( unsigned int index ) const; /** \brief Returns the physical unit of the specified features. */ const char *GetFeatureUnit( unsigned int index ) const; /** Returns quantity of the specified feature (e.g., length, radius, * area, ... ) */ double GetQuantity( unsigned int index ) const; /** \brief Returns true if the feature with the specified index exists and * is active (an inactive feature may e.g. be the area of a non-closed * polygon. */ bool IsFeatureActive( unsigned int index ) const; /** \brief Calculates quantities of all features of this planar figure. */ virtual void EvaluateFeatures(); /** \brief Intherited from parent */ virtual void UpdateOutputInformation(); /** \brief Intherited from parent */ virtual void SetRequestedRegionToLargestPossibleRegion(); /** \brief Intherited from parent */ virtual bool RequestedRegionIsOutsideOfTheBufferedRegion(); /** \brief Intherited from parent */ virtual bool VerifyRequestedRegion(); /** \brief Intherited from parent */ virtual void SetRequestedRegion(itk::DataObject *data); /** \brief Returns the current number of polylines */ virtual unsigned short GetPolyLinesSize(); /** \brief Returns the current number of helperpolylines */ virtual unsigned short GetHelperPolyLinesSize(); /** \brief Returns whether a helper polyline should be painted or not */ virtual bool IsHelperToBePainted(unsigned int index); /** \brief Returns true if the planar figure is reset to "add points" mode * when a point is selected. * * Default return value is false. Subclasses can overwrite this method and * execute any reset / initialization statements required. */ virtual bool ResetOnPointSelect(); virtual void RemoveControlPoint( unsigned int index ); /** \brief Removes last control point */ virtual void RemoveLastControlPoint(); /** \brief Copies contents and state of a figre provided as parameter to the current object. Requires a matching type of both figures. */ void DeepCopy(Self::Pointer oldFigure); void SetHoveringControlPoint( const Point2D& point ); void ResetHoveringContolPoint(); bool IsHoveringControlPointVisible(); mitk::PlanarFigure::VertexContainerType::Pointer GetHoveringControlPoint(); protected: PlanarFigure(); virtual ~PlanarFigure(); /** \brief Set the initial number of control points of the planar figure */ void ResetNumberOfControlPoints( int numberOfControlPoints ); /** \brief Allow sub-classes to apply constraints on control points. * * Sub-classes can define spatial constraints to certain control points by * overwriting this method and returning a constrained point. By default, * the points are constrained by the image bounds. */ virtual Point2D ApplyControlPointConstraints( unsigned int /*index*/, const Point2D& point ); /** Adds feature (e.g., circumference, radius, angle, ...) to feature vector * of a planar figure object and returns integer ID for the feature element. * Should be called in sub-class constructors. */ virtual unsigned int AddFeature( const char *featureName, const char *unitName ); /** Sets the name of the specified feature. INTERNAL METHOD. */ void SetFeatureName( unsigned int index, const char *featureName ); /** Sets the physical unit of the specified feature. INTERNAL METHOD. */ void SetFeatureUnit( unsigned int index, const char *unitName ); /** Sets quantity of the specified feature. INTERNAL METHOD. */ void SetQuantity( unsigned int index, double quantity ); /** Sets the specified feature as active. INTERAL METHOD. */ void ActivateFeature( unsigned int index ); /** Sets the specified feature as active. INTERAL METHOD. */ void DeactivateFeature( unsigned int index ); /** \brief Generates the poly-line representation of the planar figure. * Must be implemented in sub-classes. */ virtual void GeneratePolyLine() = 0; /** \brief Generates the poly-lines that should be drawn the same size regardless of zoom. * Must be implemented in sub-classes. */ virtual void GenerateHelperPolyLine(double mmPerDisplayUnit, unsigned int displayHeight) = 0; /** \brief Calculates quantities of all features of this planar figure. * Must be implemented in sub-classes. */ virtual void EvaluateFeaturesInternal() = 0; /** \brief Initializes the TimeSlicedGeometry describing the (time-resolved) * geometry of this figure. Note that each time step holds one Geometry2D. */ virtual void InitializeTimeSlicedGeometry( unsigned int timeSteps = 1 ); virtual void PrintSelf( std::ostream& os, itk::Indent indent ) const; - + VertexContainerType::Pointer m_ControlPoints; unsigned int m_NumberOfControlPoints; VertexContainerType::Pointer m_HoveringControlPoint; VertexContainerVectorType::Pointer m_PolyLines; VertexContainerVectorType::Pointer m_HelperPolyLines; BoolContainerType::Pointer m_HelperPolyLinesToBePainted; + + + bool m_FigurePlaced; bool m_HoveringControlPointVisible; // Currently selected control point; -1 means no point selected int m_SelectedControlPoint; + ControlPointListType m_NewControlPoints; private: struct Feature { Feature( const char *name, const char *unit ) : Name( name ), Unit( unit ), Quantity( 0.0 ), Active( true ) { }; std::string Name; std::string Unit; double Quantity; bool Active; }; Geometry2D *m_Geometry2D; - ControlPointListType m_NewControlPoints; - PolyLineType m_NewPolyLine; + std::vector m_NewPolyLines; + std::vector m_NewHelperPolyLines; + + + bool m_ControlPointsModified; + bool m_PolyLineUpToDate; + bool m_HelperLinesUpToDate; + bool m_FeaturesUpToDate; // Vector of features available for this geometric figure typedef std::vector< Feature > FeatureVectorType; FeatureVectorType m_Features; unsigned long m_FeaturesMTime; }; } // namespace mitk #endif //_MITK_PLANAR_FIGURE_H_