Mercurial > hg > orthanc-stone
changeset 2218:c098f0f16eb1
making subclasses Polygon and Structure uncopyable in DicomStructureSet
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 22 Apr 2025 18:09:13 +0200 |
parents | ccafa8ffcc6a |
children | a10b7a6ec869 |
files | OrthancStone/Sources/Toolbox/DicomStructureSet.cpp OrthancStone/Sources/Toolbox/DicomStructureSet.h |
diffstat | 2 files changed, 96 insertions(+), 55 deletions(-) [+] |
line wrap: on
line diff
--- a/OrthancStone/Sources/Toolbox/DicomStructureSet.cpp Tue Apr 22 17:01:35 2025 +0200 +++ b/OrthancStone/Sources/Toolbox/DicomStructureSet.cpp Tue Apr 22 18:09:13 2025 +0200 @@ -423,14 +423,27 @@ } + DicomStructureSet::Structure::~Structure() + { + for (Polygons::iterator it = polygons_.begin(); it != polygons_.end(); ++it) + { + assert(*it != NULL); + delete *it; + } + } + + const DicomStructureSet::Structure& DicomStructureSet::GetStructure(size_t index) const { if (index >= structures_.size()) { throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); } - - return structures_[index]; + else + { + assert(structures_[index] != NULL); + return *structures_[index]; + } } @@ -440,8 +453,11 @@ { throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); } - - return structures_[index]; + else + { + assert(structures_[index] != NULL); + return *structures_[index]; + } } void DicomStructureSet::Setup(const IDicomDataset& tags) @@ -486,18 +502,19 @@ roiNumbersIndex[roiNumber] = i; - structures_[i].name_ = reader.GetStringValue + structures_[i] = new Structure(); + structures_[i]->name_ = reader.GetStringValue (Orthanc::DicomPath(DICOM_TAG_STRUCTURE_SET_ROI_SEQUENCE, i, DICOM_TAG_ROI_NAME), "No name"); - structures_[i].interpretation_ = "No interpretation"; + structures_[i]->interpretation_ = "No interpretation"; - if (structureNamesIndex_.find(structures_[i].name_) == structureNamesIndex_.end()) + if (structureNamesIndex_.find(structures_[i]->name_) == structureNamesIndex_.end()) { - structureNamesIndex_[structures_[i].name_] = i; + 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_); + "RT-STRUCT with twice the same name for a structure: " + structures_[i]->name_); } } } @@ -535,7 +552,7 @@ throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); } - structures_[found->second].interpretation_ = interpretation; + structures_[found->second]->interpretation_ = interpretation; } } } @@ -568,7 +585,7 @@ throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); } - Structure& target = structures_[found->second]; + Structure& target = *structures_[found->second]; Vector color; if (FastParseVector(color, tags, Orthanc::DicomPath(DICOM_TAG_ROI_CONTOUR_SEQUENCE, i, @@ -676,8 +693,8 @@ LOG(ERROR) << "WARNING. The following Dicom tag (Referenced SOP Instance UID) contains an empty value : // (3006,0039)[" << i << "] / (0x3006, 0x0040)[0] / (0x3006, 0x0016)[0] / (0x0008, 0x1155)"; } - Polygon polygon(sopInstanceUid); - polygon.Reserve(countPoints); + std::unique_ptr<Polygon> polygon(new Polygon(sopInstanceUid)); + polygon->Reserve(countPoints); for (size_t k = 0; k < countPoints; k++) { @@ -685,10 +702,10 @@ v[0] = points[3 * k]; v[1] = points[3 * k + 1]; v[2] = points[3 * k + 2]; - polygon.AddPoint(v); + polygon->AddPoint(v); } - target.polygons_.push_back(polygon); + target.polygons_.push_back(polygon.release()); } } } @@ -713,6 +730,16 @@ #endif + DicomStructureSet::~DicomStructureSet() + { + for (size_t i = 0; i < structures_.size(); i++) + { + assert(structures_[i] != NULL); + delete structures_[i]; + } + } + + const std::string& DicomStructureSet::GetStructureName(size_t index) const { return GetStructure(index).name_; @@ -734,13 +761,14 @@ void DicomStructureSet::GetReferencedInstances(std::set<std::string>& instances) const { - for (Structures::const_iterator structure = structures_.begin(); - structure != structures_.end(); ++structure) + for (size_t i = 0; i < structures_.size(); i++) { - for (Polygons::const_iterator polygon = structure->polygons_.begin(); - polygon != structure->polygons_.end(); ++polygon) + assert(structures_[i] != NULL); + for (Polygons::const_iterator polygon = structures_[i]->polygons_.begin(); + polygon != structures_[i]->polygons_.end(); ++polygon) { - instances.insert(polygon->GetSopInstanceUid()); + assert(*polygon != NULL); + instances.insert((*polygon)->GetSopInstanceUid()); } } } @@ -784,13 +812,15 @@ referencedSlices_[sopInstanceUid] = ReferencedSlice(seriesInstanceUid, geometry, thickness); - for (Structures::iterator structure = structures_.begin(); - structure != structures_.end(); ++structure) + for (size_t i = 0; i < structures_.size(); i++) { - for (Polygons::iterator polygon = structure->polygons_.begin(); - polygon != structure->polygons_.end(); ++polygon) + assert(structures_[i] != NULL); + + for (Polygons::iterator polygon = structures_[i]->polygons_.begin(); + polygon != structures_[i]->polygons_.end(); ++polygon) { - polygon->UpdateReferencedSlice(referencedSlices_); + assert(*polygon != NULL); + (*polygon)->UpdateReferencedSlice(referencedSlices_); } } } @@ -827,15 +857,16 @@ void DicomStructureSet::CheckReferencedSlices() { - for (Structures::iterator structure = structures_.begin(); - structure != structures_.end(); ++structure) + for (size_t i = 0; i < structures_.size(); i++) { - for (Polygons::iterator polygon = structure->polygons_.begin(); - polygon != structure->polygons_.end(); ++polygon) + assert(structures_[i] != NULL); + for (Polygons::iterator polygon = structures_[i]->polygons_.begin(); + polygon != structures_[i]->polygons_.end(); ++polygon) { - if (!polygon->UpdateReferencedSlice(referencedSlices_)) + assert(*polygon != NULL); + if (!(*polygon)->UpdateReferencedSlice(referencedSlices_)) { - std::string sopInstanceUid = polygon->GetSopInstanceUid(); + std::string sopInstanceUid = (*polygon)->GetSopInstanceUid(); if (Orthanc::Toolbox::StripSpaces(sopInstanceUid) == "") { LOG(ERROR) << "DicomStructureSet::CheckReferencedSlices(): " @@ -889,9 +920,10 @@ for (Polygons::const_iterator polygon = structure.polygons_.begin(); polygon != structure.polygons_.end(); ++polygon) { - const Points& points = polygon->GetPoints(); + assert(*polygon != NULL); + const Points& points = (*polygon)->GetPoints(); - if (polygon->IsOnSlice(cutting, GetEstimatedNormal(), GetEstimatedSliceThickness()) && + if ((*polygon)->IsOnSlice(cutting, GetEstimatedNormal(), GetEstimatedSliceThickness()) && !points.empty()) { chains.push_back(std::vector<ScenePoint2D>()); @@ -955,7 +987,8 @@ for (Polygons::const_iterator polygon = structure.polygons_.begin(); polygon != structure.polygons_.end(); ++polygon) { - polygon->Project(rectangles, cutting, GetEstimatedNormal(), GetEstimatedSliceThickness()); + assert(*polygon != NULL); + (*polygon)->Project(rectangles, cutting, GetEstimatedNormal(), GetEstimatedSliceThickness()); } typedef std::list< std::vector<ScenePoint2D> > Contours; @@ -1009,12 +1042,13 @@ // TODO - Could be optimized by adding a multimap on "Structure", mapping // from SOP Instance UID to polygons - for (Polygons::const_iterator it = structure.polygons_.begin(); - it != structure.polygons_.end(); ++it) + for (Polygons::const_iterator polygon = structure.polygons_.begin(); + polygon != structure.polygons_.end(); ++polygon) { - if (it->GetSopInstanceUid() == sopInstanceUid) + assert(*polygon != NULL); + if ((*polygon)->GetSopInstanceUid() == sopInstanceUid) { - target.push_back(it->GetPoints()); + target.push_back((*polygon)->GetPoints()); } } } @@ -1031,13 +1065,16 @@ unsigned int countPolygons = 0; for (size_t i = 0; i < structures_.size(); i++) { - const Polygons& polygons = structures_[i].polygons_; + assert(structures_[i] != NULL); + const Polygons& polygons = structures_[i]->polygons_; - for (Polygons::const_iterator it = polygons.begin(); it != polygons.end(); ++it) + for (Polygons::const_iterator polygon = polygons.begin(); polygon != polygons.end(); ++polygon) { + assert(*polygon != NULL); + countPolygons++; - - const Points& points = it->GetPoints(); + + const Points& points = (*polygon)->GetPoints(); if (points.size() >= 3) { @@ -1114,11 +1151,13 @@ for (size_t i = 0; i < structures_.size(); i++) { - const Polygons& polygons = structures_[i].polygons_; + assert(structures_[i] != NULL); + const Polygons& polygons = structures_[i]->polygons_; - for (Polygons::const_iterator it = polygons.begin(); it != polygons.end(); ++it) + for (Polygons::const_iterator polygon = polygons.begin(); polygon != polygons.end(); ++polygon) { - const Points& points = it->GetPoints(); + assert(*polygon != NULL); + const Points& points = (*polygon)->GetPoints(); polygonsProjection.push_back(GeometryToolbox::ProjectAlongNormal(points[0], estimatedNormal_)); } }
--- a/OrthancStone/Sources/Toolbox/DicomStructureSet.h Tue Apr 22 17:01:35 2025 +0200 +++ b/OrthancStone/Sources/Toolbox/DicomStructureSet.h Tue Apr 22 18:09:13 2025 +0200 @@ -72,7 +72,7 @@ typedef std::vector<Vector> Points; - class Polygon + class Polygon : public boost::noncopyable { private: std::string sopInstanceUid_; @@ -132,9 +132,9 @@ double estimatedSliceThickness) const; }; - typedef std::list<Polygon> Polygons; + typedef std::list<Polygon*> Polygons; - struct Structure + struct Structure : public boost::noncopyable { std::string name_; std::string interpretation_; @@ -142,17 +142,17 @@ uint8_t red_; uint8_t green_; uint8_t blue_; + + ~Structure(); }; - typedef std::vector<Structure> Structures; typedef std::map<std::string, size_t> StructureNamesIndex; - Structures structures_; - ReferencedSlices referencedSlices_; - Vector estimatedNormal_; - double estimatedSliceThickness_; - StructureNamesIndex structureNamesIndex_; - + std::vector<Structure*> structures_; + ReferencedSlices referencedSlices_; + Vector estimatedNormal_; + double estimatedSliceThickness_; + StructureNamesIndex structureNamesIndex_; void Setup(const IDicomDataset& dataset); @@ -176,6 +176,8 @@ explicit DicomStructureSet(Orthanc::ParsedDicomFile& instance); #endif + ~DicomStructureSet(); + size_t GetStructuresCount() const { return structures_.size();