Mercurial > hg > orthanc-stone
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); }