33 #include <vtkActor2D.h>
34 #include <vtkCellArray.h>
35 #include <vtkCellData.h>
37 #include <vtkPoints.h>
38 #include <vtkPolyData.h>
39 #include <vtkPolyDataMapper2D.h>
40 #include <vtkProperty2D.h>
41 #include <vtkTriangle.h>
56 SimpleInterval(T start = T(), T end = T())
57 : m_LowerBoundary(
std::
min(start, end)), m_UpperBoundary(
std::
max(start, end))
61 T GetLowerBoundary()
const {
return m_LowerBoundary; }
62 T GetUpperBoundary()
const {
return m_UpperBoundary; }
63 bool empty()
const {
return m_LowerBoundary == m_UpperBoundary; }
64 bool operator<(
const SimpleInterval &otherInterval)
const
66 return this->m_UpperBoundary < otherInterval.GetLowerBoundary();
78 typedef SimpleInterval<T> IntervalType;
80 IntervalSet(IntervalType startingInterval) { m_IntervalsContainer.insert(std::move(startingInterval)); }
81 void operator-=(
const IntervalType &interval)
85 auto range = m_IntervalsContainer.equal_range(interval);
87 for (
auto iter = range.first; iter != range.second;)
89 auto subtractionResult = SubtractIntervals(*iter, interval);
92 iter = m_IntervalsContainer.erase(iter);
93 for (
auto &&interval : subtractionResult)
95 if (!interval.empty())
100 iter = m_IntervalsContainer.insert(iter, std::move(interval));
107 IntervalSet operator-(
const IntervalType &interval)
109 IntervalSet result = *
this;
114 typedef std::set<IntervalType> IntervalsContainer;
116 const IntervalsContainer &getIntervals()
const {
return m_IntervalsContainer; }
118 IntervalsContainer m_IntervalsContainer;
120 std::array<IntervalType, 2> SubtractIntervals(
const IntervalType &firstInterval,
const IntervalType &secondInterval)
122 assert(secondInterval.GetUpperBoundary() >= firstInterval.GetLowerBoundary() &&
123 firstInterval.GetUpperBoundary() >=
124 secondInterval.GetLowerBoundary());
126 if (secondInterval.GetLowerBoundary() < firstInterval.GetLowerBoundary())
128 if (firstInterval.GetUpperBoundary() < secondInterval.GetUpperBoundary())
130 std::array<IntervalType, 2> result = {{IntervalType(), IntervalType()}};
133 std::array<IntervalType, 2> result = {
134 {IntervalType(firstInterval.GetUpperBoundary(), secondInterval.GetUpperBoundary()), IntervalType()}};
138 if (firstInterval.GetUpperBoundary() < secondInterval.GetUpperBoundary())
140 std::array<IntervalType, 2> result = {
141 {IntervalType(firstInterval.GetLowerBoundary(), secondInterval.GetLowerBoundary()), IntervalType()}};
144 std::array<IntervalType, 2> result = {
145 {IntervalType(firstInterval.GetLowerBoundary(), secondInterval.GetLowerBoundary()),
146 IntervalType(secondInterval.GetUpperBoundary(), firstInterval.GetUpperBoundary())}};
161 : m_RenderOrientationArrows(false), m_ArrowOrientationPositive(true), m_DepthValue(1.0f)
168 s_AllInstances.erase(
this);
186 for (AllInstancesContainer::iterator it = s_AllInstances.begin(); it != s_AllInstances.end(); ++it)
189 if (generateDataRequired)
196 m_OtherPlaneGeometries.clear();
198 for (AllInstancesContainer::iterator it = s_AllInstances.begin(); it != s_AllInstances.end(); ++it)
200 Self *otherInstance = *it;
203 if (otherInstance ==
this)
219 if (otherGeometry && !dynamic_cast<AbstractTransformGeometry *>(otherData->
GetPlaneGeometry()))
221 m_OtherPlaneGeometries.push_back(otherNode);
225 CreateVtkCrosshair(renderer);
227 ApplyAllProperties(renderer);
238 GetDataNode()->GetVisibility(visible, renderer,
"visible");
251 if (input.IsNull() || input.GetPointer() == rendererWorldPlaneGeometryData)
261 if (worldPlaneGeometry && dynamic_cast<const AbstractTransformGeometry *>(worldPlaneGeometry) == NULL &&
275 bool hasIntersection = referenceGeometry ? CutCrossLineWithReferenceGeometry(referenceGeometry, crossLine) :
276 CutCrossLineWithPlaneGeometry(inputPlaneGeometry, crossLine);
278 if (!hasIntersection)
294 NodesVectorType::iterator otherPlanesIt = m_OtherPlaneGeometries.begin();
295 NodesVectorType::iterator otherPlanesEnd = m_OtherPlaneGeometries.end();
298 this->GetDataNode()->GetPropertyValue(
"Crosshair.Gap Size", gapSize, NULL);
300 auto intervals = IntervalSet<double>(SimpleInterval<double>(0, 1));
302 ScalarType lineLength = point1.EuclideanDistanceTo(point2);
304 float gapSizeParam = gapInMM / lineLength;
308 while (otherPlanesIt != otherPlanesEnd)
310 bool ignorePlane =
false;
311 (*otherPlanesIt)->GetPropertyValue(
"Crosshair.Ignore", ignorePlane);
319 static_cast<PlaneGeometryData *
>((*otherPlanesIt)->GetData())->GetPlaneGeometry());
321 if (otherPlaneGeometry != inputPlaneGeometry && otherPlaneGeometry != worldPlaneGeometry)
323 double intersectionParam;
325 intersectionParam < 1)
329 bool intersectionPointInsideOtherPlane =
332 TestPointInPlaneGeometry(otherPlaneGeometry, point);
334 if (intersectionPointInsideOtherPlane)
336 intervals -= SimpleInterval<double>(intersectionParam - gapSizeParam, intersectionParam + gapSizeParam);
344 for (
const auto &interval : intervals.getIntervals())
346 this->DrawLine(crossLine.
GetPoint(interval.GetLowerBoundary()),
347 crossLine.
GetPoint(interval.GetUpperBoundary()),
353 linesPolyData->SetPoints(points);
355 linesPolyData->SetLines(lines);
358 orthogonalVector = inputPlaneGeometry->
GetNormal();
359 worldPlaneGeometry->
Project(orthogonalVector, orthogonalVector);
360 orthogonalVector.Normalize();
363 ls->
m_Mapper->SetInputData(linesPolyData);
368 bool showAreaOfThickSlicing =
false;
369 GetDataNode()->GetBoolProperty(
"reslice.thickslices.showarea", showAreaOfThickSlicing);
373 referenceGeometry ? referenceGeometry->
GetSpacing() : inputPlaneGeometry->
GetSpacing(), orthogonalVector);
376 if (GetDataNode()->GetProperty(intProperty,
"reslice.thickslices.num") && intProperty)
377 thickSliceDistance *= intProperty->
GetValue() + 0.5;
379 showAreaOfThickSlicing =
false;
383 GetDataNode()->SetFloatProperty(
"reslice.thickslices.sizeinmm", thickSliceDistance * 2);
389 if (this->m_RenderOrientationArrows)
396 DrawOrientationArrow(triangles, triPoints, triangleSizeMM, orthogonalVector, point1, point2);
397 DrawOrientationArrow(triangles, triPoints, triangleSizeMM, orthogonalVector, point2, point1);
398 arrowPolyData->SetPoints(triPoints);
399 arrowPolyData->SetPolys(triangles);
406 if (showAreaOfThickSlicing)
411 Vector3D vecToHelperLine = orthogonalVector * thickSliceDistance;
413 this->DrawLine(point1 - vecToHelperLine, point2 - vecToHelperLine, helperlines, points);
414 this->DrawLine(point1 + vecToHelperLine, point2 + vecToHelperLine, helperlines, points);
417 helperlinesPolyData->SetPoints(points);
420 helperlinesPolyData->SetLines(helperlines);
433 planeGeometry->
Map(point, mappedPoint);
436 return (planeGeometry->
GetBounds()[0] < mappedPoint[0] && mappedPoint[0] < planeGeometry->
GetBounds()[1] &&
437 planeGeometry->
GetBounds()[2] < mappedPoint[1] && mappedPoint[1] < planeGeometry->
GetBounds()[3]);
443 return referenceGeometry->
IsInside(point);
452 planeGeometry->
Map(crossLine.
GetPoint(), indexLinePoint);
455 planeGeometry->
WorldToIndex(indexLinePoint, indexLinePoint);
456 planeGeometry->
WorldToIndex(indexLineDirection, indexLineDirection);
468 intersectionPoints[0],
469 intersectionPoints[1]);
471 if (nIntersections < 2)
476 planeGeometry->
IndexToWorld(intersectionPoints[0], intersectionPoints[0]);
477 planeGeometry->
IndexToWorld(intersectionPoints[1], intersectionPoints[1]);
481 planeGeometry->
Map(intersectionPoints[0], point1);
482 planeGeometry->
Map(intersectionPoints[1], point2);
491 Point3D boundingBoxMin, boundingBoxMax;
501 referenceGeometry->
WorldToIndex(boundingBoxMin, boundingBoxMin);
502 referenceGeometry->
WorldToIndex(boundingBoxMax, boundingBoxMax);
519 if (nIntersections < 2)
536 vtkIdType pidStart = points->InsertNextPoint(p0[0], p0[1], p0[2]);
537 vtkIdType pidEnd = points->InsertNextPoint(p1[0], p1[1], p1[2]);
540 lineVtk->GetPointIds()->SetId(0, pidStart);
541 lineVtk->GetPointIds()->SetId(1, pidEnd);
543 lines->InsertNextCell(lineVtk);
547 vtkSmartPointer<vtkPoints> triPoints,
548 double triangleSizeMM,
557 v1 *= triangleSizeMM;
561 v2 *= triangleSizeMM;
562 if (!this->m_ArrowOrientationPositive)
566 Point3D p1 = point1 + v1 * 2.0;
569 vtkIdType t0 = triPoints->InsertNextPoint(point1[0], point1[1], point1[2]);
570 vtkIdType t1 = triPoints->InsertNextPoint(p1[0], p1[1], p1[2]);
571 vtkIdType t2 = triPoints->InsertNextPoint(p2[0], p2[1], p2[2]);
574 triangle->GetPointIds()->SetId(0, t0);
575 triangle->GetPointIds()->SetId(1, t1);
576 triangle->GetPointIds()->SetId(2, t2);
578 triangles->InsertNextCell(triangle);
583 int thickSlicesMode = 0;
586 if (dn->
GetProperty(resliceMethodEnumProperty,
"reslice.thickslices") && resliceMethodEnumProperty)
587 thickSlicesMode = resliceMethodEnumProperty->
GetValueAsId();
590 if (dn->
GetProperty(intProperty,
"reslice.thickslices.num") && intProperty)
592 thickSlicesNum = intProperty->
GetValue();
593 if (thickSlicesNum < 1)
595 if (thickSlicesNum > 10)
599 if (thickSlicesMode == 0)
602 return thickSlicesMode;
610 ApplyColorAndOpacityProperties2D(renderer, ls->
m_ArrowActor);
613 this->GetDataNode()->GetFloatProperty(
"Line width", thickness, renderer);
618 this->GetDataNode()->GetProperty(decorationProperty,
"decoration", renderer);
619 if (decorationProperty != NULL)
623 m_RenderOrientationArrows =
true;
624 m_ArrowOrientationPositive =
true;
629 m_RenderOrientationArrows =
true;
630 m_ArrowOrientationPositive =
false;
634 m_RenderOrientationArrows =
false;
641 float rgba[4] = {1.0f, 1.0f, 1.0f, 1.0f};
645 node->
GetColor(rgba, renderer,
"color");
647 node->
GetOpacity(rgba[3], renderer,
"opacity");
649 double drgba[4] = {rgba[0], rgba[1], rgba[2], rgba[3]};
650 actor->GetProperty()->SetColor(drgba);
651 actor->GetProperty()->SetOpacity(drgba[3]);
660 aliases->
AddAlias(
"line width",
"Crosshair.Line Width",
"");
666 aliases->
AddAlias(
"decoration",
"Crosshair.Orientation Decoration",
"");
668 Superclass::SetDefaultProperties(node, renderer, overwrite);
687 m_CrosshairActor->SetMapper(m_Mapper);
688 m_ArrowActor->SetMapper(m_Arrowmapper);
689 m_CrosshairHelperLineActor->SetMapper(m_HelperLinesmapper);
691 m_CrosshairActor->SetVisibility(0);
692 m_ArrowActor->SetVisibility(0);
693 m_CrosshairHelperLineActor->SetVisibility(0);
695 m_CrosshairAssembly->AddPart(m_CrosshairActor);
696 m_CrosshairAssembly->AddPart(m_ArrowActor);
697 m_CrosshairAssembly->AddPart(m_CrosshairHelperLineActor);
700 tcoord->SetCoordinateSystemToWorld();
701 m_HelperLinesmapper->SetTransformCoordinate(tcoord);
702 m_Mapper->SetTransformCoordinate(tcoord);
704 m_Arrowmapper->SetTransformCoordinate(tcoord);
virtual vtkProp * GetVtkProp(mitk::BaseRenderer *renderer) override
returns the a prop assembly
virtual int GetPlaneDecoration()
bool IntersectionPointParam(const Line3D &line, double &t) const
Calculate line parameter of intersection point between the plane and a line.
Interface of property aliases service.
vtkSmartPointer< vtkActor2D > m_ArrowActor
virtual DataNode * GetCurrentWorldPlaneGeometryNode()
Get a DataNode pointing to a data object containing the current 2D-worldgeometry. ...
const itk::Point< TCoordRep, NPointDimension > & GetPoint1() const
Get start point of the line.
Base class for mapper specific rendering ressources.
double GetScaleFactorMMPerDisplayUnit() const
PlaneGeometryDataMapper2D()
vtkSmartPointer< vtkPolyDataMapper2D > m_Arrowmapper
vtkSmartPointer< vtkActor2D > m_CrosshairHelperLineActor
virtual bool Map(const mitk::Point3D &pt3d_mm, mitk::Point2D &pt2d_mm) const
Project a 3D point given in mm (pt3d_mm) onto the 2D geometry. The result is a 2D point in mm (pt2d_m...
void DrawOrientationArrow(vtkSmartPointer< vtkCellArray > triangles, vtkSmartPointer< vtkPoints > triPoints, double triangleSizeMM, Vector3D &orthogonalVector, Point3D &point1, Point3D &point2)
Internal class holding the mapper, actor, etc. for each of the 3 2D render windows.
Organizes the rendering process.
const mitk::Vector3D GetSpacing() const
Get the spacing (size of a pixel).
virtual bool AddAlias(const std::string &propertyName, const std::string &alias, const std::string &className="")=0
Add an alias for a specific property.
BaseData * GetData() const
Get the data object (instance of BaseData, e.g., an Image) managed by this DataNode.
virtual mitk::PlaneGeometry * GetPlaneGeometry() const
Get the reference to the PlaneGeometry that is stored by the object.
static int BoxLineIntersection(TCoordRep x1, TCoordRep y1, TCoordRep z1, TCoordRep x2, TCoordRep y2, TCoordRep z2, itk::Point< TCoordRep, 3 > p, itk::Vector< TCoordRep, 3 > d, itk::Point< TCoordRep, 3 > &s1, itk::Point< TCoordRep, 3 > &s2)
Calculates the intersection points of a straight line in 3D with a box.
mitk::BaseProperty * GetProperty(const char *propertyKey, const mitk::BaseRenderer *renderer=nullptr) const
Get the property (instance of BaseProperty) with key propertyKey from the PropertyList of the rendere...
const itk::Vector< TCoordRep, NPointDimension > & GetDirection() const
Get the direction vector of the line.
virtual void WorldToIndex(const Point2D &pt_mm, Point2D &pt_units) const
const BoundsArrayType GetBounds() const
virtual void IndexToWorld(const Point2D &pt_units, Point2D &pt_mm) const
Base class of all mappers, Vtk as well as OpenGL mappers.
vtkSmartPointer< vtkPropAssembly > m_CrosshairAssembly
Vector3D GetNormal() const
Normal of the plane.
int DetermineThickSliceMode(DataNode *dn, int &thickSlicesNum)
Returns the thick slice mode for the given datanode.
static void SetDefaultProperties(mitk::DataNode *node, mitk::BaseRenderer *renderer=NULL, bool overwrite=false)
set the default properties for this mapper
bool IsVisible(const mitk::BaseRenderer *renderer, const char *propertyKey="visible", bool defaultIsOn=true) const
Convenience access method for visibility properties (instances of BoolProperty). Return value is the ...
void ApplyColorAndOpacityProperties2D(BaseRenderer *renderer, vtkActor2D *actor)
static bool CutCrossLineWithReferenceGeometry(const BaseGeometry *referenceGeometry, Line3D &crossLine)
void AddProperty(const char *propertyKey, BaseProperty *property, const mitk::BaseRenderer *renderer=nullptr, bool overwrite=false)
Add the property (instance of BaseProperty) if it does not exist (or always ifoverwrite istrue) with ...
bool IsGenerateDataRequired(mitk::BaseRenderer *renderer, mitk::Mapper *mapper, mitk::DataNode *dataNode) const
bool GetOpacity(float &opacity, const mitk::BaseRenderer *renderer, const char *propertyKey="opacity") const
Convenience access method for opacity properties (instances of FloatProperty)
const itk::Point< TCoordRep, NPointDimension > & GetPoint() const
Get start point of the line.
static bool TestPointInPlaneGeometry(const PlaneGeometry *planeGeometry, const Point3D &point)
virtual const mitk::PlaneGeometryData * GetInput() const
virtual void UpdateVtkTransform(mitk::BaseRenderer *renderer) override
Set the vtkTransform of the m_Prop3D for the current time step of renderer.
virtual ~PlaneGeometryDataMapper2D()
void SetPoints(const itk::Point< TCoordRep, NPointDimension > &point1, const itk::Point< TCoordRep, NPointDimension > &point2)
Define line by two points.
vtkSmartPointer< vtkPolyDataMapper2D > m_Mapper
Data class containing PlaneGeometry objects.
static bool CutCrossLineWithPlaneGeometry(const PlaneGeometry *planeGeometry, Line3D &crossLine)
static AllInstancesContainer s_AllInstances
Point3D GetCornerPoint(int id) const
Get the position of the corner number id (in world coordinates)
void CreateVtkCrosshair(BaseRenderer *renderer)
vtkSmartPointer< vtkActor2D > m_CrosshairActor
vtkSmartPointer< vtkPolyDataMapper2D > m_HelperLinesmapper
virtual bool Project(const mitk::Point3D &pt3d_mm, mitk::Point3D &projectedPt3d_mm) const
Project a 3D point given in mm (pt3d_mm) onto the 2D geometry. The result is a 3D point in mm (projec...
bool HasReferenceGeometry() const
static bool TestPointInReferenceGeometry(const BaseGeometry *referenceGeometry, const Point3D &point)
const BaseGeometry * GetReferenceGeometry() const
Get the geometrical frame of reference for this PlaneGeometry.
virtual void ApplyAllProperties(BaseRenderer *renderer)
void IndexToWorld(const mitk::Vector3D &vec_units, mitk::Vector3D &vec_mm) const
Convert (continuous or discrete) index coordinates of a vector vec_units to world coordinates (in mm)...
virtual void GenerateDataForRenderer(mitk::BaseRenderer *renderer) override
Generate the data needed for rendering into renderer.
itk::Point< TCoordRep, NPointDimension > GetPoint2() const
Get end point of the line.
bool IntersectionLine(const PlaneGeometry *plane, Line3D &crossline) const
Calculate the intersecting line of two planes.
std::set< Self * > AllInstancesContainer
void UpdateGenerateDataTime()
static double CalculateSpacing(const mitk::Vector3D &spacing, const mitk::Vector3D &d)
static int RectangleLineIntersection(TCoordRep x1, TCoordRep y1, TCoordRep x2, TCoordRep y2, itk::Point< TCoordRep, 2 > p, itk::Vector< TCoordRep, 2 > d, itk::Point< TCoordRep, 2 > &s1, itk::Point< TCoordRep, 2 > &s2)
Calculates the intersection points of a straight line in 2D with a rectangle.
Describes a two-dimensional, rectangular plane.
bool IsInside(const mitk::Point3D &p) const
Test whether the point p (world coordinates in mm) is inside the bounding box.
virtual DataNode * GetDataNode() const
Get the DataNode containing the data to map. Method only returns valid DataNode Pointer if the mapper...
static IPropertyAliases * GetPropertyAliases(us::ModuleContext *context=us::GetModuleContext())
Get an IPropertyAliases instance.
bool GetColor(float rgb[3], const mitk::BaseRenderer *renderer=nullptr, const char *propertyKey="color") const
Convenience access method for color properties (instances of ColorProperty)
BaseGeometry Describes the geometry of a data object.
Class for nodes of the DataTree.
void DrawLine(Point3D p0, Point3D p1, vtkCellArray *lines, vtkPoints *points)
virtual IdType GetValueAsId() const
void WorldToIndex(const mitk::Point3D &pt_mm, mitk::Point3D &pt_units) const
Convert world coordinates (in mm) of a point to (continuous!) index coordinates.
virtual T GetValue() const
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.