diff --git a/.github/workflows/build_macos.yml b/.github/workflows/build_macos.yml
index e31c49153..eca2f61bf 100644
--- a/.github/workflows/build_macos.yml
+++ b/.github/workflows/build_macos.yml
@@ -13,7 +13,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- os: [macos-13, macos-12]
+ os: [macos-14, macos-13, macos-12]
build_type: [Debug, Release]
runs-on: ${{ matrix.os }}
@@ -33,33 +33,42 @@ jobs:
- name: Install dependencies
run: |
- brew install vtk wxmac
- echo "MACOS_QT5_HINT=$(brew --prefix qt5)" >> $GITHUB_ENV
+ brew install vtk wxwidgets
+ echo "MACOS_QT5_HINT=$(brew --prefix qt@5)" >> $GITHUB_ENV
- name: Create Build Environment
run: cmake -E make_directory ${{runner.workspace}}/build
- - name: Configure CMake
+ - name: Configure CMake (macOS 12, 13)
+ if: ${{ (matrix.os == 'macos-12') || (matrix.os == 'macos-13') }}
shell: bash
working-directory: ${{runner.workspace}}/build
run: |
cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=${{matrix.build_type}} -DCMAKE_PREFIX_PATH=${{ env.MACOS_QT5_HINT }}
+ - name: Configure CMake (macOS 14)
+ if: matrix.os == 'macos-14'
+ shell: bash
+ working-directory: ${{runner.workspace}}/build
+ run: |
+ cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=${{matrix.build_type}} -DCMAKE_PREFIX_PATH=${{ env.MACOS_QT5_HINT }} -DUSE_SSE=False
+
- name: Build
shell: bash
working-directory: ${{runner.workspace}}/build
run: cmake --build . --config ${{matrix.build_type}}
- name: Test (with OpenCL)
- if: matrix.build_type == 'Release'
+ if: ${{ (matrix.build_type == 'Release') && (matrix.os != 'macos-14') }}
# Run the full suite of tests since OpenCL is available
+ # Since macOS 14, OpenCL is no longer supported. :(
shell: bash
working-directory: ${{runner.workspace}}/build
- run: ctest -C ${{matrix.build_type}}
+ run: ctest --output-on-failure -C ${{matrix.build_type}}
- name: Test (without OpenCL)
- if: matrix.build_type == 'Debug'
+ if: ${{ (matrix.build_type == 'Debug') || (matrix.os == 'macos-14') }}
# Run a restricted suite of tests (OpenCL is available but the tests are slow on Debug)
shell: bash
working-directory: ${{runner.workspace}}/build
- run: ctest -R rdy -C ${{matrix.build_type}}
+ run: ctest --output-on-failure -R rdy -C ${{matrix.build_type}}
diff --git a/.github/workflows/build_ubuntu.yml b/.github/workflows/build_ubuntu.yml
index 11be2b2bb..5e93df340 100644
--- a/.github/workflows/build_ubuntu.yml
+++ b/.github/workflows/build_ubuntu.yml
@@ -25,7 +25,14 @@ jobs:
- name: git clone
uses: actions/checkout@v4
- - name: Install dependencies
+ - name: Install dependencies (24.04)
+ if: matrix.os == 'ubuntu-24.04'
+ run: |
+ sudo apt-get update
+ sudo apt-get install libvtk9-dev ocl-icd-opencl-dev libgtk-3-dev libwxgtk3.2-dev libpocl2 qtbase5-dev qtdeclarative5-dev
+
+ - name: Install dependencies (22.04, 20.04)
+ if: ${{ (matrix.os == 'ubuntu-22.04') || (matrix.os == 'ubuntu-20.04') }}
run: |
sudo apt-get update
sudo apt-get install libvtk7-dev ocl-icd-opencl-dev libgtk-3-dev libwxgtk3.0-gtk3-dev libpocl2
diff --git a/BUILD.txt b/BUILD.txt
index 46f2116f9..ce0c4de76 100644
--- a/BUILD.txt
+++ b/BUILD.txt
@@ -97,7 +97,9 @@ C) Build Ready:
A) Dependencies:
On Debian/Ubuntu:
-sudo apt-get install libgtk-3-dev libxt-dev ocl-icd-opencl-dev libglu1-mesa-dev libvtk7-dev libwxgtk3.0-gtk3-dev cmake-curses-gui build-essential git
+sudo apt-get install libgtk-3-dev libxt-dev ocl-icd-opencl-dev libglu1-mesa-dev libvtk9-dev libwxgtk3.2-dev cmake-curses-gui build-essential git
+
+(Or look at .github/workflows/build_ubuntu.yml)
On Fedora:
sudo dnf install vtk-devel wxGTK3-devel ocl-icd-devel opencl-headers gcc-c++
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 457686ad3..4b086a9ad 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright 2011-2021 The Ready Bunch
+# Copyright 2011-2024 The Ready Bunch
#
# This file is part of Ready.
#
@@ -411,9 +411,9 @@ endif()
#-------------------------------------------wxWidgets----------------------------------------------
if( APPLE )
- # on macOS it's best to use locally installed wxWidgets headers and libs
- set( wxWidgets_CONFIG_EXECUTABLE /usr/local/bin/wx-config )
- set( wxWidgets_wxrc_EXECUTABLE /usr/local/bin/wxrc ) # not used, but no harm leaving it in
+ # on macOS you might want to to use locally installed wxWidgets headers and libs:
+ # set( wxWidgets_CONFIG_EXECUTABLE /usr/local/bin/wx-config )
+ # set( wxWidgets_wxrc_EXECUTABLE /usr/local/bin/wxrc ) # not used, but no harm leaving it in
elseif(UNIX)
# remove -rdynamic from link options on Linux to reduce size by about 1.2MB
set( CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "" )
@@ -448,17 +448,9 @@ else()
ENDIF(VTK_USE_COCOA)
else()
find_package(PkgConfig)
- if("-lwx_gtk2u_core-3.0" IN_LIST wxWidgets_LIBRARIES)
- pkg_check_modules(GTK2 REQUIRED gtk+-2.0)
- include_directories(${GTK2_INCLUDE_DIRS})
- link_libraries(${GTK2_LIBRARIES})
- elseif("-lwx_gtk3u_core-3.0" IN_LIST wxWidgets_LIBRARIES)
- pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
- include_directories(${GTK3_INCLUDE_DIRS})
- link_libraries(${GTK3_LIBRARIES})
- else()
- message(FATAL_ERROR "Didn't find -lwx_gtk2u_core-3.0 or -lwx_gtk3u_core-3.0 in wxWidgets_LIBRARIES - unable to detect GTK version to use: ${wxWidgets_LIBRARIES}")
- endif()
+ pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
+ include_directories(${GTK3_INCLUDE_DIRS})
+ link_libraries(${GTK3_LIBRARIES})
endif()
endif()
diff --git a/Help/about.html b/Help/about.html
index 499d952e0..e3c1cd6ee 100644
--- a/Help/about.html
+++ b/Help/about.html
@@ -7,7 +7,7 @@
Ready, version 0.11.0
-
Copyright 2011-2021 The Ready Bunch:
+
Copyright 2011-2024 The Ready Bunch:
Tim Hutton, Robert Munafo, Andrew Trevorrow,
Tom Rokicki, Dan Wills.
diff --git a/README.md b/README.md
index ec6319c75..b36ea6554 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,7 @@ Ready supports 1D, 2D and 3D data, as well as polygonal and polyhedral meshes.
Linux:
```
-sudo apt-get install libgtk-3-dev libxt-dev ocl-icd-opencl-dev libglu1-mesa-dev libvtk7-dev libwxgtk3.0-gtk3-dev cmake-curses-gui build-essential git
+sudo apt-get install libgtk-3-dev libxt-dev ocl-icd-opencl-dev libglu1-mesa-dev libvtk9-dev libwxgtk3.2-dev cmake-curses-gui build-essential git
git clone https://github.com/GollyGang/ready.git
cd ready
cmake -DCMAKE_BUILD_TYPE=Release .
diff --git a/README.txt b/README.txt
index 9c9572e4c..9703555ce 100644
--- a/README.txt
+++ b/README.txt
@@ -15,7 +15,7 @@ See Help/credits.html for a list of credits and acknowledgements.
License
---------------------------------------------------------------------------------
-Copyright 2011-2021 The Ready Bunch
+Copyright 2011-2024 The Ready Bunch
The Ready Bunch is: Tim Hutton, Robert Munafo, Andrew Trevorrow, Tom Rokicki, Dan Wills
diff --git a/resources/Info.plist.in b/resources/Info.plist.in
index 584eaa45b..e6378b150 100644
--- a/resources/Info.plist.in
+++ b/resources/Info.plist.in
@@ -23,7 +23,7 @@
CFBundleShortVersionString
VERSION
CFBundleGetInfoString
- Ready version VERSION, Copyright 2011-2021 The Ready Bunch
+ Ready version VERSION, Copyright 2011-2024 The Ready Bunch
LSRequiresCarbon
NSRequiresAquaSystemAppearance
diff --git a/src/cmd/main.cpp b/src/cmd/main.cpp
index af7b4f3be..5416509a1 100644
--- a/src/cmd/main.cpp
+++ b/src/cmd/main.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/gui/HelpPanel.cpp b/src/gui/HelpPanel.cpp
index decdbe3cb..396a6464e 100644
--- a/src/gui/HelpPanel.cpp
+++ b/src/gui/HelpPanel.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/gui/HelpPanel.hpp b/src/gui/HelpPanel.hpp
index ba440ee4f..2bf335802 100644
--- a/src/gui/HelpPanel.hpp
+++ b/src/gui/HelpPanel.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/gui/HtmlInfo.cpp b/src/gui/HtmlInfo.cpp
index 98f7c10db..0e7555d2f 100644
--- a/src/gui/HtmlInfo.cpp
+++ b/src/gui/HtmlInfo.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/gui/HtmlInfo.hpp b/src/gui/HtmlInfo.hpp
index a727d016e..0fc1d2b49 100644
--- a/src/gui/HtmlInfo.hpp
+++ b/src/gui/HtmlInfo.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/gui/IDs.hpp b/src/gui/IDs.hpp
index 82d3a407d..faffe0685 100644
--- a/src/gui/IDs.hpp
+++ b/src/gui/IDs.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/gui/ImportImageDialog.cpp b/src/gui/ImportImageDialog.cpp
index d28159a52..d07b72266 100644
--- a/src/gui/ImportImageDialog.cpp
+++ b/src/gui/ImportImageDialog.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/gui/ImportImageDialog.hpp b/src/gui/ImportImageDialog.hpp
index 08e72006c..e347dc51e 100644
--- a/src/gui/ImportImageDialog.hpp
+++ b/src/gui/ImportImageDialog.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/gui/InfoPanel.cpp b/src/gui/InfoPanel.cpp
index 0467520e7..3c9c3ee70 100644
--- a/src/gui/InfoPanel.cpp
+++ b/src/gui/InfoPanel.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/gui/InfoPanel.hpp b/src/gui/InfoPanel.hpp
index 5919d3a72..d019710af 100644
--- a/src/gui/InfoPanel.hpp
+++ b/src/gui/InfoPanel.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/gui/InteractorStylePainter.cpp b/src/gui/InteractorStylePainter.cpp
index 2470eae03..679342bdb 100644
--- a/src/gui/InteractorStylePainter.cpp
+++ b/src/gui/InteractorStylePainter.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/gui/InteractorStylePainter.hpp b/src/gui/InteractorStylePainter.hpp
index 43f01a52a..813d0e711 100644
--- a/src/gui/InteractorStylePainter.hpp
+++ b/src/gui/InteractorStylePainter.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/gui/MakeNewSystem.cpp b/src/gui/MakeNewSystem.cpp
index 24c63d825..73de98ef2 100644
--- a/src/gui/MakeNewSystem.cpp
+++ b/src/gui/MakeNewSystem.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/gui/MakeNewSystem.hpp b/src/gui/MakeNewSystem.hpp
index 7dfd882a1..2dbf21582 100644
--- a/src/gui/MakeNewSystem.hpp
+++ b/src/gui/MakeNewSystem.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/gui/PatternsPanel.cpp b/src/gui/PatternsPanel.cpp
index bb91773d6..1eccecc7c 100644
--- a/src/gui/PatternsPanel.cpp
+++ b/src/gui/PatternsPanel.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/gui/PatternsPanel.hpp b/src/gui/PatternsPanel.hpp
index b968c218e..9b53c64af 100644
--- a/src/gui/PatternsPanel.hpp
+++ b/src/gui/PatternsPanel.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/gui/RecordingDialog.cpp b/src/gui/RecordingDialog.cpp
index b4fabcd46..a07a8f96e 100644
--- a/src/gui/RecordingDialog.cpp
+++ b/src/gui/RecordingDialog.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/gui/RecordingDialog.hpp b/src/gui/RecordingDialog.hpp
index 1978bc191..b2e6fd8cb 100644
--- a/src/gui/RecordingDialog.hpp
+++ b/src/gui/RecordingDialog.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/gui/app.cpp b/src/gui/app.cpp
index 7b5040a10..17fa9cd67 100644
--- a/src/gui/app.cpp
+++ b/src/gui/app.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/gui/app.hpp b/src/gui/app.hpp
index 7c7745b93..405c97801 100644
--- a/src/gui/app.hpp
+++ b/src/gui/app.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/gui/dialogs.cpp b/src/gui/dialogs.cpp
index a46405ec8..1c2ccc97a 100644
--- a/src/gui/dialogs.cpp
+++ b/src/gui/dialogs.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/gui/dialogs.hpp b/src/gui/dialogs.hpp
index e2ae43a73..3f677ee18 100644
--- a/src/gui/dialogs.hpp
+++ b/src/gui/dialogs.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/gui/frame.cpp b/src/gui/frame.cpp
index efd9db4ea..3d246209a 100644
--- a/src/gui/frame.cpp
+++ b/src/gui/frame.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
@@ -327,7 +327,7 @@ MyFrame::MyFrame(const wxString& title)
s->SetModified(false);
s->SetFilename("untitled");
s->GenerateInitialPattern();
- this->SetCurrentRDSystem(move(s));
+ this->SetCurrentRDSystem(std::move(s));
}
}
@@ -988,7 +988,7 @@ void MyFrame::OnAddMyPatterns(wxCommandEvent& event)
void MyFrame::SetCurrentRDSystem(unique_ptr sys)
{
- this->system = move(sys);
+ this->system = std::move(sys);
int iChem = IndexFromChemicalName(this->render_settings.GetProperty("active_chemical").GetChemical());
iChem = min(iChem,this->system->GetNumberOfChemicals()-1); // ensure is in valid range
this->render_settings.GetProperty("active_chemical").SetChemical(GetChemicalName(iChem));
@@ -1608,7 +1608,7 @@ void MyFrame::OnNewPattern(wxCommandEvent& event)
this->SetStatusText(_("Generating data values..."));
sys->CreateDefaultInitialPatternGenerator(sys->GetNumberOfChemicals());
sys->GenerateInitialPattern();
- this->SetCurrentRDSystem(move(sys));
+ this->SetCurrentRDSystem(std::move(sys));
this->system->SetFilename("untitled");
this->system->SetModified(false);
@@ -1680,7 +1680,7 @@ void MyFrame::OpenFile(const wxString& raw_path, bool remember)
SetDefaultRenderSettings(this->render_settings);
target_system = SystemFactory::CreateFromFile(path.mb_str(),this->is_opencl_available,opencl_platform,opencl_device,this->render_settings,warn_to_update);
this->patterns_panel->SelectPath(path);
- this->SetCurrentRDSystem(move(target_system));
+ this->SetCurrentRDSystem(std::move(target_system));
}
catch(const exception& e)
{
@@ -2715,7 +2715,7 @@ void MyFrame::MakeDefaultImageSystemFromMesh(vtkUnstructuredGrid* ug)
image_sys->CreateDefaultInitialPatternGenerator(2);
image_sys->GenerateInitialPattern();
this->render_settings.GetProperty("timesteps_per_render").SetInt(16);
- this->SetCurrentRDSystem(move(image_sys));
+ this->SetCurrentRDSystem(std::move(image_sys));
}
// ---------------------------------------------------------------------
@@ -2734,7 +2734,7 @@ void MyFrame::MakeDefaultMeshSystemFromMesh(vtkUnstructuredGrid* ug)
mesh_sys->SetNumberOfChemicals(2);
mesh_sys->CreateDefaultInitialPatternGenerator(2);
mesh_sys->GenerateInitialPattern();
- this->SetCurrentRDSystem(move(mesh_sys));
+ this->SetCurrentRDSystem(std::move(mesh_sys));
}
// ---------------------------------------------------------------------
@@ -3515,7 +3515,7 @@ void MyFrame::OnConvertToFullKernel(wxCommandEvent& event)
wxMessageBox(wxString::Format(_T("Error converting rule: %s"),e.what()));
return;
}
- this->SetCurrentRDSystem(move(sys));
+ this->SetCurrentRDSystem(std::move(sys));
}
// ---------------------------------------------------------------------
diff --git a/src/gui/frame.hpp b/src/gui/frame.hpp
index d5623e3f9..e82e54d3a 100644
--- a/src/gui/frame.hpp
+++ b/src/gui/frame.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/gui/prefs.cpp b/src/gui/prefs.cpp
index 8396d62f6..a8d3b255b 100644
--- a/src/gui/prefs.cpp
+++ b/src/gui/prefs.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/gui/prefs.hpp b/src/gui/prefs.hpp
index c28687a89..f4f213db1 100644
--- a/src/gui/prefs.hpp
+++ b/src/gui/prefs.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/gui/vtk_pipeline.cpp b/src/gui/vtk_pipeline.cpp
index 431df29b0..111f3135d 100644
--- a/src/gui/vtk_pipeline.cpp
+++ b/src/gui/vtk_pipeline.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/gui/vtk_pipeline.hpp b/src/gui/vtk_pipeline.hpp
index f3ec7dc96..f92e890a4 100644
--- a/src/gui/vtk_pipeline.hpp
+++ b/src/gui/vtk_pipeline.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/gui/wxutils.cpp b/src/gui/wxutils.cpp
index 6a129ea60..cde6aa339 100644
--- a/src/gui/wxutils.cpp
+++ b/src/gui/wxutils.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/gui/wxutils.hpp b/src/gui/wxutils.hpp
index f502c1186..3ab7be55a 100644
--- a/src/gui/wxutils.hpp
+++ b/src/gui/wxutils.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/readybase/AbstractRD.cpp b/src/readybase/AbstractRD.cpp
index 9789abfe8..abe7d9175 100644
--- a/src/readybase/AbstractRD.cpp
+++ b/src/readybase/AbstractRD.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
@@ -23,7 +23,9 @@
#include
// SSE:
+#if USE_SSE
#include
+#endif
using namespace std;
diff --git a/src/readybase/AbstractRD.hpp b/src/readybase/AbstractRD.hpp
index 050f4c792..9f795e8fa 100644
--- a/src/readybase/AbstractRD.hpp
+++ b/src/readybase/AbstractRD.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/readybase/FormulaOpenCLImageRD.cpp b/src/readybase/FormulaOpenCLImageRD.cpp
index 1226d37c4..e34500ad7 100644
--- a/src/readybase/FormulaOpenCLImageRD.cpp
+++ b/src/readybase/FormulaOpenCLImageRD.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/readybase/FormulaOpenCLImageRD.hpp b/src/readybase/FormulaOpenCLImageRD.hpp
index 828852afd..ef379d939 100644
--- a/src/readybase/FormulaOpenCLImageRD.hpp
+++ b/src/readybase/FormulaOpenCLImageRD.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/readybase/FormulaOpenCLMeshRD.cpp b/src/readybase/FormulaOpenCLMeshRD.cpp
index 7e5f113ef..5a8b22bdc 100644
--- a/src/readybase/FormulaOpenCLMeshRD.cpp
+++ b/src/readybase/FormulaOpenCLMeshRD.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/readybase/FormulaOpenCLMeshRD.hpp b/src/readybase/FormulaOpenCLMeshRD.hpp
index f76ec2ce7..89ec3f272 100644
--- a/src/readybase/FormulaOpenCLMeshRD.hpp
+++ b/src/readybase/FormulaOpenCLMeshRD.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/readybase/FullKernelOpenCLImageRD.cpp b/src/readybase/FullKernelOpenCLImageRD.cpp
index a3ed0fbf5..dd70fb5ee 100644
--- a/src/readybase/FullKernelOpenCLImageRD.cpp
+++ b/src/readybase/FullKernelOpenCLImageRD.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/readybase/FullKernelOpenCLImageRD.hpp b/src/readybase/FullKernelOpenCLImageRD.hpp
index 5be5650a6..7681403ff 100644
--- a/src/readybase/FullKernelOpenCLImageRD.hpp
+++ b/src/readybase/FullKernelOpenCLImageRD.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/readybase/FullKernelOpenCLMeshRD.cpp b/src/readybase/FullKernelOpenCLMeshRD.cpp
index 8fce537bc..c0273ee18 100644
--- a/src/readybase/FullKernelOpenCLMeshRD.cpp
+++ b/src/readybase/FullKernelOpenCLMeshRD.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/readybase/FullKernelOpenCLMeshRD.hpp b/src/readybase/FullKernelOpenCLMeshRD.hpp
index 59e58249c..495ace51c 100644
--- a/src/readybase/FullKernelOpenCLMeshRD.hpp
+++ b/src/readybase/FullKernelOpenCLMeshRD.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/readybase/GrayScottImageRD.cpp b/src/readybase/GrayScottImageRD.cpp
index b1446ae6e..5739a2dd7 100644
--- a/src/readybase/GrayScottImageRD.cpp
+++ b/src/readybase/GrayScottImageRD.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/readybase/GrayScottImageRD.hpp b/src/readybase/GrayScottImageRD.hpp
index 131eac5f9..944cff00b 100644
--- a/src/readybase/GrayScottImageRD.hpp
+++ b/src/readybase/GrayScottImageRD.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/readybase/GrayScottMeshRD.cpp b/src/readybase/GrayScottMeshRD.cpp
index 5399f7556..57ad13179 100644
--- a/src/readybase/GrayScottMeshRD.cpp
+++ b/src/readybase/GrayScottMeshRD.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/readybase/GrayScottMeshRD.hpp b/src/readybase/GrayScottMeshRD.hpp
index 4c246e40f..1d3f90b52 100644
--- a/src/readybase/GrayScottMeshRD.hpp
+++ b/src/readybase/GrayScottMeshRD.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/readybase/IO_XML.cpp b/src/readybase/IO_XML.cpp
index bd6472a2f..1323ae3c2 100644
--- a/src/readybase/IO_XML.cpp
+++ b/src/readybase/IO_XML.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/readybase/IO_XML.hpp b/src/readybase/IO_XML.hpp
index 484359130..b486d921d 100644
--- a/src/readybase/IO_XML.hpp
+++ b/src/readybase/IO_XML.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 The Ready Bunch
+/* Copyright 2011-2024 The Ready Bunch
This file is part of Ready.
diff --git a/src/readybase/ImageRD.cpp b/src/readybase/ImageRD.cpp
index 9920b4bc3..e3bcf07b9 100644
--- a/src/readybase/ImageRD.cpp
+++ b/src/readybase/ImageRD.cpp
@@ -1,1711 +1,1720 @@
-/* Copyright 2011-2021 The Ready Bunch
-
- This file is part of Ready.
-
- Ready is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Ready 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 General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Ready. If not, see . */
-
-// local:
-#include "ImageRD.hpp"
-#include "IO_XML.hpp"
-#include "overlays.hpp"
-#include "Properties.hpp"
-#include "scene_items.hpp"
-#include "utils.hpp"
-
-// STL:
-#include
-#include
-#include
-
-// VTK:
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-using namespace std;
-
-// -------------------------------------------------------------------
-
-ImageRD::ImageRD(int data_type)
- : AbstractRD(data_type)
- , image_top1D(2.0)
- , image_ratio1D(30.0)
-{
- this->starting_pattern = vtkSmartPointer::New();
- this->assign_attribute_filter = NULL;
- this->rearrange_fields_filter = NULL;
-}
-
-// ---------------------------------------------------------------------
-
-ImageRD::~ImageRD()
-{
- this->DeallocateImages();
-}
-
-// ---------------------------------------------------------------------
-
-void ImageRD::DeallocateImages()
-{
- this->images.clear();
- this->n_chemicals = 0;
-}
-
-// ---------------------------------------------------------------------
-
-int ImageRD::GetArenaDimensionality() const
-{
- assert(this->images.front());
- int dimensionality=0;
- for(int iDim=0;iDim<3;iDim++)
- if(this->images.front()->GetDimensions()[iDim]>1)
- dimensionality++;
- return dimensionality;
-}
-
-// ---------------------------------------------------------------------
-
-float ImageRD::GetX() const
-{
- return this->images.front()->GetDimensions()[0];
-}
-
-// ---------------------------------------------------------------------
-
-float ImageRD::GetY() const
-{
- return this->images.front()->GetDimensions()[1];
-}
-
-// ---------------------------------------------------------------------
-
-float ImageRD::GetZ() const
-{
- return this->images.front()->GetDimensions()[2];
-}
-
-// ---------------------------------------------------------------------
-
-vtkImageData* ImageRD::GetImage(int iChemical) const
-{
- return this->images[iChemical];
-}
-
-// ---------------------------------------------------------------------
-
-void ImageRD::GetImage(vtkImageData *im) const
-{
- vtkSmartPointer iac = vtkSmartPointer::New();
- for(int i=0;iGetNumberOfChemicals();i++)
- {
- iac->AddInputData(this->GetImage(i));
- }
- iac->Update();
- im->DeepCopy(iac->GetOutput());
-}
-
-// ---------------------------------------------------------------------
-
-void ImageRD::CopyFromImage(vtkImageData* im)
-{
- int n_arrays = im->GetPointData()->GetNumberOfArrays();
- int n_components = im->GetNumberOfScalarComponents();
-
- bool has_named_arrays = true;
- for(int iChem=0;iChemGetNumberOfChemicals();iChem++)
- {
- if(!im->GetPointData()->HasArray(GetChemicalName(iChem).c_str()))
- {
- has_named_arrays = false;
- break;
- }
- }
-
- if(has_named_arrays && n_components==1 && n_arrays==this->GetNumberOfChemicals())
- {
- // convert named array data to single-component data in multiple images
- for(int iChem=0;iChemGetNumberOfChemicals();iChem++)
- {
- this->images[iChem]->SetExtent(im->GetExtent());
- this->images[iChem]->GetPointData()->SetScalars(im->GetPointData()->GetArray(GetChemicalName(iChem).c_str()));
- }
- }
- else if(n_arrays==1 && n_components==this->GetNumberOfChemicals())
- {
- // convert multi-component data to single-component data in multiple images
- vtkSmartPointer iec = vtkSmartPointer::New();
- iec->SetInputData(im);
- for(int i=0;iGetNumberOfChemicals();i++)
- {
- iec->SetComponents(i);
- iec->Update();
- this->images[i]->DeepCopy(iec->GetOutput());
- }
- }
- else
- throw runtime_error("ImageRD::CopyFromImage : chemical count mismatch");
-
- this->undo_stack.clear();
-}
-
-// ---------------------------------------------------------------------
-
-void ImageRD::CopyFromMesh(
- vtkUnstructuredGrid* mesh,
- const int num_chemicals,
- const size_t target_chemical,
- const size_t largest_dimension,
- const float value_inside,
- const float value_outside)
-{
- // decide the size of the image
- mesh->ComputeBounds();
- double bounds[6];
- mesh->GetBounds(bounds);
- const double mesh_size[3] = { bounds[1] - bounds[0], bounds[3] - bounds[2], bounds[5] - bounds[4] };
- const float max_mesh_size = std::max(mesh_size[0], std::max(mesh_size[1], mesh_size[2]));
- const float scale = (largest_dimension-1) / max_mesh_size;
- int image_size[3];
- for(size_t xyz = 0; xyz < 3; ++xyz)
- {
- image_size[xyz] = 1;
- while( image_size[xyz] < mesh_size[xyz] * scale )
- {
- image_size[xyz] <<= 1;
- }
- }
- AllocateImages(image_size[0], image_size[1], image_size[2], num_chemicals, this->GetDataType());
- BlankImage(value_outside);
-
- // write data into the image
- vtkSmartPointer transform = vtkSmartPointer::New();
- transform->PostMultiply();
- transform->Translate(-(bounds[0] + bounds[1]) / 2.0, -(bounds[2] + bounds[3]) / 2.0, -(bounds[4] + bounds[5]) / 2.0); // center at origin
- transform->Scale(scale, scale, scale);
- transform->Translate(image_size[0] / 2, image_size[1] / 2, image_size[2] / 2); // center in volume
- vtkSmartPointer transform_filter = vtkSmartPointer::New();
- transform_filter->SetTransform(transform);
- transform_filter->SetInputData(mesh);
- vtkSmartPointer get_surface = vtkSmartPointer::New();
- get_surface->SetInputConnection(transform_filter->GetOutputPort());
- vtkSmartPointer pol2stenc = vtkSmartPointer::New();
- pol2stenc->SetInputConnection(get_surface->GetOutputPort());
- vtkSmartPointer imgstenc = vtkSmartPointer::New();
- imgstenc->SetInputData(this->images[target_chemical]);
- imgstenc->SetStencilConnection(pol2stenc->GetOutputPort());
- imgstenc->ReverseStencilOn();
- imgstenc->SetBackgroundValue(value_inside);
- imgstenc->Update();
- this->images[target_chemical]->DeepCopy(imgstenc->GetOutput());
-}
-
-// ---------------------------------------------------------------------
-
-void ImageRD::AllocateImages(int x,int y,int z,int nc,int data_type)
-{
- this->DeallocateImages();
- this->n_chemicals = nc;
- this->images.resize(nc);
- for(int i=0;iimages[i] = AllocateVTKImage(x,y,z,data_type);
- this->is_modified = true;
- this->undo_stack.clear();
-}
-
-// ---------------------------------------------------------------------
-
-/* static */ vtkSmartPointer ImageRD::AllocateVTKImage(int x,int y,int z,int data_type)
-{
- vtkSmartPointer im = vtkSmartPointer::New();
- im->SetDimensions(x,y,z);
- im->AllocateScalars(data_type,1);
- if(im->GetDimensions()[0]!=x || im->GetDimensions()[1]!=y || im->GetDimensions()[2]!=z)
- throw runtime_error("ImageRD::AllocateVTKImage : Failed to allocate image data - dimensions too big?");
- return im;
-}
-
-// ---------------------------------------------------------------------
-
-void ImageRD::GenerateInitialPattern()
-{
- if (this->initial_pattern_generator.ShouldZeroFirst()) {
- this->BlankImage();
- }
-
- const int X = this->images.front()->GetDimensions()[0];
- const int Y = this->images.front()->GetDimensions()[1];
- const int Z = this->images.front()->GetDimensions()[2];
-
- for (size_t iOverlay = 0; iOverlay < this->initial_pattern_generator.GetNumberOfOverlays(); iOverlay++)
- {
- this->initial_pattern_generator.GetOverlay(iOverlay).Reseed();
- }
-
- for(int z=0;zinitial_pattern_generator.GetNumberOfOverlays(); iOverlay++)
- {
- const Overlay& overlay = this->initial_pattern_generator.GetOverlay(iOverlay);
-
- int iC = overlay.GetTargetChemical();
- if(iC<0 || iC>=this->GetNumberOfChemicals())
- continue; // best for now to silently ignore this overlay, because the user has no way of editing the overlays (short of editing the file)
- //throw runtime_error("Overlay: chemical out of range: "+GetChemicalName(iC));
-
- vector vals(this->GetNumberOfChemicals());
- for(int i=0;iGetNumberOfChemicals();i++)
- vals[i] = this->GetImage(i)->GetScalarComponentAsDouble(x,y,z,0);
- this->GetImage(iC)->SetScalarComponentFromDouble(x, y, z, 0, overlay.Apply(vals, *this, x, y, z));
- }
- }
- }
- }
- for(int i=0;i<(int)this->images.size();i++)
- this->images[i]->Modified();
- this->timesteps_taken = 0;
-}
-
-// ---------------------------------------------------------------------
-
-void ImageRD::BlankImage(float value)
-{
- for(int iImage=0;iImage<(int)this->images.size();iImage++)
- {
- this->images[iImage]->GetPointData()->GetScalars()->FillComponent(0, value);
- this->images[iImage]->Modified();
- }
- this->timesteps_taken = 0;
- this->undo_stack.clear();
-}
-
-// ---------------------------------------------------------------------
-
-void ImageRD::Update(int n_steps)
-{
- this->undo_stack.clear();
- this->InternalUpdate(n_steps);
-
- this->timesteps_taken += n_steps;
-
- for(int ic=0;icGetNumberOfChemicals();ic++)
- this->images[ic]->Modified();
-
- if(this->rearrange_fields_filter && this->assign_attribute_filter)
- {
- // manually update the rendering pipeline to allow for changing array names
- // TODO: this step shouldn't be necessary
- this->rearrange_fields_filter->Update();
- assign_attribute_filter->Assign(this->rearrange_fields_filter->GetOutput()->GetCellData()->GetArray(0)->GetName(),
- vtkDataSetAttributes::SCALARS, vtkAssignAttribute::CELL_DATA);
- }
-}
-
-// ---------------------------------------------------------------------
-
-void ImageRD::InitializeRenderPipeline(vtkRenderer* pRenderer,const Properties& render_settings)
-{
- this->rearrange_fields_filter = NULL;
- this->assign_attribute_filter = NULL;
-
- switch(this->GetArenaDimensionality())
- {
- // TODO: merge the dimensionalities (often want one/more slices from lower dimensionalities)
- case 0:
- case 1: this->InitializeVTKPipeline_1D(pRenderer,render_settings); break;
- case 2: this->InitializeVTKPipeline_2D(pRenderer,render_settings); break;
- case 3: this->InitializeVTKPipeline_3D(pRenderer,render_settings); break;
- default:
- throw runtime_error("ImageRD::InitializeRenderPipeline : Unsupported dimensionality");
- }
-}
-
-// ---------------------------------------------------------------------
-
-void ImageRD::InitializeVTKPipeline_1D(vtkRenderer* pRenderer,const Properties& render_settings)
-{
- float low = render_settings.GetProperty("low").GetFloat();
- float high = render_settings.GetProperty("high").GetFloat();
- float vertical_scale_1D = render_settings.GetProperty("vertical_scale_1D").GetFloat();
- bool use_image_interpolation = render_settings.GetProperty("use_image_interpolation").GetBool();
- int iActiveChemical = IndexFromChemicalName(render_settings.GetProperty("active_chemical").GetChemical());
- bool show_multiple_chemicals = render_settings.GetProperty("show_multiple_chemicals").GetBool();
- bool show_color_scale = render_settings.GetProperty("show_color_scale").GetBool();
- bool show_cell_edges = render_settings.GetProperty("show_cell_edges").GetBool();
- bool show_chemical_label = render_settings.GetProperty("show_chemical_label").GetBool();
- bool show_phase_plot = render_settings.GetProperty("show_phase_plot").GetBool();
- int iPhasePlotX = IndexFromChemicalName(render_settings.GetProperty("phase_plot_x_axis").GetChemical());
- int iPhasePlotY = IndexFromChemicalName(render_settings.GetProperty("phase_plot_y_axis").GetChemical());
- int iPhasePlotZ = IndexFromChemicalName(render_settings.GetProperty("phase_plot_z_axis").GetChemical());
- bool plot_ab_orthogonally = render_settings.GetProperty("plot_ab_orthogonally").GetBool();
- if (plot_ab_orthogonally && this->GetNumberOfChemicals() <= 1)
- {
- plot_ab_orthogonally = false;
- }
-
- int iFirstChem = 0;
- int iLastChem = this->GetNumberOfChemicals() - 1;
- if(!show_multiple_chemicals)
- {
- if (plot_ab_orthogonally && iActiveChemical < 2)
- {
- iFirstChem = 0;
- iLastChem = 1;
- }
- else
- {
- iFirstChem = iActiveChemical;
- iLastChem = iFirstChem;
- }
- }
-
- float scaling = vertical_scale_1D / (high-low); // vertical_scale gives the height of the graph in worldspace units
- const float image_height = this->GetX() / this->image_ratio1D; // we thicken it
- const float y_gap = image_height;
-
- vtkSmartPointer lut = GetColorMap(render_settings);
-
- for(int iChem = iFirstChem; iChem <= iLastChem; ++iChem)
- {
- // pass the image through the lookup table
- vtkSmartPointer image_mapper = vtkSmartPointer::New();
- image_mapper->SetLookupTable(lut);
- image_mapper->SetInputData(this->GetImage(iChem));
-
- // will convert the x*y 2D image to a x*y grid of quads
- const float image_offset = this->image_top1D - image_height * 2.0f * (iChem - iFirstChem);
- vtkSmartPointer plane = vtkSmartPointer::New();
- plane->SetXResolution(this->GetX());
- plane->SetYResolution(this->GetY());
- plane->SetOrigin(0,image_offset-image_height,0);
- plane->SetPoint1(this->GetX(),image_offset-image_height,0);
- plane->SetPoint2(0,image_offset,0);
-
- vtkSmartPointer texture = vtkSmartPointer::New();
- texture->SetInputConnection(image_mapper->GetOutputPort());
- if(use_image_interpolation)
- texture->InterpolateOn();
- vtkSmartPointer mapper = vtkSmartPointer::New();
- mapper->SetInputConnection(plane->GetOutputPort());
-
- vtkSmartPointer actor = vtkSmartPointer::New();
- actor->SetMapper(mapper);
- actor->SetTexture(texture);
- if(show_cell_edges)
- actor->GetProperty()->EdgeVisibilityOn();
- actor->GetProperty()->SetEdgeColor(0,0,0);
- actor->GetProperty()->LightingOff();
- pRenderer->AddActor(actor);
-
- // add a text label
- if(show_chemical_label && this->GetNumberOfChemicals()>1)
- {
- vtkSmartPointer captionActor = vtkSmartPointer::New();
- captionActor->SetAttachmentPoint(-image_height, image_offset - image_height/2, 0);
- captionActor->SetPosition(0, 0);
- captionActor->SetCaption(GetChemicalName(iChem).c_str());
- captionActor->BorderOff();
- captionActor->LeaderOff();
- captionActor->SetPadding(0);
- captionActor->GetCaptionTextProperty()->SetJustificationToLeft();
- captionActor->GetCaptionTextProperty()->BoldOff();
- captionActor->GetCaptionTextProperty()->ShadowOff();
- captionActor->GetCaptionTextProperty()->ItalicOff();
- captionActor->GetCaptionTextProperty()->SetFontFamilyToArial();
- captionActor->GetCaptionTextProperty()->SetFontSize(16);
- captionActor->GetCaptionTextProperty()->SetVerticalJustificationToCentered();
- captionActor->GetTextActor()->SetTextScaleModeToNone();
- pRenderer->AddActor(captionActor);
- }
- }
-
- // also add a scalar bar to show how the colors correspond to values
- if(show_color_scale)
- {
- AddScalarBar(pRenderer,lut);
- }
-
- // add a line graph for all the chemicals (active one highlighted)
- const float graph_bottom = this->image_top1D + y_gap;
- const float graph_top = graph_bottom + (high-low) * scaling;
- for(int iChemical = iFirstChem; iChemical <= iLastChem; iChemical++)
- {
- if (plot_ab_orthogonally && iChemical == 1)
- {
- continue;
- }
- vtkSmartPointer mapper = vtkSmartPointer::New();
- vtkSmartPointer actor = vtkSmartPointer::New();
- if (plot_ab_orthogonally && iChemical == 0)
- {
- // plot the merged ab pair here
- vtkSmartPointer plane = vtkSmartPointer::New();
- plane->SetInputData(this->GetImage(0));
- vtkSmartPointer warp_y = vtkSmartPointer::New();
- warp_y->SetInputConnection(plane->GetOutputPort());
- warp_y->SetScaleFactor(scaling);
- warp_y->SetNormal(0, 1, 0);
- vtkSmartPointer plane2 = vtkSmartPointer::New();
- plane2->SetInputData(this->GetImage(1));
- vtkSmartPointer merge = vtkSmartPointer::New();
- merge->SetGeometryConnection(warp_y->GetOutputPort());
- merge->SetScalarsConnection(plane2->GetOutputPort());
- vtkSmartPointer warp_z = vtkSmartPointer::New();
- warp_z->SetInputConnection(merge->GetOutputPort());
- warp_z->SetScaleFactor(scaling);
- warp_z->SetNormal(0, 0, -1);
- vtkSmartPointer stripper = vtkSmartPointer::New();
- stripper->SetInputConnection(warp_z->GetOutputPort());
- vtkSmartPointer tube = vtkSmartPointer::New();
- tube->SetInputConnection(stripper->GetOutputPort());
- tube->SetRadius(this->GetX() / 512.0);
- tube->SetNumberOfSides(6);
- mapper->SetInputConnection(tube->GetOutputPort());
- actor->GetProperty()->SetColor(1, 1, 1);
- actor->GetProperty()->SetAmbient(0.3);
- }
- else
- {
- // plot this chemical in the normal way
- vtkSmartPointer plane = vtkSmartPointer::New();
- plane->SetInputData(this->GetImage(iChemical));
- vtkSmartPointer warp = vtkSmartPointer::New();
- warp->SetInputConnection(plane->GetOutputPort());
- warp->SetScaleFactor(scaling);
- warp->SetNormal(0, 1, 0);
- mapper->SetInputConnection(warp->GetOutputPort());
- actor->GetProperty()->SetAmbient(1);
- if (iChemical == iActiveChemical)
- actor->GetProperty()->SetColor(1, 1, 1);
- else
- actor->GetProperty()->SetColor(0.5, 0.5, 0.5);
- }
- mapper->ScalarVisibilityOff();
- actor->SetMapper(mapper);
- actor->PickableOff();
- actor->SetPosition(0, graph_bottom - low * scaling,0);
- pRenderer->AddActor(actor);
- }
-
- // add an axis
- vtkSmartPointer axis = vtkSmartPointer::New();
- axis->SetCamera(pRenderer->GetActiveCamera());
- axis->SetBounds(0,0,graph_bottom,graph_top,0,0);
- axis->SetRanges(0,0,low,high,0,0);
- axis->UseRangesOn();
- axis->XAxisVisibilityOff();
- axis->ZAxisVisibilityOff();
- axis->SetYLabel("");
- axis->SetLabelFormat("%.2f");
- axis->SetInertia(10000);
- axis->SetCornerOffset(0);
- axis->SetNumberOfLabels(5);
- axis->PickableOff();
- pRenderer->AddActor(axis);
- if (plot_ab_orthogonally)
- {
- axis->SetYLabel("a");
- vtkSmartPointer axis = vtkSmartPointer::New();
- axis->SetCamera(pRenderer->GetActiveCamera());
- axis->SetBounds(0, 0, graph_top, graph_top, -low * scaling, -high * scaling);
- axis->SetRanges(0, 0, 0, 0, low, high);
- axis->UseRangesOn();
- axis->XAxisVisibilityOff();
- axis->YAxisVisibilityOff();
- axis->SetZLabel("b");
- axis->SetLabelFormat("%.2f");
- axis->SetInertia(10000);
- axis->SetCornerOffset(0);
- axis->SetNumberOfLabels(5);
- axis->PickableOff();
- pRenderer->AddActor(axis);
- }
-
- // add a phase plot
- const float phase_plot_bottom = graph_top + y_gap*2;
- if(show_phase_plot && this->GetNumberOfChemicals()>=2)
- {
- this->AddPhasePlot(pRenderer,scaling,low,high,0.0f, phase_plot_bottom,0.0f,iPhasePlotX,iPhasePlotY,iPhasePlotZ);
- }
-}
-
-// ---------------------------------------------------------------------
-
-void ImageRD::InitializeVTKPipeline_2D(vtkRenderer* pRenderer,const Properties& render_settings)
-{
- float low = render_settings.GetProperty("low").GetFloat();
- float high = render_settings.GetProperty("high").GetFloat();
- float vertical_scale_2D = render_settings.GetProperty("vertical_scale_2D").GetFloat();
- bool use_image_interpolation = render_settings.GetProperty("use_image_interpolation").GetBool();
- int iActiveChemical = IndexFromChemicalName(render_settings.GetProperty("active_chemical").GetChemical());
- bool use_wireframe = render_settings.GetProperty("use_wireframe").GetBool();
- float surface_r,surface_g,surface_b;
- render_settings.GetProperty("surface_color").GetColor(surface_r,surface_g,surface_b);
- bool show_multiple_chemicals = render_settings.GetProperty("show_multiple_chemicals").GetBool();
- bool show_displacement_mapped_surface = render_settings.GetProperty("show_displacement_mapped_surface").GetBool();
- bool show_color_scale = render_settings.GetProperty("show_color_scale").GetBool();
- bool color_displacement_mapped_surface = render_settings.GetProperty("color_displacement_mapped_surface").GetBool();
- bool show_cell_edges = render_settings.GetProperty("show_cell_edges").GetBool();
- bool show_bounding_box = render_settings.GetProperty("show_bounding_box").GetBool();
- bool show_chemical_label = render_settings.GetProperty("show_chemical_label").GetBool();
- bool show_phase_plot = render_settings.GetProperty("show_phase_plot").GetBool();
- int iPhasePlotX = IndexFromChemicalName(render_settings.GetProperty("phase_plot_x_axis").GetChemical());
- int iPhasePlotY = IndexFromChemicalName(render_settings.GetProperty("phase_plot_y_axis").GetChemical());
- int iPhasePlotZ = IndexFromChemicalName(render_settings.GetProperty("phase_plot_z_axis").GetChemical());
-
- const float scaling = vertical_scale_2D / (high-low); // vertical_scale gives the height of the graph in worldspace units
- const float x_gap = this->x_spacing_proportion * this->GetX();
- const float y_gap = this->y_spacing_proportion * this->GetY();
-
- double offset[3] = {0,0,0};
- const float surface_bottom = offset[1] + 0.5 + this->GetY() + y_gap;
- const float surface_top = surface_bottom + this->GetY();
-
- int iFirstChem = 0;
- int iLastChem = this->GetNumberOfChemicals() - 1;
- if(!show_multiple_chemicals) { iFirstChem = iActiveChemical; iLastChem = iFirstChem; }
-
+/* Copyright 2011-2024 The Ready Bunch
+
+ This file is part of Ready.
+
+ Ready is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Ready 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Ready. If not, see . */
+
+// local:
+#include "ImageRD.hpp"
+#include "IO_XML.hpp"
+#include "overlays.hpp"
+#include "Properties.hpp"
+#include "scene_items.hpp"
+#include "utils.hpp"
+
+// STL:
+#include
+#include
+#include
+
+// VTK:
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+using namespace std;
+
+// -------------------------------------------------------------------
+
+ImageRD::ImageRD(int data_type)
+ : AbstractRD(data_type)
+ , image_top1D(2.0)
+ , image_ratio1D(30.0)
+{
+ this->starting_pattern = vtkSmartPointer::New();
+ this->assign_attribute_filter = NULL;
+ this->rearrange_fields_filter = NULL;
+}
+
+// ---------------------------------------------------------------------
+
+ImageRD::~ImageRD()
+{
+ this->DeallocateImages();
+}
+
+// ---------------------------------------------------------------------
+
+void ImageRD::DeallocateImages()
+{
+ this->images.clear();
+ this->n_chemicals = 0;
+}
+
+// ---------------------------------------------------------------------
+
+int ImageRD::GetArenaDimensionality() const
+{
+ assert(this->images.front());
+ int dimensionality=0;
+ for(int iDim=0;iDim<3;iDim++)
+ if(this->images.front()->GetDimensions()[iDim]>1)
+ dimensionality++;
+ return dimensionality;
+}
+
+// ---------------------------------------------------------------------
+
+float ImageRD::GetX() const
+{
+ return this->images.front()->GetDimensions()[0];
+}
+
+// ---------------------------------------------------------------------
+
+float ImageRD::GetY() const
+{
+ return this->images.front()->GetDimensions()[1];
+}
+
+// ---------------------------------------------------------------------
+
+float ImageRD::GetZ() const
+{
+ return this->images.front()->GetDimensions()[2];
+}
+
+// ---------------------------------------------------------------------
+
+vtkImageData* ImageRD::GetImage(int iChemical) const
+{
+ return this->images[iChemical];
+}
+
+// ---------------------------------------------------------------------
+
+void ImageRD::GetImage(vtkImageData *im) const
+{
+ vtkSmartPointer iac = vtkSmartPointer::New();
+ for(int i=0;iGetNumberOfChemicals();i++)
+ {
+ iac->AddInputData(this->GetImage(i));
+ }
+ iac->Update();
+ im->DeepCopy(iac->GetOutput());
+}
+
+// ---------------------------------------------------------------------
+
+void ImageRD::CopyFromImage(vtkImageData* im)
+{
+ int n_arrays = im->GetPointData()->GetNumberOfArrays();
+ int n_components = im->GetNumberOfScalarComponents();
+
+ bool has_named_arrays = true;
+ for(int iChem=0;iChemGetNumberOfChemicals();iChem++)
+ {
+ if(!im->GetPointData()->HasArray(GetChemicalName(iChem).c_str()))
+ {
+ has_named_arrays = false;
+ break;
+ }
+ }
+
+ if(has_named_arrays && n_components==1 && n_arrays==this->GetNumberOfChemicals())
+ {
+ // convert named array data to single-component data in multiple images
+ for(int iChem=0;iChemGetNumberOfChemicals();iChem++)
+ {
+ this->images[iChem]->SetExtent(im->GetExtent());
+ this->images[iChem]->GetPointData()->SetScalars(im->GetPointData()->GetArray(GetChemicalName(iChem).c_str()));
+ }
+ }
+ else if(n_arrays==1 && n_components==this->GetNumberOfChemicals())
+ {
+ // convert multi-component data to single-component data in multiple images
+ vtkSmartPointer iec = vtkSmartPointer::New();
+ iec->SetInputData(im);
+ for(int i=0;iGetNumberOfChemicals();i++)
+ {
+ iec->SetComponents(i);
+ iec->Update();
+ this->images[i]->DeepCopy(iec->GetOutput());
+ }
+ }
+ else
+ throw runtime_error("ImageRD::CopyFromImage : chemical count mismatch");
+
+ this->undo_stack.clear();
+}
+
+// ---------------------------------------------------------------------
+
+void ImageRD::CopyFromMesh(
+ vtkUnstructuredGrid* mesh,
+ const int num_chemicals,
+ const size_t target_chemical,
+ const size_t largest_dimension,
+ const float value_inside,
+ const float value_outside)
+{
+ // decide the size of the image
+ mesh->ComputeBounds();
+ double bounds[6];
+ mesh->GetBounds(bounds);
+ const double mesh_size[3] = { bounds[1] - bounds[0], bounds[3] - bounds[2], bounds[5] - bounds[4] };
+ const float max_mesh_size = std::max(mesh_size[0], std::max(mesh_size[1], mesh_size[2]));
+ const float scale = (largest_dimension-1) / max_mesh_size;
+ int image_size[3];
+ for(size_t xyz = 0; xyz < 3; ++xyz)
+ {
+ image_size[xyz] = 1;
+ while( image_size[xyz] < mesh_size[xyz] * scale )
+ {
+ image_size[xyz] <<= 1;
+ }
+ }
+ AllocateImages(image_size[0], image_size[1], image_size[2], num_chemicals, this->GetDataType());
+ BlankImage(value_outside);
+
+ // write data into the image
+ vtkSmartPointer transform = vtkSmartPointer::New();
+ transform->PostMultiply();
+ transform->Translate(-(bounds[0] + bounds[1]) / 2.0, -(bounds[2] + bounds[3]) / 2.0, -(bounds[4] + bounds[5]) / 2.0); // center at origin
+ transform->Scale(scale, scale, scale);
+ transform->Translate(image_size[0] / 2, image_size[1] / 2, image_size[2] / 2); // center in volume
+ vtkSmartPointer transform_filter = vtkSmartPointer::New();
+ transform_filter->SetTransform(transform);
+ transform_filter->SetInputData(mesh);
+ vtkSmartPointer get_surface = vtkSmartPointer::New();
+ get_surface->SetInputConnection(transform_filter->GetOutputPort());
+ vtkSmartPointer pol2stenc = vtkSmartPointer::New();
+ pol2stenc->SetInputConnection(get_surface->GetOutputPort());
+ vtkSmartPointer imgstenc = vtkSmartPointer::New();
+ imgstenc->SetInputData(this->images[target_chemical]);
+ imgstenc->SetStencilConnection(pol2stenc->GetOutputPort());
+ imgstenc->ReverseStencilOn();
+ imgstenc->SetBackgroundValue(value_inside);
+ imgstenc->Update();
+ this->images[target_chemical]->DeepCopy(imgstenc->GetOutput());
+}
+
+// ---------------------------------------------------------------------
+
+void ImageRD::AllocateImages(int x,int y,int z,int nc,int data_type)
+{
+ this->DeallocateImages();
+ this->n_chemicals = nc;
+ this->images.resize(nc);
+ for(int i=0;iimages[i] = AllocateVTKImage(x,y,z,data_type);
+ this->is_modified = true;
+ this->undo_stack.clear();
+}
+
+// ---------------------------------------------------------------------
+
+/* static */ vtkSmartPointer ImageRD::AllocateVTKImage(int x,int y,int z,int data_type)
+{
+ vtkSmartPointer im = vtkSmartPointer::New();
+ im->SetDimensions(x,y,z);
+ im->AllocateScalars(data_type,1);
+ if(im->GetDimensions()[0]!=x || im->GetDimensions()[1]!=y || im->GetDimensions()[2]!=z)
+ throw runtime_error("ImageRD::AllocateVTKImage : Failed to allocate image data - dimensions too big?");
+ return im;
+}
+
+// ---------------------------------------------------------------------
+
+void ImageRD::GenerateInitialPattern()
+{
+ if (this->initial_pattern_generator.ShouldZeroFirst()) {
+ this->BlankImage();
+ }
+
+ const int X = this->images.front()->GetDimensions()[0];
+ const int Y = this->images.front()->GetDimensions()[1];
+ const int Z = this->images.front()->GetDimensions()[2];
+
+ for (size_t iOverlay = 0; iOverlay < this->initial_pattern_generator.GetNumberOfOverlays(); iOverlay++)
+ {
+ this->initial_pattern_generator.GetOverlay(iOverlay).Reseed();
+ }
+
+ for(int z=0;zinitial_pattern_generator.GetNumberOfOverlays(); iOverlay++)
+ {
+ const Overlay& overlay = this->initial_pattern_generator.GetOverlay(iOverlay);
+
+ int iC = overlay.GetTargetChemical();
+ if(iC<0 || iC>=this->GetNumberOfChemicals())
+ continue; // best for now to silently ignore this overlay, because the user has no way of editing the overlays (short of editing the file)
+ //throw runtime_error("Overlay: chemical out of range: "+GetChemicalName(iC));
+
+ vector vals(this->GetNumberOfChemicals());
+ for(int i=0;iGetNumberOfChemicals();i++)
+ vals[i] = this->GetImage(i)->GetScalarComponentAsDouble(x,y,z,0);
+ this->GetImage(iC)->SetScalarComponentFromDouble(x, y, z, 0, overlay.Apply(vals, *this, x, y, z));
+ }
+ }
+ }
+ }
+ for(int i=0;i<(int)this->images.size();i++)
+ this->images[i]->Modified();
+ this->timesteps_taken = 0;
+}
+
+// ---------------------------------------------------------------------
+
+void ImageRD::BlankImage(float value)
+{
+ for(int iImage=0;iImage<(int)this->images.size();iImage++)
+ {
+ this->images[iImage]->GetPointData()->GetScalars()->FillComponent(0, value);
+ this->images[iImage]->Modified();
+ }
+ this->timesteps_taken = 0;
+ this->undo_stack.clear();
+}
+
+// ---------------------------------------------------------------------
+
+void ImageRD::Update(int n_steps)
+{
+ this->undo_stack.clear();
+ this->InternalUpdate(n_steps);
+
+ this->timesteps_taken += n_steps;
+
+ for(int ic=0;icGetNumberOfChemicals();ic++)
+ this->images[ic]->Modified();
+
+ if(this->rearrange_fields_filter && this->assign_attribute_filter)
+ {
+ // manually update the rendering pipeline to allow for changing array names
+ // TODO: this step shouldn't be necessary
+ this->rearrange_fields_filter->Update();
+ assign_attribute_filter->Assign(this->rearrange_fields_filter->GetOutput()->GetCellData()->GetArray(0)->GetName(),
+ vtkDataSetAttributes::SCALARS, vtkAssignAttribute::CELL_DATA);
+ }
+}
+
+// ---------------------------------------------------------------------
+
+void ImageRD::InitializeRenderPipeline(vtkRenderer* pRenderer,const Properties& render_settings)
+{
+ this->rearrange_fields_filter = NULL;
+ this->assign_attribute_filter = NULL;
+
+ switch(this->GetArenaDimensionality())
+ {
+ // TODO: merge the dimensionalities (often want one/more slices from lower dimensionalities)
+ case 0:
+ case 1: this->InitializeVTKPipeline_1D(pRenderer,render_settings); break;
+ case 2: this->InitializeVTKPipeline_2D(pRenderer,render_settings); break;
+ case 3: this->InitializeVTKPipeline_3D(pRenderer,render_settings); break;
+ default:
+ throw runtime_error("ImageRD::InitializeRenderPipeline : Unsupported dimensionality");
+ }
+}
+
+// ---------------------------------------------------------------------
+
+void ImageRD::InitializeVTKPipeline_1D(vtkRenderer* pRenderer,const Properties& render_settings)
+{
+ float low = render_settings.GetProperty("low").GetFloat();
+ float high = render_settings.GetProperty("high").GetFloat();
+ float vertical_scale_1D = render_settings.GetProperty("vertical_scale_1D").GetFloat();
+ bool use_image_interpolation = render_settings.GetProperty("use_image_interpolation").GetBool();
+ int iActiveChemical = IndexFromChemicalName(render_settings.GetProperty("active_chemical").GetChemical());
+ bool show_multiple_chemicals = render_settings.GetProperty("show_multiple_chemicals").GetBool();
+ bool show_color_scale = render_settings.GetProperty("show_color_scale").GetBool();
+ bool show_cell_edges = render_settings.GetProperty("show_cell_edges").GetBool();
+ bool show_chemical_label = render_settings.GetProperty("show_chemical_label").GetBool();
+ bool show_phase_plot = render_settings.GetProperty("show_phase_plot").GetBool();
+ int iPhasePlotX = IndexFromChemicalName(render_settings.GetProperty("phase_plot_x_axis").GetChemical());
+ int iPhasePlotY = IndexFromChemicalName(render_settings.GetProperty("phase_plot_y_axis").GetChemical());
+ int iPhasePlotZ = IndexFromChemicalName(render_settings.GetProperty("phase_plot_z_axis").GetChemical());
+ bool plot_ab_orthogonally = render_settings.GetProperty("plot_ab_orthogonally").GetBool();
+ if (plot_ab_orthogonally && this->GetNumberOfChemicals() <= 1)
+ {
+ plot_ab_orthogonally = false;
+ }
+
+ int iFirstChem = 0;
+ int iLastChem = this->GetNumberOfChemicals() - 1;
+ if(!show_multiple_chemicals)
+ {
+ if (plot_ab_orthogonally && iActiveChemical < 2)
+ {
+ iFirstChem = 0;
+ iLastChem = 1;
+ }
+ else
+ {
+ iFirstChem = iActiveChemical;
+ iLastChem = iFirstChem;
+ }
+ }
+
+ float scaling = vertical_scale_1D / (high-low); // vertical_scale gives the height of the graph in worldspace units
+ const float image_height = this->GetX() / this->image_ratio1D; // we thicken it
+ const float y_gap = image_height;
+
+ vtkSmartPointer lut = GetColorMap(render_settings);
+
+ for(int iChem = iFirstChem; iChem <= iLastChem; ++iChem)
+ {
+ // pass the image through the lookup table
+ vtkSmartPointer image_mapper = vtkSmartPointer::New();
+ image_mapper->SetLookupTable(lut);
+ image_mapper->SetInputData(this->GetImage(iChem));
+
+ // will convert the x*y 2D image to a x*y grid of quads
+ const float image_offset = this->image_top1D - image_height * 2.0f * (iChem - iFirstChem);
+ vtkSmartPointer plane = vtkSmartPointer::New();
+ plane->SetXResolution(this->GetX());
+ plane->SetYResolution(this->GetY());
+ plane->SetOrigin(0,image_offset-image_height,0);
+ plane->SetPoint1(this->GetX(),image_offset-image_height,0);
+ plane->SetPoint2(0,image_offset,0);
+
+ vtkSmartPointer texture = vtkSmartPointer::New();
+ texture->SetInputConnection(image_mapper->GetOutputPort());
+ if(use_image_interpolation)
+ texture->InterpolateOn();
+ vtkSmartPointer mapper = vtkSmartPointer::New();
+ mapper->SetInputConnection(plane->GetOutputPort());
+
+ vtkSmartPointer actor = vtkSmartPointer::New();
+ actor->SetMapper(mapper);
+ actor->SetTexture(texture);
+ if(show_cell_edges)
+ actor->GetProperty()->EdgeVisibilityOn();
+ actor->GetProperty()->SetEdgeColor(0,0,0);
+ actor->GetProperty()->LightingOff();
+ pRenderer->AddActor(actor);
+
+ // add a text label
+ if(show_chemical_label && this->GetNumberOfChemicals()>1)
+ {
+ vtkSmartPointer captionActor = vtkSmartPointer::New();
+ captionActor->SetAttachmentPoint(-image_height, image_offset - image_height/2, 0);
+ captionActor->SetPosition(0, 0);
+ captionActor->SetCaption(GetChemicalName(iChem).c_str());
+ captionActor->BorderOff();
+ captionActor->LeaderOff();
+ captionActor->SetPadding(0);
+ captionActor->GetCaptionTextProperty()->SetJustificationToLeft();
+ captionActor->GetCaptionTextProperty()->BoldOff();
+ captionActor->GetCaptionTextProperty()->ShadowOff();
+ captionActor->GetCaptionTextProperty()->ItalicOff();
+ captionActor->GetCaptionTextProperty()->SetFontFamilyToArial();
+ captionActor->GetCaptionTextProperty()->SetFontSize(16);
+ captionActor->GetCaptionTextProperty()->SetVerticalJustificationToCentered();
+ captionActor->GetTextActor()->SetTextScaleModeToNone();
+ pRenderer->AddActor(captionActor);
+ }
+ }
+
+ // also add a scalar bar to show how the colors correspond to values
+ if(show_color_scale)
+ {
+ AddScalarBar(pRenderer,lut);
+ }
+
+ // add a line graph for all the chemicals (active one highlighted)
+ const float graph_bottom = this->image_top1D + y_gap;
+ const float graph_top = graph_bottom + (high-low) * scaling;
+ for(int iChemical = iFirstChem; iChemical <= iLastChem; iChemical++)
+ {
+ if (plot_ab_orthogonally && iChemical == 1)
+ {
+ continue;
+ }
+ vtkSmartPointer mapper = vtkSmartPointer::New();
+ vtkSmartPointer actor = vtkSmartPointer::New();
+ if (plot_ab_orthogonally && iChemical == 0)
+ {
+ // plot the merged ab pair here
+ vtkSmartPointer plane = vtkSmartPointer::New();
+ plane->SetInputData(this->GetImage(0));
+ vtkSmartPointer warp_y = vtkSmartPointer::New();
+ warp_y->SetInputConnection(plane->GetOutputPort());
+ warp_y->SetScaleFactor(scaling);
+ warp_y->SetNormal(0, 1, 0);
+ vtkSmartPointer