changeset 1178:3c7cdbf32e2a broker

DicomStructureSet::ProjectOntoLayer()
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 20 Nov 2019 14:12:11 +0100
parents c3d219b6266b
children 177e7d431cd1
files Framework/Toolbox/DicomStructureSet.cpp Framework/Toolbox/DicomStructureSet.h
diffstat 2 files changed, 106 insertions(+), 52 deletions(-) [+]
line wrap: on
line diff
--- a/Framework/Toolbox/DicomStructureSet.cpp	Wed Nov 20 13:37:50 2019 +0100
+++ b/Framework/Toolbox/DicomStructureSet.cpp	Wed Nov 20 14:12:11 2019 +0100
@@ -31,8 +31,8 @@
 #include <Plugins/Samples/Common/DicomDatasetReader.h>
 
 #if defined(_MSC_VER)
-#pragma warning(push)
-#pragma warning(disable:4244)
+#  pragma warning(push)
+#  pragma warning(disable:4244)
 #endif
 
 #include <limits>
@@ -43,7 +43,7 @@
 #include <boost/geometry/multi/geometries/multi_polygon.hpp>
 
 #if defined(_MSC_VER)
-#pragma warning(pop)
+#  pragma warning(pop)
 #endif
 
 typedef boost::geometry::model::d2::point_xy<double> BoostPoint;
@@ -81,7 +81,7 @@
   }
 }
 
-#ifdef USE_BOOST_UNION_FOR_POLYGONS
+#if USE_BOOST_UNION_FOR_POLYGONS == 1
 
 static BoostPolygon CreateRectangle(float x1, float y1,
                                     float x2, float y2)
@@ -99,7 +99,7 @@
 namespace OrthancStone
 {
   static RtStructRectangleInSlab CreateRectangle(float x1, float y1,
-    float x2, float y2)
+                                                 float x2, float y2)
   {
     RtStructRectangleInSlab rect;
     rect.xmin = std::min(x1, x2);
@@ -174,15 +174,15 @@
       double magnitude =
         GeometryToolbox::ProjectAlongNormal(v, geometry_.GetNormal());
       if(!LinearAlgebra::IsNear(
-        magnitude,
-        projectionAlongNormal_,
-        sliceThickness_ / 2.0 /* in mm */ ))
+           magnitude,
+           projectionAlongNormal_,
+           sliceThickness_ / 2.0 /* in mm */ ))
       {
         LOG(ERROR) << "This RT-STRUCT contains a point that is off the "
-          << "slice of its instance | "
-          << "magnitude = " << magnitude << " | "
-          << "projectionAlongNormal_ = " << projectionAlongNormal_ << " | "
-          << "tolerance (sliceThickness_ / 2.0) = " << (sliceThickness_ / 2.0);
+                   << "slice of its instance | "
+                   << "magnitude = " << magnitude << " | "
+                   << "projectionAlongNormal_ = " << projectionAlongNormal_ << " | "
+                   << "tolerance (sliceThickness_ / 2.0) = " << (sliceThickness_ / 2.0);
 
         throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
       }
@@ -202,10 +202,10 @@
       if (!onSlice)
       {
         LOG(WARNING) << "This RT-STRUCT contains a point that is off the "
-          << "slice of its instance | "
-          << "magnitude = " << magnitude << " | "
-          << "projectionAlongNormal_ = " << projectionAlongNormal_ << " | "
-          << "tolerance (sliceThickness_ / 2.0) = " << (sliceThickness_ / 2.0);
+                     << "slice of its instance | "
+                     << "magnitude = " << magnitude << " | "
+                     << "projectionAlongNormal_ = " << projectionAlongNormal_ << " | "
+                     << "tolerance (sliceThickness_ / 2.0) = " << (sliceThickness_ / 2.0);
       }
       return onSlice;
     }
@@ -378,9 +378,9 @@
 
       
       /*
-      Please read the comments in the section above, by taking into account
-      the fact that, in this case, the plane has a constant X, not Y (in 
-      polygon geometry_ coordinates)
+        Please read the comments in the section above, by taking into account
+        the fact that, in this case, the plane has a constant X, not Y (in 
+        polygon geometry_ coordinates)
       */
 
       if (x < extent_.GetX1() ||
@@ -512,11 +512,11 @@
       }
 
       LOG(INFO) << "New RT structure: \"" << structures_[i].name_ 
-                   << "\" with interpretation \"" << structures_[i].interpretation_
-                   << "\" containing " << countSlices << " slices (color: " 
-                   << static_cast<int>(structures_[i].red_) << "," 
-                   << static_cast<int>(structures_[i].green_) << ","
-                   << static_cast<int>(structures_[i].blue_) << ")";
+                << "\" with interpretation \"" << structures_[i].interpretation_
+                << "\" containing " << countSlices << " slices (color: " 
+                << static_cast<int>(structures_[i].red_) << "," 
+                << static_cast<int>(structures_[i].green_) << ","
+                << static_cast<int>(structures_[i].blue_) << ")";
 
       // These temporary variables avoid allocating many vectors in the loop below
       OrthancPlugins::DicomPath countPointsPath(DICOM_TAG_ROI_CONTOUR_SEQUENCE, i,
@@ -771,14 +771,14 @@
           if (Orthanc::Toolbox::StripSpaces(sopInstanceUid) == "")
           {
             LOG(ERROR) << "DicomStructureSet::CheckReferencedSlices(): "
-              << " missing information about referenced instance "
-              << "(sopInstanceUid is empty!)";
+                       << " missing information about referenced instance "
+                       << "(sopInstanceUid is empty!)";
           }
           else
           {
             LOG(ERROR) << "DicomStructureSet::CheckReferencedSlices(): "
-              << " missing information about referenced instance "
-              << "(sopInstanceUid = " << sopInstanceUid << ")";
+                       << " missing information about referenced instance "
+                       << "(sopInstanceUid = " << sopInstanceUid << ")";
           }
           //throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
         }
@@ -801,17 +801,18 @@
     }
   }
 
-#ifdef USE_BOOST_UNION_FOR_POLYGONS 
-  bool DicomStructureSet::ProjectStructure(std::vector< std::vector<Point2D> >& polygons,
-                                           const Structure& structure,
-                                           const CoordinateSystem3D& slice) const
+  bool DicomStructureSet::ProjectStructure(
+#if USE_BOOST_UNION_FOR_POLYGONS == 1
+    std::vector< std::vector<Point2D> >& polygons,
 #else
-  bool DicomStructureSet::ProjectStructure(std::vector< std::pair<Point2D, Point2D> >& segments,
+    std::vector< std::pair<Point2D, Point2D> >& segments,
+#endif
     const Structure& structure,
-    const CoordinateSystem3D& slice) const
-#endif
+    const CoordinateSystem3D& sourceSlice) const
   {
-#ifdef USE_BOOST_UNION_FOR_POLYGONS 
+    const CoordinateSystem3D slice = CoordinateSystem3D::NormalizeCuttingPlane(sourceSlice);
+    
+#if USE_BOOST_UNION_FOR_POLYGONS == 1
     polygons.clear();
 #else
     segments.clear();
@@ -829,7 +830,7 @@
       {
         if (polygon->IsOnSlice(slice))
         {
-#ifdef USE_BOOST_UNION_FOR_POLYGONS 
+#if USE_BOOST_UNION_FOR_POLYGONS == 1
           polygons.push_back(std::vector<Point2D>());
           
           for (Points::const_iterator p = polygon->GetPoints().begin();
@@ -880,7 +881,7 @@
 #if 1
       // Sagittal or coronal projection
 
-#ifdef USE_BOOST_UNION_FOR_POLYGONS 
+#if USE_BOOST_UNION_FOR_POLYGONS == 1
       std::vector<BoostPolygon> projected;
 
       for (Polygons::const_iterator polygon = structure.polygons_.begin();
@@ -912,15 +913,15 @@
           // x1,y1 and x2,y2 are in "slice" coordinates (the cutting plane 
           // geometry)
           projected.push_back(std::make_pair(CreateRectangle(
-            static_cast<float>(x1), 
-            static_cast<float>(y1), 
-            static_cast<float>(x2), 
-            static_cast<float>(y2)),curZ));
+                                               static_cast<float>(x1), 
+                                               static_cast<float>(y1), 
+                                               static_cast<float>(x2), 
+                                               static_cast<float>(y2)),curZ));
         }
       }
 #endif
 
-#ifndef USE_BOOST_UNION_FOR_POLYGONS
+#if USE_BOOST_UNION_FOR_POLYGONS != 1
       // projected contains a set of rectangles specified by two opposite
       // corners (x1,y1,x2,y2)
       // we need to merge them 
@@ -1010,4 +1011,44 @@
       return false;
     }
   }
+
+
+  void DicomStructureSet::ProjectOntoLayer(PolylineSceneLayer& layer,
+                                           const CoordinateSystem3D& plane,
+                                           size_t structureIndex,
+                                           const Color& color) const
+  {
+#if USE_BOOST_UNION_FOR_POLYGONS == 1
+    std::vector< std::vector<Point2D> > polygons;
+    if (ProjectStructure(polygons, structureIndex, plane))
+    {
+      for (size_t j = 0; j < polygons.size(); j++)
+      {
+        std::vector<ScenePoint2D> chain;
+        chain.reserve(polygons[j].size());
+
+        for (size_t k = 0; k < polygons[j].size(); k++)
+        {
+          chain.push_back(ScenePoint2D(polygons[j][k].x, polygons[j][k].y));
+        }
+
+        layer.AddChain(chain, true, color.GetRed(), color.GetGreen(), color.GetBlue());
+      }
+    }
+    
+#else
+    std::vector< std::pair<Point2D, Point2D> >  segments;
+
+    if (ProjectStructure(segments, structureIndex, plane))
+    {
+      for (size_t j = 0; j < segments.size(); j++)
+      {
+        std::vector<ScenePoint2D> chain(2);
+        chain[0] = ScenePoint2D(segments[j].first.x, segments[j].first.y);
+        chain[1] = ScenePoint2D(segments[j].second.x, segments[j].second.y);
+        layer.AddChain(chain, false, color.GetRed(), color.GetGreen(), color.GetBlue());
+      }
+    }
+#endif
+  }
 }
--- a/Framework/Toolbox/DicomStructureSet.h	Wed Nov 20 13:37:50 2019 +0100
+++ b/Framework/Toolbox/DicomStructureSet.h	Wed Nov 20 14:12:11 2019 +0100
@@ -25,6 +25,7 @@
 #include "CoordinateSystem3D.h"
 #include "Extent2D.h"
 #include "../Scene2D/Color.h"
+#include "../Scene2D/PolylineSceneLayer.h"
 
 //#define USE_BOOST_UNION_FOR_POLYGONS 1
 
@@ -141,15 +142,15 @@
 
     Structure& GetStructure(size_t index);
   
-#ifdef USE_BOOST_UNION_FOR_POLYGONS 
-    bool ProjectStructure(std::vector< std::vector<Point2D> >& polygons,
-                          const Structure& structure,
-                          const CoordinateSystem3D& slice) const;
+    bool ProjectStructure(
+#if USE_BOOST_UNION_FOR_POLYGONS == 1
+      std::vector< std::vector<Point2D> >& polygons,
 #else
-    bool ProjectStructure(std::vector< std::pair<Point2D, Point2D> >& segments,
+      std::vector< std::pair<Point2D, Point2D> >& segments,
+#endif
       const Structure& structure,
       const CoordinateSystem3D& slice) const;
-#endif
+
   public:
     DicomStructureSet(const OrthancPlugins::FullOrthancDataset& instance);
 
@@ -185,7 +186,7 @@
 
     Vector GetNormal() const;
 
-#ifdef USE_BOOST_UNION_FOR_POLYGONS 
+#if USE_BOOST_UNION_FOR_POLYGONS == 1
     bool ProjectStructure(std::vector< std::vector<Point2D> >& polygons,
                           size_t index,
                           const CoordinateSystem3D& slice) const
@@ -194,11 +195,23 @@
     }
 #else
     bool ProjectStructure(std::vector< std::pair<Point2D, Point2D> >& segments,
-      size_t index,
-      const CoordinateSystem3D& slice) const
+                          size_t index,
+                          const CoordinateSystem3D& slice) const
     {
       return ProjectStructure(segments, GetStructure(index), slice);
     }
 #endif
+
+    void ProjectOntoLayer(PolylineSceneLayer& layer,
+                          const CoordinateSystem3D& plane,
+                          size_t structureIndex,
+                          const Color& color) const;
+
+    void ProjectOntoLayer(PolylineSceneLayer& layer,
+                          const CoordinateSystem3D& plane,
+                          size_t structureIndex) const
+    {
+      ProjectOntoLayer(layer, plane, structureIndex, GetStructureColor(structureIndex));
+    }
   };
 }