# HG changeset patch # User Sebastien Jodogne # Date 1507132427 -7200 # Node ID e66b2c757790282483723e357642192fa7d6dfea # Parent 063f7f3d9f1474f42958fdec161a1326c3b3b289 displaying rt-struct diff -r 063f7f3d9f14 -r e66b2c757790 Applications/Samples/SingleFrameApplication.h --- a/Applications/Samples/SingleFrameApplication.h Wed Oct 04 15:51:34 2017 +0200 +++ b/Applications/Samples/SingleFrameApplication.h Wed Oct 04 17:53:47 2017 +0200 @@ -197,7 +197,7 @@ virtual void NotifyLayerReady(std::auto_ptr& layer, const ILayerSource& source, - const Slice& slice, + const CoordinateSystem3D& slice, bool isError) { } diff -r 063f7f3d9f14 -r e66b2c757790 Applications/Samples/SingleVolumeApplication.h --- a/Applications/Samples/SingleVolumeApplication.h Wed Oct 04 15:51:34 2017 +0200 +++ b/Applications/Samples/SingleVolumeApplication.h Wed Oct 04 17:53:47 2017 +0200 @@ -30,6 +30,9 @@ #include #include +#include // TODO REMOVE +#include "../../Framework/Layers/DicomStructureSetRendererFactory.h" // TODO REMOVE + namespace OrthancStone { namespace Samples @@ -80,10 +83,13 @@ widget_(widget), layer_(layer) { - printf("OOO\n"); } }; + + std::auto_ptr struct_; + + public: virtual void DeclareCommandLineOptions(boost::program_options::options_description& options) { @@ -170,7 +176,7 @@ std::auto_ptr widget(new LayerWidget); -#if 0 +#if 1 std::auto_ptr volume(new OrthancVolumeImage(context.GetWebService(), true)); if (series.empty()) { @@ -195,6 +201,12 @@ widget->SetLayerStyle(0, s); } #else + { + OrthancPlugins::OrthancHttpConnection orthanc; + struct_.reset(new DicomStructureSet(orthanc, "54460695-ba3885ee-ddf61ac0-f028e31d-a6e474d9")); // IBA + //struct_.reset(new DicomStructureSet(orthanc, "17cd032b-ad92a438-ca05f06a-f9e96668-7e3e9e20")); // 0522c0001 TCIA + } + std::auto_ptr ct(new OrthancVolumeImage(context.GetWebService(), false)); //ct->ScheduleLoadSeries("dd069910-4f090474-7d2bba07-e5c10783-f9e4fb1d"); ct->ScheduleLoadSeries("a04ecf01-79b2fc33-58239f7e-ad9db983-28e81afa"); // IBA @@ -209,9 +221,10 @@ widget->AddLayer(new VolumeImageSource(*ct)); widget->AddLayer(new VolumeImageSource(*pet)); + widget->AddLayer(new DicomStructureSetRendererFactory(*struct_)); - //context.AddInteractor(new Interactor(*pet, *widget, projection, 1)); - context.AddInteractor(new VolumeImageInteractor(*ct, *widget, projection)); + context.AddInteractor(new Interactor(*pet, *widget, projection, 1)); + //context.AddInteractor(new VolumeImageInteractor(*ct, *widget, projection)); context.AddVolume(ct.release()); context.AddVolume(pet.release()); diff -r 063f7f3d9f14 -r e66b2c757790 Framework/Layers/DicomStructureSetRendererFactory.cpp --- a/Framework/Layers/DicomStructureSetRendererFactory.cpp Wed Oct 04 15:51:34 2017 +0200 +++ b/Framework/Layers/DicomStructureSetRendererFactory.cpp Wed Oct 04 17:53:47 2017 +0200 @@ -29,12 +29,12 @@ { private: const DicomStructureSet& structureSet_; - SliceGeometry slice_; + CoordinateSystem3D slice_; bool visible_; public: Renderer(const DicomStructureSet& structureSet, - const SliceGeometry& slice) : + const CoordinateSystem3D& slice) : structureSet_(structureSet), slice_(slice), visible_(true) @@ -42,8 +42,7 @@ } virtual bool RenderLayer(CairoContext& context, - const ViewportGeometry& view, - const SliceGeometry& viewportSlice) + const ViewportGeometry& view) { if (visible_) { @@ -54,6 +53,11 @@ return true; } + virtual const CoordinateSystem3D& GetLayerSlice() + { + return slice_; + } + virtual void SetLayerStyle(const RenderStyle& style) { visible_ = style.visible_; @@ -66,22 +70,12 @@ }; - ILayerRenderer* DicomStructureSetRendererFactory::CreateLayerRenderer(const SliceGeometry& displaySlice) + void DicomStructureSetRendererFactory::ScheduleLayerCreation(const CoordinateSystem3D& viewportSlice) { bool isOpposite; - if (GeometryToolbox::IsParallelOrOpposite(isOpposite, displaySlice.GetNormal(), structureSet_.GetNormal())) + if (GeometryToolbox::IsParallelOrOpposite(isOpposite, viewportSlice.GetNormal(), structureSet_.GetNormal())) { - return new Renderer(structureSet_, displaySlice); - } - else - { - return NULL; + NotifyLayerReady(new Renderer(structureSet_, viewportSlice), viewportSlice, false); } } - - - ISliceableVolume& DicomStructureSetRendererFactory::GetSourceVolume() const - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } } diff -r 063f7f3d9f14 -r e66b2c757790 Framework/Layers/DicomStructureSetRendererFactory.h --- a/Framework/Layers/DicomStructureSetRendererFactory.h Wed Oct 04 15:51:34 2017 +0200 +++ b/Framework/Layers/DicomStructureSetRendererFactory.h Wed Oct 04 17:53:47 2017 +0200 @@ -22,11 +22,11 @@ #pragma once #include "../Toolbox/DicomStructureSet.h" -#include "ILayerRendererFactory.h" +#include "LayerSourceBase.h" namespace OrthancStone { - class DicomStructureSetRendererFactory : public ILayerRendererFactory + class DicomStructureSetRendererFactory : public LayerSourceBase { private: class Renderer; @@ -34,27 +34,17 @@ const DicomStructureSet& structureSet_; public: - DicomStructureSetRendererFactory(const DicomStructureSet& structureSet) : + DicomStructureSetRendererFactory(const DicomStructureSet& structureSet) : structureSet_(structureSet) { } - virtual bool GetExtent(double& x1, - double& y1, - double& x2, - double& y2, - const SliceGeometry& displaySlice) + virtual bool GetExtent(std::vector& points, + const CoordinateSystem3D& viewportSlice) { return false; } - virtual ILayerRenderer* CreateLayerRenderer(const SliceGeometry& displaySlice); - - virtual bool HasSourceVolume() const - { - return false; - } - - virtual ISliceableVolume& GetSourceVolume() const; + virtual void ScheduleLayerCreation(const CoordinateSystem3D& viewportSlice); }; } diff -r 063f7f3d9f14 -r e66b2c757790 Framework/Layers/ILayerSource.h --- a/Framework/Layers/ILayerSource.h Wed Oct 04 15:51:34 2017 +0200 +++ b/Framework/Layers/ILayerSource.h Wed Oct 04 17:53:47 2017 +0200 @@ -55,7 +55,7 @@ // std::auto_ptr virtual void NotifyLayerReady(std::auto_ptr& layer, const ILayerSource& source, - const Slice& slice, // TODO Shouldn't this be CoordinateSystem3D? Is it necessary given ILayerS::GetLayerSlice()? + const CoordinateSystem3D& slice, bool isError) = 0; // TODO Shouldn't this be separate as NotifyLayerError? }; diff -r 063f7f3d9f14 -r e66b2c757790 Framework/Layers/LayerSourceBase.cpp --- a/Framework/Layers/LayerSourceBase.cpp Wed Oct 04 15:51:34 2017 +0200 +++ b/Framework/Layers/LayerSourceBase.cpp Wed Oct 04 17:53:47 2017 +0200 @@ -31,12 +31,12 @@ { private: std::auto_ptr layer_; - const Slice& slice_; + const CoordinateSystem3D& slice_; bool isError_; public: LayerReadyFunctor(ILayerRenderer* layer, - const Slice& slice, + const CoordinateSystem3D& slice, bool isError) : layer_(layer), slice_(slice), @@ -73,7 +73,7 @@ } void LayerSourceBase::NotifyLayerReady(ILayerRenderer* layer, - const Slice& slice, + const CoordinateSystem3D& slice, bool isError) { LayerReadyFunctor functor(layer, slice, isError); diff -r 063f7f3d9f14 -r e66b2c757790 Framework/Layers/LayerSourceBase.h --- a/Framework/Layers/LayerSourceBase.h Wed Oct 04 15:51:34 2017 +0200 +++ b/Framework/Layers/LayerSourceBase.h Wed Oct 04 17:53:47 2017 +0200 @@ -43,7 +43,7 @@ void NotifySliceChange(const Slice& slice); void NotifyLayerReady(ILayerRenderer* layer, - const Slice& slice, + const CoordinateSystem3D& slice, bool isError); public: diff -r 063f7f3d9f14 -r e66b2c757790 Framework/Layers/OrthancFrameLayerSource.cpp --- a/Framework/Layers/OrthancFrameLayerSource.cpp Wed Oct 04 15:51:34 2017 +0200 +++ b/Framework/Layers/OrthancFrameLayerSource.cpp Wed Oct 04 17:53:47 2017 +0200 @@ -56,7 +56,7 @@ { bool isFull = (quality == SliceImageQuality_Full); LayerSourceBase::NotifyLayerReady(FrameRenderer::CreateRenderer(image.release(), slice, isFull), - slice, false); + slice.GetGeometry(), false); } void OrthancFrameLayerSource::NotifySliceImageError(const OrthancSlicesLoader& loader, @@ -64,7 +64,7 @@ const Slice& slice, SliceImageQuality quality) { - LayerSourceBase::NotifyLayerReady(NULL, slice, true); + LayerSourceBase::NotifyLayerReady(NULL, slice.GetGeometry(), true); } @@ -124,7 +124,7 @@ else { Slice slice; - LayerSourceBase::NotifyLayerReady(NULL, slice, true); + LayerSourceBase::NotifyLayerReady(NULL, slice.GetGeometry(), true); } } } diff -r 063f7f3d9f14 -r e66b2c757790 Framework/Toolbox/DicomStructureSet.cpp --- a/Framework/Toolbox/DicomStructureSet.cpp Wed Oct 04 15:51:34 2017 +0200 +++ b/Framework/Toolbox/DicomStructureSet.cpp Wed Oct 04 17:53:47 2017 +0200 @@ -232,7 +232,7 @@ if (!tags.GetSequenceSize(countSlices, DicomPath(DICOM_TAG_ROI_CONTOUR_SEQUENCE, i, DICOM_TAG_CONTOUR_SEQUENCE))) { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); + countSlices = 0; } LOG(WARNING) << "New RT structure: \"" << structures_[i].name_ @@ -253,7 +253,7 @@ throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); } - LOG(INFO) << "Parsing slice containing " << countPoints << " vertices"; + //LOG(INFO) << "Parsing slice containing " << countPoints << " vertices"; std::string type = reader.GetMandatoryStringValue(DicomPath(DICOM_TAG_ROI_CONTOUR_SEQUENCE, i, DICOM_TAG_CONTOUR_SEQUENCE, j, @@ -371,6 +371,19 @@ for (Structures::const_iterator structure = structures_.begin(); structure != structures_.end(); ++structure) { + if (structure->name_ != "SKIN" && + structure->name_ != "HEART" && + //structure->name_ != "CORD" && + structure->name_ != "ESOPHAGUS" && + structure->name_ != "LUNG_LT" && + structure->name_ != "LUNG_RT" && + structure->name_ != "GTV_EXH_PRIMARY" && + structure->name_ != "GTV_INH_PRIMARY" && + structure->name_ != "GTV_PRIMARY") + { + continue; + } + for (Polygons::const_iterator polygon = structure->polygons_.begin(); polygon != structure->polygons_.end(); ++polygon) { @@ -394,10 +407,10 @@ slice.ProjectPoint(x, y, *polygon->points_.begin()); cairo_line_to(cr, x, y); + + cairo_stroke(cr); } } } - - cairo_stroke(cr); } } diff -r 063f7f3d9f14 -r e66b2c757790 Framework/Toolbox/OrthancSlicesLoader.cpp --- a/Framework/Toolbox/OrthancSlicesLoader.cpp Wed Oct 04 15:51:34 2017 +0200 +++ b/Framework/Toolbox/OrthancSlicesLoader.cpp Wed Oct 04 17:53:47 2017 +0200 @@ -659,7 +659,6 @@ compressor.Uncompress(raw, answer, size); const Orthanc::DicomImageInformation& info = operation.GetSlice().GetImageInformation(); - unsigned int frame = operation.GetSlice().GetFrame(); if (info.GetBitsAllocated() == 32 && info.GetBitsStored() == 32 && diff -r 063f7f3d9f14 -r e66b2c757790 Framework/Toolbox/Slice.cpp --- a/Framework/Toolbox/Slice.cpp Wed Oct 04 15:51:34 2017 +0200 +++ b/Framework/Toolbox/Slice.cpp Wed Oct 04 17:53:47 2017 +0200 @@ -104,9 +104,6 @@ thickness_ = -thickness_; } - printf("%d: %f %f %f\n", frame_, geometry_.GetOrigin()[0], geometry_.GetOrigin()[1], geometry_.GetOrigin()[2]); - //printf("%f %f %f\n", pixelSpacingX_, pixelSpacingY_, thickness_); - return true; } diff -r 063f7f3d9f14 -r e66b2c757790 Framework/Widgets/LayerWidget.cpp --- a/Framework/Widgets/LayerWidget.cpp Wed Oct 04 15:51:34 2017 +0200 +++ b/Framework/Widgets/LayerWidget.cpp Wed Oct 04 17:53:47 2017 +0200 @@ -33,6 +33,7 @@ { private: CoordinateSystem3D slice_; + double thickness_; size_t countMissing_; std::vector renderers_; @@ -56,11 +57,17 @@ public: Scene(const CoordinateSystem3D& slice, + double thickness, size_t countLayers) : slice_(slice), + thickness_(thickness), countMissing_(countLayers), renderers_(countLayers, NULL) { + if (thickness <= 0) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } } ~Scene() @@ -193,6 +200,34 @@ renderers_[index]->SetLayerStyle(style); } } + + bool ContainsPlane(const CoordinateSystem3D& slice) const + { + bool isOpposite; + if (!GeometryToolbox::IsParallelOrOpposite(isOpposite, + slice.GetNormal(), + slice_.GetNormal())) + { + return false; + } + else + { + double z = (slice_.ProjectAlongNormal(slice.GetOrigin()) - + slice_.ProjectAlongNormal(slice_.GetOrigin())); + + if (z < 0) + { + z = -z; + } + + return z <= thickness_; + } + } + + double GetThickness() const + { + return thickness_; + } }; @@ -266,13 +301,23 @@ void LayerWidget::ResetPendingScene() { - pendingScene_.reset(new Scene(slice_, layers_.size())); + double thickness; + if (pendingScene_.get() == NULL) + { + thickness = 1.0; + } + else + { + thickness = pendingScene_->GetThickness(); + } + + pendingScene_.reset(new Scene(slice_, thickness, layers_.size())); } void LayerWidget::UpdateLayer(size_t index, ILayerRenderer* renderer, - const Slice& slice) + const CoordinateSystem3D& slice) { LOG(INFO) << "Updating layer " << index; @@ -292,13 +337,13 @@ renderer->SetLayerStyle(styles_[index]); if (currentScene_.get() != NULL && - slice.ContainsPlane(currentScene_->GetSlice())) + currentScene_->ContainsPlane(slice)) { currentScene_->SetLayer(index, tmp.release()); NotifyChange(); } else if (pendingScene_.get() != NULL && - slice.ContainsPlane(pendingScene_->GetSlice())) + pendingScene_->ContainsPlane(slice)) { pendingScene_->SetLayer(index, tmp.release()); @@ -483,13 +528,11 @@ void LayerWidget::NotifyLayerReady(std::auto_ptr& renderer, const ILayerSource& source, - const Slice& slice, + const CoordinateSystem3D& slice, bool isError) { size_t index; - if (slice.IsValid() && - LookupLayer(index, source) && - slice.ContainsPlane(slice_)) // Whether the slice comes from an older request + if (LookupLayer(index, source)) { if (isError) { @@ -506,7 +549,8 @@ } else if (isError) { - UpdateLayer(index, new SliceOutlineRenderer(slice), slice); + // TODO + //UpdateLayer(index, new SliceOutlineRenderer(slice), slice); } } } diff -r 063f7f3d9f14 -r e66b2c757790 Framework/Widgets/LayerWidget.h --- a/Framework/Widgets/LayerWidget.h Wed Oct 04 15:51:34 2017 +0200 +++ b/Framework/Widgets/LayerWidget.h Wed Oct 04 17:53:47 2017 +0200 @@ -64,7 +64,7 @@ virtual void NotifyLayerReady(std::auto_ptr& renderer, const ILayerSource& source, - const Slice& slice, + const CoordinateSystem3D& slice, bool isError); void ResetChangedLayers(); @@ -80,7 +80,7 @@ void UpdateLayer(size_t index, ILayerRenderer* renderer, - const Slice& slice); + const CoordinateSystem3D& slice); void InvalidateAllLayers(); diff -r 063f7f3d9f14 -r e66b2c757790 Framework/dev.h --- a/Framework/dev.h Wed Oct 04 15:51:34 2017 +0200 +++ b/Framework/dev.h Wed Oct 04 17:53:47 2017 +0200 @@ -615,13 +615,13 @@ LayerSourceBase::NotifyLayerReady( FrameRenderer::CreateRenderer(frame.release(), *slice, isFullQuality), //new SliceOutlineRenderer(slice), - *slice, false); + slice->GetGeometry(), false); return; } } // Error - Slice slice; + CoordinateSystem3D slice; LayerSourceBase::NotifyLayerReady(NULL, slice, true); } }; @@ -819,7 +819,7 @@ viewportSlice.GetOrigin(), viewportSlice.GetNormal())) { // The two slice are parallel, don't try and display the intersection - NotifyLayerReady(NULL, reference, false); + NotifyLayerReady(NULL, reference.GetGeometry(), false); } else { @@ -834,12 +834,12 @@ extent.GetX1(), extent.GetY1(), extent.GetX2(), extent.GetY2())) { - NotifyLayerReady(new LineLayerRenderer(x1, y1, x2, y2, slice), reference, false); + NotifyLayerReady(new LineLayerRenderer(x1, y1, x2, y2, slice), reference.GetGeometry(), false); } else { // Parallel slices - NotifyLayerReady(NULL, reference, false); + NotifyLayerReady(NULL, reference.GetGeometry(), false); } } } diff -r 063f7f3d9f14 -r e66b2c757790 Resources/CMake/OrthancStoneConfiguration.cmake --- a/Resources/CMake/OrthancStoneConfiguration.cmake Wed Oct 04 15:51:34 2017 +0200 +++ b/Resources/CMake/OrthancStoneConfiguration.cmake Wed Oct 04 17:53:47 2017 +0200 @@ -160,13 +160,13 @@ endif() list(APPEND ORTHANC_STONE_SOURCES - #${ORTHANC_STONE_DIR}/Framework/Layers/DicomStructureSetRendererFactory.cpp #${ORTHANC_STONE_DIR}/Framework/Layers/SeriesFrameRendererFactory.cpp #${ORTHANC_STONE_DIR}/Framework/Layers/SiblingSliceLocationFactory.cpp #${ORTHANC_STONE_DIR}/Framework/Layers/SingleFrameRendererFactory.cpp ${ORTHANC_STONE_DIR}/Framework/Enumerations.cpp ${ORTHANC_STONE_DIR}/Framework/Layers/CircleMeasureTracker.cpp ${ORTHANC_STONE_DIR}/Framework/Layers/ColorFrameRenderer.cpp + ${ORTHANC_STONE_DIR}/Framework/Layers/DicomStructureSetRendererFactory.cpp ${ORTHANC_STONE_DIR}/Framework/Layers/FrameRenderer.cpp ${ORTHANC_STONE_DIR}/Framework/Layers/GrayscaleFrameRenderer.cpp ${ORTHANC_STONE_DIR}/Framework/Layers/LayerSourceBase.cpp diff -r 063f7f3d9f14 -r e66b2c757790 UnitTestsSources/UnitTestsMain.cpp --- a/UnitTestsSources/UnitTestsMain.cpp Wed Oct 04 15:51:34 2017 +0200 +++ b/UnitTestsSources/UnitTestsMain.cpp Wed Oct 04 17:53:47 2017 +0200 @@ -117,7 +117,7 @@ Orthanc::WebServiceParameters web; OrthancStone::OracleWebService orthanc(oracle, web); - OrthancStone::OrthancVolumeImage volume(orthanc); + OrthancStone::OrthancVolumeImage volume(orthanc, true); //volume.ScheduleLoadInstance("19816330-cb02e1cf-df3a8fe8-bf510623-ccefe9f5", 0); //volume.ScheduleLoadSeries("318603c5-03e8cffc-a82b6ee1-3ccd3c1e-18d7e3bb"); // COMUNIX PET