Mercurial > hg > orthanc-stone
changeset 1771:f302bbddf94d
sync, trying to fix DicomVolumeImageReslicer
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 12 May 2021 15:09:32 +0200 |
parents | 073484e33bee |
children | 6c246f862b00 |
files | Applications/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp Applications/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h Applications/Samples/Sdl/CMakeLists.txt OrthancStone/Sources/Loaders/DicomStructureSetLoader.cpp OrthancStone/Sources/Volumes/DicomVolumeImageMPRSlicer.cpp OrthancStone/Sources/Volumes/DicomVolumeImageReslicer.cpp UnitTestsSources/CMakeLists.txt UnitTestsSources/UnitTestsSources.cmake UnitTestsSources/VolumeRenderingTests.cpp |
diffstat | 9 files changed, 171 insertions(+), 48 deletions(-) [+] |
line wrap: on
line diff
--- a/Applications/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp Wed May 12 10:53:37 2021 +0200 +++ b/Applications/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp Wed May 12 15:09:32 2021 +0200 @@ -313,6 +313,37 @@ } + static bool ReadJsonInternal(Json::Value& target, + const void* buffer, + size_t size, + bool collectComments) + { +#if JSONCPP_USE_DEPRECATED == 1 + Json::Reader reader; + return reader.parse(reinterpret_cast<const char*>(buffer), + reinterpret_cast<const char*>(buffer) + size, target, collectComments); +#else + Json::CharReaderBuilder builder; + builder.settings_["collectComments"] = collectComments; + + const std::unique_ptr<Json::CharReader> reader(builder.newCharReader()); + assert(reader.get() != NULL); + + JSONCPP_STRING err; + if (reader->parse(reinterpret_cast<const char*>(buffer), + reinterpret_cast<const char*>(buffer) + size, &target, &err)) + { + return true; + } + else + { + LogError("Cannot parse JSON: " + std::string(err)); + return false; + } +#endif + } + + bool ReadJson(Json::Value& target, const std::string& source) { @@ -324,29 +355,25 @@ const void* buffer, size_t size) { -#if JSONCPP_USE_DEPRECATED == 1 - Json::Reader reader; - return reader.parse(reinterpret_cast<const char*>(buffer), - reinterpret_cast<const char*>(buffer) + size, target); -#else - Json::CharReaderBuilder builder; - const std::unique_ptr<Json::CharReader> reader(builder.newCharReader()); - assert(reader.get() != NULL); - JSONCPP_STRING err; - if (reader->parse(reinterpret_cast<const char*>(buffer), - reinterpret_cast<const char*>(buffer) + size, &target, &err)) - { - return true; - } - else - { - LogError("Cannot parse JSON: " + err); - return false; - } -#endif + return ReadJsonInternal(target, buffer, size, true); } + bool ReadJsonWithoutComments(Json::Value& target, + const std::string& source) + { + return ReadJsonWithoutComments(target, source.empty() ? NULL : source.c_str(), source.size()); + } + + + bool ReadJsonWithoutComments(Json::Value& target, + const void* buffer, + size_t size) + { + return ReadJsonInternal(target, buffer, size, false); + } + + void WriteFastJson(std::string& target, const Json::Value& source) { @@ -2699,10 +2726,18 @@ delete *it; } + size_ = 0; content_.clear(); } - void Flatten(std::string& target) const + /** + * Since Orthanc 1.9.3, this function also clears the content of + * the ChunkedBuffer in order to mimic the behavior of the + * original class "Orthanc::ChunkedBuffer". This prevents the + * forgetting of calling "Clear()" in order to reduce memory + * consumption. + **/ + void Flatten(std::string& target) { target.resize(size_); @@ -2718,10 +2753,14 @@ memcpy(&target[pos], (*it)->c_str(), s); pos += s; } + + delete *it; } - assert(size_ == 0 || - pos == target.size()); + assert(pos == target.size()); + + size_ = 0; + content_.clear(); } void AddChunk(const void* data, @@ -2752,7 +2791,7 @@ return headers_; } - const ChunkedBuffer& GetBody() const + ChunkedBuffer& GetBody() { return body_; }
--- a/Applications/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h Wed May 12 10:53:37 2021 +0200 +++ b/Applications/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h Wed May 12 15:09:32 2021 +0200 @@ -483,6 +483,13 @@ const void* buffer, size_t size); + bool ReadJsonWithoutComments(Json::Value& target, + const std::string& source); + + bool ReadJsonWithoutComments(Json::Value& target, + const void* buffer, + size_t size); + void WriteFastJson(std::string& target, const Json::Value& source);
--- a/Applications/Samples/Sdl/CMakeLists.txt Wed May 12 10:53:37 2021 +0200 +++ b/Applications/Samples/Sdl/CMakeLists.txt Wed May 12 15:09:32 2021 +0200 @@ -22,6 +22,8 @@ project(OrthancStone) +set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "hg") +set(ORTHANC_FRAMEWORK_DEFAULT_VERSION "mainline") include(${CMAKE_SOURCE_DIR}/../../Platforms/Sdl/OrthancStoneSdlParameters.cmake) if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "system") @@ -46,6 +48,7 @@ include(${CMAKE_SOURCE_DIR}/../../Platforms/Sdl/OrthancStoneSdlConfiguration.cmake) include(${CMAKE_SOURCE_DIR}/Utilities.cmake) +include(${CMAKE_SOURCE_DIR}/../../../UnitTestsSources/UnitTestsSources.cmake) if (NOT ORTHANC_FRAMEWORK_SOURCE STREQUAL "system") # This include must be after "OrthancStoneConfiguration.cmake" to @@ -108,16 +111,7 @@ add_executable(UnitTests ${GOOGLE_TEST_SOURCES} - ${CMAKE_SOURCE_DIR}/../../../UnitTestsSources/DicomTests.cpp - ${CMAKE_SOURCE_DIR}/../../../UnitTestsSources/GenericToolboxTests.cpp - ${CMAKE_SOURCE_DIR}/../../../UnitTestsSources/GeometryToolboxTests.cpp - ${CMAKE_SOURCE_DIR}/../../../UnitTestsSources/ImageToolboxTests.cpp - ${CMAKE_SOURCE_DIR}/../../../UnitTestsSources/PixelTestPatternsTests.cpp - ${CMAKE_SOURCE_DIR}/../../../UnitTestsSources/SortedFramesTests.cpp - ${CMAKE_SOURCE_DIR}/../../../UnitTestsSources/TestMessageBroker.cpp - ${CMAKE_SOURCE_DIR}/../../../UnitTestsSources/TestStrategy.cpp - ${CMAKE_SOURCE_DIR}/../../../UnitTestsSources/TestStructureSet.cpp - ${CMAKE_SOURCE_DIR}/../../../UnitTestsSources/UnitTestsMain.cpp + ${UNIT_TESTS_SOURCES} ) target_link_libraries(UnitTests OrthancStone)
--- a/OrthancStone/Sources/Loaders/DicomStructureSetLoader.cpp Wed May 12 10:53:37 2021 +0200 +++ b/OrthancStone/Sources/Loaders/DicomStructureSetLoader.cpp Wed May 12 15:09:32 2021 +0200 @@ -343,6 +343,24 @@ std::unique_ptr<PolylineSceneLayer> layer(new PolylineSceneLayer); layer->SetThickness(2); +#if 0 + // For testing - This displays a cross at the origin of the 3D + // cutting plane in the 2D viewport + { + PolylineSceneLayer::Chain chain; + chain.push_back(ScenePoint2D(-100, 0)); + chain.push_back(ScenePoint2D(100, 0)); + layer->AddChain(chain, false, Color(255, 0, 0)); + } + + { + PolylineSceneLayer::Chain chain; + chain.push_back(ScenePoint2D(0, -100)); + chain.push_back(ScenePoint2D(0, 100)); + layer->AddChain(chain, false, Color(255, 0, 0)); + } +#endif + for (size_t i = 0; i < content_.GetStructuresCount(); i++) { if ((visibility_.size() == 0) || visibility_.at(i))
--- a/OrthancStone/Sources/Volumes/DicomVolumeImageMPRSlicer.cpp Wed May 12 10:53:37 2021 +0200 +++ b/OrthancStone/Sources/Volumes/DicomVolumeImageMPRSlicer.cpp Wed May 12 15:09:32 2021 +0200 @@ -86,6 +86,11 @@ texture.reset(dynamic_cast<TextureBaseSceneLayer*> (configurator->CreateTextureFromDicom(reader.GetAccessor(), parameters))); + + if (texture.get() == NULL) + { + return NULL; + } } const CoordinateSystem3D& system = volume_.GetGeometry().GetProjectionGeometry(projection_);
--- a/OrthancStone/Sources/Volumes/DicomVolumeImageReslicer.cpp Wed May 12 10:53:37 2021 +0200 +++ b/OrthancStone/Sources/Volumes/DicomVolumeImageReslicer.cpp Wed May 12 15:09:32 2021 +0200 @@ -60,7 +60,7 @@ throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, "Must provide a layer style configurator"); } - + reslicer.SetOutputFormat(that_.volume_->GetPixelData().GetFormat()); reslicer.Apply(that_.volume_->GetPixelData(), that_.volume_->GetGeometry(), @@ -68,22 +68,53 @@ if (reslicer.IsSuccess()) { - std::unique_ptr<TextureBaseSceneLayer> layer + std::unique_ptr<TextureBaseSceneLayer> texture (configurator->CreateTextureFromDicom(reslicer.GetOutputSlice(), that_.volume_->GetDicomParameters())); - if (layer.get() == NULL) + if (texture.get() == NULL) { return NULL; } - double s = reslicer.GetPixelSpacing(); - layer->SetPixelSpacing(s, s); - layer->SetOrigin(reslicer.GetOutputExtent().GetX1() + 0.5 * s, - reslicer.GetOutputExtent().GetY1() + 0.5 * s); + const double s = reslicer.GetPixelSpacing(); + +#if 1 + const double x1 = reslicer.GetOutputExtent().GetX1(); + //const double x2 = reslicer.GetOutputExtent().GetX2(); + const double y1 = reslicer.GetOutputExtent().GetY1(); + const double y2 = reslicer.GetOutputExtent().GetY2(); + + const Vector p1 = cuttingPlane.MapSliceToWorldCoordinates(x1, y1); + const Vector p2 = cuttingPlane.MapSliceToWorldCoordinates(x1, y2); + + if (1) + { + texture->SetCuttingPlaneTransform(cuttingPlane, p1, + s * cuttingPlane.GetAxisX(), + s * cuttingPlane.GetAxisY()); + } + else + { + /** + * TODO - ONE WAS TO SOMETIMES FLIP the Y axis. Is it also + * possible for the X axis? + **/ + + texture->SetCuttingPlaneTransform(cuttingPlane, p2, + s * cuttingPlane.GetAxisX(), + -s * cuttingPlane.GetAxisY()); + } + +#else + texture->SetPixelSpacing(s, s); + texture->SetOrigin(reslicer.GetOutputExtent().GetX1() + 0.5 * s, + reslicer.GetOutputExtent().GetY1() + 0.5 * s); + //texture->SetFlipY(true); // TODO - Angle!! +#endif - return layer.release(); + return texture.release(); } else {
--- a/UnitTestsSources/CMakeLists.txt Wed May 12 10:53:37 2021 +0200 +++ b/UnitTestsSources/CMakeLists.txt Wed May 12 15:09:32 2021 +0200 @@ -42,7 +42,13 @@ include(${ORTHANC_STONE_ROOT}/../Resources/CMake/OrthancStoneConfiguration.cmake) include(${CMAKE_CURRENT_SOURCE_DIR}/UnitTestsSources.cmake) -add_executable(UnitTests ${UNIT_TESTS_SOURCES}) +add_executable(UnitTests + ${UNIT_TESTS_SOURCES} + ${AUTOGENERATED_SOURCES} + ${BOOST_EXTENDED_SOURCES} + ${GOOGLE_TEST_SOURCES} + ${ORTHANC_STONE_SOURCES} + ) #####################################################################
--- a/UnitTestsSources/UnitTestsSources.cmake Wed May 12 10:53:37 2021 +0200 +++ b/UnitTestsSources/UnitTestsSources.cmake Wed May 12 15:09:32 2021 +0200 @@ -28,9 +28,5 @@ ${CMAKE_CURRENT_LIST_DIR}/TestStrategy.cpp ${CMAKE_CURRENT_LIST_DIR}/TestStructureSet.cpp ${CMAKE_CURRENT_LIST_DIR}/UnitTestsMain.cpp - - ${AUTOGENERATED_SOURCES} - ${BOOST_EXTENDED_SOURCES} - ${GOOGLE_TEST_SOURCES} - ${ORTHANC_STONE_SOURCES} + ${CMAKE_CURRENT_LIST_DIR}/VolumeRenderingTests.cpp )
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/UnitTestsSources/VolumeRenderingTests.cpp Wed May 12 15:09:32 2021 +0200 @@ -0,0 +1,27 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2021 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero 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 + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include <gtest/gtest.h> + +TEST(VolumeRendering, Basic) +{ +} +