diff --git a/Core/Code/Rendering/mitkPointSetGLMapper2D.cpp b/Core/Code/Rendering/mitkPointSetGLMapper2D.cpp new file mode 100644 index 0000000000..791f062ec2 --- /dev/null +++ b/Core/Code/Rendering/mitkPointSetGLMapper2D.cpp @@ -0,0 +1,524 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#include "mitkPointSetGLMapper2D.h" +#include "mitkPointSet.h" +#include "mitkPlaneGeometry.h" +#include "mitkColorProperty.h" +#include "mitkProperties.h" +#include "vtkLinearTransform.h" +#include "mitkStringProperty.h" +#include "mitkPointSet.h" +#include "mitkVtkPropRenderer.h" +#include "mitkGL.h" + +//const float selectedColor[]={1.0,0.0,0.6}; //for selected! + + +mitk::PointSetGLMapper2D::PointSetGLMapper2D() +: m_Polygon(false), + m_ShowPoints(true), + m_ShowDistances(false), + m_DistancesDecimalDigits(1), + m_ShowAngles(false), + m_ShowDistantLines(true), + m_LineWidth(1) +{ +} + + +mitk::PointSetGLMapper2D::~PointSetGLMapper2D() +{ +} + + +const mitk::PointSet *mitk::PointSetGLMapper2D::GetInput(void) +{ + return static_cast ( GetDataNode()->GetData() ); +} + + +void mitk::PointSetGLMapper2D::ApplyAllProperties(mitk::BaseRenderer* renderer) +{ + GLMapper::ApplyColorAndOpacityProperties( renderer ); + + const mitk::DataNode* node=GetDataNode(); + if( node == NULL ) + return; + + node->GetBoolProperty("show contour", m_Polygon); + node->GetBoolProperty("close contour", m_PolygonClosed); + node->GetBoolProperty("show points", m_ShowPoints); + node->GetBoolProperty("show distances", m_ShowDistances); + node->GetIntProperty("distance decimal digits", m_DistancesDecimalDigits); + node->GetBoolProperty("show angles", m_ShowAngles); + node->GetBoolProperty("show distant lines", m_ShowDistantLines); + node->GetIntProperty("line width", m_LineWidth); + node->GetIntProperty("point line width", m_PointLineWidth); + node->GetIntProperty("point 2D size", m_Point2DSize); +} + + + +static bool makePerpendicularVector2D(const mitk::Vector2D& in, mitk::Vector2D& out) +{ + if((fabs(in[0])>0) && ( (fabs(in[0])>fabs(in[1])) || (in[1] == 0) ) ) + { + out[0]=-in[1]/in[0]; + out[1]=1; + out.Normalize(); + return true; + } + else + if(fabs(in[1])>0) + { + out[0]=1; + out[1]=-in[0]/in[1]; + out.Normalize(); + return true; + } + else + return false; +} + + +void mitk::PointSetGLMapper2D::Paint( mitk::BaseRenderer *renderer ) +{ + + const mitk::DataNode* node=GetDataNode(); + if( node == NULL ) + return; + + const int text2dDistance = 10; + + bool visible = true; + GetDataNode()->GetVisibility(visible, renderer, "visible"); + if ( !visible) return; + + // @FIXME: Logik fuer update + bool updateNeccesary=true; + + if (updateNeccesary) + { + // ok, das ist aus GenerateData kopiert + mitk::PointSet::Pointer input = const_cast(this->GetInput()); + + // Get the TimeSlicedGeometry of the input object + const TimeSlicedGeometry* inputTimeGeometry = input->GetTimeSlicedGeometry(); + if (( inputTimeGeometry == NULL ) || ( inputTimeGeometry->GetTimeSteps() == 0 ) ) + { + return; + } + + // + // get the world time + // + const Geometry2D* worldGeometry = renderer->GetCurrentWorldGeometry2D(); + assert( worldGeometry != NULL ); + ScalarType time = worldGeometry->GetTimeBounds()[ 0 ]; + + // + // convert the world time in time steps of the input object + // + int timeStep=0; + if ( time > ScalarTypeNumericTraits::NonpositiveMin() ) + timeStep = inputTimeGeometry->MSToTimeStep( time ); + if ( inputTimeGeometry->IsValidTime( timeStep ) == false ) + { + return; + } + + + mitk::PointSet::DataType::Pointer itkPointSet = input->GetPointSet( timeStep ); + + if ( itkPointSet.GetPointer() == NULL) + { + return; + } + + + mitk::DisplayGeometry::Pointer displayGeometry = renderer->GetDisplayGeometry(); + + assert(displayGeometry.IsNotNull()); + + //apply color and opacity read from the PropertyList + this->ApplyAllProperties(renderer); + + vtkLinearTransform* transform = GetDataNode()->GetVtkTransform(); + + //List of the Points + PointSet::DataType::PointsContainerConstIterator it, end; + it = itkPointSet->GetPoints()->Begin(); + end = itkPointSet->GetPoints()->End(); + + //iterator on the additional data of each point + PointSet::DataType::PointDataContainerIterator selIt, selEnd; + bool pointDataBroken = (itkPointSet->GetPointData()->Size() != itkPointSet->GetPoints()->Size()); + selIt = itkPointSet->GetPointData()->Begin(); + selEnd = itkPointSet->GetPointData()->End(); + + int counter = 0; + + //for writing text + int j = 0; + + //for switching back to old color after using selected color + float recallColor[4]; + glGetFloatv(GL_CURRENT_COLOR,recallColor); + + //get the properties for coloring the points + float unselectedColor[4] = {1.0, 1.0, 0.0, 1.0};//yellow + //check if there is an unselected property + if (dynamic_cast(node->GetPropertyList(renderer)->GetProperty("unselectedcolor")) != NULL) + { + mitk::Color tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("unselectedcolor"))->GetValue(); + unselectedColor[0] = tmpColor[0]; + unselectedColor[1] = tmpColor[1]; + unselectedColor[2] = tmpColor[2]; + unselectedColor[3] = 1.0f; //!!define a new ColorProp to be able to pass alpha value + } + else if (dynamic_cast(node->GetPropertyList(NULL)->GetProperty("unselectedcolor")) != NULL) + { + mitk::Color tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("unselectedcolor"))->GetValue(); + unselectedColor[0] = tmpColor[0]; + unselectedColor[1] = tmpColor[1]; + unselectedColor[2] = tmpColor[2]; + unselectedColor[3] = 1.0f; //!!define a new ColorProp to be able to pass alpha value + } + else + { + //get the color from the dataNode + node->GetColor(unselectedColor, NULL); + } + + //get selected property + float selectedColor[4] = {1.0, 0.0, 0.6, 1.0}; + if (dynamic_cast(node->GetPropertyList(renderer)->GetProperty("selectedcolor")) != NULL) + { + mitk::Color tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("selectedcolor"))->GetValue(); + selectedColor[0] = tmpColor[0]; + selectedColor[1] = tmpColor[1]; + selectedColor[2] = tmpColor[2]; + selectedColor[3] = 1.0f; + } + else if (dynamic_cast(node->GetPropertyList(NULL)->GetProperty("selectedcolor")) != NULL) + { + mitk::Color tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("selectedcolor"))->GetValue(); + selectedColor[0] = tmpColor[0]; + selectedColor[1] = tmpColor[1]; + selectedColor[2] = tmpColor[2]; + selectedColor[3] = 1.0f; + } + + //check if there is an pointLineWidth property + if (dynamic_cast(node->GetPropertyList(renderer)->GetProperty("point line width")) != NULL) + { + m_PointLineWidth = dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("point line width"))->GetValue(); + } + else if (dynamic_cast(node->GetPropertyList(NULL)->GetProperty("point line width")) != NULL) + { + m_PointLineWidth = dynamic_cast(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("point line width"))->GetValue(); + } + + //check if there is an point 2D size property + if (dynamic_cast(node->GetPropertyList(renderer)->GetProperty("point 2D size")) != NULL) + { + m_Point2DSize = dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("point 2D size"))->GetValue(); + } + else if (dynamic_cast(node->GetPropertyList(NULL)->GetProperty("point 2D size")) != NULL) + { + m_Point2DSize = dynamic_cast(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("point 2D size"))->GetValue(); + } + + Point3D p; // currently visited point + Point3D lastP; // last visited point + Vector3D vec; // p - lastP + Vector3D lastVec; // lastP - point before lastP + vec.Fill(0); + + mitk::Point3D projected_p; // p projected on viewplane + + Point2D pt2d; // projected_p in display coordinates + Point2D lastPt2d; // last projected_p in display coordinates + Point2D preLastPt2d;// projected_p in display coordinates before lastPt2d + + Point2D lastPt2DInPointSet; // The last point in the pointset in display coordinates + mitk::PointSet::DataType::PointType plob; + plob.Fill(0); + itkPointSet->GetPoint( itkPointSet->GetNumberOfPoints()-1, &plob); + + //map lastPt2DInPointSet to display coordinates + float vtkp[3]; + + itk2vtk(plob, vtkp); + transform->TransformPoint(vtkp, vtkp); + vtk2itk(vtkp,p); + + displayGeometry->Project(p, projected_p); + + displayGeometry->Map(projected_p, lastPt2DInPointSet); + displayGeometry->WorldToDisplay(lastPt2DInPointSet, lastPt2DInPointSet); + + while(it!=end) // iterate over all points + { + lastP = p; // valid only for counter > 0 + lastVec = vec; // valid only for counter > 1 + + preLastPt2d = lastPt2d; // valid only for counter > 1 + lastPt2d = pt2d; // valid only for counter > 0 + + + itk2vtk(it->Value(), vtkp); + transform->TransformPoint(vtkp, vtkp); + vtk2itk(vtkp,p); + + vec = p-lastP; // valid only for counter > 0 + + displayGeometry->Project(p, projected_p); + Vector3D diff=p-projected_p; + ScalarType scalardiff = diff.GetSquaredNorm(); + + //MouseOrientation + bool isInputDevice=false; + + bool isRendererSlice = scalardiff < 0.00001; //cause roundoff error + if(this->GetDataNode()->GetBoolProperty("inputdevice",isInputDevice) && isInputDevice && !isRendererSlice ) + { + displayGeometry->Map(projected_p, pt2d); + displayGeometry->WorldToDisplay(pt2d, pt2d); + + //Point size depending of distance to slice + /*float p_size = (1/scalardiff)*10*m_Point2DSize; + if(p_size < m_Point2DSize * 0.6 ) + p_size = m_Point2DSize * 0.6 ; + else if ( p_size > m_Point2DSize ) + p_size = m_Point2DSize;*/ + float p_size = (1/scalardiff)*100.0; + if(p_size < 6.0 ) + p_size = 6.0 ; + else if ( p_size > 10.0 ) + p_size = 10.0; + + //draw Point + float opacity = (p_size<8)?0.3:1.0;//don't get the opacity from the node? Feature not a bug! Otehrwise the 2D cross is hardly seen. + glColor4f(unselectedColor[0],unselectedColor[1],unselectedColor[2],opacity); + glPointSize(p_size); + //glShadeModel(GL_FLAT); + glBegin (GL_POINTS); + glVertex2fv(&pt2d[0]); + glEnd (); + } + + //for point set + if(!isInputDevice && ( (scalardiff<4.0) || (m_Polygon))) + { + Point2D tmp; + displayGeometry->Map(projected_p, pt2d); + displayGeometry->WorldToDisplay(pt2d, pt2d); + + Vector2D horz,vert; + horz[0]=(float)m_Point2DSize-scalardiff*2; horz[1]=0; + vert[0]=0; vert[1]=(float)m_Point2DSize-scalardiff*2; + + // now paint text if available + if (dynamic_cast(this->GetDataNode() + ->GetProperty("label")) != NULL) + { + const char * pointLabel = dynamic_cast( + this->GetDataNode()->GetProperty("label"))->GetValue(); + std::string l = pointLabel; + if (input->GetSize()>1) + { + // char buffer[20]; + // sprintf(buffer,"%d",it->Index()); + std::stringstream ss; + ss << it->Index(); + l.append(ss.str()); + } + if (unselectedColor != NULL) + { + mitk::VtkPropRenderer* OpenGLrenderer = dynamic_cast( renderer ); + float rgb[3];//yellow + rgb[0] = unselectedColor[0]; rgb[1] = unselectedColor[1]; rgb[2] = unselectedColor[2]; + OpenGLrenderer->WriteSimpleText(l, pt2d[0] + text2dDistance, pt2d[1] + text2dDistance,rgb[0], rgb[1],rgb[2]); + } + else + { + mitk::VtkPropRenderer* OpenGLrenderer = dynamic_cast( renderer ); + OpenGLrenderer->WriteSimpleText(l, pt2d[0] + text2dDistance, pt2d[1] + text2dDistance,0.0,1.0,0.0); + } + } + + if((m_ShowPoints) && (scalardiff<4.0)) + { + //check if the point is to be marked as selected + if(selIt != selEnd || pointDataBroken) + { + bool addAsSelected = false; + if (pointDataBroken) + addAsSelected = false; + else if (selIt->Value().selected) + addAsSelected = true; + else + addAsSelected = false; + + if (addAsSelected) + { + horz[0]=(float)m_Point2DSize; + vert[1]=(float)m_Point2DSize; + glColor3f(selectedColor[0],selectedColor[1],selectedColor[2]); + glLineWidth(m_PointLineWidth); + //a diamond around the point with the selected color + glBegin (GL_LINE_LOOP); + tmp=pt2d-horz; glVertex2fv(&tmp[0]); + tmp=pt2d+vert; glVertex2fv(&tmp[0]); + tmp=pt2d+horz; glVertex2fv(&tmp[0]); + tmp=pt2d-vert; glVertex2fv(&tmp[0]); + glEnd (); + glLineWidth(1); + //the actual point in the specified color to see the usual color of the point + glColor3f(unselectedColor[0],unselectedColor[1],unselectedColor[2]); + glPointSize(1); + glBegin (GL_POINTS); + tmp=pt2d; glVertex2fv(&tmp[0]); + glEnd (); + } + else //if not selected + { + glColor3f(unselectedColor[0],unselectedColor[1],unselectedColor[2]); + glLineWidth(m_PointLineWidth); + //drawing crosses + glBegin (GL_LINES); + tmp=pt2d-horz; glVertex2fv(&tmp[0]); + tmp=pt2d+horz; glVertex2fv(&tmp[0]); + tmp=pt2d-vert; glVertex2fv(&tmp[0]); + tmp=pt2d+vert; glVertex2fv(&tmp[0]); + glEnd (); + glLineWidth(1); + } + } + } + + bool drawLinesEtc = true; + if (!m_ShowDistantLines && counter > 0) // check, whether this line should be drawn + { + ScalarType currentDistance = displayGeometry->GetWorldGeometry()->SignedDistance(p); + ScalarType lastDistance = displayGeometry->GetWorldGeometry()->SignedDistance(lastP); + if ( currentDistance * lastDistance > 0.5 ) // points on same side of plane + drawLinesEtc = false; + } + + // draw a line + if ((m_Polygon && counter>0 && drawLinesEtc) || + (m_Polygon && m_PolygonClosed && drawLinesEtc)) + { + if ((counter == 0) && ( m_PolygonClosed)) + { + lastPt2d = lastPt2DInPointSet; + } + + //get contour color property + float contourColor[4] = {unselectedColor[0], unselectedColor[1], unselectedColor[2], unselectedColor[3]};//so if no property set, then use unselected color + if (dynamic_cast(node->GetPropertyList(renderer)->GetProperty("contourcolor")) != NULL) + { + mitk::Color tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("contourcolor"))->GetValue(); + contourColor[0] = tmpColor[0]; + contourColor[1] = tmpColor[1]; + contourColor[2] = tmpColor[2]; + contourColor[3] = 1.0f; + } + else if (dynamic_cast(node->GetPropertyList(NULL)->GetProperty("contourcolor")) != NULL) + { + mitk::Color tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("contourcolor"))->GetValue(); + contourColor[0] = tmpColor[0]; + contourColor[1] = tmpColor[1]; + contourColor[2] = tmpColor[2]; + contourColor[3] = 1.0f; + } + //set this color + glColor3f(contourColor[0],contourColor[1],contourColor[2]); + + glLineWidth( m_LineWidth ); + glBegin (GL_LINES); + glVertex2fv(&pt2d[0]); + glVertex2fv(&lastPt2d[0]); + glEnd (); + glLineWidth(1.0); + if(m_ShowDistances) // calculate and print a distance + { + std::stringstream buffer; + float distance = vec.GetNorm(); + buffer<( renderer ); + OpenGLrenderer->WriteSimpleText(buffer.str(), pos2d[0], pos2d[1]); + //this->WriteTextXY(pos2d[0], pos2d[1], buffer.str(),renderer); + } + + if(m_ShowAngles && counter > 1 ) // calculate and print the angle btw. two lines + { + std::stringstream buffer; + //buffer << angle(vec.Get_vnl_vector(), -lastVec.Get_vnl_vector())*180/vnl_math::pi << "�"; + buffer << angle(vec.Get_vnl_vector(), -lastVec.Get_vnl_vector())*180/vnl_math::pi << (char)176; + + Vector2D vec2d = pt2d-lastPt2d; + vec2d.Normalize(); + Vector2D lastVec2d = lastPt2d-preLastPt2d; + lastVec2d.Normalize(); + vec2d=vec2d-lastVec2d; + vec2d.Normalize(); + + Vector2D pos2d = lastPt2d.GetVectorFromOrigin()+vec2d*text2dDistance*text2dDistance; + + mitk::VtkPropRenderer* OpenGLrenderer = dynamic_cast( renderer ); + OpenGLrenderer->WriteSimpleText(buffer.str(), pos2d[0], pos2d[1]); + //this->WriteTextXY(pos2d[0], pos2d[1], buffer.str(),renderer); + } + } + counter++; + } + ++it; + if(selIt != selEnd && !pointDataBroken) + ++selIt; + j++; + } + + //recall the color to the same color before this drawing + glColor3f(recallColor[0],recallColor[1],recallColor[2]); + } +} + +void mitk::PointSetGLMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) +{ + node->AddProperty( "line width", mitk::IntProperty::New(2), renderer, overwrite ); // width of the line from one point to another + node->AddProperty( "point line width", mitk::IntProperty::New(1), renderer, overwrite ); //width of the cross marking a point + node->AddProperty( "point 2D size", mitk::IntProperty::New(8), renderer, overwrite ); // length of the cross marking a point // length of an edge of the box marking a point + node->AddProperty( "show contour", mitk::BoolProperty::New(false), renderer, overwrite ); // contour of the line between points + node->AddProperty( "close contour", mitk::BoolProperty::New(false), renderer, overwrite ); + node->AddProperty( "show points", mitk::BoolProperty::New(true), renderer, overwrite ); //show or hide points + node->AddProperty( "show distances", mitk::BoolProperty::New(false), renderer, overwrite ); //show or hide distance measure (not always available) + node->AddProperty( "distance decimal digits", mitk::IntProperty::New(2), renderer, overwrite ); //set the number of decimal digits to be shown + node->AddProperty( "show angles", mitk::BoolProperty::New(false), renderer, overwrite ); //show or hide angle measurement (not always available) + node->AddProperty( "show distant lines", mitk::BoolProperty::New(false), renderer, overwrite ); //show the line between to points from a distant view (equals "always on top" option) + node->AddProperty( "layer", mitk::IntProperty::New(1), renderer, overwrite ); // default to draw pointset above images (they have a default layer of 0) + Superclass::SetDefaultProperties(node, renderer, overwrite); +} diff --git a/Core/Code/Rendering/mitkPointSetGLMapper2D.h b/Core/Code/Rendering/mitkPointSetGLMapper2D.h new file mode 100644 index 0000000000..f20ff02ddf --- /dev/null +++ b/Core/Code/Rendering/mitkPointSetGLMapper2D.h @@ -0,0 +1,97 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#ifndef MITKPointSetMAPPER2D_H_HEADER_INCLUDED +#define MITKPointSetMAPPER2D_H_HEADER_INCLUDED + +#include +#include "mitkGLMapper.h" + +namespace mitk { + +class BaseRenderer; +class PointSet; + +/** + * @brief OpenGL-based mapper to display a mitk::PointSet in a 2D window. + * + * This mapper can actually more than just draw a number of points of a + * mitk::PointSet. If you set the right properties of the mitk::DataNode, + * which contains the point set, then this mapper will also draw lines + * connecting the points, and calculate and display distances and angles + * between adjacent points. Here is a complete list of boolean properties, + * which might be of interest: + * + * - \b "show contour": Draw not only the points but also the connections between + * them (default false) + * - \b "line width": IntProperty which gives the width of the contour lines + * - \b "show points": Wheter or not to draw the actual points (default true) + * - \b "show distances": Wheter or not to calculate and print the distance + * between adjacent points (default false) + * - \b "show angles": Wheter or not to calculate and print the angle between + * adjacent points (default false) + * - \b "show distant lines": When true, the mapper will also draw contour + * lines that are far away form the current slice (default true) + * - \b "label": StringProperty with a label for this point set + * + * BUG 1321 - possible new features: + * point-2d-size (length of lines in cross/diamond) + * point-linewidth + * + * @ingroup Mapper + */ + +/** \deprecatedSince{2013_06} This mapper is replaced by PointSetVtkMapper2D. The child classes of this class are deprecated. +/* To further ensure their functionality PointSetGLMapper2D cannot be removed and is set deprecated too. */ +DEPRECATED(class MITK_CORE_EXPORT PointSetGLMapper2D) : public GLMapper +{ +public: + mitkClassMacro(PointSetGLMapper2D, GLMapper); + + itkNewMacro(Self); + + /** @brief Get the PointDataList to map */ + virtual const mitk::PointSet * GetInput(void); + + virtual void Paint(mitk::BaseRenderer * renderer); + + virtual void ApplyAllProperties(mitk::BaseRenderer* renderer); + + static void SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer = NULL, bool overwrite = false); + +protected: + PointSetGLMapper2D(); + + virtual ~PointSetGLMapper2D(); + + bool m_Polygon; + bool m_PolygonClosed; + bool m_ShowPoints; + bool m_ShowDistances; + int m_DistancesDecimalDigits; + bool m_ShowAngles; + bool m_ShowDistantLines; + int m_LineWidth; + int m_PointLineWidth; + int m_Point2DSize; +}; + +} // namespace mitk + + + +#endif /* MITKPointSetMapper2D_H_HEADER_INCLUDED */