feat (WIP): base VTK visualisation of Eulerian flow fields
This commit is contained in:
parent
4cd545c788
commit
985fd6b9ed
|
|
@ -0,0 +1,6 @@
|
|||
.DS_Store
|
||||
src/.DS_Store
|
||||
src/.cache
|
||||
src/build
|
||||
.idea
|
||||
src/cmake-build-debug
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
## Location of data
|
||||
The data path is hardcoded such that the following tree structure is assumed:
|
||||
```
|
||||
data/
|
||||
grid.h5
|
||||
hydrodynamic_U.h5
|
||||
hydrodynamic_V.h5
|
||||
interactive-track-and-trace/
|
||||
opening-hdf5/
|
||||
...
|
||||
```
|
||||
|
||||
## Compiling
|
||||
Let the current directory be the `src` directory. Run:
|
||||
```shell
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make
|
||||
```
|
||||
|
||||
### Building with Linux
|
||||
Makes use of `mdspan` which is not supported by glibc++ at time of writing. See [compiler support](https://en.cppreference.com/w/cpp/compiler_support/23) for `mdspan`. The solution to this is to use Clang and libc++; this is configured in our CMake setup, however the default installation of the `netcdf-cxx` package on at least Arch linux (and suspectedly Debian derivatives as well) specifically builds for the glibc implementation. To get the netcdf C++ bindings functional with the libc++ implementation, one needs to build from source. On Linux, this requires a few changes to the CMake file included with the netcdf-cxx source code, which are detailed below.
|
||||
|
||||
Step-by-step to build the program using clang++ and libc++ on linux:
|
||||
1. Download the source code of netcdf-cxx, found at 'https://github.com/Unidata/netcdf-cxx4/releases/tag/v4.3.1' (make sure to download the release source code, as the master branch contains non-compilable code).
|
||||
2. Edit the CMakeLists.txt file, by appending '-stdlib=libc++' to the `CMAKE_CXX_FLAGS` variable in line 430. This means line 430 should read:
|
||||
```cmake
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall -Wno-unused-variable -Wno-unused-parameter -stdlib=libc++")
|
||||
```
|
||||
2. Build the source code with the following:
|
||||
```sh
|
||||
mkdir build && cd build
|
||||
cmake .. -DCMAKE_CXX_COMPILER=/usr/bin/clang++
|
||||
make
|
||||
ctest
|
||||
sudo make install
|
||||
```
|
||||
3. Now the code should compile through the standard steps described in the Compiling section.
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
cmake_minimum_required(VERSION 3.12 FATAL_ERROR)
|
||||
|
||||
project(VtkBase)
|
||||
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
find_package(VTK COMPONENTS
|
||||
CommonColor
|
||||
CommonCore
|
||||
CommonDataModel
|
||||
FiltersGeneral
|
||||
InteractionStyle
|
||||
RenderingContextOpenGL2
|
||||
RenderingCore
|
||||
RenderingFreeType
|
||||
RenderingGL2PSOpenGL2
|
||||
RenderingOpenGL2
|
||||
CommonColor
|
||||
FiltersGeometry
|
||||
RenderingCore)
|
||||
|
||||
if (NOT VTK_FOUND)
|
||||
message(FATAL_ERROR "VtkBase: Unable to find the VTK build folder.")
|
||||
endif()
|
||||
|
||||
# netcdf setup
|
||||
find_package(netCDF REQUIRED)
|
||||
|
||||
add_executable(VtkBase MACOSX_BUNDLE main.cpp )
|
||||
|
||||
execute_process(
|
||||
COMMAND nc-config --includedir
|
||||
OUTPUT_VARIABLE NETCDF_INCLUDE_DIR
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
execute_process(
|
||||
COMMAND ncxx4-config --libdir
|
||||
OUTPUT_VARIABLE NETCDFCXX_LIB_DIR
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
target_include_directories(VtkBase PUBLIC ${netCDF_INCLUDE_DIR})
|
||||
|
||||
find_library(NETCDF_LIB NAMES netcdf-cxx4 netcdf_c++4 PATHS ${NETCDFCXX_LIB_DIR} NO_DEFAULT_PATH)
|
||||
|
||||
# Prevent a "command line is too long" failure in Windows.
|
||||
set(CMAKE_NINJA_FORCE_RESPONSE_FILE "ON" CACHE BOOL "Force Ninja to use response files.")
|
||||
target_link_libraries(VtkBase ${NETCDF_LIB} ${VTK_LIBRARIES})
|
||||
|
||||
# vtk_module_autoinit is needed
|
||||
vtk_module_autoinit(
|
||||
TARGETS VtkBase
|
||||
MODULES ${VTK_LIBRARIES}
|
||||
)
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
#include <vtkActor.h>
|
||||
#include <vtkActor2D.h>
|
||||
#include <vtkCamera.h>
|
||||
#include <vtkDoubleArray.h>
|
||||
#include <vtkMapper2D.h>
|
||||
#include <vtkNamedColors.h>
|
||||
#include <vtkNew.h>
|
||||
#include <vtkPolyDataMapper.h>
|
||||
#include <vtkPolyDataMapper2D.h>
|
||||
#include <vtkProperty.h>
|
||||
#include <vtkRectilinearGrid.h>
|
||||
#include <vtkRectilinearGridGeometryFilter.h>
|
||||
#include <vtkRenderWindow.h>
|
||||
#include <vtkRenderWindowInteractor.h>
|
||||
#include <vtkRenderer.h>
|
||||
|
||||
#include <netcdf>
|
||||
|
||||
#define NLATS 67
|
||||
#define NLONS 116
|
||||
|
||||
using namespace std;
|
||||
using namespace netCDF;
|
||||
|
||||
template <typename T>
|
||||
vector<T> getVarVector(const NcVar &var) {
|
||||
int length = 1;
|
||||
for (NcDim dim : var.getDims()) {
|
||||
length *= dim.getSize();
|
||||
}
|
||||
|
||||
vector<T> vec(length);
|
||||
|
||||
var.getVar(vec.data());
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
||||
tuple<vector<int>, vector<double>, vector<double>> readGrid() {
|
||||
netCDF::NcFile data("../../../../data/grid.h5", netCDF::NcFile::read);
|
||||
multimap< string, NcVar > vars = data.getVars();
|
||||
vector<int> time = getVarVector<int>(vars.find("times")->second);
|
||||
vector<double> longitude = getVarVector<double>(vars.find("longitude")->second);
|
||||
vector<double> latitude = getVarVector<double>(vars.find("latitude")->second);
|
||||
|
||||
return {time, latitude, longitude};
|
||||
}
|
||||
|
||||
int main() {
|
||||
vtkNew<vtkNamedColors> colors;
|
||||
|
||||
|
||||
vtkNew<vtkDoubleArray> pCoords;
|
||||
pCoords->SetNumberOfComponents(3);
|
||||
pCoords->SetNumberOfTuples(NLATS*NLONS);
|
||||
auto [times, lats, lons] = readGrid();
|
||||
|
||||
double i = 0;
|
||||
for (double lat : lats) {
|
||||
for (double lon : lons) {
|
||||
pCoords->InsertTuple3(i++, 0, lat, lon);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
vtkNew<vtkPoints> points;
|
||||
points->SetData(pCoords);
|
||||
|
||||
vtkNew<vtkPolyData> polydata;
|
||||
polydata->SetPoints(points);
|
||||
|
||||
|
||||
vtkNew<vtkPolyDataMapper2D> mapper;
|
||||
mapper->SetInputData(polydata);
|
||||
mapper->SetScalarRange(0, 40);
|
||||
|
||||
vtkNew<vtkActor2D> actor;
|
||||
actor->SetMapper(mapper);
|
||||
|
||||
vtkNew<vtkRenderer> ren;
|
||||
ren->AddActor(actor);
|
||||
ren->SetBackground(colors->GetColor3d("DarkSlateGray").GetData());
|
||||
|
||||
vtkNew<vtkRenderWindow> renWin;
|
||||
renWin->AddRenderer(ren);
|
||||
renWin->SetSize(900, 600);
|
||||
|
||||
vtkNew<vtkRenderWindowInteractor> iren;
|
||||
iren->SetRenderWindow(renWin);
|
||||
iren->Start();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue