changeset 1945:98952be6fb97

rendering plugin: rendering of multiple structures
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 02 Jun 2022 12:23:45 +0200
parents 3daecfa5791c
children 3c68cdfbdcab
files OrthancStone/Sources/Toolbox/DicomStructureSet.cpp OrthancStone/Sources/Toolbox/DicomStructureSet.h RenderingPlugin/Sources/Plugin.cpp
diffstat 3 files changed, 54 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancStone/Sources/Toolbox/DicomStructureSet.cpp	Thu Jun 02 11:45:28 2022 +0200
+++ b/OrthancStone/Sources/Toolbox/DicomStructureSet.cpp	Thu Jun 02 12:23:45 2022 +0200
@@ -401,6 +401,8 @@
     }
 
     structures_.resize(count);
+    structureNamesIndex_.clear();
+    
     for (size_t i = 0; i < count; i++)
     {
       structures_[i].interpretation_ = reader.GetStringValue
@@ -413,6 +415,16 @@
                             DICOM_TAG_ROI_NAME),
          "No name");
 
+      if (structureNamesIndex_.find(structures_[i].name_) == structureNamesIndex_.end())
+      {
+        structureNamesIndex_[structures_[i].name_] = i;
+      }
+      else
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat,
+                                        "RT-STRUCT with twice the same name for a structure: " + structures_[i].name_);
+      }
+
       Vector color;
       if (FastParseVector(color, tags, Orthanc::DicomPath(DICOM_TAG_ROI_CONTOUR_SEQUENCE, i,
                                                           DICOM_TAG_ROI_DISPLAY_COLOR)) &&
@@ -1018,4 +1030,21 @@
       estimatedSliceThickness_ = LinearAlgebra::ComputeMedian(deltas);
     }
   }
+
+
+  bool DicomStructureSet::LookupStructureName(size_t& structureIndex /* out */,
+                                              const std::string& name) const
+  {
+    StructureNamesIndex::const_iterator found = structureNamesIndex_.find(name);
+
+    if (found == structureNamesIndex_.end())
+    {
+      return false;
+    }
+    else
+    {
+      structureIndex = found->second;
+      return true;
+    }
+  }
 }
--- a/OrthancStone/Sources/Toolbox/DicomStructureSet.h	Thu Jun 02 11:45:28 2022 +0200
+++ b/OrthancStone/Sources/Toolbox/DicomStructureSet.h	Thu Jun 02 12:23:45 2022 +0200
@@ -148,12 +148,15 @@
       uint8_t       blue_;
     };
 
-    typedef std::vector<Structure>  Structures;
+    typedef std::vector<Structure>         Structures;
+    typedef std::map<std::string, size_t>  StructureNamesIndex;
 
     Structures        structures_;
     ReferencedSlices  referencedSlices_;
     Vector            estimatedNormal_;
     double            estimatedSliceThickness_;
+    StructureNamesIndex  structureNamesIndex_;
+    
 
     void Setup(const IDicomDataset& dataset);
     
@@ -235,5 +238,8 @@
     {
       return estimatedSliceThickness_;
     }
+
+    bool LookupStructureName(size_t& structureIndex /* out */,
+                             const std::string& name) const;
   };
 }
--- a/RenderingPlugin/Sources/Plugin.cpp	Thu Jun 02 11:45:28 2022 +0200
+++ b/RenderingPlugin/Sources/Plugin.cpp	Thu Jun 02 12:23:45 2022 +0200
@@ -743,7 +743,7 @@
   };
   
   DataAugmentationParameters dataAugmentation;
-  std::string structureName;
+  std::vector<std::string> structureNames;
   std::string instanceId;
   bool compress = false;
 
@@ -756,7 +756,7 @@
     {
       if (key == "structure")
       {
-        structureName = value;
+        Orthanc::Toolbox::TokenizeString(structureNames, value, ',');
       }
       else if (key == "instance")
       {
@@ -773,10 +773,10 @@
     }
   }
 
-  if (structureName.empty())
+  if (structureNames.empty())
   {
     throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol,
-                                    "Missing option \"structure\" to provide the structure name");
+                                    "Missing option \"structure\" to provide the names of the structures of interest");
   }
 
   if (instanceId.empty())
@@ -787,30 +787,28 @@
   
   std::unique_ptr<OrthancStone::DicomInstanceParameters> parameters(GetInstanceParameters(instanceId));
 
-  std::list< std::vector<OrthancStone::Vector> > polygons;
+  typedef std::list< std::vector<OrthancStone::Vector> > Polygons;
+
+  Polygons polygons;
 
   {
     DicomStructureCache::Accessor accessor(DicomStructureCache::GetSingleton(), request->groups[0]);
 
-    size_t structureIndex;
-    bool found = false;
-    for (size_t i = 0; i < accessor.GetRtStruct().GetStructuresCount(); i++)
+    for (size_t i = 0; i < structureNames.size(); i++)
     {
-      if (accessor.GetRtStruct().GetStructureName(i) == structureName)
+      size_t structureIndex;
+      if (accessor.GetRtStruct().LookupStructureName(structureIndex, structureNames[i]))
       {
-        structureIndex = i;
-        found = true;
-        break;
+        Polygons p;
+        accessor.GetRtStruct().GetStructurePoints(p, structureIndex, parameters->GetSopInstanceUid());
+        polygons.splice(polygons.begin(), p);
+      }
+      else
+      {
+        LOG(WARNING) << "Missing structure name \"" << structureNames[i]
+                     << "\" in RT-STRUCT: " << parameters->GetSopInstanceUid();
       }
     }
-
-    if (!found)
-    {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_InexistentItem,
-                                      "Unknown structure name: " + structureName);
-    }
-
-    accessor.GetRtStruct().GetStructurePoints(polygons, structureIndex, parameters->GetSopInstanceUid());
   }
 
   // We use a "XOR" filler for the polygons in order to deal with holes in the RT-STRUCT