Mercurial > hg > orthanc-stone
diff OrthancStone/Resources/Graveyard/RTStructTentativeReimplementation-BGO/DicomStructureSetUtils.cpp @ 1908:affde38b84de
moved tentative bgo reimplementation of rt-struct into graveyard
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 01 Feb 2022 08:38:32 +0100 |
parents | OrthancStone/Sources/Toolbox/DicomStructureSetUtils.cpp@14c8f339d480 |
children | 07964689cb0b |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancStone/Resources/Graveyard/RTStructTentativeReimplementation-BGO/DicomStructureSetUtils.cpp Tue Feb 01 08:38:32 2022 +0100 @@ -0,0 +1,274 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2022 Osimis S.A., Belgium + * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/>. + **/ + +#include "DicomStructureSetUtils.h" + +namespace OrthancStone +{ + +#if 0 + void DicomStructure2::PartitionRectangleList(std::vector< std::vector<size_t> > & sets, const std::vector<RtStructRectanglesInSlab> slabCuts) + { + // map position ( <slabIndex,rectIndex> )--> disjoint set index + std::map<std::pair<size_t, size_t>, size_t> posToIndex; + + // disjoint set index --> position + std::map<size_t, std::pair<size_t, size_t> > indexToPos; + + size_t nextIndex = 0; + for (size_t i = 0; i < slabCuts.size(); ++i) + { + for (size_t j = 0; j < slabCuts[i].size(); ++j) + { + std::pair<size_t, size_t> pos(i, j); + posToIndex<pos> = nextIndex; + indexToPos<nextIndex> = pos; + } + } + // nextIndex is now the total rectangle count + DisjointDataSet ds(nextIndex); + + // we loop on all slabs (except the last one) and we connect all rectangles + if (slabCuts.size() < 2) + { +#error write special case + } + else + { + for (size_t i = 0; i < slabCuts.size() - 1; ++i) + { + for (size_t j = 0; j < slabCuts[i].size(); ++j) + { + const RtStructRectangleInSlab& r1 = slabCuts[i][j]; + const size_t r1i = posToIndex(std::pair<size_t, size_t>(i, j)); + for (size_t k = 0; k < slabCuts[i + 1].size(); ++k) + { + const RtStructRectangleInSlab& r2 = slabCuts[i + 1][k]; + const size_t r2i = posToIndex(std::pair<size_t, size_t>(i, j)); + // rect.xmin <= rectBottom.xmax && rectBottom.xmin <= rect.xmax + if ((r1.xmin <= r2.xmax) && (r2.xmin <= r1.xmax)) + { +#error now go! + } + + } + } + } + } +#endif + + /* + + compute list of segments : + + numberOfRectsFromHereOn = 0 + possibleNext = {in_k,in_kplus1} + + for all boundaries: + - we create a vertical segment and we push it + - if boundary is a start, numberOfRectsFromHereOn += 1. + - if we switch from 0 to 1, we start a segment + - if we switch from 1 to 2, we end the current segment and we record it + - if boundary is an end, numberOfRectsFromHereOn -= 1. + - if we switch from 1 to 0, we end the current segment and we record it + - if we switch from 2 to 1, we start a segment + */ + + // static + void AddSlabBoundaries( + std::vector<std::pair<double, RectangleBoundaryKind> > & boundaries, + const std::vector<RtStructRectanglesInSlab> & slabCuts, size_t iSlab) + { + if (iSlab < slabCuts.size()) + { + const RtStructRectanglesInSlab& slab = slabCuts[iSlab]; + for (size_t iRect = 0; iRect < slab.size(); ++iRect) + { + const RtStructRectangleInSlab& rect = slab[iRect]; + { + std::pair<double, RectangleBoundaryKind> boundary(rect.xmin, RectangleBoundaryKind_Start); + boundaries.insert(std::lower_bound(boundaries.begin(), boundaries.end(), boundary), boundary); + } + { + std::pair<double, RectangleBoundaryKind> boundary(rect.xmax, RectangleBoundaryKind_End); + boundaries.insert(std::lower_bound(boundaries.begin(), boundaries.end(), boundary), boundary); + } + } + } + } + + // static + void ProcessBoundaryList( + std::vector< std::pair<ScenePoint2D, ScenePoint2D> > & segments, + const std::vector<std::pair<double, RectangleBoundaryKind> > & boundaries, + double y) + { + ScenePoint2D start; + ScenePoint2D end; + int curNumberOfSegments = 0; // we count the number of segments. we only draw if it is 1 (not 0 or 2) + for (size_t i = 0; i < boundaries.size(); ++i) + { + switch (boundaries[i].second) + { + case RectangleBoundaryKind_Start: + curNumberOfSegments += 1; + switch (curNumberOfSegments) + { + case 0: + assert(false); + break; + case 1: + // a new segment has begun! + start = ScenePoint2D(boundaries[i].first, y); + break; + case 2: + // an extra segment has begun : stop the current one (we don't draw overlaps) + end = ScenePoint2D(boundaries[i].first, y); + segments.push_back(std::pair<ScenePoint2D, ScenePoint2D>(start, end)); + break; + default: + //assert(false); // seen IRL ! + break; + } + break; + case RectangleBoundaryKind_End: + curNumberOfSegments -= 1; + switch (curNumberOfSegments) + { + case 0: + // a lone (thus active) segment has ended. + end = ScenePoint2D(boundaries[i].first, y); + segments.push_back(std::pair<ScenePoint2D, ScenePoint2D>(start, end)); + break; + case 1: + // an extra segment has ended : start a new one one + start = ScenePoint2D(boundaries[i].first, y); + break; + default: + // this should not happen! + //assert(false); + break; + } + break; + default: + assert(false); + break; + } + } + } + +#if 0 + void ConvertListOfSlabsToSegments( + std::vector< std::pair<ScenePoint2D, ScenePoint2D> >& segments, + const std::vector<RtStructRectanglesInSlab>& slabCuts, + const size_t totalRectCount) + { +#error to delete + } +#else + // See https://www.dropbox.com/s/bllco6q8aazxk44/2019-09-18-rtstruct-cut-algorithm-rect-merge.png + void ConvertListOfSlabsToSegments( + std::vector< std::pair<ScenePoint2D, ScenePoint2D> > & segments, + const std::vector<RtStructRectanglesInSlab> & slabCuts, + const size_t totalRectCount) + { + if (slabCuts.size() == 0) + return; + + if (totalRectCount > 0) + segments.reserve(4 * totalRectCount); // worst case, but common. + + /* + VERTICAL + */ + for (size_t iSlab = 0; iSlab < slabCuts.size(); ++iSlab) + { + for (size_t iRect = 0; iRect < slabCuts[iSlab].size(); ++iRect) + { + const RtStructRectangleInSlab& rect = slabCuts[iSlab][iRect]; + { + ScenePoint2D p1(rect.xmin, rect.ymin); + ScenePoint2D p2(rect.xmin, rect.ymax); + segments.push_back(std::pair<ScenePoint2D, ScenePoint2D>(p1, p2)); + } + { + ScenePoint2D p1(rect.xmax, rect.ymin); + ScenePoint2D p2(rect.xmax, rect.ymax); + segments.push_back(std::pair<ScenePoint2D, ScenePoint2D>(p1, p2)); + } + } + } + + /* + HORIZONTAL + */ + + // if we have N slabs, we have N+1 potential vertical positions for horizontal segments + // - one for top of slab 0 + // - N-1 for all positions between two slabs + // - one for bottom of slab N-1 + + // this adds all the horizontal segments for the tops of 3the rectangles + // in row 0 + if (slabCuts[0].size() > 0) + { + std::vector<std::pair<double, RectangleBoundaryKind> > boundaries; + AddSlabBoundaries(boundaries, slabCuts, 0); + + ProcessBoundaryList(segments, boundaries, slabCuts[0][0].ymin); + } + + // this adds all the horizontal segments belonging to two slabs + for (size_t iSlab = 0; iSlab < slabCuts.size() - 1; ++iSlab) + { + std::vector<std::pair<double, RectangleBoundaryKind> > boundaries; + AddSlabBoundaries(boundaries, slabCuts, iSlab); + AddSlabBoundaries(boundaries, slabCuts, iSlab + 1); + double curY = 0; + if (slabCuts[iSlab].size() > 0) + { + curY = slabCuts[iSlab][0].ymax; + ProcessBoundaryList(segments, boundaries, curY); + } + else if (slabCuts[iSlab + 1].size() > 0) + { + curY = slabCuts[iSlab + 1][0].ymin; + ProcessBoundaryList(segments, boundaries, curY); + } + else + { + // nothing to do!! : both slab lists are empty! + } + } + + // this adds all the horizontal segments for the BOTTOM of the rectangles + // on last row + if (slabCuts[slabCuts.size() - 1].size() > 0) + { + std::vector<std::pair<double, RectangleBoundaryKind> > boundaries; + AddSlabBoundaries(boundaries, slabCuts, slabCuts.size() - 1); + + ProcessBoundaryList(segments, boundaries, slabCuts[slabCuts.size() - 1][0].ymax); + } + } +#endif + }