changeset 1896:b3c08e607d9f

simplified signature of DicomStructureSet::ProjectStructure()
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 26 Jan 2022 17:19:37 +0100
parents 14c8f339d480
children 144f8f82c15a
files Applications/Samples/Common/RtViewerApp.cpp Applications/Samples/Common/RtViewerApp.h Applications/Samples/Common/RtViewerView.cpp Applications/Samples/RtViewerPlugin/Plugin.cpp OrthancStone/Sources/Loaders/DicomStructureSetLoader.cpp OrthancStone/Sources/Toolbox/DicomStructureSet.cpp OrthancStone/Sources/Toolbox/DicomStructureSet.h OrthancStone/Sources/Toolbox/DicomStructureSetUtils.h
diffstat 8 files changed, 84 insertions(+), 175 deletions(-) [+]
line wrap: on
line diff
--- a/Applications/Samples/Common/RtViewerApp.cpp	Wed Jan 19 14:51:55 2022 +0100
+++ b/Applications/Samples/Common/RtViewerApp.cpp	Wed Jan 26 17:19:37 2022 +0100
@@ -67,12 +67,17 @@
     }
   }
 
-  const VolumeImageGeometry& RtViewerApp::GetMainGeometry()
+  VolumeImageGeometry RtViewerApp::GetMainGeometry()
   {
     ORTHANC_ASSERT(geometryProvider_.get() != NULL);
-    ORTHANC_ASSERT(geometryProvider_->HasGeometry());
-    const VolumeImageGeometry& geometry = geometryProvider_->GetImageGeometry();
-    return geometry;
+    if (geometryProvider_->HasGeometry())
+    {
+      return geometryProvider_->GetImageGeometry();
+    }
+    else
+    {
+      return VolumeImageGeometry();
+    }
   }
 
   RtViewerApp::RtViewerApp() :
--- a/Applications/Samples/Common/RtViewerApp.h	Wed Jan 19 14:51:55 2022 +0100
+++ b/Applications/Samples/Common/RtViewerApp.h	Wed Jan 26 17:19:37 2022 +0100
@@ -95,7 +95,7 @@
     */
     void SetArgument(const std::string& key, const std::string& value);
 
-    const VolumeImageGeometry& GetMainGeometry();
+    VolumeImageGeometry GetMainGeometry();
 
     static boost::shared_ptr<RtViewerApp> Create();
 
--- a/Applications/Samples/Common/RtViewerView.cpp	Wed Jan 19 14:51:55 2022 +0100
+++ b/Applications/Samples/Common/RtViewerView.cpp	Wed Jan 26 17:19:37 2022 +0100
@@ -206,7 +206,7 @@
 
   void RtViewerView::RetrieveGeometry()
   {
-    const VolumeImageGeometry& geometry = GetApp()->GetMainGeometry();
+    VolumeImageGeometry geometry = GetApp()->GetMainGeometry();
 
     const unsigned int depth = geometry.GetProjectionDepth(projection_);
     currentPlane_ = depth / 2;
--- a/Applications/Samples/RtViewerPlugin/Plugin.cpp	Wed Jan 19 14:51:55 2022 +0100
+++ b/Applications/Samples/RtViewerPlugin/Plugin.cpp	Wed Jan 26 17:19:37 2022 +0100
@@ -41,7 +41,7 @@
       {
         throw Orthanc::OrthancException(
           Orthanc::ErrorCode_InternalError,
-          "The Stone MPR RT viewer requires the Web Viewer plugin to be installed");
+          "The Stone MPR RT viewer requires the Orthanc Web Viewer plugin to be installed");
       }
     }
   }
--- a/OrthancStone/Sources/Loaders/DicomStructureSetLoader.cpp	Wed Jan 19 14:51:55 2022 +0100
+++ b/OrthancStone/Sources/Loaders/DicomStructureSetLoader.cpp	Wed Jan 26 17:19:37 2022 +0100
@@ -366,45 +366,10 @@
 
       for (size_t i = 0; i < content_.GetStructuresCount(); i++)
       {
-        if ((visibility_.size() == 0) || visibility_.at(i))
+        if (visibility_.size() == 0 ||
+            visibility_.at(i))
         {
-          const Color& color = content_.GetStructureColor(i);
-
-#if USE_BOOST_UNION_FOR_POLYGONS == 1
-          std::vector< std::vector<ScenePoint2D> > polygons;
-          
-          if (content_.ProjectStructure(polygons, i, cuttingPlane))
-          {
-            for (size_t j = 0; j < polygons.size(); j++)
-            {
-              PolylineSceneLayer::Chain chain;
-              chain.resize(polygons[j].size());
-              
-              for (size_t k = 0; k < polygons[j].size(); k++)
-              {
-                chain[k] = ScenePoint2D(polygons[j][k].GetX(), polygons[j][k].GetY());
-              }
-              
-              layer->AddChain(chain, true /* closed */, color);
-            }
-          }
-#else
-          std::vector< std::pair<ScenePoint2D, ScenePoint2D> > segments;
-
-          if (content_.ProjectStructure(segments, i, cuttingPlane))
-          {
-            for (size_t j = 0; j < segments.size(); j++)
-            {
-              PolylineSceneLayer::Chain chain;
-              chain.resize(2);
-
-              chain[0] = ScenePoint2D(segments[j].first.GetX(), segments[j].first.GetY());
-              chain[1] = ScenePoint2D(segments[j].second.GetX(), segments[j].second.GetY());
-
-              layer->AddChain(chain, false /* NOT closed */, color);
-            }
-          }
-#endif        
+          content_.ProjectOntoLayer(*layer, cuttingPlane, i, content_.GetStructureColor(i));
         }
       }
 
--- a/OrthancStone/Sources/Toolbox/DicomStructureSet.cpp	Wed Jan 19 14:51:55 2022 +0100
+++ b/OrthancStone/Sources/Toolbox/DicomStructureSet.cpp	Wed Jan 26 17:19:37 2022 +0100
@@ -21,6 +21,8 @@
  **/
 
 
+#define USE_BOOST_UNION_FOR_POLYGONS 1
+
 #include "DicomStructureSet.h"
 #include "DicomStructureSetUtils.h"  // TODO REMOVE
 
@@ -42,13 +44,20 @@
 #  include <boost/date_time/posix_time/posix_time.hpp>
 #endif
 
+#if !defined(USE_BOOST_UNION_FOR_POLYGONS)
+#  error Macro USE_BOOST_UNION_FOR_POLYGONS must be defined
+#endif
+
 #include <limits>
 #include <stdio.h>
 #include <boost/math/constants/constants.hpp>
-#include <boost/geometry.hpp>
-#include <boost/geometry/geometries/point_xy.hpp>
-#include <boost/geometry/geometries/polygon.hpp>
-#include <boost/geometry/multi/geometries/multi_polygon.hpp>
+
+#if USE_BOOST_UNION_FOR_POLYGONS == 1
+#  include <boost/geometry.hpp>
+#  include <boost/geometry/geometries/point_xy.hpp>
+#  include <boost/geometry/geometries/polygon.hpp>
+#  include <boost/geometry/multi/geometries/multi_polygon.hpp>
+#endif
 
 #if defined(_MSC_VER)
 #  pragma warning(pop)
@@ -59,11 +68,12 @@
 #endif
 
 
+#if USE_BOOST_UNION_FOR_POLYGONS == 1
+
 typedef boost::geometry::model::d2::point_xy<double> BoostPoint;
 typedef boost::geometry::model::polygon<BoostPoint> BoostPolygon;
 typedef boost::geometry::model::multi_polygon<BoostPolygon>  BoostMultiPolygon;
 
-
 static void Union(BoostMultiPolygon& output,
                   std::vector<BoostPolygon>& input)
 {
@@ -94,8 +104,6 @@
   }
 }
 
-#if USE_BOOST_UNION_FOR_POLYGONS == 1
-
 static BoostPolygon CreateRectangle(float x1, float y1,
                                     float x2, float y2)
 {
@@ -122,12 +130,14 @@
     return rect;
   }
 
-  bool CompareRectanglesForProjection(const std::pair<RtStructRectangleInSlab,double>& r1, const std::pair<RtStructRectangleInSlab, double>& r2)
+  bool CompareRectanglesForProjection(const std::pair<RtStructRectangleInSlab,double>& r1,
+                                      const std::pair<RtStructRectangleInSlab, double>& r2)
   {
     return r1.second < r2.second;
   }
 
-  bool CompareSlabsY(const RtStructRectanglesInSlab& r1, const RtStructRectanglesInSlab& r2)
+  bool CompareSlabsY(const RtStructRectanglesInSlab& r1,
+                     const RtStructRectanglesInSlab& r2)
   {
     if ((r1.size() == 0) || (r2.size() == 0))
       return false;
@@ -829,22 +839,13 @@
     }
   }
 
-  bool DicomStructureSet::ProjectStructure(
-#if USE_BOOST_UNION_FOR_POLYGONS == 1
-    std::vector< std::vector<ScenePoint2D> >& polygons,
-#else
-    std::vector< std::pair<ScenePoint2D, ScenePoint2D> >& segments,
-#endif
-    const Structure& structure,
-    const CoordinateSystem3D& sourceSlice) const
+  bool DicomStructureSet::ProjectStructure(std::vector< std::vector<ScenePoint2D> >& chains,
+                                           const Structure& structure,
+                                           const CoordinateSystem3D& sourceSlice) const
   {
     const CoordinateSystem3D slice = CoordinateSystem3D::NormalizeCuttingPlane(sourceSlice);
     
-#if USE_BOOST_UNION_FOR_POLYGONS == 1
-    polygons.clear();
-#else
-    segments.clear();
-#endif
+    chains.clear();
 
     Vector normal = GetNormal();
     
@@ -853,51 +854,30 @@
     {
       // This is an axial projection
 
+      chains.reserve(structure.polygons_.size());
+      
       for (Polygons::const_iterator polygon = structure.polygons_.begin();
            polygon != structure.polygons_.end(); ++polygon)
       {
-        if (polygon->IsOnSlice(slice))
+        const Points& points = polygon->GetPoints();
+        
+        if (polygon->IsOnSlice(slice) &&
+            !points.empty())
         {
-#if USE_BOOST_UNION_FOR_POLYGONS == 1
-          polygons.push_back(std::vector<ScenePoint2D>());
+          chains.push_back(std::vector<ScenePoint2D>());
+          chains.back().reserve(points.size() + 1);
           
-          for (Points::const_iterator p = polygon->GetPoints().begin();
-               p != polygon->GetPoints().end(); ++p)
+          for (Points::const_iterator p = points.begin();
+               p != points.end(); ++p)
           {
             double x, y;
             slice.ProjectPoint2(x, y, *p);
-            polygons.back().push_back(ScenePoint2D(x, y));
+            chains.back().push_back(ScenePoint2D(x, y));
           }
-#else
-          // we need to add all the segments corresponding to this polygon
-          const std::vector<Vector>& points3D = polygon->GetPoints();
-          if (points3D.size() >= 3)
-          {
-            ScenePoint2D prev2D;
-            {
-              Vector prev = points3D[0];
-              double prevX, prevY;
-              slice.ProjectPoint2(prevX, prevY, prev);
-              prev2D = ScenePoint2D(prevX, prevY);
-            }
 
-            size_t pointCount = points3D.size();
-            for (size_t ipt = 1; ipt < pointCount; ++ipt)
-            {
-              Vector next = points3D[ipt];
-              double nextX, nextY;
-              slice.ProjectPoint2(nextX, nextY, next);
-              ScenePoint2D next2D(nextX, nextY);
-              segments.push_back(std::pair<ScenePoint2D, ScenePoint2D>(prev2D, next2D));
-              prev2D = next2D;
-            }
-          }
-          else
-          {
-            LOG(ERROR) << "Contour with less than 3 points!";
-            // !!!
-          }
-#endif
+          double x0, y0;
+          slice.ProjectPoint2(x0, y0, points.front());
+          chains.back().push_back(ScenePoint2D(x0, y0));
         }
       }
 
@@ -906,7 +886,6 @@
     else if (GeometryToolbox::IsParallelOrOpposite(isOpposite, normal, slice.GetAxisX()) ||
              GeometryToolbox::IsParallelOrOpposite(isOpposite, normal, slice.GetAxisY()))
     {
-#if 1
       // Sagittal or coronal projection
 
 #if USE_BOOST_UNION_FOR_POLYGONS == 1
@@ -997,40 +976,33 @@
       // now we need to sort the slabs in increasing Y order (see ConvertListOfSlabsToSegments)
       std::sort(rectanglesForEachSlab.begin(), rectanglesForEachSlab.end(), CompareSlabsY);
 
+      std::vector< std::pair<ScenePoint2D, ScenePoint2D> > segments;
       ConvertListOfSlabsToSegments(segments, rectanglesForEachSlab, projected.size());
+
+      chains.resize(segments.size());
+      for (size_t i = 0; i < segments.size(); i++)
+      {
+        chains[i].resize(2);
+        chains[i][0] = segments[i].first;
+        chains[i][1] = segments[i].second;
+      }
+      
 #else
       BoostMultiPolygon merged;
       Union(merged, projected);
 
-      polygons.resize(merged.size());
+      chains.resize(merged.size());
       for (size_t i = 0; i < merged.size(); i++)
       {
         const std::vector<BoostPoint>& outer = merged[i].outer();
 
-        polygons[i].resize(outer.size());
+        chains[i].resize(outer.size());
         for (size_t j = 0; j < outer.size(); j++)
         {
-          polygons[i][j] = ScenePoint2D(outer[j].x(), outer[j].y());
+          chains[i][j] = ScenePoint2D(outer[j].x(), outer[j].y());
         }
       }  
 #endif
-
-#else
-      for (Polygons::iterator polygon = structure.polygons_.begin();
-           polygon != structure.polygons_.end(); ++polygon)
-      {
-        double x1, y1, x2, y2;
-        if (polygon->Project(x1, y1, x2, y2, slice))
-        {
-          std::vector<ScenePoint2D> p(4);
-          p[0] = std::make_pair(x1, y1);
-          p[1] = std::make_pair(x2, y1);
-          p[2] = std::make_pair(x2, y2);
-          p[3] = std::make_pair(x1, y2);
-          polygons.push_back(p);
-        }
-      }
-#endif
       
       return true;
     }
@@ -1046,38 +1018,15 @@
                                            size_t structureIndex,
                                            const Color& color) const
   {
-#if USE_BOOST_UNION_FOR_POLYGONS == 1
-    std::vector< std::vector<ScenePoint2D> > polygons;
-    if (ProjectStructure(polygons, structureIndex, plane))
+    std::vector< std::vector<ScenePoint2D> > chains;
+    
+    if (ProjectStructure(chains, structureIndex, plane))
     {
-      for (size_t j = 0; j < polygons.size(); j++)
+      for (size_t j = 0; j < chains.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());
+        layer.AddChain(chains[j], false, color.GetRed(), color.GetGreen(), color.GetBlue());
       }
     }
-    
-#else
-    std::vector< std::pair<ScenePoint2D, ScenePoint2D> >  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.GetX(), segments[j].first.GetY());
-        chain[1] = ScenePoint2D(segments[j].second.GetX(), segments[j].second.GetY());
-        layer.AddChain(chain, false, color.GetRed(), color.GetGreen(), color.GetBlue());
-      }
-    }
-#endif
   }
 
 
--- a/OrthancStone/Sources/Toolbox/DicomStructureSet.h	Wed Jan 19 14:51:55 2022 +0100
+++ b/OrthancStone/Sources/Toolbox/DicomStructureSet.h	Wed Jan 26 17:19:37 2022 +0100
@@ -40,8 +40,6 @@
 #  include <DicomParsing/ParsedDicomFile.h>
 #endif
 
-//#define USE_BOOST_UNION_FOR_POLYGONS 1
-
 
 #include <list>
 
@@ -160,14 +158,9 @@
 
     Structure& GetStructure(size_t index);
   
-    bool ProjectStructure(
-#if USE_BOOST_UNION_FOR_POLYGONS == 1
-      std::vector< std::vector<ScenePoint2D> >& polygons,
-#else
-      std::vector< std::pair<ScenePoint2D, ScenePoint2D> >& segments,
-#endif
-      const Structure& structure,
-      const CoordinateSystem3D& slice) const;
+    bool ProjectStructure(std::vector< std::vector<ScenePoint2D> >& chains,
+                          const Structure& structure,
+                          const CoordinateSystem3D& slice) const;
 
     void EstimateGeometry();
     
@@ -207,21 +200,12 @@
 
     Vector GetNormal() const;
 
-#if USE_BOOST_UNION_FOR_POLYGONS == 1
-    bool ProjectStructure(std::vector< std::vector<ScenePoint2D> >& polygons,
+    bool ProjectStructure(std::vector< std::vector<ScenePoint2D> >& chains,
                           size_t index,
                           const CoordinateSystem3D& slice) const
     {
-      return ProjectStructure(polygons, GetStructure(index), slice);
+      return ProjectStructure(chains, GetStructure(index), slice);
     }
-#else
-    bool ProjectStructure(std::vector< std::pair<ScenePoint2D, ScenePoint2D> >& segments,
-                          size_t index,
-                          const CoordinateSystem3D& slice) const
-    {
-      return ProjectStructure(segments, GetStructure(index), slice);
-    }
-#endif
 
     void ProjectOntoLayer(PolylineSceneLayer& layer,
                           const CoordinateSystem3D& plane,
--- a/OrthancStone/Sources/Toolbox/DicomStructureSetUtils.h	Wed Jan 19 14:51:55 2022 +0100
+++ b/OrthancStone/Sources/Toolbox/DicomStructureSetUtils.h	Wed Jan 26 17:19:37 2022 +0100
@@ -49,12 +49,18 @@
 #endif
 
   /** Internal */
-  void ConvertListOfSlabsToSegments(std::vector< std::pair<ScenePoint2D, ScenePoint2D> >& segments, const std::vector<RtStructRectanglesInSlab>& slabCuts, const size_t totalRectCount);
+  void ConvertListOfSlabsToSegments(std::vector< std::pair<ScenePoint2D, ScenePoint2D> >& segments,
+                                    const std::vector<RtStructRectanglesInSlab>& slabCuts,
+                                    const size_t totalRectCount);
 
   /** Internal */
-  void AddSlabBoundaries(std::vector<std::pair<double, RectangleBoundaryKind> >& boundaries, const std::vector<RtStructRectanglesInSlab>& slabCuts, size_t iSlab);
+  void AddSlabBoundaries(std::vector<std::pair<double, RectangleBoundaryKind> >& boundaries,
+                         const std::vector<RtStructRectanglesInSlab>& slabCuts,
+                         size_t iSlab);
 
   /** Internal */
-  void ProcessBoundaryList(std::vector< std::pair<ScenePoint2D, ScenePoint2D> >& segments, const std::vector<std::pair<double, RectangleBoundaryKind> >& boundaries, double y);
+  void ProcessBoundaryList(std::vector< std::pair<ScenePoint2D, ScenePoint2D> >& segments,
+                           const std::vector<std::pair<double, RectangleBoundaryKind> >& boundaries,
+                           double y);
 
 }